一个函数在ACL2中定义,我们的任务是创建一个测量函数来帮助证明终止。这是函数定义:
(defunc f (x a)
:input-contract (and (integerp x) (listp a))
:output-contract (integerp (f x a))
(cond
((endp a) 68)
((equal (len a) x) 71)
((equal (len a) (+ x 1)) 74)
((< x (len a)) (f (+ x 1) (rest a)))
(t (f (- x 1) (cons 1 a)))))
解决方案测量功能就是这个(简写):
(m x a) = (if (equal (len a) (+ x 1))
0
(abs (- (len a) x)))
我们能够根据函数中的两个递归调用确定包含measure函数的else情况。但是,我们不了解其余部分,以及确定此度量函数的过程。
供参考,测量功能:
导致确定此度量函数的过程是什么?
答案 0 :(得分:1)
在确定一个度量函数时,问自己的问题是:在每次迭代中消耗的“潜在能量”是什么,在某一点它已经消失并且迭代停止了?
首先要看的是终止条件。在这种情况下,有三个,但最后两个是最有趣的:他们说如果x
和(len a)
之间的差异太小,我们就会停止迭代。
这给了我们一个想法:如果(len a)
和x
之间的潜在能量差异怎么办?为了确定这是否有意义,我们需要检查递归情况并确保它们中的每一个消耗掉一些能量,即减少差异。事情看起来很不错:
x
小于(len a)
,我们会将x
增加1并将(len a)
减少1.因此,如果它们之间的差异为 n ,然后在下一次迭代中它将是 n-2 ,除非 x = (len a)
- 1 。 x
大于(len a)
,我们将x
减少1并将(len a)
增加1.再次,如果它们之间的差异为 n < / em>,然后在下一次迭代中它将是 n-2 ,除非 x = (len a)
+ 1 。从那里可以很容易地看出我们应该选择 x = (len a)
+ 1 作为我们的“低能量状态”,因为它处理了这两个的讨厌细节除非条款。