Python 用numpy求解整数上的线性系统

Python 用numpy求解整数上的线性系统,python,numpy,linear-algebra,Python,Numpy,Linear Algebra,我想用numpy解一个超定线性方程组。目前,我正在做类似的事情(作为一个简单的例子): [0, 1] 为了将解决方案转换为int数组,期望[1,1],但显然我遗漏了一些东西。有人能给我指出正确的方向吗?当您转换为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.,

我想用numpy解一个超定线性方程组。目前,我正在做类似的事情(作为一个简单的例子):

[0, 1]
为了将解决方案转换为int数组,期望
[1,1]
,但显然我遗漏了一些东西。有人能给我指出正确的方向吗?

当您转换为
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])

我可能误解了您的问题,但我认为您只需要将
round
astype(int)
组合起来即可

例如


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


您的问题可以用a编写,但它是一个问题,因此请使用
openopt
或其他模块来解决。因为这是一个非常简单、不受约束的方法,也许还有其他方法。但对于初学者来说,这并不是一开始看起来很简单的问题,openopt中有一些程序可以有效地解决这类问题。

您看到的是一个线性系统。一个快速的谷歌搜索就会出现 费利克斯·拉兹布尼克。在该文件中,作者考虑了以下问题:

给定一个线性方程组Ax=b,其中a=a(i,j)是一个m×n矩阵 对于整数项,b是一个带有整数分量的m×1列向量,系统是否 是否有整数解,即具有整数分量的n×1解向量x


+1对于seberg,这里有一个反例来说明您不应该映射圆:
(很抱歉,这是matlab风格,但您很容易将其pythonize)


我需要这样做,并最终将Keith Matthews编写的PHP程序移植到Python中,您可以在上找到该程序。我最初使用Numpy数组,但遇到了整数溢出的问题,所以切换到使用任意精度数值表示的Sympy矩阵

这段代码是根据麻省理工学院的许可证在GitHub上发布的,所以请随意使用它,如果遇到任何问题,请告诉我(很抱歉,没有更好的文档记录)。主分支使用Sympy,但您可以在“Numpy”分支中访问原始的Numpy实现,这对于合理稀疏的系统来说似乎可以正常工作


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

有一种方法称为“在有限域上搜索您的答案”。对于这个特定问题,您可以找到block lanczos解算器

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

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.]

我想是这样的——那么有没有办法在计算中只使用整数来避免这些浮点误差呢?我认为
np.round
应该可以。对不起,这在这里是可行的,因为这个例子的精确解恰好是整数。没有理由舍入/截断将为您提供最佳的整数解决方案。谢谢,这也很有帮助。所以numpy没有一个函数专门用于求解整数上的线性系统?我本来打算用这样的舍入法作为最后的手段,但这不会有太大的区别。@a.R.S:你想用整数算术解线性代数,还是希望结果是整数数据类型?我认为前者不可能。对于后者,我认为这里给出的建议应该足够了。我同意tiango的观点,从这个问题上我认为这是不正确的,因为舍入并不能保证找到最佳的整数解(除非一开始是整数),但如果手头有一个超定的系统,这似乎不太可能。虽然我承认,这个例子碰巧有一个精确解。@A.R.S.-不,据我所知,numpy没有任何方法来解一个保证得到整数解的方程组。在内部,numpy只是从
LAPACK
等调用例程,因此
lstsq
等函数本身就是浮点函数。我认为NPE的答案是确定一个解决方案是否存在,而seberg的建议是尝试一个非线性解算器,不过,你可能可以把一些东西放在一起。一个四舍五入或截断的浮点解可能会给非线性解算器提供一个很好的开始猜测,如果没有其他问题的话。你真的应该澄清这个问题。这篇文章说的是超定的,所以可能我解释错了,但这向我表明,你不知道有一个精确解,而且我也不明白为什么最好的/精确解应该是整数(如果你知道其中一个是一个巨大的缺失信息)。在这种情况下,示例过于简化,因为它有一个最佳(甚至是精确的)整数解。 [0, 1]
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])
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)
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
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.]