How to prove False from obviously contradictory assumptions - coq

Suppose I want to prove following Theorem:
Theorem succ_neq_zero : forall n m: nat, S n = m -> 0 = m -> False.
This one is trivial since m cannot be both successor and zero, as assumed. However I found it quite tricky to prove it, and I don't know how to make it without an auxiliary lemma:
Lemma succ_neq_zero_lemma : forall n : nat, O = S n -> False.
Proof.
intros.
inversion H.
Qed.
Theorem succ_neq_zero : forall n m: nat, S n = m -> 0 = m -> False.
Proof.
intros.
symmetry in H.
apply (succ_neq_zero_lemma n).
transitivity m.
assumption.
assumption.
Qed.
I am pretty sure there is a better way to prove this. What is the best way to do it?

You just need to substitute for m in the first equation:
Theorem succ_neq_zero : forall n m: nat, S n = m -> 0 = m -> False.
Proof.
intros n m H1 H2; rewrite <- H2 in H1; inversion H1.
Qed.

There's a very easy way to prove it:
Theorem succ_neq_zero : forall n m: nat, S n = m -> 0 = m -> False.
Proof.
congruence.
Qed.
The congruence tactic is a decision procedure for ground equalities on uninterpreted symbols. It's complete for uninterpreted symbols and for constructors, so in cases like this one, it can prove that the equality 0 = m is impossible.

It might be useful to know how congruence works.
To prove that two terms constructed by different constructors are in fact different, just create a function that returns True in one case and False in the other cases, and then use it to prove True = False. I think this is explained in Coq'Art
Example not_congruent: 0 <> 1.
intros C. (* now our goal is 'False' *)
pose (fun m=>match m with 0=>True |S _=>False end) as f.
assert (Contra: f 1 = f 0) by (rewrite C; reflexivity).
now replace False with True by Contra.
Qed.

Related

Coq - How to prove eqb_neq?

I'm trying to prove eqb_neq:
Theorem eqb_neq : forall x y : nat,
x =? y = false <-> x <> y.
This is my current proof status:
During the proof I reached a final step where I just need to prove the additional helper theorem:
Theorem eqb_false_helper : forall n m : nat,
n <> m -> S n <> S m.
I've tried multiple strategies but now I'm not even sure it's possible to prove this helper theorem.
I'm not sure how to prove the base case using induction:
What else can I try? Any tips for eqb_neq or the helper theorem?
Thanks
It is actually quite simple for your helper theorem if you just unfold not :
Theorem eqb_false_helper : forall n m : nat,
n <> m -> S n <> S m.
Proof.
unfold not; intros.
apply H; injection H0; intro; assumption.
Qed.
You actually just need to prove that S n = S m -> False, you assume that n = m -> False, thus you can prove that S n = S m -> n = m, which is done injecting hypothesis S n = S m.

Proving the symmetry of natural numbers

