如何使用递减参数进行递归调用?

时间:2019-05-11 11:34:32

标签: coq

Inductive bar {X : Type} : list X -> Prop :=
  | bar_nil : bar []
  | bar_fst : forall x l, bar (rev l ++ l) -> bar (rev l ++ [x] ++ l)
  | bar_snd : forall x l, bar (rev l ++ [x] ++ l) -> bar (rev l ++ [x; x] ++ l).

Axiom bar_surround :
  forall X x (l : list X),
  bar l -> bar ([x] ++ l ++ [x]).

Inductive list_last {X : Type} : list X -> Prop :=
  | ll_nil : list_last []
  | ll_snoc : forall l x, list_last l -> list_last (l ++ [x]).

Axiom ll_app :
  forall X (a b : list X),
  list_last a -> list_last b -> list_last (a ++ b).

Axiom ll_from_list :
  forall {X} (l : list X),
  list_last l.

Axiom app_head_eq :
  forall X (a b c : list X),
  a ++ c = b ++ c -> a = b.

Theorem foo :
  forall X (l: list X), l = rev l -> bar l.
Proof.
intros.
induction l.
- constructor.
- assert (Hll := ll_from_list l).
  inversion Hll.
  + apply (bar_fst x []). apply bar_nil.
  + rewrite <- H1 in H.
    simpl in H.
    rewrite rev_app_distr in H.
    rewrite <- app_assoc in H.
    simpl in H.
    inversion H.
    apply app_head_eq in H4.
    apply bar_surround.
1 subgoal
X : Type
x : X
l, l0 : list X
x0 : X
H : x :: l0 ++ [x0] = x0 :: rev l0 ++ [x]
IHl : l = rev l -> bar l
Hll : list_last l
H0 : list_last l0
H1 : l0 ++ [x0] = l
H3 : x = x0
H4 : l0 = rev l0
______________________________________(1/1)
bar l0

我距离解决此练习仅一步之遥,但是我不知道该如何做归纳步骤。请注意,IHl在这里没有用,用l上的归纳代替Hll上的归纳也会有类似的问题。在这两种情况下,归纳假设都将使呼叫减少一个步骤,而我则需要两个-一个在等式两边都从列表的开头和结尾处取出项目。

请考虑我要证明的函数类型为forall X (l: list X), l = rev l -> bar l,并且我的目标是l0 = rev l0 -> bar l0l0是一个简化的参数,从而使递归调用变得安全。

我在这里应该做什么?

2 个答案:

答案 0 :(得分:1)

您可以证明以下归纳谓词:

Inductive delist {A : Type} : list A -> Prop :=
| delist_nil : delist []
| delist_one x : delist [x]
| delist_cons x y l : delist l -> delist (x :: l ++ [y])
.

Theorem all_delist {A} : forall xs : list A, delist xs.

然后在您的最终定理中,对delist xs的归纳将分解为您需要的情况。


另一种解决方案是通过对列表的长度进行有力的归纳:

Lemma foo_len X : forall (n : nat) (l: list X), length l <= n -> l = rev l -> bar l.
Proof.
  induction n.
  (* Nat.le_succ_r from the Arith module is useful here *)
  ...
Qed.

(* Final theorem *)
Theorem foo X : forall (l : list X), l = rev l -> bar l.
Proof.
  intros; apply foo_len; auto.
Qed.

这是比delist更普遍和系统的原理,但是要在主要证明中使用归纳假设,您需要做的工作不仅仅是上面的即席归纳类型。

答案 1 :(得分:0)

这是如何实施其他答案中建议的第一部分。我可以证实,解决该问题非常简单。话虽如此,我很感兴趣如何使用简单的归纳法来解决上述问题。必须实现delist及其功能比我希望的复杂。

Inductive delist {A : Type} : list A -> Prop :=
| delist_nil : delist []
| delist_one x : delist [x]
| delist_wrap x y l : delist l -> delist (x :: l ++ [y]).

Theorem delist_cons {A} :
  forall x (l : list A),
  delist l -> delist (x :: l).
Proof.
intros.
generalize dependent x.
induction H; intros.
- constructor.
- replace [x; x0] with (x :: [] ++ [x0]).
  2 : { reflexivity. }
  + apply delist_wrap with (l := []). constructor.
- replace (x0 :: x :: l ++ [y]) with (x0 :: (x :: l) ++ [y]).
  2 : { reflexivity. }
  constructor.
  apply IHdelist.
Qed.

Theorem delist_from_list {A} : 
  forall l : list A,
  delist l.
Proof.
induction l.
- constructor.
- assert (ll := ll_from_list l).
  destruct ll.
  + constructor.
  + apply delist_cons. assumption.
Qed.