2

I am working on an exercise where I came up with a proposition to prove but I am stuck. Hope someone and enlighten my thought.

I am defining an inductive proposition that defines subsequence relation, where the elements in first list needs to appear in the second list in order, but not necessarily consecutively.

Here is my definition:

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).

and the theorem that I want to prove:

Theorem subseq_shrink : forall h l1 l2,
  subseq (h :: l1) l2 -> subseq l1 l2.

basically it says a list will still be subsequence if the head is chopped off. quite intuitive, no? However, I am stuck.

following is a part of my proof:

Proof.
  intros h l1 l2 H. generalize dependent h. induction l1.
  - intros. apply emptyseq.
  - intros h H. 

the proof doesn't look good already.

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

that looks so clueless to me. Am I making a mistake somewhere? Which part am i missing to get stuck in this easy theorem?

Anton Trunov
  • 15,074
  • 2
  • 23
  • 43
Jason Hu
  • 6,239
  • 1
  • 20
  • 41

2 Answers2

3

You can use induction on subseq derivation. Notice remember below: we need it because of the way Coq works with indices of type families. I think it was described somewhere in the Software Foundations book. Try removing it and see what happens.

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.
Anton Trunov
  • 15,074
  • 2
  • 23
  • 43
  • 2
    For `remember`, it seems like http://www.cis.upenn.edu/~bcpierce/sf/current/IndProp.html#lab219 is the link you wanted. – eponier Mar 23 '17 at 09:55
3

There are multiple solutions here. But what is important is to understand why we need induction. Actually, what we want is to remove the h in front of l1. And due to the definition of subseq, we know that h is the first element of l2, or, if not, it will be the second, or, if not, it will be the third, or...

Actually, we need to find the h in l2 and for that we need to do an induction on l2, not on l1. Doing the induction on subseq as suggested by another answer also helps to find the h in l2, that's why it will also work.

Doing the induction on l2 seems more simple. Here is the very beginning of the proof:

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.
eponier
  • 3,062
  • 9
  • 20
  • in general, though, how should i notice which one is the best to perform induction on? – Jason Hu Mar 23 '17 at 15:09
  • That's what I wanted to show in my first paragraph. If you try without induction, you should notice what operation you want to do repetitively (here access the next element of `l2`), and deduce on which object the induction should be done. – eponier Mar 23 '17 at 17:38