在 Sympy 中解决约束满足问题

Solving constraint satisfaction problems in Sympy

我正在尝试在 Sympy 中解决一些简单的 Boolean satisfiability problems。在这里,我试图解决包含 Or 逻辑运算符的约束:

from sympy import *
a,b = symbols("a b")

print(solve(Or(Eq(3, b*2), Eq(3, b*3))))
# In other words: (3 equals b*2) or (3 equals b*3)
# [1,3/2] was the answer that I expected

令人惊讶的是,这会导致错误:

TypeError: unsupported operand type(s) for -: 'Or' and 'int'

我可以使用 Piecewise 来解决这个问题,但这要冗长得多:

from sympy import *
a,b = symbols("a b")
print(solve(Piecewise((Eq(3, b*2),Eq(3, b*2)), (Eq(3, b*3),Eq(3, b*3)))))
#prints [1,3/2], as expected

不幸的是,当我尝试求解两个变量而不是一个变量时,此解决方法失败了:

from sympy import *
a,b = symbols("a b")

print(solve([Eq(a,3+b),Piecewise((Eq(b,3),Eq(b,3)), (Eq(b,4),Eq(b,4)))]))
#AttributeError: 'BooleanTrue' object has no attribute 'n'

在 Sympy 中有没有更可靠的方法来解决像这样的约束?

每个方程都可以表示为等于 0 的值。例如,3-2*b = 0 而不是 3 = 2*b。 (在 Sympy 中,假设您甚至不必编写 =0 部分。)然后您可以简单地乘以方程来表达 OR 逻辑:

>>> from sympy import *
>>> a,b = symbols("a b")
>>> solve((3-b*2)*(3-b*3))
[1, 3/2]
>>> solve([a-3-b, (3-b*2)*(3-b*3)])
[{b: 1, a: 4}, {b: 3/2, a: 9/2}]

为了扩展 zaq 的答案,SymPy 无法识别 solve 中的逻辑运算符,但您可以使用

a*b = 0

相当于

a = 0 OR b = 0

也就是两个方程相乘

solve((3 - 2*b)*(3 - 3*b), b)

作为附加说明,如果您想使用 AND 而不是 OR,您可以求解一个系统。即,

solve([eq1, eq2])

相当于求解

eq1 = 0 AND eq2 = 0