证明一个被斩首的子序列是同一个序列的子序列
Prove that a beheaded subsequence is a subsequence of the same sequence
我正在做一个练习,我想出了一个要证明的命题,但我被卡住了。希望有人开导我的思想。
我正在定义一个定义子序列关系的归纳命题,其中第一个列表中的元素需要按顺序出现在第二个列表中,但不一定连续出现。
这是我的定义:
Inductive subseq : list nat -> list nat -> Prop :=
| emptyseq : forall l, subseq [] l
| matchh : forall h l1 l2, subseq l1 l2 -> subseq (h :: l1) (h :: l2)
| nmatchh : forall h l1 l2, subseq l1 l2 -> subseq l1 (h :: l2).
以及我要证明的定理:
Theorem subseq_shrink : forall h l1 l2,
subseq (h :: l1) l2 -> subseq l1 l2.
基本上它说如果头部被砍掉,列表仍然是子序列。很直观,不是吗?但是,我卡住了。
以下是我证明的一部分:
Proof.
intros h l1 l2 H. generalize dependent h. induction l1.
- intros. apply emptyseq.
- intros h H.
证据看起来并不好。
1 subgoals
x : nat
l1 : list nat
l2 : list nat
IHl1 : forall h : nat, subseq (h :: l1) l2 -> subseq l1 l2
h : nat
H : subseq (h :: x :: l1) l2
______________________________________(1/1)
subseq (x :: l1) l2
这让我看起来很无能。我在某处犯错了吗?我错过了哪一部分来陷入这个简单的定理?
您可以在 subseq
推导中使用归纳法。请注意下面的 remember
:我们需要它,因为 Coq 使用类型族索引的方式。我认为它在《软件基础》一书中的某处有所描述。尝试删除它,看看会发生什么。
Theorem subseq_shrink : forall h l1 l2,
subseq (h :: l1) l2 -> subseq l1 l2.
Proof.
intros h l1 l2 H.
remember (h :: l1) eqn:Eq.
induction H.
- inversion Eq.
- inversion Eq; clear Eq; subst.
now constructor.
- destruct l0; inversion Eq; clear Eq; subst.
now constructor; apply IHsubseq.
Qed.
这里有多种解决方案。但重要的是理解为什么我们需要归纳法。其实我们想要的是去掉l1
前面的h
。而由于subseq
的定义,我们知道h
是l2
的第一个元素,否则就是第二个,否则就是第三个,或者...
实际上,我们需要在 l2
中找到 h
,为此我们需要对 l2
而不是 l1
进行归纳。按照另一个答案的建议对 subseq
进行归纳也有助于在 l2
中找到 h
,这就是它也可以工作的原因。
对l2
进行归纳似乎更简单。这是证明的开头:
Theorem subseq_shrink : forall h l1 l2,
subseq (h :: l1) l2 -> subseq l1 l2.
Proof.
intros h l1 l2. revert h l1. induction l2; intros.
我正在做一个练习,我想出了一个要证明的命题,但我被卡住了。希望有人开导我的思想。
我正在定义一个定义子序列关系的归纳命题,其中第一个列表中的元素需要按顺序出现在第二个列表中,但不一定连续出现。
这是我的定义:
Inductive subseq : list nat -> list nat -> Prop :=
| emptyseq : forall l, subseq [] l
| matchh : forall h l1 l2, subseq l1 l2 -> subseq (h :: l1) (h :: l2)
| nmatchh : forall h l1 l2, subseq l1 l2 -> subseq l1 (h :: l2).
以及我要证明的定理:
Theorem subseq_shrink : forall h l1 l2,
subseq (h :: l1) l2 -> subseq l1 l2.
基本上它说如果头部被砍掉,列表仍然是子序列。很直观,不是吗?但是,我卡住了。
以下是我证明的一部分:
Proof.
intros h l1 l2 H. generalize dependent h. induction l1.
- intros. apply emptyseq.
- intros h H.
证据看起来并不好。
1 subgoals
x : nat
l1 : list nat
l2 : list nat
IHl1 : forall h : nat, subseq (h :: l1) l2 -> subseq l1 l2
h : nat
H : subseq (h :: x :: l1) l2
______________________________________(1/1)
subseq (x :: l1) l2
这让我看起来很无能。我在某处犯错了吗?我错过了哪一部分来陷入这个简单的定理?
您可以在 subseq
推导中使用归纳法。请注意下面的 remember
:我们需要它,因为 Coq 使用类型族索引的方式。我认为它在《软件基础》一书中的某处有所描述。尝试删除它,看看会发生什么。
Theorem subseq_shrink : forall h l1 l2,
subseq (h :: l1) l2 -> subseq l1 l2.
Proof.
intros h l1 l2 H.
remember (h :: l1) eqn:Eq.
induction H.
- inversion Eq.
- inversion Eq; clear Eq; subst.
now constructor.
- destruct l0; inversion Eq; clear Eq; subst.
now constructor; apply IHsubseq.
Qed.
这里有多种解决方案。但重要的是理解为什么我们需要归纳法。其实我们想要的是去掉l1
前面的h
。而由于subseq
的定义,我们知道h
是l2
的第一个元素,否则就是第二个,否则就是第三个,或者...
实际上,我们需要在 l2
中找到 h
,为此我们需要对 l2
而不是 l1
进行归纳。按照另一个答案的建议对 subseq
进行归纳也有助于在 l2
中找到 h
,这就是它也可以工作的原因。
对l2
进行归纳似乎更简单。这是证明的开头:
Theorem subseq_shrink : forall h l1 l2,
subseq (h :: l1) l2 -> subseq l1 l2.
Proof.
intros h l1 l2. revert h l1. induction l2; intros.