4

我对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 为我解决这样的问题?

4

2 回答 2

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

结果是一个全零的解决方案。既然那个解显然不能完全解决原来的问题,那么肯定不存在这样的正解。

于 2013-05-03T20:13:36.520 回答
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 解决方案相同的结果)

于 2013-05-03T19:18:54.210 回答