How to make coq simplify expressions inside an implication hypothesis - coq

Im trying to prove the following lemma:
Inductive even : nat → Prop :=
| ev_0 : even 0
| ev_SS (n : nat) (H : even n) : even (S (S n)).
Lemma even_Sn_not_even_n : forall n,
even (S n) <-> not (even n).
Proof.
intros n. split.
+ intros H. unfold not. intros H1. induction H1 as [|n' E' IHn].
- inversion H.
- inversion_clear H. apply IHn in H0. apply H0.
+ unfold not. intros H. induction n as [|n' E' IHn].
-
Qed.
Here is what I got at the end:
1 subgoal (ID 173)
H : even 0 -> False
============================
even 1
I want coq to evaluate "even 0" to true and "even 1" to false. I tried simpl, apply ev_0 in H. but they give an error. What to do?

Answer to the title
simpl in H.
Real answer
The above code will not work.
The definition of even from the Logical Foundations book is:
Inductive even : nat → Prop :=
| ev_0 : even 0
| ev_SS (n : nat) (H : even n) : even (S (S n)).
even 0 is a Prop, not a bool. Looks like you're mixing up the types True and False and the booleans true and false. They're totally different things, and not interchangeable under Coq's logic. In short, even 0 does not simplify to true or True or anything. It is just even 0. If you want to show even 0 is logically true, you should construct a value of that type.
I don't remember which tactics are available at that point in LF, but here are some possibilities:
(* Since you know `ev_0` is a value of type `even 0`,
construct `False` from H and destruct it.
This is an example of forward proof. *)
set (contra := H ev_0). destruct contra.
(* ... or, in one step: *)
destruct (H ev_0).
(* We all know `even 1` is logically false,
so change the goal to `False` and work from there.
This is an example of backward proof. *)
exfalso. apply H. apply ev_0.

Related

Coq's proof #Coq

I try to solve this proof but I don't find how to it.
I have two subgoals but I don't even know if it's correct.
Here the lemma that I trid to solve with this but I'm stuck :
2 subgoals
a, b : Nat
H : Equal (leB a b) True
______________________________________(1/2)
Equal match b with
| Z => False
| S m' => leB a m'
end (leB a b) / Equal (leB b (S a)) (leB a b)
______________________________________(2/2)
Equal (leB (S a) b) True / Equal (leB b (S a)) True
Inductive Bool : Type :=
True : Bool | False : Bool.
Definition Not(b : Bool) : Bool :=
Bool_rect (fun a => Bool)
False
True
b.
Lemma classic : forall b : Bool, Equal b (Not (Not b)).
Proof.
intro.
induction b.
simpl.
apply refl.
simpl.
apply refl.
Qed.
Definition Equal(T : Type)(x y : T) : Prop :=
forall P : T -> Prop, (P x) -> (P y).
Arguments Equal[T].
(* Avec certaines versions Arguments Equal[T] *)
Lemma refl : forall T : Type, forall x : T, Equal x x.
Proof.
intros.
unfold Equal.
intros.
assumption.
Qed.
Fixpoint leB n m : Bool :=
match n, m with
| Z, _ => True
| _, Z => False
| S n', S m' => leB n' m'
end.
First, don't introduce all variables in the beginning with intros. You will get a too weak induction hypothesis. Just introduce a.
Then in each branch, consider the different cases of b with the destruct tactic. It will simplify your goal and you can see if it is the left or the right side of goal that is true, and use your refl lemma to finish the goal.
The last case require that you use your induction hypothesis, and it is here that it is important that it holds for all b, not just one specific b.
Also, you didn't provide a definition for you Nat type, I guess it is something like this:
Inductive Nat := Z | S (n:Nat).
Here is a proof.
Lemma Linear : forall a b, (Equal (leB a b) True) \/ (Equal (leB b a) True).
Proof.
induction a.
- intros b. destruct b; simpl.
+ left. apply refl.
+ left. apply refl.
- intros b. destruct b; simpl.
+ right. apply refl.
+ destruct (IHa b) as [Hleft | Hright].
++ left. apply Hleft.
++ right. apply Hright.
Qed.
While it may not be as insightful, you can also use tactics that try these steps to get a shorter proof.
induction a; destruct b; firstorder.
will also prove your lemma.

proof of adding 1 to some number changes the parity in Coq

