我有一组可以表示为矩阵的方程式,我还要求解决方案中的所有变量x i ,(x i ) 3 - x i = 0.例如,
A = [0 1 0 0]
[0 0 1 0]
[1 0 0 1]
我也不是所有变量都是=。
这意味着
x 2 = 0
x 3 = 0
x 1 + x 4 = 0
(x 1 ) 3 - x 1 = 0
(x 2 ) 3 - x 2 = 0
(x 3 ) 3 - x 3 = 0
(x 4 ) 3 - x 4 = 0
一个简单的解决方案是x 1 = 1且x 4 = -1。
如何解决像这样的方程组的小实例?我想要一个至少可以从python中调用的解决方案。
我目前解决问题的方法是尝试所有3个 n 不同的向量,其值为-1,0,1。
for v in itertools.product([-1,0,1], repeat = n):
vector = np.asarray(v)
if (not np.dot(M,v).any()):
print "Solution found!"
break
修改
这应该是对@ alko答案的评论,但它太长了。让我通过一个例子来研究这个方法。
A = np.matrix([[0, 1, 1, 1, 1, 0, 1], [1, 0, 1, 1, 1, 1, 0], [0, 1, 0, 1, 1, 1, 1], [1, 0, 1, 0, 1, 1, 1], [0, 1, 0, 1, 0, 1, 1]])
p,l,u=scipy.linalg.lu(A)
print u
[[ 1. 0. 1. 1. 1. 1. 0.]
[ 0. 1. 1. 1. 1. 0. 1.]
[ 0. 0. -1. 0. 0. 1. 0.]
[ 0. 0. 0. -1. 0. 0. 1.]
[ 0. 0. 0. 0. -1. 0. 0.]]
我不清楚下一步会是什么......?
答案 0 :(得分:2)
这种问题叫做约束编程。有一些python库可以解决这个问题。例如,以下代码使用or-tools
from constraint_solver import pywrapcp as cs
import numpy as np
A = np.array(
[[0, 1, 0, 0],
[0, 0, 1, 0],
[1, 0, 0, 1]], np.bool)
#A = np.array( [[0, 1, 1, 1, 1, 0, 1],
# [1, 0, 1, 1, 1, 1, 0],
# [0, 1, 0, 1, 1, 1, 1],
# [1, 0, 1, 0, 1, 1, 1],
# [0, 1, 0, 1, 0, 1, 1]], np.bool)
values = [-1, 0, 1]
solver = cs.Solver("name")
X = np.array([solver.IntVar(values) for i in range(A.shape[1])])
Xl = X.tolist()
for row in A:
x = X[row].tolist()
solver.Add(solver.Sum(x) == 0)
db = solver.Phase(Xl,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT)
solver.NewSearch(db)
while solver.NextSolution():
solution = [x.Value() for x in Xl]
print solution
输出:
[-1, 0, 0, 1]
[0, 0, 0, 0]
[1, 0, 0, -1]
答案 1 :(得分:2)
既然你放了SymPy标签,我会指出SymPy可以很容易地象征性地解决这个问题
In [6]: x1, x2, x3, x4 = symbols('x1:5')
In [7]: solve([x2, x3, x1 + x4, x1**3 - x1, x2**3 - x2, x3**3 - x3, x4**3 - x4], [x1, x2, x3, x4], dict=True)
Out[7]: [{x₁: -1, x₂: 0, x₃: 0, x₄: 1}, {x₁: 0, x₂: 0, x₃: 0, x₄: 0}, {x₁: 1, x₂: 0, x₃: 0, x₄: -1}]
如果你的解决方案不是整数,那么事情会变得更加毛茸茸,因为激进分子的解决方案可能不存在,或者至少SymPy可能无法找到它们。如果是这种情况并且您只对数字解决方案感兴趣,那么您应该使用像numpy或scipy这样的数字库,但由于您的解决方案都是-1,0或1,因此这不是问题。
修改强>
如果您有Matrix,请说:
A = Matrix([[0, 1, 0, 0],
[0, 0, 1, 0],
[1, 0, 0, 1]])
然后将其转换为系统很容易。只需将它乘以包含符号的向量(为方便起见,我在此处切换到基于0的索引):
In [13]: syms = symbols("x:4")
In [14]: s = Matrix(syms)
In [15]: constraints = [xi**3 - xi for xi in syms]
In [16]: A*s
Out[16]:
⎡ x₁ ⎤
⎢ ⎥
⎢ x₂ ⎥
⎢ ⎥
⎣x₀ + x₃⎦
In [17]: solve(list(A*s) + constraints, syms, dict=True)
Out[17]: [{x₀: -1, x₁: 0, x₂: 0, x₃: 1}, {x₀: 0, x₁: 0, x₂: 0, x₃: 0}, {x₀: 1, x₁: 0, x₂: 0, x₃: -1}]
以下是您的大型系统的解决方案:
In [35]: A = np.matrix([[0, 1, 1, 1, 1, 0, 1], [1, 0, 1, 1, 1, 1, 0], [0, 1, 0, 1, 1, 1, 1], [1, 0, 1, 0, 1, 1, 1], [0, 1, 0, 1, 0, 1, 1]])
In [36]: A = Matrix(A).applyfunc(int)
In [37]: syms = symbols("x:7")
In [38]: s = Matrix(syms)
In [39]: constraints = [xi**3 - xi for xi in syms]
In [40]: solve(list(A*s) + constraints, syms, dict=True)
Out[40]:
[{x₀: -1, x₁: 1, x₂: 1, x₃: -1, x₄: 0, x₅: 1, x₆: -1}, {x₀: 0, x₁: 0, x₂: 0, x₃: 0, x₄: 0, x₅: 0, x₆: 0}, {x₀: 1, x₁: -1, x₂: -1, x₃: 1, x₄: 0, x₅: -1, x₆:
1}]
两个注释:
您无需在LU中获取它。 SymPy的解决方案将为您解决(如果您的计算时间过长,您可以开始担心这些事情)。
In [36]
将Matrix条目转换为int(默认情况下为浮点数)。没有必要,但一般来说,当你知道它们是准确的时候,SymPy会用确切的数字做得更好,特别是因为你知道你的解决方案无论如何都是整数。如果您从一开始就使用SymPy Matrix
,则无需担心这一点。
答案 2 :(得分:0)
您可以将A
分解为lu
decomposition:
import numpy as np
import scipy.linalg
A = np.matrix([[0, 1, 1, 1, 1, 0, 1],
[1, 0, 1, 1, 1, 1, 0],
[0, 1, 0, 1, 1, 1, 1],
[1, 0, 1, 0, 1, 1, 1],
[0, 1, 0, 1, 0, 1, 1]])
p, l, u = scipy.linalg.lu(A)
为简单起见,我们假设A具有最大等级,即其中一些适当的未成年人是可逆的。如果不是这样,你可以将矩阵A减少到一个较小的A',其具有与下面相同的LU分解,其中A'满足该属性并且在等式方面是等价的(u
的最后一行将为零,删除他们继续)。您的等式Ax=0
等于(plu)x=0
,而p
和l
是可逆矩阵ux=0
。 u
,反过来是上三角
print u
# [[ 1. 0. 1. 1. 1. 1. 0.]
# [ 0. 1. 1. 1. 1. 0. 1.]
# [ 0. 0. -1. 0. 0. 1. 0.]
# [ 0. 0. 0. -1. 0. 0. 1.]
# [ 0. 0. 0. 0. -1. 0. 0.]]
您只对最后(两列)列感兴趣,这两列定义了最后一个变量值的所有变量。探测所有x4可能的非零值,1
和-1
,您可以检查您的方程组是否有解:
from itertools import product
idx = u.shape[0] - u.shape[1]
m, v = u[:, :idx], u[:,idx:]
for spare in product({1, 0, -1}, repeat=-idx):
if any(spare): # to exclude all zeros
sol = scipy.linalg.solve(m, -np.dot(v, spare))
if not set(sol).difference({0,1,-1}):
print 'solution: ', sol, spare
# solution: [-1. 1. 1. -1. -0.] (1, -1)
# solution: [ 1. -1. -1. 1. -0.] (-1, 1)