在Coq中显示cumsum的终止递归

时间:2014-12-04 20:42:31

标签: recursion coq totality

我想证明计算ab之间的累积和会终止。

我使用Acc lt x术语来表示递归减少,就像这样

Require Import Omega.

Lemma L1 : forall a b, a<b -> (b-(1+a)) < (b-a).
  intros; omega. Qed.

Lemma term_lemma: forall a b, Acc lt (b-a) ->  Acc lt (b-(1+a)).
    intros;  inversion H; clear H; constructor; intros; apply H0; omega.
Defined.

Fixpoint cumsum a b (H: Acc lt (b-a)) {struct H} : nat.
refine (
    match lt_dec a b  with
    | left a_lt_b => a + cumsum (1+a) b _
    | right a_ge_b => if beq_nat a b then a else 0
    end
  ).
apply (term_lemma _ _ H).
Qed.

它会清除所有子目标,但不会在Qed语句中进行类型检查。 Coq抱怨道:

Recursive definition of cumsum is ill-formed
Recursive call to cumsum has principal argument equal to
"term_lemma a b H" instead of a subterm of "H".

我想我应该以某种方式使用L1来表明递归调用中H项中的参数实际上更小,但我该怎么做?

1 个答案:

答案 0 :(得分:2)

因为您在使用H重新构建类似内容之前反转constructor ; apply H0,所以您得到的term_lemma模式匹配等同于您想要的模式,但会混淆Coq的终止检查器(您可以使用Print NAME.检查术语。)

如果您记得a < b感谢您在lt_dec a b上的案例分析,则无需执行所有此反转业务。通过让你的引理采取额外的论证,你现在可以使用Acc可见性谓词的严格子项来获得你的见证:

Require Import Omega.

Lemma term_lemma: forall a b, a < b -> Acc lt (b-a) ->  Acc lt (b-(1+a)).
 intros a b altb [H]; apply H; omega.
Defined.

Fixpoint cumsum a b (H: Acc lt (b-a)) {struct H} : nat.
refine (
    match lt_dec a b  with
    | left a_lt_b => a + cumsum (1+a) b _
    | right a_ge_b => if beq_nat a b then a else 0
    end
  ).
apply (term_lemma _ _ a_lt_b H).
Defined.