【问题标题】:best way to obtain one answer that satisfy a linear equation in matlab在matlab中获得满足线性方程的答案的最佳方法
【发布时间】:2014-07-16 15:40:27
【问题描述】:

我有一个线性方程:

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。

【问题讨论】:

  • 最快的方法是将x1x2设置为已知并求解x3x1x2 可以由您设置,也可以随机生成。如果你随机生成它们,你应该确保vt 小于v1*x1 + v2*x2。您也可以使用linprog 并将其形成一个线性程序并解决它。 x1x2 是否相同有关系吗?
  • @rayryeng 这也是我最初的想法。我想不出一种巧妙的方法来随机生成 x1 和 x2 并确保 vt
  • @rayryeng 同样,如果 x1 和 x2 是从某个分布(例如均匀分布)中随机抽取的(带有某种约束的随机分布),则更为可取。
  • 没关系。我们可以使用linprog 一起避免这一切。我给你写一个答案。

标签: matlab linear-programming linear-equation


【解决方案1】:

有两种方法可以解决这个问题:

  1. 根据您在帖子中设计的方法。随机生成x1x2并确保vt < v1*x1 + v2*x2,然后继续求解x3
  2. 将此公式化为线性程序。线性程序基本上是求解受不等式或等式约束的方程组。换句话说:

因此,我们可以将您的问题转化为线性规划问题。 “最大化”语句就是所谓的目标函数——你试图完成的总体目标。在线性规划问题中,我们试图最小化或最大化这个目标。为此,我们必须满足 subject to 条件中的不等式。通常,这个程序以规范形式表示,因此每个变量的约束应该是正的。

最大化条件可以是任意的,因为您不关心目标。您只关心任何解决方案。整个范例可以通过 MATLAB 中的linprog 来实现。您应该注意的是如何指定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 是三个随机生成的数字,位于01 之间。在矩阵形式中,这是:

 [-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]Ab 是为不等式约束定义的矩阵和列向量,Aeqbeq 是为等式约束定义的矩阵和列向量.因此,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.2vt = 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 &gt;= v1*rand1 + v2*rand2 + v3*rand3 以确保收敛。既然您说v1,v2,v3 介于01 之间,最坏的情况是v1,v2,v3 都等于1。因此,我们确实需要确保vt &gt; rand1 + rand2 + rand3。如果情况不是,那么只需将rand1, rand2, rand3 的每个值除以(rand1 + rand2 + rand3) / vt。因此,这将确保总和等于vt(假设所有权重均为 1),这将允许线性规划正确收敛。

如果你不这样做,那么由于 b 的不等式条件,解将不会收敛,你将不会得到正确的答案。只是一些思考的食物!因此,请在运行 linprog 之前为 b 执行此操作

if sum(-b) > vt
   b = b ./ (sum(-b) / vt);
end

祝你好运!

【讨论】:

  • 感谢您的回答!一个问题,那么向量 b 是否对应于 -eps?在这种情况下,做 b = -rand(3,1)*0.0001 这样的事情有意义吗? @rayryeng​​span>
  • @Cici - 是的,这是我在小警告中提到的。将rand 乘以一个小的值,以确保我们得到答案。除此之外,这应该会给你你正在寻找的东西。
  • 现在我明白为什么 b = -rand(3,1)*0.0001 不是一个超级好主意!因为有时它只是返回一个太接近零的答案。
  • @Cici - 这就是为什么你应该根据我在我的小警告中指定的内容来缩放它。这样一来,您就不会得到如此接近 0 的解。
  • 感谢您的精彩回答!我应该补充一点,您的答案非常容易扩展到线性方程中有 N 个变量的系统。太棒了! @rayryeng​​span>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-24
  • 1970-01-01
  • 1970-01-01
  • 2016-10-14
  • 2011-11-18
  • 1970-01-01
  • 2011-12-03
相关资源
最近更新 更多