Найти целочисленные решения набора уравнений с большим числом неизвестных, чем уравнения
Я пытаюсь построить систему, для которой нужно найти решение системы линейных уравнений с (гораздо) больше переменных, чем уравнений.
проблема сводится к следующему:
представьте себе набор уравнений:
A = A1*X1 + A2*X2 + ... + AnXn
B = B1*X1 + B2*X2 + ... + BnXn
Как найти одно или несколько (положительных) целочисленных решений для этой системы?
примечание: Я смотрел на библиотеку apache-commons-math, но я не мог найти никаких указаний о том, как решить/найти решение системы со свободными переменными.
6 ответов
используйте алгоритм уменьшения базиса решетки Ленстра-Ленстра-Ловаш, чтобы найти нормальную форму Эрмита вашей системы.
Это straaightforward в matlab http://fr.mathworks.com/help/symbolic/mupad_ref/linalg-hermiteform.html
Проверьте NTL для c++ http://www.shoup.net/ntl/index.html
следуйте этому примеру: предположим, что уравнения:
7 = x + 3y + 4z + 9w
12 = 4x + 2y + 3z + 7w
есть 2 уравнения и 4 неизвестных. Вы можете установить на 2 неизвестными параметрами, поэтому система будет иметь столько уравнений, сколько неизвестных:
7 - (4z + 9w) = x + 3y
12 - (3z + 7w) = 4x + 2y
мы будем использовать x и y в качестве неизвестных. Его можно решить и оставить w и z в качестве параметров в линейном решении:
x = (22 - 3w - z)/10
y = (16 - 29w - 13z)/10
теперь, вам нужно сделать числители делятся на 10, знаменатель. Если есть решение, вы можете проверить все параметры от 1 до 10.
в общем, вы делаете это:
- выберите Параметры, чтобы было столько неизвестных, сколько уравнений. Попробуйте оставить неизвестные, которые генерируют наименьшее абсолютное значение для определителя (в примере это было 10, но выбор y и z был бы лучше, так как это было бы |det|=3)
- решите линейную систему и сгенерируйте ответ в зависимости от параметров
- испытывать значения параметров от 1 до абсолютного значения det (если есть решение, вы найдете его в этот момент), пока не будет целочисленного решения для всех неизвестных (именно поэтому вы выбираете наименьшее определяющее абсолютное значение раньше) и проверьте, является ли оно положительным (это не было проиллюстрировано в Примере).
Извините, если это грубая сила на последнем шаге, но, по крайней мере, есть возможность минимизировать диапазон теста. Возможно, могло быть и лучше. способ решения конечной системы диофантовых уравнений, но я не знаю никакого метода.
EDIT1
существует метод, чтобы избежать грубого принуждения последней части. Опять же, в примере, вы должны сделать:
22 = 3w + z (congruent, mod 10)
16 = 29w + 13z (congruent, mod 10)
применение модуля:
2 = 3w + z (congruent, mod 10)
6 = 9w + 3z (congruent, mod 10)
вы можете сделать систему конгруэнций треугольной (исключение Гаусса), умножая конгруэнцию на инверсии в модуле 10 и суммируя с другими. Инверсия 9 по модулю 10 равно -1, поэтому мы умножаем последнюю конгруэнцию:
2 = 3w + z (congruent, mod 10)
-6 = -9w + -3z (congruent, mod 10)
эквивалентно:
2 = 3w + z (congruent, mod 10)
4 = w + 7z (congruent, mod 10)
затем умножьте на -3 и добавьте к первому:
2 - 3*4 = 3w + z -3w - 21z (congruent, mod 10)
4 = w + 7z (congruent, mod 10)
эквивалентно:
-10 = -20z (congruent, mod 10)
4 = w + 7z (congruent, mod 10)
затем вы решаете сверху вниз (этот пример, похоже, верен для любого значения z). Может быть некоторая степень свободы, если у вас больше параметров, чем конгруэнций, но они эквивалентны, и вы можете установить избыточные параметры при любом значении, предпочтительно наименьшем которая составляет 1.
Дайте мне знать, если есть что-то не понятно еще!
Я бы попробовал следующий подход (обратите внимание, что мне никогда не приходилось иметь дело с этой проблемой, поэтому возьмите этот ответ как попытку решить с вами проблему, а не реальный аналитический ответ).
вы просто находите решения, как если бы это была обычная система, поэтому вы можете найти бесконечно много решений:
пример:
y = x + 3
тогда пара действительных чисел (2,5) является возможным реальным решением для этой системы, как только у вас есть бесконечно много решений вы просто ограничиваете подмножество решений, которые сделаны целыми числами.
конечно, у вас есть ограничения, в нашем случае решение имеет только 1 свободную переменную, поэтому мы можем написать все такие решения:
(x, x+3)
сюрприз:
если где-то есть иррациональное число, нет целочисленных решений:
(x, x+pi) => neither 1st or 2nd number here can be whole at same time
таким образом, вы, вероятно, можете найти целочисленные решения, если и только если Ваш " бесконечно много решения " ограничены целыми или рациональными числами.
Предположим, у вас есть следующие вектора:
( 3x, (2/5)y, y, x, x+y)
тогда целое решение может быть:
x=3
y=10/2
если вы чувствуете, что ответ не удовлетворяет вас, просто скажите: Я удалю его, чтобы не получить очки щедрости
возможно, вы захотите взглянуть на решатели ограничений, такие как Z3 и. Есть также JavaExample.
полезный учебник, объясняющий некоторые из возможностей Z3, можно найти здесь.
EDIT: Также посмотрите на алгоритм решения систем линейных неравенств
это взято из уместные Википедия раздел.
- перепишите уравнения с матричным обозначением
AX=C
. - вычислить Смит в нормальной форме of
A
. Грубо говоря, это поискB=UAV
здесьB[i][j] == 0
Еслиi != j
. B(inverse(V))X=UC
- As
B[i][j] == 0
Еслиi != j
, тривиально найти значение(inverse(V))X
и такX
.
Если я правильно понимаю проблему, у вас есть несколько пакетов, каждый с разными почтовыми расходами. Вы хотите оплатить эти почтовые расходы из пула марок, которые у вас есть. Проблему можно решить с помощью целочисленного программирования. Решение ниже решает для всех пакетов сразу. У вас будет несколько переменных, равных numPackages*numStampDenominations (вероятно, неудобно для большого количества пакетов).
ограничение равенства выглядит как Aeqx = Бек. Матрица Aeq для двух пакетов с 4 номиналами марок (numVarsnumPackages) выглядит так:
.21 .68 .47 .01 .00 .00 .00 .00 .89
* x =
.00 .00 .00 .00 .21 .68 .47 .01 .50
первая строка-это коэффициенты ограничений (значения штампа) для пакета 1. Ненулевые коэффициенты-это значения штампов. Переменная нулевых коэффициентов, связанная с другими пакетами, не заботится.
второй набор ограничений (неравенство) касается пула марок, которые у меня есть. Ограничение неравенства выглядит как A*x = b. Матрица a для 4 номинала марок и 8 переменных (numPackages * numStampDenominations) выглядят так:
1 0 0 0 1 0 0 0 10
0 1 0 0 0 1 0 0 10
* x <=
0 0 1 0 0 0 1 0 10
0 0 0 1 0 0 0 1 20
функция стоимости-f' * x, которая представляет собой общее количество марок. Его коэффициенты являются всего лишь единицами в виде вектора столбца.
следующий скрипт в MATLAB, который решает проблему описанным способом. Вероятно, он был бы сформулирован примерно так же в octave, GNU, предлагающем аналогичное matlab. Matlab или Октава не могут быть правильным решением для вы, но они, по крайней мере, говорят вам, что работает, и дают вам песочницу для разработки решения.
% The value of each stamp available as a 4x1 matrix
sv = [.21; .68; .47; .01];
% The number of each stamp available as a 4x1 matrix
sq = [10;10;10;40];
% Number of demominations
m = size(sv, 1);
% The postage required for each package as a 4x1 matrix
% -- probably read from a file
postage = [.89;.50;1.01;.47;.47];
% Number of packages -- just a count of the postage rows
packageCount = size(postage, 1);
% Number of variables is m*packageCount
numVar = m*packageCount;
% lower bound -- zero stamps of a given denomination
lb = zeros(numVar,1);
% upper bound -- use constraints for upper bound
ub = [];
% The cost function -- minimize the number of stamps used
% min(f'*x)
f = ones(numVar,1);
% integer constraints
intcon = 1:numVar;
% Construct postage constraint matrix
Aeq = zeros(numVar, packageCount);
for i = 1:packageCount
first = i*m - 3;
last = first + 3;
Aeq(first:last,i) = sv(:);
end
% Construct stamp count constraint matrix
A = zeros(numVar, m);
for r = 1:m
for j = 1:m
c = (j-1)*m + 1;
A(c,r) = 1;
end
end
x = intlinprog(f, intcon, A', b, Aeq', beq, lb, ub)