【问题标题】:Getting all solutions of a boolean expression in Z3Py never ends在 Z3Py 中获取布尔表达式的所有解决方案永无止境
【发布时间】:2020-03-27 18:11:09
【问题描述】:

可能是与 Z3 相关的一个基本问题:我正在尝试获取布尔表达式的所有解决方案,例如对于a OR b,我想得到{(true, true),(false,true),(true,false)}

基于找到的其他回复,例如Z3: finding all satisfying models,我有以下代码:

a = Bool('a')
b = Bool('b')

f1=Or(a,b)
s=Solver()
s.add(f1)

while s.check() == sat:
  print s
  s.add(Not(And(a == s.model()[a], b == s.model()[b])))

问题在于它在第二次迭代时进入了无限循环:约束 a == s.model()[a] 被评估为 false b/c s.model()[a] 不再存在。

谁能告诉我我做错了什么?

【问题讨论】:

    标签: z3 z3py


    【解决方案1】:

    我建议您尝试像这样编写循环:

    from z3 import *
    
    a = Bool('a')
    b = Bool('b')
    
    f1 = Or(a,b)
    s = Solver()
    s.add(f1)
    
    while s.check() == sat:
    
        m = s.model()
    
        v_a = m.eval(a, model_completion=True)
        v_b = m.eval(b, model_completion=True)
    
        print("Model:")
        print("a := " + str(v_a))
        print("b := " + str(v_b))
    
        bc = Or(a != v_a, b != v_b)
        s.add(bc)
    

    输出是:

    Model:
    a := True
    b := False
    Model:
    a := False
    b := True
    Model:
    a := True
    b := True
    

    参数model_completion=True 是必要的,否则m.eval(x) 的行为类似于任何x 布尔变量的身份关系,在当前模型m 中具有不关心 值,并且它结果返回x 而不是True/False。 (See related Q/A)


    注意:因为z3 善意标记不关心布尔变量,另一种选择是编写您自己的模型生成器来自动完成任何部分模型.这将减少对s.check() 的调用次数。这种实现的性能影响很难衡量,但它可能会稍微快一些。

    【讨论】:

    • 感谢 Patrick 的快速回复 - 我从你的脚本中得到的输出是 [a = True, b = False] [b = True] - 无限循环确实是固定的,但是我如何推断出这组解决方案?
    • 不是在循环中打印,而是简单地将值 a 和 b 作为一对放在一个累积列表中并在最后返回它。
    • 原谅我的无知,但它是如何解决问题的呢?该循环仍将仅迭代两次,而我希望它迭代三次。或者我应该明白,当只返回[b = True] 时,这意味着a 可以取任何值?
    • @f1f2 问题是a 的模型值在第二次迭代中等于a,这可能是因为a 的值在第二次迭代中是don't care模型。我必须考虑几分钟如何修复脚本:)
    • Patrick 的解决方案效果很好。但是补充一下我的评论,当您执行eval 时,您会明确获得一个值,因此您可以避免“完成”问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多