在 Python 中解决符号布尔变量

xxx*_*--- 5 python boolean symbolic-math sympy sage

我需要解决一组符号布尔表达式,例如:

>>> solve(x | y = False)
(False, False)

>>> solve(x & y = True)
(True, True)

>>> solve (x & y & z = True)
(True, True, True)

>>> solve(x ^ y = False)
((False, False), (True, True))
Run Code Online (Sandbox Code Playgroud)

此类变量的数量很大(~200),因此无法使用蛮力策略。我在网上搜索,发现SympySage具有符号操作功能(特别是thisthis可能很有用)。我怎样才能做到这一点?

编辑:我主要试图操纵这些东西:

>>> from sympy import *

>>> x=Symbol('x', bool=True)

>>> y=Symbol('y', bool=True)

>>> solve(x & y, x)
Run Code Online (Sandbox Code Playgroud)

这导致NotImplementedError. 然后我尝试 solve(x * y, x)which give [0](我不知道这是什么意思),solve(x * y = True, x)结果是 a SyntaxErrorsolve(x * y, True, x)然后solve(x & y, True, x)给了AttributeError. 我不知道还能尝试什么!

编辑(2):我也发现了这个,可能有用!

asm*_*rer 4

首先,纠正您的问题中明显错误的一些内容:

  • solve求解代数表达式。solve(expr, x)求解方程 expr = 0 的x

  • solve(x | y = False)等等都是无效语法。在 Python 中不能使用=来表示相等。请参阅http://docs.sympy.org/latest/tutorial/gotchas.html#equals-signs(我建议也阅读该教程的其余部分)。

  • 正如我在另一个问题的回答中提到的,Symbol('y', bool=True)什么也不做。Symbol('x', something=True)is_something假设设置为x,但bool不是 SymPy 任何部分认可的假设。只需使用正则Symbol('x')布尔表达式即可。

正如一些评论者指出的那样,您想要的是satisfiable实现 SAT 求解器的 。satisfiable(expr)告诉您是否expr可满足,即其中的变量值是否expr使其为真。如果可以满足,它会返回这些值的映射(称为“模型”)。如果不存在这样的映射,即expr矛盾,则返回False

因此,satisfiable(expr)与求解 相同expr = True。如果你想求解expr = False,你应该使用satisfiable(~expr)~在 SymPy 中意味着不是)。

In [5]: satisfiable(x & y)
Out[5]: {x: True, y: True}

In [6]: satisfiable(~(x | y))
Out[6]: {x: False, y: False}

In [7]: satisfiable(x & y & z)
Out[7]: {x: True, y: True, z: True}
Run Code Online (Sandbox Code Playgroud)

最后,请注意,satisfiable仅返回一个解决方案,因为通常这就是您想要的,而找到所有解决方案通常非常昂贵,因为它们可能有很多2**n,其中n是表达式中变量的数量。

但是,如果您想找到所有这些,通常的技巧是将原始表达式附加~E,其中E是先前解决方案的合取。例如,

In [8]: satisfiable(x ^ y)
Out[8]: {x: True, y: False}

In [9]: satisfiable((x ^ y) & ~(x & ~y))
Out[9]: {x: False, y: True}
Run Code Online (Sandbox Code Playgroud)

& ~(x & ~y)意味着您不想要一个x既正确又y错误的解决方案(可以认为&是在您的解决方案上添加额外的条件)。以这种方式迭代,您可以生成所有解决方案。