为什么 Z3Py 不提供所有可能的解决方案
Why Z3Py does not provide all possible solutions
我 运行 遇到一个问题,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 中的所有解决方案都包含所有定义的变量。
The other thing is that not all the solutions in Z3Py contain all the defined variables.
这意味着未提及的变量不会影响结果。因此,将 ['-2', '-4', '3', '5']
作为解决方案相当于同时拥有 ['1', '-2', '-4', '3', '5']
和 ['-1', '-2', '-4', '3', '5']
。
如果您在比较解决方案时考虑到这一点,则两个求解器提供的解决方案集是等效的。
请注意,模型将仅包含对 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']
我相信这就是您要找的。
我 运行 遇到一个问题,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 中的所有解决方案都包含所有定义的变量。
The other thing is that not all the solutions in Z3Py contain all the defined variables.
这意味着未提及的变量不会影响结果。因此,将 ['-2', '-4', '3', '5']
作为解决方案相当于同时拥有 ['1', '-2', '-4', '3', '5']
和 ['-1', '-2', '-4', '3', '5']
。
如果您在比较解决方案时考虑到这一点,则两个求解器提供的解决方案集是等效的。
请注意,模型将仅包含对 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']
我相信这就是您要找的。