I defined even as:
Inductive even : nat -> Prop :=
| ev0: even O
| evSS: forall n, even n -> even (S (S n)).
But now I want to prove:
Lemma add1_diff (x: nat) : even (S x) = ~even x.
Can I prove:
even (S O) = (~ even O)
Thanks in advance.
You usually can't prove the equality of two Props. An equality in Prop means that the proof terms for a logical statement are equal. This is sometimes the case, but rarely. Here are a few examples:
Require Import PeanoNat.
Import Nat.
Inductive even : nat -> Prop :=
| ev0: even O
| evSS: forall n, even n -> even (S (S n)).
Example ex1 (n : nat) : (n >= 1) = (1 <= n).
Proof.
(* The proofs are equal because >= is defined in terms of <= *)
reflexivity.
Qed.
Example ex2: even (2+2) = even 4.
Proof.
(* The proofs are equal because 2+2 can be reduced to 4 *)
reflexivity.
Qed.
Example ex3 (n : nat) : even (2+n) = even (n+2).
Proof.
(* The proofs are equal because 2+n is equal to n+2 *)
rewrite add_comm.
reflexivity.
Qed.
Example ex4 (n : nat): even (S (S n)) = even n.
Proof.
(* The proofs cannot be equal, because the left side proof always
requires one evSS constructor more than the right hand side. *)
Abort.
For this reason one uses the equivalence of two Props, which is <->, rather than the equality. The equivalence of the last statement is provable:
Example ex4 (n : nat): even (S (S n)) <-> even n.
Proof.
split; intros H.
- inversion H.
assumption.
- constructor.
assumption.
Qed.
So to answer your question: the equality of the two statements is most likely not provable, but the equivalence is. In case you need help with that, please ask.
No, you cannot prove your goal: natively there is basically no way to prove equality of propositions. What you can do instead is to use propositional equivalence, rather than equality, that is prove
even (S 0) <-> ~ (even 0)
or more generally
Lemma add1_diff (x : nat) : even (S x) <-> ~ (even x)

How to prove statement is wrong

Trying to prove the following lemma I got stuck. Usully theorems about lists are proven using induction, but I don't know where to move next.
I am trying to prove a statement, which is wrong. Therefore trying to prove it false. Here is lemma statement.Plz guide me in closing this sub-lemma.
Theorem list_length :
forall (l:list nat),
(length l =? 0) = false ->
(length l - length l =? 0) = false.
Proof.
intros. induction (length l).
simpl in *. apply H. simpl.
rewrite IHn0. auto. simpl in H.
The first problem is that forall (l:list nat),
(length l =? 0) = false ->
(length l - length l =? 0) = false is unprovable if you notice the case when the length of the list is 0, is actually true but to others cases is not.
If you're trying to prove the statement but it's wrong, so you just have to negate.
Theorem list_length :
forall (l:list nat),
~ (length l - length l =? 0) = false.
intros.
intro H.
(*now, do your magic here *)
By now, the proof is very trivial.
I will let you finish this proof now.
As you rightly noticed, the hypothesis I named abs in my version of the script is false and you should be able to derive anything from this. The only
difficulty is to make Coq see it.
You need to a theorem to explain that (something - something) is always 0. I give you the search command for this. Then, you have
to know that Coq will finish the proof using computation. Here, 0 =? 0 computes to true. Then abs modulo computation is true = false.
The tactic discriminate has been designed specifically to finish proofs in this case.
Search (?x - ?x).
Theorem index_val_0:
forall (l:list nat), (length l =? 0) = false ->
(length l - length l=?0)=false->
(index_value(length l - length l-1) l =? 0) = true.
Proof.
intros l lnnil abs.
Fail discriminate.
rewrite Nat.sub_diag in abs.
discriminate.
Qed.

Elim versus induction

