使用SMT-LIB通过公式计算模块数量

时间:2019-01-07 12:48:07

标签: python z3 smt z3py

我不确定是否可以使用SMT-LIB做到这一点,如果不可能的话,可以使用替代求解器吗?

考虑方程式

  • a < 10a > 5
  • b < 5b > 0
  • b < c < a
  • 具有abc整数

存在ab时满足等式的最大模型数量的a=9b=1的值。

SMT-LIB是否支持以下内容:对于ab的每个值,请计算满足公式的模型数量,并为a和{{1}给出值},从而使计数最大化。

2 个答案:

答案 0 :(得分:2)

我认为您通常无法做到这一点;也就是说,当您可以对任意理论施加任意约束时。您在问一个“元”问题:“最大化模型数量”不是关于问题本身的问题,而是关于问题的模型的问题。 SMTLib无法处理的事情。

但是,我认为应该可以针对特定问题对其进行编码。在您给出的示例中,当a - b最大时,模型空间将最大化。所以你可以简单地写:

(set-option :produce-models true)

(declare-fun a () Int)
(declare-fun b () Int)
(declare-fun c () Int)

(assert (< 5 a 10))
(assert (< 0 b  5))
(assert (< b c  a))

(maximize (- a b))
(check-sat)
(get-value (a b))

z3响应:

sat
((a 9)
 (b 1))

根据需要。或者,您可以使用Python绑定:

from z3 import *

a, b, c = Ints('a b c')
o = Optimize()
o.add(And(5 < a, a < 10, 0 < b, b < 5, b < c, c < a))
o.maximize(a - b)

if o.check() == sat:
    m = o.model()
    print "a = %s, b = %s" % (m[a], m[b])
else:
    print "unsatisfiable or unknown"

打印:

a = 9, b = 1

还有C / C ++ / Java / Scala / Haskell等的绑定。这些绑定也使您可以在这些主机上进行或多或少的相同操作。

但是这里的关键点是我们必须手动提出最大化a - b可以解决这里问题的目标。这一步需要人工干预,因为它适用于您当前遇到的任何问题。 (想象一下,您正在使用浮点数或任意数据类型的理论;提出这样的措施可能是不可能的。)我不认为可以使用传统的SMT解决方案神奇地使零件自动化。 (除非Patrick提出了聪明的编码,否则他还是很聪明的!)

答案 1 :(得分:1)

让我们打破目标:

  • 您想枚举ab (...以及更多)的所有可能方式
  • 对于每种组合,您要计算可满足的模型数量

通常,这是不可能的,因为问题中某些变量的域可能包含无限数量的元素。

即使人们可以放心地假设所有其他变量的域都包含有限数量的元素,它仍然低效率。 例如,如果您的问题中只有布尔变量,那么在搜索过程中仍然需要考虑指数组合的值(因此还有候选模型)。

但是,您的实际应用实际上在实践中可能还没有那么复杂,因此可以由 SMT Solver 处理。

总体思路可能是使用某些 SMT Solver API 并按如下步骤进行:

  • assert整个公式
  • 重复直到完成值的组合:
    • push回溯点
    • assert一种特定的值组合,例如a = 8 and b = 2
    • 永远重复:
      • check寻找解决方案
      • 如果UNSAT,退出最里面的循环
      • 如果SAT,请为ab的给定值组合增加模型的计数
      • 采用任何其他变量的模型值,例如c = 5 and d = 6
      • assert一个新的约束,要求至少一个“ other” 变量更改其值,例如c != 5 or d != 6
    • pop回溯点

或者,您可以隐式而不是显式枚举ab上的可能分配。这个想法如下:

  • assert整个公式
  • 永远重复:
    • check寻找解决方案
    • 如果UNSAT,则退出循环
    • 如果SAT,采用模型中控制变量值的组合(例如a = 8 and b = 2),则检查内部映射是否曾经遇到过此组合,如果未将计数器设置为{ {1}},否则将计数器增加1
    • 采用任何其他变量的模型值,例如1
    • c = 5 and d = 6一个新的约束,要求一个新的解决方案,例如assert

如果您不确定要选择哪个 SMT求解器,我建议您使用pysmt开始解决您的任务,该任务可以让您在多个中选择> SMT引擎


如果对于您的应用程序而言,显式的模型枚举太慢而无法实用,那么我建议您查看有关 CSP计数解决方案的大量文献,其中已经解决了该问题并且似乎存在几种估算CSP解决方案数量的方法。