Z3:找到所有令人满意的模型

mar*_*oid 24 theorem-proving smt z3

我正在尝试使用微软研究院开发的SMT求解器Z3检索所有可能的一阶理论模型.这是一个最小的工作示例:

(declare-const f Bool)
(assert (or (= f true) (= f false)))
Run Code Online (Sandbox Code Playgroud)

在这个命题案例中,有两个令人满意的任务:f->truef->false.因为Z3(以及一般的SMT求解器)只会尝试找到一个令人满意的模型,所以找不到所有解决方案是不可能的.在这里,我发现了一个有用的命令(next-sat),但似乎最新版本的Z3不再支持这一点.这对我来说有点不幸,总的来说我觉得这个命令非常有用.还有另一种方法吗?

Tay*_*son 27

实现此目的的一种方法是使用其中一个API以及模型生成功能.然后,您可以使用来自一个可满足性检查的生成模型来添加约束,以防止先前的模型值用于后续可满足性检查,直到没有更令人满意的分配.当然,你必须使用有限排序(或者有一些限制来确保这一点),但如果你不想找到所有可能的模型(例如,在生成一堆后停止),你也可以使用无限排序. .

以下是使用z3py的示例(链接到z3py脚本:http://rise4fun.com/Z3Py/a6MC ):

a = Int('a')
b = Int('b')

s = Solver()
s.add(1 <= a)
s.add(a <= 20)
s.add(1 <= b)
s.add(b <= 20)
s.add(a >= 2*b)

while s.check() == sat:
  print s.model()
  s.add(Or(a != s.model()[a], b != s.model()[b])) # prevent next model from using the same assignment as a previous model
Run Code Online (Sandbox Code Playgroud)

在一般情况下,使用不相连的所有涉及常量应该工作(例如,ab这里).这列举了ab(1和之间20)满足的所有整数赋值a >= 2b.例如,如果我们限制ab对之间位于15代替,输出为:

[b = 1, a = 2]
[b = 2, a = 4]
[b = 1, a = 3]
[b = 2, a = 5]
[b = 1, a = 4]
[b = 1, a = 5]
Run Code Online (Sandbox Code Playgroud)

  • 从某种意义上来说,Z3是否具有状态,它将会从这里继续进行搜索?似乎每次重新开始都是浪费,当(直观地)所有工作完全相同时,除了最后. (5认同)
  • @GManNickG对于我使用过这种方法的例子,看起来确实是有状态的,因为在初始模型之后找到接下来的几个模型更快.以下是具有58个型号的特定情况的运行时列表(以毫秒为单位):`8942 801 1663 5 599 320 450 2 2 3 1 5 1377 36 5 738 162 105 1639 3 5 16 2041 27 475 953 562 746 45 151 18 4206 3416 9 850 120 3 4 12 615 593 1219 449 154 987 3 10 1365 16 438 792 1686 743 46 5 8 412 126`.请注意,第一个肯定是最长的,但其他的更随机(可能取决于问题和解算器获得的幸运). (4认同)
  • @GManNickG是的,只要您使用相同的Solver对象,它就会保留所有学习的子句。您可以使用push和pop选择性地将学习到的子句忘记回到上一个push(除去约束的唯一方法是弹出回到上一个push)。 (3认同)