找到欠定线性方程组的正解

时间:2013-05-03 18:51:31

标签: matlab mathematical-optimization equation-solving

我对matlab有点新鲜,很抱歉,如果这非常简单。

考虑以下问题:

查找x_1, x_2, x_3 > 0以便

67.5 = 60*x_1 +  90*x_2 + 120*x_3 and
60   = 30*x_1 + 120*x_2 +  90*x_3

在这种情况下,我想要解决方案

0 < x_3 < 3/7,
x_2 = 7/20 - 4/10*x_3, and
x_1 = 2/5  -  7/5*x_3

是否有一种简单的方法可以让Matlab为我解决这样的问题?

2 个答案:

答案 0 :(得分:8)

简单的答案,因为你只需要对参数进行非负性约束,就是使用lsqnonneg。这个问题根本不需要lsqlin,因为lsqnonneg是MATLAB的一部分,所以不需要优化TB。

A = [60 90 120; 30 120 90];
b = [67.5; 60];

x = lsqnonneg(A,b)
x =
                         0
         0.178571428571428
         0.428571428571429

我们可以测试结果,看它是否解决了原始问题。

A*x - b
ans =
     0
     0

当然你可以使用lsqlin,但为什么要这么麻烦?

事实上,我们必须考虑一个问题,因为欠定系统有无限多的解决方案。我们可以在我们的解决方案中添加任意数量的数组A的零空间。在这种情况下,零空间具有等级1.它的特征在于向量N:

N = null(A)
N =
        -0.792593923901216
         -0.22645540682892
         0.566138517072299

理解它的一个简单方法是识别A的零空间意味着什么。 N是一个向量(或一组基本向量,如果零空间的维度大于1,则跨越子空间),这样就

A*N = 0

基本上,N是与A的所有行正交的向量。如果零空间的维度大于1,则N可以是零空间的基向量的任何线性组合。因此,如果X是确定系统的任何解决方案

A*x = b

那么对于任何任意常数c,x + c * N也必须是一个解。 (请记住,A * N将为零。)

例如,我会为N选择一个任意系数:

x2 = x + N*(-.1)
x2 =
        0.0792593923901216
          0.20121696925432
         0.371957576864199

同样,x2也是一种解决方案。它也具有完全正系数。 (你可以在N上找到系数的值范围,使得解决方案完全是正的。)

A*x2 - b
ans =
      -1.4210854715202e-14
       -7.105427357601e-15

(注意,它们实际上是零,在浮点运算中找到的双精度垃圾中。)

因此,如果我们想要这样做,很容易从lsqnonneg或反斜杠或pinv解决方案开始,并找到系统的完整解决方案集,使系数完全正。提示:您需要做的就是考虑向量x和N,然后寻找问题的解决方案

(x + c*N) > 0

其中c是一些标量常量。显然,C不能是正数,否则总和的第一个元素将是负数。

C = -x./N
C =
            0
      0.78855
     -0.75701

x + C(1)*N
ans =
            0
      0.17857
      0.42857

x + C(3)*N
ans =
          0.6
         0.35
            0

正如我们所看到的,当c是闭区间[-.75701,0]中的任何值时,我们得到一个完全正解的问题,形式为(x + c * N)。但是,除了这些限制之外,其他任何一个或多个元素都将为负数。

在一些问题上,根本没有解决方案可以得到解决方案向量的所有正元素的精确解。这是完全可能的。例如,假设我们将原始问题更改为:

A = [60 90 120; 30 120 90];
b = [-67.5; -60];

现在我们申请lsqnonneg后会发生什么?

lsqnonneg(A,b)
ans =
     0
     0
     0

产生全零解决方案。由于该解决方案显然不能完全解决原始问题,因此不存在这样的正解决方案。

答案 1 :(得分:1)

A = [60 90 120; 30 120 90];
b = [67.5; 60];

您可以使用

获得Ax = b的解x
x = A\b;

x = pinv(A)*b;

但是如果你想要x的约束,你将不得不使用类似lsqlin的东西:

lsqlin(A,b,[],[],[],[],[0; 0; 0],[])

(在这种情况下给出与pinv解决方案相同的结果)