找到一组方程的整数解,其中包含比方程更多的未知数

时间:2016-08-06 13:27:11

标签: java math apache-commons-math

我正在尝试构建一个系统,我需要找到一组线性方程的解决方案,其中包含比方程更多的变量。

问题可归结为以下几点:

想象一组方程式:

var filter = GPUImageFilter.FromFragmentShaderString(fragShaderString);

如何为此系统找到一个或多个(正)整数解?

注意:我一直在查看apache-commons-math库,但是我找不到任何关于如何解决/找到带有自由变量的系统解决方案的指示。

4 个答案:

答案 0 :(得分: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中的倒数,并将其与其他的相加。模数10中9的倒数是-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.

让我知道是否还有不清楚的事情!

答案 1 :(得分:1)

我会尝试以下方法(注意我从来没有处理过这个问题,所以把这个答案作为尝试解决问题而不是真正的分析答案)。

您只需找到与常规系统相同的解决方案,因此您可能会找到很多解决方案:

示例:

y = x + 3

那么实数对(2,5)是该系统的一种可能的真正解决方案,一旦你拥有无限多的解决方案,你就可以限制由整数组成的解决方案的子集。

当然你有约束,在我们的例子中,解决方案只有一个自由变量,所以我们可以编写所有类似的解决方案:

(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

如果您认为答案不能令您满意,请告诉我:我会删除它以获得赏金点数

答案 2 :(得分:1)

您可能希望了解Z3之类的约束求解器。还有JavaExample

可以找到一个有用的教程,解释Z3的一些强大功能here

编辑:另请查看Algorithm for solving systems of linear inequalities

答案 3 :(得分:1)

如果我正确理解了问题,那么您有多个包,每个包都有不同的邮资费用。您想从您可用的邮票池中支付这些邮资费用。可以用整数编程来解决问题。下面的解决方案一次解决所有包。你将有许多变量等于numPackages * numStampDenominations(对于大量的包可能不方便)。

等式约束看起来像Aeq x = beq。具有4个印章面额(numVars numPackages)的两个包的矩阵Aeq看起来像:

.21 .68 .47 .01 .00 .00 .00 .00           .89
                                   * x = 
.00 .00 .00 .00 .21 .68 .47 .01           .50 

第一行是包1的约束系数(标记值)。非零系数是标记值。与其他包相关的零系数变量并不关心。

第二组约束(不平等)处理我可用的邮票库。不等式约束看起来像A * x = b。 4个邮票面额的矩阵A和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&#39; * x,它只是邮票的总数。它的系数只是列向量的形式。

以下是在matlab中运行的脚本,它以所述方式解决问题。它可能会在八度音阶中表达相同,这是一个类似于matlab的GNU产品。 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)