I am a beginner in coq. I want to prove symmetry of a boolean equality on natural numbers. I have applied induction and destruct commands, but it does not work. Please guide me in proving the theorem.
Fixpoint beqnat(n m : nat): bool:=
match n with
|0=> match m with
|0=> true
|S m' => false
end
|S n'=> match m with
|0=>false
|S m'=> beqnat n' m'
end
end.
Theorem beq sys:
forall(n m:nat),
beqnat n m = beqnat m n.
The proof follows by induction on n followed by destruction on m:
Theorem beq_sym: forall n m : nat, beqnat n m = beqnat m n.
Proof.
induction n as [|n' IH]; destruct m; auto.
apply IH.
Qed.
To understand what is happening:
Do induction n which gives subgoals for n = 0 and n = S n'.
Do simpl on each subgoal to see how the first match/with reduces.
Now you need to do something to m to reduce the second match/with. Induction is not necessary because your beqnat is structurally recursive on n (type Print beqnat and look for {struct n} to confirm), not m. So, destruct m suffices. Again, use simpl to see why.
The induction hypothesis is needed for the recursive call to beqnat in the second subgoal.

Wellfounded induction in CoQ

Let's say that I know certain natural numbers are good. I know 1 is good, if n is good then 3n is, and if n is good then n+5 is, and those are only ways of constructing good numbers. It seems to me that the adequate formalization of this in Coq is
Inductive good : nat -> Prop :=
| g1 : good 1
| g3 : forall n, good n -> good (n * 3)
| g5 : forall n, good n -> good (n + 5).
However, despite being obvious, the fact that 0 is not good seems not being provable using this definition (because when I invert, in case of g3 I only get the same thing in the hypothesis).
Now it isn't so obvious what exactly are good numbers. And it really seems that I don't need to characterize them totally in order to know that 0 is not good. For example, I can know that 2 is not good just by doing few inversions.
Indeed g3 can be applied an unbounded number of times when trying to disprove good 0. That is why we can think this proof requires induction (and we can see that the auxiliary lemma needed in the solution of #AntonTrunov uses induction). The same idea is used in theorem loop_never_stop of http://www.cis.upenn.edu/~bcpierce/sf/current/Imp.html#lab428.
Require Import Omega.
Example not_good_0 : ~ good 0.
Proof.
intros contra. remember 0 as n. induction contra.
discriminate. apply IHcontra. omega. omega.
Qed.
This problem needs induction. And induction needs some predicate P : nat -> Prop to work with. A primitive (constant) predicate like (fun n => ~good 0) doesn't give you much: you won't be able to prove the base case for 1 (which corresponds to the constructor g1), because the predicate "forgets" its argument.
So you need to prove some logically equivalent (or stronger) statement which readily will give you the necessary predicate.
An example of such equivalent statement is forall n, good n -> n > 0, which you can later use to disprove good 0. The corresponding predicate P is (fun n => n > 0).
Require Import Coq.Arith.Arith.
Require Import Coq.omega.Omega.
Inductive good : nat -> Prop :=
| g1 : good 1
| g3 : forall n, good n -> good (n * 3)
| g5 : forall n, good n -> good (n + 5).
Lemma good_gt_O: forall n, good n -> n > 0.
Proof.
intros n H. induction H; omega.
Qed.
Goal ~ good 0.
intro H. now apply good_ge_O in H.
Qed.
Here is a proof of the aforementioned equivalence:
Lemma not_good0_gt_zero_equiv_not_good0 :
(forall n, good n -> n > 0) <-> ~ good 0.
Proof.
split; intros; firstorder.
destruct n; [tauto | omega].
Qed.
And it's easy to show that forall n, n = 0 -> ~ good n which implicitly appears in #eponier's answer is equivalent to ~ good 0 too.
Lemma not_good0_eq_zero_equiv_not_good0 :
(forall n, n = 0 -> ~ good n) <-> ~ good 0.
Proof.
split; intros; subst; auto.
Qed.
Now, the corresponding predicate used to prove forall n, n = 0 -> ~ good n is fun n => n = 0 -> False. This can be shown by using manual application of the goal_ind induction principle, automatically generated by Coq:
Example not_good_0_manual : forall n, n = 0 -> ~ good n.
Proof.
intros n Eq contra.
generalize Eq.
refine (good_ind (fun n => n = 0 -> False) _ _ _ _ _);
try eassumption; intros; omega.
Qed.
generalize Eq. introduces n = 0 as a premise to the current goal. Without it the goal to prove would be False and the corresponding predicate would be the boring fun n => False again.

Not equal succesors in Coq

I am trying to prove the following lemma in Coq:
Lemma not_eq_S2: forall m n, S m <> S n -> m <> n.
It seems easy but I do not find how to finish the proof. Can anybody help me please?
Thank you.
The thing to know is that in Coq, a negation is a function that implies False, so the S m <> S n is really S m = S n -> False. So instead of proving n <> m we can introduce the n = m (we can either unfold not or tell intros explicitly to do it) and get the goal False instead. But with n = m in the context we can rewrite HS: S n <> S m into HS: S n <> S n, which can be handled by auto, or many other tactics such as apply HS. reflexivity. or congruence. etc.
Lemma not_eq_S2: forall m n, S m <> S n -> m <> n.
Proof. intros m n HS HC.
rewrite HC in HS. auto.
Qed.
It's really easy (but the negation makes it a bit confusing).
Lemma not_eq_S2: forall m n, S m <> S n -> m <> n.
Proof.
unfold not. (* |- ... -> False *)
intros m n H C. (* ..., H : S m = S n -> False |- False *)
apply H. (* ... |- S m = S n *)
(* f_equal gets rid of functions applied on both sides of an equality,
this is probably what you didn't find *)
(* basically, f_equal turns a goal [f a = f b] into [a = b] *)
f_equal. (* ..., C : m = n |- m = n *)
exact C.
Qed.

Coq induction start at specific nat

I'm trying to learn coq so please assume I know nothing about it.
If I have a lemma in coq that starts
forall n m:nat, n>=1 -> m>=1 ...
And I want to proceed by induction on n. How do I start the induction at 1? Currently when I use the "induction n." tactic it starts at zero and this makes the base statement false which makes it hard to proceed.
Any hints?
The following is a proof that every proposition P is true forall n>=1, if P is true for 1 and if P is inductively true.
Require Import Omega.
Parameter P : nat -> Prop.
Parameter p1 : P 1.
Parameter pS : forall n, P n -> P (S n).
Goal forall n, n>=1 -> P n.
We begin the proof by induction.
induction n; intro.
A false base case is no problem, if you have a false hypothesis laying around. In this case 0>=1.
- exfalso. omega.
The inductive case is tricky, because to access a proof of P n, we first have to proof that n>=1. The trick is to do a case analysis on n. If n=0, then we can trivially proof the goal P 1. If n>=1, we can access P n, and then proof the rest.
- destruct n.
+ apply p1.
+ assert (S n >= 1) by omega.
intuition.
apply pS.
trivial.
Qed.