I would like to understand the use of "elim" and "induction" on Coq...
Why ?
Because i have been tried to do some exercises and didn't not understand why i must use sometimes the "elim" and other times "induction"...
For example :
Lemma parte2_1_b : forall l, sum(rev l) = sum l.
Proof.
intro.
induction l.
simpl.
reflexivity.
simpl.
SearchRewrite(_++_).
SearchAbout(_++_).
rewrite parte2_1_a.
simpl.
rewrite IHl.
SearchAbout(_+_).
rewrite <- plus_n_O.
(*omega.
Qed*)
(*
ring.
Qed.
*)
SearchRewrite(_+_).
rewrite plus_comm.
reflexivity.
Qed.
The other example :
Lemma parte2_1_c : forall l1 l2, Prefix l1 l2 -> sum l1 <= sum l2.
Proof.
intros.
elim H.
intros.
simpl.
SearchPattern(_<=_).
apply le_0_n.
intros.
simpl.
SearchPattern(_<=_).
(*omega*)
apply plus_le_compat_l.
assumption.
Qed.
I've been looking for the documentation on the website, and i still don't understand on how am i supposed to choose the one correctly...
May someone helps me, please ?
Missing Functions :
Fixpoint sum (l: list nat) : nat := match l with
| nil => 0
| a::t => a + sum t
end.
The other function :
Lemma parte2_1_a : forall l1 l2, sum (l1++l2) = sum l1 + sum l2.
Proof.
intros.
induction l1.
simpl.
reflexivity.
simpl.
(*
omega.
Qed.
*)
rewrite IHl1.
SearchRewrite(_+_).
rewrite plus_assoc.
reflexivity.
Qed.
I think that now, you will be able to run the program now.
As #Ptival said, elim and induction perform almost the exact same action on the goal. The main difference you will see is that the shape of the goal might be a bit different: for example elim leaves the induction hypothesis in the goal:
Lemma parte2_1_b : forall l, sum(rev l) = sum l.
Proof.
intro.
induction l.
simpl.
reflexivity.
1 subgoal
l : list nat
====================================================================== (1/1)
forall (a : nat) (l0 : list nat),
sum (rev l0) = sum l0 -> sum (rev (a :: l0)) = sum (a :: l0)
whereas induction names it in the context:
Lemma parte2_1_b : forall l, sum(rev l) = sum l.
Proof.
intro.
induction l.
simpl.
reflexivity.
1 subgoal
a : nat
l : list nat
IHl : sum (rev l) = sum l
====================================================================== (1/1)
sum (rev (a :: l)) = sum (a :: l)
In the first case, if you do clear l; intros a l IHl, you will end up having the exact same goal as in the second one.
There exists very particular uses for elim that induction can't do, but the only relevant cases I know are for hardcore crazy users, which is not really useful most of the time. I have used Coq for years now and have I encountered such a case only once, and I didn't really need it in the end, so I advise you don't bother yourself and stick to using induction for now.
As a general question-related advice, it's hard to help you when we can't run the code you give. Giving a working minimal example or a pointer to the definitions you use is appreciated.
As for your question, elim x. and induction x. seem to be doing very similar things. As far as I can see, the difference seems to be that induction performs a bit more work by:
introducing the induction hypothesis in your context, whereas elim leaves them quantified over in the goal
cleaning up the context of the variable being inducted upon, whereas elim leaves it there
They might have some more specific differences in behaviors, but as far as proving is concerned, I'm fairly sure they are similarly powerful (in that they both call the inductor of your type). So you shouldn't be too concerned I believe. I personally never use elim and always use induction, because I tend to like the extra work it does.

induction hypothesis for even numbers

I am trying to write an induction hypothesis specifically for proving properties of even numbers. I formulated and proved the following:
Theorem ind_hyp_on_evens:
forall (p : nat -> Prop),
(p 0 -> (forall n, p n -> p (S (S n))) ->
forall n, p (n + n)).
Proof.
intros p P0 P1.
intro n.
assert(p (n + n) /\ p (S (S (n + n)))).
induction n as [| n'].
split. unfold plus. assumption.
unfold plus.
apply (P1 0).
assumption.
destruct IHn' as [A B].
split.
rewrite <- plus_Snm_nSm.
rewrite -> ? plus_Sn_m.
assumption.
rewrite <- plus_Snm_nSm.
rewrite -> ? plus_Sn_m.
apply (P1 (S (S (n' + n')))).
assumption.
destruct H as [H1 H2].
assumption. Qed.
Despite the fact that it's proved, any attempt to use it results in the error message: "Error: Not the right number of induction arguments."
Can someone please tell me what is the problem with the induction hypothesis, or otherwise, how to apply it??
Thanks,
Mayer
I believe induction assumes that any induction principle that will be used has the
fixed form
forall ... (P : SomeType -> Type) ..., (* or ->Set or ->Prop *)
... ->
forall (v : SomeType), P v
Your ind_hyp_on_evens matches only P (plus n n) which seems to confuse induction.
If you have a suitable goal, say forall n, is_even (n+n), you can manually do the
steps that induction normally does and extend that to handle the special form.
intro n0; (* temp. var *)
pattern (n0 + n0); (* restructure as (fun x => (is_even x)) (n0+n0) *)
refine (ind_hyp_on_evens _ _ _ n0); (* apply ind. scheme *)
clear n0; [| intros n IHn ]. (* clear temp., do one 'intros' per branch *)
I don't know if it's possible to pack that up as a general helper tactic for any induction scheme, packing these steps up as a per-scheme Ltac tactic should work however.
You could consider writing an inductive predicate that describes even numbers (code not tested):
Inductive even : nat -> Prop :=
| evenO : even O
| evenSSn : forall n, even n -> even (S (S n))
.
Coq will generate the induction principle automatically.
You would have to prove that even n holds before being able to perform induction on the "evenness" of n.