【问题标题】:Trying to find all solutions to a boolean formula using Z3 in python试图在python中使用Z3找到布尔公式的所有解决方案
【发布时间】:2020-08-03 14:32:29
【问题描述】:

我是 Z3 的新手,正在尝试制作一个求解器,它将每个可满足的解决方案返回一个布尔公式。从其他 SO-posts 中记笔记,我已经编写了我希望能工作的代码,但事实并非如此。问题似乎是通过添加以前的解决方案,我删除了一些变量,但是它们在以后的解决方案中返回?

目前我只是在尝试解决 a 或 b 或 c。

如果我解释得不好,请告诉我,我会尝试进一步解释。

提前感谢您的回复:)

我的代码:

from z3 import *

a, b, c = Bools('a b c')
s = Solver()
s.add(Or([a, b, c]))

while (s.check() == sat):
        print(s.check())
        print(s)
        print(s.model())
        print(s.model().decls())
        print("\n")
        s.add(Or([ f() != s.model()[f] for f in s.model().decls() if f.arity() == 0])) 

我的输出:

sat
[Or(a, b, c)]
[c = False, b = False, a = True]
[c, b, a]


sat
[Or(a, b, c), Or(c != False, b != False, a != True)]
[b = True, a = False]
[b, a]


sat
[Or(a, b, c),
 Or(c != False, b != False, a != True),
 Or(b != True, a != False)]
[b = True, a = True]
[b, a]


sat
[Or(a, b, c),
 Or(c != False, b != False, a != True),
 Or(b != True, a != False),
 Or(b != True, a != True)]
[b = False, c = True]
[b, c]

【问题讨论】:

    标签: z3 z3py sat-solvers


    【解决方案1】:

    编码此类问题的典型方法如下:

    from z3 import *
    
    a, b, c = Bools('a b c')
    s = Solver()
    s.add(Or([a, b, c]))
    
    res = s.check()
    while (res == sat):
      m = s.model()
      print(m)
      block = []
      for var in m:
          block.append(var() != m[var])
      s.add(Or(block))
      res = s.check()
    

    打印出来:

    [b = True, a = False, c = False]
    [a = True]
    [c = True, a = False]
    

    您会注意到并非所有模型都是“完整的”。这是因为 z3 通常会在确定问题解决后“停止”分配变量,因为其他变量无关紧要。

    我想您的困惑是应该有 7 个模型来解决您的问题:除了全 False 分配之外,您还应该有一个模型。如果您想以这种方式获取所有变量的值,则应显式查询它们,如下所示:

    from z3 import *
    
    a, b, c = Bools('a b c')
    s = Solver()
    s.add(Or([a, b, c]))
    
    myvars = [a, b, c]
    
    res = s.check()
    while (res == sat):
      m = s.model()
      block = []
      for var in myvars:
          v = m.evaluate(var, model_completion=True)
          print("%s = %s " % (var, v)),
          block.append(var != v)
      s.add(Or(block))
      print("\n")
      res = s.check()
    

    打印出来:

    a = False  b = True  c = False
    
    a = True  b = False  c = False
    
    a = True  b = True  c = False
    
    a = True  b = True  c = True
    
    a = True  b = False  c = True
    
    a = False  b = False  c = True
    
    a = False  b = True  c = True
    

    如您所料,一共有 7 种型号。

    注意model_completion 参数。对于新手来说这是一个常见的陷阱,因为 z3 中没有“开箱即用”的方法来获取所有可能的分配,因此您必须像上面那样小心地自己编码。没有这样一个函数的原因是它通常很难实现:想想如果你的变量是函数、数组、用户定义的数据类型等而不是简单的布尔值,它应该如何工作。在正确有效地处理所有这些可能性的情况下,实现一个通用的全卫星功能可能会变得非常棘手。所以,它留给了用户,因为大多数时候你只关心一个特定的全卫星概念,一旦你学习了基本的习语,通常就不难编码。

    【讨论】:

    • 我明白了!非常感谢你!这真的很有帮助。是的,我希望在打印模型时获得 7 个解决方案并获得所有变量。再次,非常感谢!真的很感激:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-24
    • 1970-01-01
    相关资源
    最近更新 更多