我正在尝试在ACL2中以一元表示法(O
,(S O)
,(S (S O))
,...)对自然数进行建模,并证明加法的可交换性。这是我的尝试:
; a NATURAL is 'O or a list ('S n') where n' is a NATURAL
(defun naturalp (n)
(cond ((equal n 'O) t)
(t (and (true-listp n)
(equal (length n) 2)
(equal (first n) 'S)
(naturalp (second n))))))
(defun pred (n)
(cond ((equal n 'O) 'O)
((naturalp n) (second n))))
(defun succ (n)
(list 'S n))
(defun plus (n m)
(cond ((equal n 'O) m)
((naturalp n) (succ (plus (pred n) m)))))
; FIXME: cannot prove this because rewriting loops...
(defthm plus_comm
(implies (and (naturalp n) (naturalp m))
(iff (equal (plus n m) (plus m n)) t)))
这可能不是最常用的LISPy方式,我已经习惯了模式匹配的语言。
我的问题是评论所建议的:证明者循环,试图证明同一事物的嵌套版本越来越多。我怎么阻止这个?该手册简要提到了循环重写规则,但它没有说明如何处理它们。
我的期望是这个证明会失败,给我提示完成它需要什么辅助引理。我可以使用循环证明的输出来找出可能会停止循环的引理吗?
答案 0 :(得分:2)
ACL2最终会进入不同类型的循环。一种常见的类型是重写器循环,通常非常明显。例如,以下内容:
(defun f (x) x)
(defun g (x) x)
(defthm f-is-g (implies (consp x) (equal (f x) (g x))))
(defthm g-is-f (implies (consp x) (equal (g x) (f x))))
(in-theory (disable f g))
(defthm loop (equal (f (cons a b)) (cons a b)))
激发重写循环,并提供信息性的调试消息:
HARD ACL2 ERROR in REWRITE: The call depth limit of 1000 has been
exceeded in the ACL2 rewriter. To see why the limit was exceeded,
first execute
:brr t
and then try the proof again, and then execute the form (cw-gstack)
or, for less verbose output, instead try (cw-gstack :frames 30). You
will then probably notice a loop caused by some set of enabled rules,
some of which you can then disable; see :DOC disable. Also see :DOC
rewrite-stack-limit.
不幸的是,你的例子正在进入另一种循环。特别是,看起来ACL2正在进入一个循环
这不是很容易看出这是正在发生的事情。我做的事情就是在提交定理之前运行(set-gag-mode nil)
,然后检查打断证明器后打印的输出。
避免这种情况的一种方法是给出一个提示,特别是你可以告诉ACL2不要这样导入:
(defthm plus_comm
(implies (and (naturalp n) (naturalp m))
(iff (equal (plus n m) (plus m n)) t))
:hints(("Goal" :do-not-induct t)))
但是如果你这样做那么它就会立即被卡住,因为你可能做想要导入来证明这个定理。所以你真正想要告诉它的是:"引导一次,但不要引入更多。"语法有点愚蠢:
(defthm plus_comm
(implies (and (naturalp n) (naturalp m))
(iff (equal (plus n m) (plus m n)) t))
:hints(("Goal"
:induct t ;; Induct once.
:do-not-induct t ;; But don't induct more than once.
)))
这应该为您提供一个明智的检查点,然后您可以通过添加重写规则或提供进一步的提示来尝试调试。
祝你好运!