如何使用sympy求解具有约束条件的方程组

时间:2018-12-17 11:14:34

标签: python python-3.x sympy equation

像这样的例子:

    x1 + x2 + x3 + x4 = 1
    x3 + x4 = 1
    x4 + x5 = 1
    x4 + x5 + x6 = 2
    x1,x2,x3,x4,x5,x6 belong to this set {0, 1}

所以您看到,这是一个线性方程组。

因为x属于{0,1} <-> x ** 2-x = 0 所以我在下面解决了这个问题...但是我认为这很愚蠢:

In [1]: import numpy as np

In [2]: from sympy import *

In [3]: x1,x2,x3,x4,x5,x6 = symbols('x:6')

In [4]: res = solve([x1+x2+x3+x4-1, x3+x4-1, x4+x5-1, x4+x5+x6-2, x1**2-x1, x5**2-x5, x2**2-x2, x3**2-x3, x4**2-x4, x5*
   ...: *2-x5, x6**2-x6],[x1,x2,x3,x4,x5,x6])

In [5]: np.array(res)
Out[5]:
array([[0, 0, 0, 1, 0, 1],
       [0, 0, 1, 0, 1, 1]], dtype=object)

我知道var可以添加一些约束条件:

x = Symbol("x", positive=True)

那么,是否可以像这样添加一些约束条件?

x1, x2, x3, x4, x5, x6 = symbols('x:6', domain=(0, 1))

帮帮我,谢谢。

1 个答案:

答案 0 :(得分:0)

这是我想出的:

我使用linsolve来求解线性方程,而不会限制域。然后,解集可能是空的,完全确定的或依赖于一些自由变量。然后,我尝试对{0,1}中的可用变量进行所有替换,并仅收集那些导致解决方案的变量,以使每个变量都位于{0,1}中。

from sympy import *

def eval_solution(concrete_solution):
    concrete_solution_eval = list(map(lambda x: x == 1 or x == 0,concrete_solution))
    if sum(concrete_solution_eval) == len(concrete_solution):
        return True

    return False

def enumerate_solutions(Sols):

    if Sols.free_symbols == set(): # no free variables. see if all variables belong to {0,1}

        concrete_solution = Sols.args[0]
        if concrete_solution == set(): # no solutions
            return []
        if eval_solution(concrete_solution):
            return [concrete_solution]
        else:
            return []
    # create a list of tuples of free variables, one for each valid value
    free_vars = []
    for i in range(2**len(Sols.free_symbols)):
        free_vars.append(tuple(Sols.free_symbols))

    # generate values to substitute for free variables
    free_vals = [list(bin(i))[2:] for i in range(2**len(Sols.free_symbols))] 
    free_vals = [tuple(map(int, list('0'*(len(Sols.free_symbols)-len(s)))+s )) for s in free_vals] 

    # zip twice to generate lists of pairs of variable and value
    free_zip = zip(free_vars,free_vals)
    free_zip_fin = list([list( zip( x[0], x[1] )) for x in free_zip ] )

    correct_solutions = []

    for substitution in free_zip_fin:
        concrete_solution = list(map(lambda x: x.subs(substitution),Sols.args[0]))
        if eval_solution(concrete_solution):
            correct_solutions.append(concrete_solution)

    return correct_solutions

x1,x2,x3,x4,x5,x6 = symbols('x1,x2,x3,x4,x5,x6')

res=linsolve([x1+x2+x3+x4-1, x3+x4-1, x4+x5-1, x4+x5+x6-2],[x1,x2,x3,x4,x5,x6])

l = enumerate_solutions(res)

print (l)

这可能会或可能不会比您的想法快。亲自看看这是否对您有用