用numpy求整数整数线性系统

时间:2012-12-16 03:01:32

标签: python numpy linear-algebra

我正试图用numpy来解决一个超定的线性方程组。目前,我正在做这样的事情(作为一个简单的例子):

a = np.array([[1,0], [0,1], [-1,1]])
b = np.array([1,1,0])

print np.linalg.lstsq(a,b)[0]
[ 1.  1.]

这可行,但使用浮点数。有没有办法只用整数解决系统?

我尝试了一些东西
print map(int, np.linalg.lstsq(a,b)[0])
[0, 1]

为了将解决方案转换为整数数组,期待[1, 1],但显然我错过了一些东西。有人能指出我正确的方向吗?

8 个答案:

答案 0 :(得分:6)

您应该使用专门的整数问题求解器(请注意整数问题甚至不易解决)。 openopt是一个包,例如应该为整数二次优化提供良好的包装,就像你正在做的那样。尝试使用线性代数根本无法直接为您提供正确的解决方案。

您的问题可以用quadratic program编写,但它是integer,因此请使用openopt或其他模块。由于它是一个非常简单,不受约束的,也许还有其他方法。但对于初学者来说,它起初并不是一个简单的问题,而且openopt等程序已经准备就绪,可以有效地解决这类问题。

答案 1 :(得分:4)

您正在查看线性diophantine equations系统。一个快速的谷歌搜索出现 费利克斯·拉泽布尼克Systems of Linear Diophantine Equations。在该论文中,作者考虑了以下问题:

  

给定线性方程组Ax = b,其中A = a(i,j)是m×n矩阵   具有整数条目,并且b是具有整数分量的m×1列向量,是系统   具有整数解,即具有整数分量的n×1解向量x

答案 2 :(得分:2)

转换为int时,元素的小数部分会被截断,因此会向下舍入。

a = np.array([[1,0], [0,1], [-1,1]])
b = np.array([1,1,0])

x = np.linalg.lstsq(a,b)[0]

结果:

>>> x
array([ 1.,  1.])
>>> x[0]
0.99999999999999967
>>> x[1]
1.0000000000000002
>>> x.astype(int)
array([0, 1])
>>> map(int, x)
[0, 1]
>>> np.array([1.,1.]).astype(int) # works fine here
array([1, 1])

答案 3 :(得分:1)

我可能误解了您的问题,但我认为您只需要round然后astype(int)的组合?

E.g。

a = np.array([[1,0], [0,1], [-1,1]])
b = np.array([1,1,0])

x = np.linalg.lstsq(a,b)[0]
print x.round().astype(int)

答案 4 :(得分:1)

+1 to seberg,这是一个反例,说明你不应该映射:
(对不起,它是matlab风格,但你很容易pythonize)

a =
     3     0
     0     3
     1     1
b = 
    2.71
   11.7
    0.5
x = a\b =
    0.5121
    3.5088
round(x) =
    1
    4
norm(a*round(x)-b) = 4.5193
norm(a*[0;4]-b) = 4.4367
norm(a*[1;3]-b) = 4.4299

答案 5 :(得分:1)

我的方法是先找到非整数解,然后放大到整数一

from fractions import Fraction, gcd
from functools import reduce

def lcm(a, b):
    return a * b // gcd(a, b)

def common_int(*numbers):
    fractions = [Fraction(n).limit_denominator() for n in numbers[0]]
    multiple = reduce(lcm, [f.denominator for f in fractions])
    ints = [f * multiple for f in fractions]
    divisor = reduce(gcd, ints)

    return [int(n / divisor) for n in ints]

sol = np.linalg.solve(np.array([[1, 2, 3], [2, 1, 0], [2, 1, 4]]), np.array([1., 1., 1.]))  # system of equation
# [0.3333333, 0.3333333, 0.]

common_int(sol)
# [1., 1., 0.]

答案 6 :(得分:0)

我需要这样做并最终将由Keith Matthews编写的PHP程序(可以在http://www.numbertheory.org/php/php.html上找到)移植到Python中。我最初使用Numpy数组但遇到了整数溢出的问题,因此切换到使用任意精度数值表示的Sympy矩阵。

代码在GITHub上的https://github.com/tclose/Diophantine根据MIT许可证发布,所以请随意使用它,如果您遇到任何问题请告诉我(抱歉没有更好的文档记录)。主分支使用Sympy但您可以在'numpy'分支中访问原始的Numpy实现,这对于合理稀疏的系统似乎没有用。

如果您最终将其用于科学出版物,请引用Keith的论文(并可能添加指向GitHub回购的链接)。

答案 7 :(得分:0)

有一种名为block lanczos.的方法。这可以通过有限的字段来回答。您可以找到针对此特定问题的块lanczos解算器。