Найдите положительные решения недоопределенной линейной системы уравнений

Я немного новичок в 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 решить такую ​​​​проблему для меня?


person htd    schedule 03.05.2013    source источник


Ответы (2)


Простой ответ, поскольку вам просто нужны ограничения неотрицательности параметров, — использовать 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

тогда должно быть верно, что x+c*N также является решением для любой произвольной константы c. (Помните, что 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

В результате получается нулевое решение. Поскольку это решение явно не может точно решить исходную проблему, должно быть верно, что такого положительного решения не существует.

person Community    schedule 03.05.2013
comment
Это кажется совершенно потрясающим ответом, но мне придется потратить некоторое время, чтобы взглянуть на него. Спасибо, теперь я вернусь :) - person htd; 04.05.2013

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

Вы можете получить решение x для Ax = b, используя

x = A\b;

or

x = pinv(A)*b;

но если вам нужны ограничения на x, вам придется использовать что-то вроде lsqlin :

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

(что в данном случае дает тот же результат, что и решение pinv)

person ioums    schedule 03.05.2013
comment
Спасибо за ваш ответ. Мне как бы нужны неравенства - часть решения, которую я уже знал. Может ли lsqlin найти то, что я ищу? - person htd; 03.05.2013
comment
Предполагая, что у вас есть набор инструментов для оптимизации, я не понимаю, почему бы и нет. - person ioums; 03.05.2013