even_Sn_not_even_n - apply 1 hypothesis in another
Question
Unfortunately I got stuck again:
Inductive even : nat -> Prop := | ev_0 : even 0 | ev_SS (n : nat) (H : even n) : even (S (S n)).forall n : nat, even (S n) <-> ~ even nforall n : nat, even (S n) <-> ~ even nn: nateven (S n) <-> ~ even nn: nateven (S n) -> ~ even nn: nat~ even n -> even (S n)n: nateven (S n) -> ~ even nn: nat
H: even (S n)~ even nn: nat
H: even (S n)even n -> Falsen: nat
H: even (S n)
H1: even nFalseH: even 1Falsen': nat
H: even (S (S (S n')))
E': even n'
IHn: even (S n') -> FalseFalseinversion H.H: even 1Falsen': nat
H: even (S (S (S n')))
E': even n'
IHn: even (S n') -> FalseFalsen': nat
E': even n'
IHn: even (S n') -> False
H0: even (S n')Falseapply H0.n': nat
E': even n'
IHn: even (S n') -> False
H0: FalseFalsen: nat~ even n -> even (S n)n: nat
H: ~ even neven (S n)H: ~ even 0even 1n': nat
H: ~ even (S n')
IHn: ~ even n' -> even (S n')even (S (S n'))H: ~ even 0even 1H: ~ even 0Falseapply ev_0.H: ~ even 0even 0n': nat
H: ~ even (S n')
IHn: ~ even n' -> even (S n')even (S (S n'))n': nat
H: ~ even (S n')
IHn: ~ even n' -> even (S n')even n'
Here is the result:
As far I could prove it in words:
(n' + 1) is not even according to H. Therefore according to IHn, it is not true that n' is not even (double negation):
IHn : ~ ~ even n'
Unfolding double negation, we conclude that n' is even.
But how to write it in coq?
Answer
The usual way to strip double negation is to introduce the "excluded middle" axiom, which is defined under the name classic in Coq.Logic.Classical_Prop, and apply the lemma NNPP.
However, in this particular case, you can use the technique called reflection by showing that the Prop is consistent with a boolean function (you might remember the evenb function introduced earlier in the book).
(Assuming you're at the beginning of IndProp) You'll soon see the following definition later in that chapter:
Inductive reflect (P : Prop) : bool -> Prop :=
| ReflectT (H : P) : reflect P true
| ReflectF (H : ~ P) : reflect P false.
You can prove the statement
forall n : nat, reflect (even n) (evenb n)
and then use it to move between a Prop and a boolean (which contain the same information i.e. the (non-)evenness of n) at the same time. This also means that you can do classical reasoning on that particular property without using the classic axiom.
I suggest to complete the exercises under Reflection section in IndProp, and then try the following exercises. (Edit: I uploaded the full answer here.)
(* Since ``evenb`` has a nontrivial recursion structure, you need the following lemma: *)forall P : nat -> Prop, P 0 -> P 1 -> (forall n : nat, P n -> P (S (S n))) -> forall n : nat, P nforall P : nat -> Prop, P 0 -> P 1 -> (forall n : nat, P n -> P (S (S n))) -> forall n : nat, P nIH: forall P : nat -> Prop, P 0 -> P 1 -> (forall n : nat, P n -> P (S (S n))) -> forall n : nat, P nforall P : nat -> Prop, P 0 -> P 1 -> (forall n : nat, P n -> P (S (S n))) -> forall n : nat, P nIH: forall P : nat -> Prop, P 0 -> P 1 -> (forall n : nat, P n -> P (S (S n))) -> forall n : nat, P n
P: nat -> Prop
H: P 0
H0: P 1
H1: forall n : nat, P n -> P (S (S n))
n: natP nIH: forall P : nat -> Prop, P 0 -> P 1 -> (forall n : nat, P n -> P (S (S n))) -> forall n : nat, P n
P: nat -> Prop
H: P 0
H0: P 1
H1: forall n : nat, P n -> P (S (S n))
n: natP (S (S n))apply IH; auto. Qed. (* This is covered in an earlier chapter *)IH: forall P : nat -> Prop, P 0 -> P 1 -> (forall n : nat, P n -> P (S (S n))) -> forall n : nat, P n
P: nat -> Prop
H: P 0
H0: P 1
H1: forall n : nat, P n -> P (S (S n))
n: natP nforall x : bool, negb (negb x) = xintros []; auto. Qed. (* This one too. *)forall x : bool, negb (negb x) = xforall n : nat, evenb (S n) = negb (evenb n)forall n : nat, evenb (S n) = negb (evenb n)evenb 1 = negb (evenb 0)n: nat
IHn: evenb (S n) = negb (evenb n)evenb (S (S n)) = negb (evenb (S n))auto.evenb 1 = negb (evenb 0)n: nat
IHn: evenb (S n) = negb (evenb n)evenb (S (S n)) = negb (evenb (S n))n: nat
IHn: evenb (S n) = negb (evenb n)evenb (S (S n)) = negb (negb (evenb n))destruct (evenb n); auto. Qed. (* Exercises. *)n: nat
IHn: evenb (S n) = negb (evenb n)evenb n = negb (negb (evenb n))forall n : nat, evenb n = true -> even nforall n : nat, evenb n = true -> even n(* Fill in here *) Admitted.evenb 0 = true -> even 0evenb 1 = true -> even 1n: nat
IHn: evenb n = true -> even nevenb (S (S n)) = true -> even (S (S n))forall n : nat, evenb n = false -> ~ even nforall n : nat, evenb n = false -> ~ even n(* Fill in here *) Admitted.evenb 0 = false -> ~ even 0evenb 1 = false -> ~ even 1n: nat
IHn: evenb n = false -> ~ even nevenb (S (S n)) = false -> ~ even (S (S n))forall n : nat, reflect (even n) (evenb n)Admitted.forall n : nat, reflect (even n) (evenb n)forall n : nat, even n <-> evenb n = trueAdmitted.forall n : nat, even n <-> evenb n = trueforall (P : Prop) (b : bool), reflect P b -> ~ P <-> b = falseAdmitted.forall (P : Prop) (b : bool), reflect P b -> ~ P <-> b = falseforall n : nat, ~ even n <-> evenb n = falseAdmitted.forall n : nat, ~ even n <-> evenb n = falseforall n : nat, even (S n) <-> ~ even n(* Fill in here. Hint: Now you can convert all the (non-)evenness properties to booleans, and then work with boolean logic! *) Admitted.forall n : nat, even (S n) <-> ~ even n