我遇到了一个问题,其中Z3Py并未枚举给定布尔条款的所有可能解决方案。我想知道是否有人知道为什么会这样。
这是我用于Z3Py的代码。有5个布尔值:1 2 3 4和5。
from z3 import *
a,b,c,d,e = Bools('1 2 3 4 5')
solver = Solver()
solver.add(Or(Not(a), Not(b)))
solver.add(Or(Not(b), Not(c)))
solver.add(Or(Not(c), Not(d)))
solver.add(Or(Not(d), Not(e)))
while solver.check() == sat:
model = solver.model()
block = []
for declaration in model:
constant = declaration()
block.append(constant != model[declaration])
solver.append(Or(block))
solution = []
for val in model:
if is_true(model[val]):
solution.append(str(val()))
else:
solution.append('-' + str(val()))
solution.sort()
print(solution)
这将产生以下模型:
['-1', '-2', '-3', '-4', '-5']
['-2', '-3', '-5', '1']
['-2', '-3', '-4', '1', '5']
['-2', '-4', '3', '5']
['-2', '-4', '-5', '3']
['-1', '-3', '-4', '-5', '2']
['-1', '-3', '-4', '2', '5']
['-1', '-2', '-3', '-4', '5']
['-1', '-2', '-3', '-5', '4']
['-1', '-3', '-5', '2', '4']
如果我使用带有以下代码的Pycosat运行相同的子句:
import pycosat
clauses = [(-1, -2), (-2, -3), (-3, -4), (-4, -5)]
for solution in pycosat.itersolve(clauses):
print(solution)
我得到那些结果:
[-1, -2, -3, -4, -5]
[-1, -2, -3, -4, 5]
[-1, -2, -3, 4, -5]
[-1, -2, 3, -4, -5]
[-1, -2, 3, -4, 5]
[-1, 2, -3, -4, -5]
[-1, 2, -3, -4, 5]
[-1, 2, -3, 4, -5]
[1, -2, -3, 4, -5]
[1, -2, -3, -4, -5]
[1, -2, -3, -4, 5]
[1, -2, 3, -4, -5]
[1, -2, 3, -4, 5]
因此,Z3Py根据Pycosat的结果错过了3种可能的解决方案。这些是:
[1, -2, 3, -4, 5]
[1, -2, -3, 4, -5]
[1, -2, 3, -4, -5]
我知道这些是不同的求解器,但是基于用于它们的相同子句,我希望结果匹配。谁知道在这种情况下Z3Py为什么会错过这些解决方案? 另一件事是,并非Z3Py中的所有解决方案都包含所有定义的变量。
答案 0 :(得分:1)
另一件事是,并非Z3Py中的所有解决方案都包含所有已定义的变量。
这意味着未提及的变量不会影响结果。因此,将['-2', '-4', '3', '5']
作为解决方案等同于同时拥有['1', '-2', '-4', '3', '5']
和['-1', '-2', '-4', '3', '5']
。
如果在比较解决方案时考虑到这一点,则两个求解器提供的解决方案集是等效的。
答案 1 :(得分:1)
请注意,模型将只包含对在sat
结果中重要的变量的赋值。任何无关紧要的变量都不会明确分配。为避免此问题,请循环遍历您域中的变量,并将参数model_completion=True
用于eval
方法,如下所示:
from z3 import *
a,b,c,d,e = Bools('1 2 3 4 5')
solver = Solver()
solver.add(Or(Not(a), Not(b)))
solver.add(Or(Not(b), Not(c)))
solver.add(Or(Not(c), Not(d)))
solver.add(Or(Not(d), Not(e)))
while solver.check() == sat:
model = solver.model()
block = []
solution = []
for var in [a, b, c, d, e]:
v = model.eval(var, model_completion=True)
block.append(var != v)
solution.append(str(var) if is_true(v) else '-' + str(var))
solver.add(Or(block))
solution.sort()
print(solution)
此打印:
['-1', '-2', '-3', '-4', '-5']
['-2', '-3', '-4', '-5', '1']
['-2', '-3', '-5', '1', '4']
['-1', '-2', '-3', '-5', '4']
['-1', '-2', '-3', '-4', '5']
['-1', '-2', '-4', '3', '5']
['-2', '-4', '-5', '1', '3']
['-2', '-4', '1', '3', '5']
['-2', '-3', '-4', '1', '5']
['-1', '-3', '-4', '2', '5']
['-1', '-3', '-4', '-5', '2']
['-1', '-2', '-4', '-5', '3']
['-1', '-3', '-5', '2', '4']
我相信这是您要寻找的。 p>