我有一个线性方程:
vt = v1*x1 + v2*x2 + v3*x3
vt、v1、v2、v3 是值在 0 和 1 之间的标量。生成满足上述等式的 x1、x2 和 x3 的一组(任何一组都可以)的最佳方法是什么。也满足
x1>0
x2>0
x3>0
我有几千套 vt、v1、v2 和 v3,因此我需要能够以编程方式生成 x1、x2 和 x3。
我有一个线性方程:
vt = v1*x1 + v2*x2 + v3*x3
vt、v1、v2、v3 是值在 0 和 1 之间的标量。生成满足上述等式的 x1、x2 和 x3 的一组(任何一组都可以)的最佳方法是什么。也满足
x1>0
x2>0
x3>0
我有几千套 vt、v1、v2 和 v3,因此我需要能够以编程方式生成 x1、x2 和 x3。
有两种方法可以解决这个问题:
x1
并x2
确保vt < v1*x1 + v2*x2
,然后继续求解x3
。因此,我们可以将您的问题转化为线性规划问题。“最大化”语句就是所谓的目标函数——你试图完成的总体目标。在线性规划问题中,我们试图最小化或最大化这个目标。要做到这一点,我们必须满足在条件主体中看到的不等式。通常,该程序以规范形式表示,因此每个变量的约束应该是正的。
最大化条件可以是任意的,因为您不关心目标。您只关心任何解决方案。这整个范例可以通过linprog
在 MATLAB 中实现。您应该注意的是如何linprog
指定。事实上,目标是最小化而不是最大化。然而,除了确保所有变量都是正数之外,条件是相同的。我们必须自己编写代码。
就任意目标而言,我们可以简单地做x1 + x2 + x3
。因此,c = [1 1 1]
. 我们的等式约束是:v1*x1 + v2*x2 + v3*x3 = vt
. 我们还必须确保这x
是积极的。为了编码这个,我们可以做的是选择一个小的常数,以便所有的值x
都大于这个值。现在,linprog
不支持严格的不等式(即x > 0
),所以我们必须通过这个技巧来规避这个问题。此外,为了确保值是正数,linprog
假设Ax <= b
. 因此,一个常用的技巧是否定 的不等式x >= 0
,因此这等价于-x <= 0
。为了确保这些值不为零,我们实际上会这样做-x <= -eps
:eps
是一个小常数。然而,当我做实验时,通过这种方式,两个变量最终成为相同的解决方案。因此,我建议我们做的是每次生成随机的好的解决方案,让我们b
从你所说的均匀随机分布中抽取。每次我们想解决这个问题时,这将为我们提供一个起点。
因此,我们的不等式是:
-x1 <= -rand1
-x2 <= -rand2
-x3 <= -rand3
rand1, rand2, rand3
是介于0
和之间的三个随机生成的数字1
。在矩阵形式中,这是:
[-1 0 0][x1] [-rand1]
[0 -1 0][x2] <= [-rand2]
[0 0 -1][x3] [-rand3]
最后,我们之前的等式约束是:
[v1 v2 v3][x1] [vt]
[x2] =
[x3]
现在,要使用linprog
,您可以这样做:
X = linprog(c, A, b, Aeq, beq);
c
是为目标定义的系数数组。在这种情况下,它将被定义为[1 1 1]
,A
并且b
是为不等式约束定义的矩阵和列向量,Aeq
并且beq
是为等式约束定义的矩阵和列向量。 X
因此会在收敛后给我们解决方案linprog
(即x1, x2, x3
)。因此,您可以这样做:
A = -eye(3,3);
b = -rand(3,1);
Aeq = [v1 v2 v3];
beq = vt;
c = [1 1 1];
X = linprog(c, A, b, Aeq, beq);
例如,假设v1 = 0.33, v2 = 0.5, v3 = 0.2
和vt = 2.5
。所以:
rng(123); %// Set seed for reproducibility
v1 = 0.33; v2 = 0.5; v3 = 0.2;
vt = 2.5;
A = -eye(3,3);
b = -rand(3,1);
Aeq = [v1 v2 v3];
beq = vt;
c = [1 1 1];
X = linprog(c, A, b, Aeq, beq);
我得到:
X =
0.6964
4.4495
0.2268
为了验证这等于vt
,我们会这样做:
s = Aeq*X
s = 2.5000
以上只是简单的v1*x1 + v2*x2 + v3*x3
。这是以点积形式计算的,以使事情变得容易,因为X
它是列向量并且v1, v2, v3
已经设置Aeq
并且是行向量。
因此,无论哪种方式都很好,但至少使用linprog
,您不必继续循环,直到满足该条件!
我在上述方法中忘记提到的一个小警告是,您需要确保vt >= v1*rand1 + v2*rand2 + v3*rand3
确保收敛。既然你说v1,v2,v3
介于0
和之间1
,最坏的情况是v1,v2,v3
它们都等于 1。因此,我们确实需要确保vt > rand1 + rand2 + rand3
。如果不是这种情况,则只需取 的每个值rand1, rand2, rand3
,然后除以(rand1 + rand2 + rand3) / vt
。因此,这将确保总和等于vt
假设所有权重为 1,这将允许线性程序正确收敛。
如果不这样做,则由于 for 中的不等式条件,解决方案将不会收敛b
,并且您将不会得到正确的答案。只是一些思考的食物!因此,请b
在运行之前执行此操作linprog
if sum(-b) > vt
b = b ./ (sum(-b) / vt);
end
祝你好运!