我在玩归纳性命题。我有以下归纳定义:
Inductive subseq {X : Type} : list X -> list X -> Prop :=
| empty_subseq : subseq [ ] [ ]
| subseq_left_elim : forall (l1 l2 : list X) (x : X),
subseq (x :: l1) l2 -> subseq l1 l2
| subseq_intro : forall (l1 l2 : list X) (x : X),
subseq l1 l2 -> subseq (x :: l1) (x :: l2).
Notation "l <<< k" := (subseq l k) (at level 10).
我正试图证明这样一个引理:
Lemma subseq_right_elim : forall (X : Type) (l1 l2 : list X) (x y : X),
(x :: l1) <<< (y :: l2) -> x = y \/ (x :: l1) <<< l2.
Proof.
intros X l1 l2 x y H.
induction H as [| l1' l2' z E IH | l1' l2' z E IH ].
+ right. apply empty_subseq_l.
(* empty_subseq_l : forall (X : Type) (l : list X), [ ] <<< l. *)
+ destruct IH as [IH | IH].
* left. apply IH.
* right. apply subseq_left_elim with z.
apply IH.
+ (* stuck *)
Abort.
我不知道如何证明subseq_intro
的情况。这似乎是真的,因为非正式地,如果将subseq_intro应用于产生(x :: l1) <<< (y :: l2)
,则x
和y
必须相等,并且这只是目标。但是在第三种情况下,Coq没有提供这样的断言。如何强制执行此操作,就像是否应用了反转策略?
答案 0 :(得分:4)
您可以使用remember
策略,因为induction
(和destruct
)“忘记了” indices的确切形状。在类型arg1 <<< arg2
中,arg1
和arg2
都是索引。顺便提一下,James Wilcox的this blog post详细解释了它的工作原理。无论如何,如果要对归纳类型族进行归纳,则通常希望索引是变量(带有额外的方程式,可以保留所有需要的信息)。
所以,如果您这样开始:
remember (x :: l1) as xl1 eqn: E1.
remember (y :: l2) as xl2 eqn: E2.
您得到了方程式,但最终将遇到麻烦,因为归纳假设将不可用。为了使它们可用,只需简单地归纳归纳假设即可
revert x y l1 l2 E1 E2.
更明确的说,你就是这样开始的
Lemma subseq_right_elim (X : Type) (l1 l2 : list X) (x y : X) :
(x :: l1) <<< (y :: l2) -> (x = y) \/ (x :: l1) <<< l2.
Proof.
intros H.
remember (x :: l1) as xl1 eqn: E1; remember (y :: l2) as xl2 eqn: E2.
revert x y l1 l2 E1 E2.
induction H as [| l1' l2' z S IH | l1' l2' z S IH ]; intros x y l1 l2 E1 E2.
就其价值而言,引理的陈述不够笼统,因此归纳法无济于事–这次您将能够解决第三个子目标,但不能解决第二个子目标。为了克服这个困难,使引理的陈述更像subseq_left_elim
。
SPOILER ALERT :this gist拥有充分的证据。
现在,您遇到的困难源于the回定义子序列概念的方式。通过一个非常简单的示例的证明,您可以更清楚地看到它:
Goal [1; 3; 5] <<< [0; 1; 2; 3; 4; 5; 6].
Proof.
apply subseq_left_elim with 0. apply subseq_intro.
apply subseq_intro.
apply subseq_left_elim with 2. apply subseq_intro.
apply subseq_intro.
apply subseq_left_elim with 4. apply subseq_intro.
apply subseq_intro.
apply subseq_left_elim with 6. apply subseq_intro.
apply empty_subseq.
Qed.
基本上,您必须扩大目标的大小才能在以后缩小目标。
您是否选择了更简单的编码,例如
Reserved Notation "l <<< k" (at level 10).
Inductive subseq {X : Type} : list X -> list X -> Prop :=
| empty_subseq : [ ] <<< [ ]
| subseq_drop_right l1 l2 x : l1 <<< l2 -> l1 <<< (x :: l2)
| subseq_drop_both l1 l2 x : l1 <<< l2 -> (x :: l1) <<< (x :: l2)
where "l <<< k" := (subseq l k).
您的生活会更加轻松!例如。这是上述简单事实的新证明:
Goal [1; 3; 5] <<< [0; 1; 2; 3; 4; 5; 6].
apply subseq_drop_right.
apply subseq_drop_both.
apply subseq_drop_right.
apply subseq_drop_both.
apply subseq_drop_right.
apply subseq_drop_both.
apply subseq_drop_right.
apply empty_subseq.
Qed.
这一次您只是将目标减小了一步。