我试图在微软的 SMT 求解器 Z3 中证明一个归纳事实。我知道 Z3 通常不提供此功能,如Z3 指南(第 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 来证明这些事实,还是我错误地表述了我的问题?