在Z3中证明归纳事实

时间:2012-11-02 15:20:15

标签: z3 smt

我试图在微软的SMT求解器Z3中证明一个归纳事实。我知道Z3一般不提供此功能,如Z3 guide(第8节:数据类型)中所述,但是当我们约束我们想要证明事实的域时,这似乎是可能的。请考虑以下示例:

(declare-fun p (Int) Bool)
(assert (p 0))

(assert (forall ((x Int)) 
    (=> 
    (and (> x 0) (<= x 20))
    (= (p (- x 1)) (p x) ))))
(assert (not (p 20)))

(check-sat)

解算器使用unsat正确响应,这意味着(p 20)有效。问题是当我们进一步放宽这个约束时(我们在前面的例子中用大于20的任何整数替换20),求解器以unknown响应。

我发现这很奇怪,因为解决原始问题不需要Z3很长时间,但是当我们将上限增加1时,突然变得不可能。我试图在量词中添加一个模式如下:

(declare-fun p (Int) Bool)
(assert (p 0))

(assert (forall ((x Int)) 
    (! (=> 
    (and (> x 0) (<= x 40))
    (= (p (- x 1)) (p x) )) :pattern ((<= x 40)))))
(assert (not (p 40)))

(check-sat)

这似乎更好,但现在上限是40.这是否意味着我最好不要使用Z3来证明这些事实,或者我是否错误地制定了我的问题?

1 个答案:

答案 0 :(得分:4)

Z3使用许多启发式来控制量词实例化。其中一个基于&#34;实例化深度&#34;。 Z3使用&#34;深度&#34;标记每个表达式。属性。所有用户提供的断言都标记为深度0.当量化器被实例化时,新表达式的深度会被触发。 Z3不会使用标记深度大于预定义阈值的表达式来实例化量词。在您的问题中,达到阈值:(p 40)深度为0,(p 39)深度为1,(p 38)为深度2,等等。

要增加阈值,您应该使用选项:

(set-option :qi-eager-threshold 100)

以下是使用此选项的示例:http://rise4fun.com/Z3/ZdxO

当然,使用此设置,Z3将超时,例如(p 110)

将来,Z3将更好地支持有限量化&#34;。在大多数情况下,处理这种量词的最佳方法是扩展它。 使用程序化API,我们可以轻松地实例化&#34;在我们将它们发送到Z3之前的表达式。 以下是Python中的一个示例(http://rise4fun.com/Z3Py/44lE):

p = Function('p', IntSort(), BoolSort())

s = Solver()

s.add(p(0))
s.add([ p(x+1) == p(x) for x in range(40)])
s.add(Not(p(40)))

print s.check()

最后,在Z3中,包含算术符号的模式不是很有效。问题是Z3在解决之前预先处理了公式。然后,大多数包含算术符号的模式永远不会匹配。有关如何有效使用模式/触发器的更多信息,请参阅this article。作者还提供了slide deck