教授coq检查终止

时间:2018-01-09 17:40:09

标签: coq termination totality

Coq与许多其他人不同,它接受一个可选的显式参数,该参数可用于指示固定点定义的递减结构。

来自Gallina规范,1.3.4,

Fixpoint ident params {struct ident0 } : type0 := term0

定义语法。但是从中我们已经知道它必须是一个标识符,而不是一般的衡量标准。

然而,通常,存在递归函数,终止不是很明显,或者实际上是,但终止检查器难以找到递减结构。例如,以下程序交错两个列表,

Fixpoint interleave (A : Set) (l1 l2 : list A) : list A :=
  match l1 with
  | [] => []
  | h :: t => h :: interleave l2 t
  end

这个功能明显终止,而Coq无法理解。原因是每个周期l1l2都没有减少。但是如果我们考虑一个定义为length l1 + length l2的度量呢?然后,这个度量明显减少了每次递归。

所以我的问题是,在复杂的情况下,代码不能直接以终止可检查的方式组织,你如何教育coq并说服它接受修复点定义?

2 个答案:

答案 0 :(得分:7)

你有多种选择,最后归结为结构递归。

序言

Fixpoint interleave1 {A} (l1 l2 : list A) {struct l1} : list A :=
  match l1, l2 with
  | [], _ => l2
  | _, [] => l1
  | h1 :: t1, h2 :: t2 => h1 :: h2 :: interleave1 t1 t2
  end.

结构递归

有时你可以用结构递归的方式重构你的算法:

fix

顺便提一下,在某些情况下,您可以使用嵌套Fixpoint es的技巧 - 请参阅this definition of Ackermann function(它不适用于Program Fixpoint)。

Program Fixpoint

您可以使用From Coq Require Import Program Arith. Program Fixpoint interleave2 {A} (l1 l2 : list A) {measure (length l1 + length l2)} : list A := match l1 with | [] => l2 | h :: t => h :: interleave2 l2 t end. Next Obligation. simpl; rewrite Nat.add_comm; trivial with arith. Qed. 机制,让您自然地编写程序,然后证明它始终终止。

Function

Function

另一种选择是使用Program Fixpoint命令,与From Coq Require Recdef. Definition sum_len {A} (ls : (list A * list A)) : nat := length (fst ls) + length (snd ls). Function interleave3 {A} (ls : (list A * list A)) {measure sum_len ls} : list A := match ls with | ([], _) => [] | (h :: t, l2) => h :: interleave3 (l2, t) end. Proof. intros A ls l1 l2 h t -> ->; unfold sum_len; simpl; rewrite Nat.add_comm; trivial with arith. Defined. 相比,该命令可能有些限制。您可以找到有关他们的差异的更多信息here

From Equations Require Import Equations.

Equations interleave4 {A} (l1 l2 : list A) : list A :=
interleave4 l1 l2 by rec (length l1 + length l2) lt :=
interleave4 nil l2 := l2;
interleave4 (cons h t) l2 := cons h (interleave4 l2 t).
Next Obligation. rewrite Nat.add_comm; trivial with arith. Qed.

Equations插件

这是一个外部插件,它解决了在Coq中定义函数的许多问题,包括依赖类型和终止。

Fix

如果您应用this fix,则上述代码有效。

Fix_F_2 / mergeSort组合子

如果您点击this question关于mergeSort功能的链接,您可以详细了解此(手动)方法。顺便说一下,如果你应用我前面提到的嵌套Fix技巧,可以在不使用fix的情况下定义Fix_F_2函数。这是一个使用mergeSort组合子的解决方案,因为我们有两个参数而不是像Definition ordering {A} (l1 l2 : list A * list A) : Prop := length (fst l1) + length (snd l1) < length (fst l2) + length (snd l2). Lemma ordering_wf' {A} : forall (m : nat) (p : list A * list A), length (fst p) + length (snd p) <= m -> Acc (@ordering A) p. Proof. unfold ordering; induction m; intros p H; constructor; intros p'. - apply Nat.le_0_r, Nat.eq_add_0 in H as [-> ->]. intros contra%Nat.nlt_0_r; contradiction. - intros H'; eapply IHm, Nat.lt_succ_r, Nat.lt_le_trans; eauto. Defined. Lemma ordering_wf {A} : well_founded (@ordering A). Proof. now red; intro ; eapply ordering_wf'. Defined. (* it's in the stdlib but unfortunately opaque -- this blocks evaluation *) Lemma destruct_list {A} (l : list A) : { x:A & {tl:list A | l = x::tl} } + { l = [] }. Proof. induction l as [|h tl]; [right | left]; trivial. exists h, tl; reflexivity. Defined. Definition interleave5 {A} (xs ys : list A) : list A. refine (Fix_F_2 (fun _ _ => list A) (fun (l1 l2 : list A) (interleave : (forall l1' l2', ordering (l1', l2') (l1, l2) -> list A)) => match destruct_list l1 with | inright _ => l2 | inleft pf => let '(existT _ h (exist _ tl eq)) := pf in h :: interleave l2 tl _ end) (ordering_wf (xs,ys))). Proof. unfold ordering; rewrite eq, Nat.add_comm; auto. Defined. 一样:

Check eq_refl : interleave1 [1;2;3] [4;5;6] = [1;4;2;5;3;6].
Check eq_refl : interleave2 [1;2;3] [4;5;6] = [1;4;2;5;3;6].
Check eq_refl : interleave3 ([1;2;3], [4;5;6]) = [1;4;2;5;3;6].
Fail Check eq_refl : interleave4 [1;2;3] [4;5;6] = [1;4;2;5;3;6]. (* Equations plugin *)
Check eq_refl : interleave5 [1;2;3] [4;5;6] = [1;4;2;5;3;6].

评估测试

destruct_list

练习:如果您注释掉@keyup.shift.50引理,最后一次检查会发生什么?

答案 1 :(得分:0)

您可以使用名为measure的内容而不是结构参数来终止。为此,我相信你必须使用Program Fixpoint机制,它有点牵扯并且会使你的证明看起来更加丑陋(因为它会从你提供的证明中产生结构递归,因此你将使用它的功能)实际使用并不是你写的功能。)

详细信息: https://coq.inria.fr/refman/program.html

看起来像Equations这样的东西可以处理措施? 比照http://mattam82.github.io/Coq-Equations/examples/RoseTree.html https://www.irif.fr/~sozeau/research/coq/equations.en.html