Найти целочисленные решения в систему уравнений с более неизвестными, чем уравнения

Я пытаюсь построить систему, для которой мне нужно найти решение для набора линейных уравнений с (большим) числом переменных, чем уравнения.

Проблема сводится к следующему:

Представьте себе систему уравнений:

A = A1*X1 + A2*X2 + ... + AnXn
B = B1*X1 + B2*X2 + ... + BnXn

Как я могу найти одно или несколько (положительных) целочисленных решений для этой системы?

Примечание. Я смотрел библиотеку apache-commons-math, но не мог найти никаких указаний о том, как решить/найти решение системы со свободными переменными.

Ответ 2

Следуйте этому примеру: предположим, что уравнения:

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.

Сообщите мне, есть ли еще что-то непонятное!

Ответ 3

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

Вы просто находите решения, как если бы это была обычная система, поэтому вы можете найти бесконечно много решений:

Пример:

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

Если вы чувствуете, что ответ вам не подходит, просто скажите: я удалю его, чтобы не получить очки бонусов.

Ответ 6

Если я правильно понимаю проблему, у вас есть несколько пакетов, каждый из которых имеет разные почтовые расходы. Вы хотите оплатить эти почтовые расходы из пула марок, которые у вас есть. Можно решить проблему с целым программированием. Решение ниже решает для всех пакетов сразу. У вас будет число переменных, равное numPackages * numStampDenominations (вероятно, неудобно для большого количества пакетов).

Ограничение равенства выглядит как Aeqx = beq. Матрица Aeq для двух пакетов с четырьмя марками (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 выполняется script, который решает проблему описанным образом. Вероятно, он будет сформулирован примерно так же в октавах, предлагающих 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)