我们需要添加哪些额外的公理,以便 Z3 可以验证递归程序的可满足性?

What additional axioms do we need to add so that Z3 can verify the satisfiability of programs with recurrences?

因为我们 know Z3 有重复的限制。有什么办法可以得到以下程序的结果吗?什么将附加方程帮助 z3 得到结果?

    from z3 import *
    ackermann=Function('ackermann',IntSort(),IntSort(),IntSort())
    m=Int('m')
    n=Int('n')
    s=Solver()
    s.add(ForAll([n,m],Implies(And(n>=0,m>=0),ackermann(m,n) == If(m!=0,If(n!=0,ackermann(m - 1,ackermann(m,n - 1)),If(n==0,ackermann(m - 1,1),If(m==0,n + 1,0))),If(m==0,n + 1,0)))))
    s.add(n>=0)
    s.add(m>=0)
    s.add(Not(Implies(ackermann(m,n)>=0,ackermann(m+1,0)>=0)))
    s.check()

使用像阿克曼函数这样的嵌套递归定义,我认为您无法说服 Z3(或任何其他 SMT 求解器)实际进行任何有趣的证明。此类属性需要巧妙的归纳论证,而 SMT 求解器并不是此类验证的合适工具。 Isabelle、HOL、Coq 等定理证明器是更好的选择。

话虽如此,在 SMT 中建立递归函数属性的基本方法是将归纳假设逐字编码为量化公理,并安排您想要证明的 属性 与该公理精确对齐axiom 当电子匹配引擎启动时,它可以实例化量词 "correctly." 我在这里把单词 正确地 放在引号中,因为匹配引擎将继续并保持以非生产性的方式实例化公理,尤其是对于像 Ackermann 的函数。另一方面,定理证明者可以精确地控制证明结构,因此您可以明确地指导证明者完成证明搜索 space.

这是一个您可以查看的示例:list concat in z3 它使用 SMT-Lib 接口对比您的目标更简单的归纳 属性 进行归纳证明。虽然扩展它来处理您的特定示例并不容易,但它可能会提供一些关于如何处理它的见解。

在 Z3 的特殊情况下,您还可以利用其使用 PDR 算法的定点推理引擎来回答有关某些递归函数的查询。请参阅 http://rise4fun.com/z3/tutorialcontent/fixedpoints#h22 示例,该示例展示了如何将 McCarthy 著名的 91 函数建模为一个有趣的案例研究。

Z3 不会尝试通过归纳为您做任何事情,但是(正如 Levent Erkok 提到的那样)您可以给它归纳假设并让它检查结果是否遵循。

这适用于您的示例,如下所示。

(declare-fun ackermann (Int Int) Int)

(assert (forall ((m Int) (n Int))
                (= (ackermann m n)
                   (ite (= m 0) (+ n 1)
                        (ite (= n 0) (ackermann (- m 1) 1)
                             (ackermann (- m 1) (ackermann m (- n 1))))))))

(declare-const m Int)
(declare-const n Int)

(assert (>= m 0))
(assert (>= n 0))

; Here's the induction hypothesis
(assert (forall ((ihm Int) (ihn Int))
                (=> (and (<= 0 ihm) (<= 0 ihn)
                         (or (< ihm m) (and (= ihm m) (< ihn n))))
                    (>= (ackermann ihm ihn) 0))))

(assert (not (>= (ackermann m n) 0)))
(check-sat) ; reports unsat as desired