Functional programming 如何基于此递归函数确定度量函数?

Functional programming 如何基于此递归函数确定度量函数?,functional-programming,logic,acl,Functional Programming,Logic,Acl,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)

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)))))
根据函数中的两个递归调用,我们能够确定将包含度量函数的else情况。然而,我们不了解它的其余部分,以及计算这个度量函数的过程

作为参考,度量函数:

  • m是定义在f参数上的容许函数
  • m与f具有相同的输入合同
  • m有一个输出合同,声明它总是返回一个自然数;及
  • 在每次递归调用中,应用于该递归调用的参数的m减小, 在导致递归调用的条件下

  • 导致确定该度量函数的过程是什么?

    在确定度量函数时,要问自己的问题是:在每次迭代中消耗的“势能”是多少,到某个点它都消失了,迭代停止了

    首先要看的通常是终止条件。在本例中有三个,但最后两个是最有趣的:他们说如果
    x
    (lena)
    之间的差异太小,我们就停止迭代

    这给了我们一个想法:如果势能是
    (lena)
    x
    之间的差值,会怎么样?为了验证这是否有意义,我们需要检查递归情况,并确保每个递归情况都会消耗一些能量,即减小差异。这里的情况看起来不错:

    • 如果
      x
      小于
      (len a)
      我们将
      x
      增加1,将
      (len a)
      减少1。因此,如果它们之间的差值是n,那么在下一次迭代中,它将是n-2,除非x=
      (lena)
      -1
    • 否则,
      x
      大于
      (len a)
      ,我们将
      x
      减少1,将
      (len a)
      增加1。同样,如果它们之间的差值是n,那么在下一次迭代中,它将是n-2,除非x=
      (lena)
      +1
    从这里很容易看出,我们应该选择x=
    (lena)
    +1作为我们的“低能态”,因为它处理了这两个除非子句的烦人细节

    (m x a) = (if (equal (len a) (+ x 1))
                  0
                  (abs (- (len a) x)))