你如何证明递归列表长度的终止?

时间:2015-09-07 17:00:03

标签: recursion termination reasoning formal-verification formal-methods

假设我们有一个清单:

List = nil | Cons(car cdr:List).

请注意,我在谈论可修改的列表! 还有一个简单的递归长度函数:

recursive Length(List l) = match l with
   | nil => 0
   | Cons(car cdr) => 1 + Length cdr
end.

当然,只有当列表是非循环时它才会终止:

inductive NonCircular(List l) = {
   empty: NonCircular(nil) |
   \forall head, tail: NonCircular(tail) => NonCircular (Cons(head tail))
}

请注意,此谓词作为递归函数实现,也不会在循环列表中终止。

通常我会看到列表遍历终止的证据,它使用列表长度作为有界减少因子。他们认为Length是非负面的。但是,正如我所看到的那样,这个事实(Length l >= 0)来自首先Length的终止。

您如何证明LengthNonCircular(或等效的,更明确的谓词)列表中终止并且是否定的?

我在这里错过了一个重要的概念吗?

2 个答案:

答案 0 :(得分:0)

除非长度函数有循环检测,否则无法保证它会停止!

对于单个链接列表,可以使用Tortoise and hare algorithm来确定cdr中可能存在圆圈的长度。

只有两个游标,乌龟从第一个元素开始,野兔从第二个元素开始。乌龟一次移动一个指针,而兔子移动两个(如果可以的话)。野兔最终要么与乌龟相同,这表示一个循环,否则它将终止,知道长度是2 *步或2 *步+ 1。

与在树中查找循环相比,这非常便宜,并且在终止列表时也可以作为没有循环检测的函数执行。

答案 1 :(得分:0)

您拥有的List的定义似乎不允许循环列表。每次调用"构造函数" Cons将创建一个新指针,并且您不允许稍后修改指针以创建圆形。

如果要处理循环,则需要更复杂的List定义。您可能需要定义包含数据值和地址的Cell,以及包含Cell和指向前一个节点的地址的Node,然后您需要定义解除引用运算符以从地址返回到Cells 。您还可以尝试在此对象上定义非圆形。

我的直觉是你还需要从"简单"中定义一个内射函数。您已经在上面列出了我已经列出的复杂的列表定义,然后最后您将能够证明您的结果。

另一件事,NonCircular的定义不需要终止。它不是一个程序,它是一个证据。如果它成立,那么您可以检查证明,看看它为什么成立并在其他证明中使用它。 编辑:感谢Necto指出我错了。