How can I prove `false` and by extension anything from Coq hypothesis 'd=d+1'? - coq

Goal forall (d : nat), d + 1 = d -> False.
Proof.
intros d H.
Abort.
How can I prove False from H? inversion H is just replicating it.

Here is how you can discover some helpful lemmas to do derive a contradiction from your context. First of all we need to import a module containing them, otherwise the Search command won't be able to discover those lemmas:
Require Import Coq.Arith.Arith.
Let's check if we have exactly the lemma we need (recall that x <> y is a notation for not (eq x y), and not A stands for A -> False):
Search (?x + _ <> ?x).
No luck this time. Ok, addition is commutative, let's trying it this way:
Search (_ + ?x <> ?x).
Nothing again. But we certainly should have something like that:
Search (S ?x <> ?x).
Finally we have the following lemma:
Nat.neq_succ_diag_l: forall n : nat, S n <> n
which we can use like so:
Require Import Coq.Arith.Arith.
Goal forall (d : nat), d + 1 = d -> False.
Proof.
intros d H.
rewrite Nat.add_comm in H.
now apply Nat.neq_succ_diag_l in H.
Qed.

The proof follows by induction on d and uses:
eq_add_S
: forall n m : nat, S n = S m -> n = m
The base case is 0 = 1 which by inversion leads to False, this concluding the case. The inductive case you have d + 1 = d -> False as the induction hypothesis and S d + 1 = S d -> False as your goal. We know that x + 1 = y + 1 -> x + y from eq_add_S, so we rewrite our goal and apply the induction hypothesis.
Complete proof:
Goal forall (d : nat), d + 1 = d -> False.
Proof.
induction d.
intros.
- inversion H.
- intros H.
erewrite <- eq_add_S in H; eauto.
Qed.

Related

Proof irrelevance for boolean equality

I'm trying to prove group axioms for Z_3 type:
Require Import Coq.Arith.PeanoNat.
Record Z_3 : Type := Z3
{
n :> nat;
proof : (Nat.ltb n 3) = true
}.
Proposition lt_0_3 : (0 <? 3) = true.
Proof.
simpl. reflexivity.
Qed.
Definition z3_0 : Z_3 := (Z3 0 lt_0_3).
Proposition lt_1_3 : (1 <? 3) = true.
Proof.
reflexivity.
Qed.
Definition z3_1 : Z_3 := (Z3 1 lt_1_3).
Proposition lt_2_3 : (2 <? 3) = true.
Proof.
reflexivity.
Qed.
Definition z3_2 : Z_3 := (Z3 2 lt_2_3).
Proposition three_ne_0 : 3 <> 0.
Proof.
discriminate.
Qed.
Lemma mod_upper_bound_bool : forall (a b : nat), (not (eq b O)) -> (Nat.ltb (a mod b) b) = true.
Proof.
intros a b H. apply (Nat.mod_upper_bound a b) in H. case Nat.ltb_spec0.
- reflexivity.
- intros Hcontr. contradiction.
Qed.
Definition Z3_op (x y: Z_3) : Z_3 :=
let a := (x + y) mod 3 in
Z3 a (mod_upper_bound_bool _ 3 three_ne_0).
Lemma Z3_eq n m p q : n = m -> Z3 n p = Z3 m q.
Proof.
intros H. revert p q. rewrite H. clear H. intros. apply f_equal.
We are almost done:
1 subgoal (ID 41)
n, m : nat
p, q : (m <? 3) = true
============================
p = q
What theorem should I use to prove that p = q?
Update 1
Theorem bool_dec :
(forall x y: bool, {x = y} + {x <> y}).
Proof.
intros x y. destruct x.
- destruct y.
+ left. reflexivity.
+ right. intro. discriminate H.
- destruct y.
+ right. intro. discriminate H.
+ left. reflexivity.
Qed.
Lemma Z3_eq n m p q : n = m -> Z3 n p = Z3 m q.
Proof.
intros H. revert p q. rewrite H. clear H. intros. apply f_equal. apply UIP_dec. apply bool_dec.
Qed.
You are probably interested in knowing that every two proofs of a decidable equality are equal. This is explained and proved here: https://coq.inria.fr/library/Coq.Logic.Eqdep_dec.html
You are interested in particular in the lemma UIP_dec: https://coq.inria.fr/library/Coq.Logic.Eqdep_dec.html#UIP_dec
Theorem UIP_dec :
forall (A:Type),
(forall x y:A, {x = y} + {x <> y}) ->
forall (x y:A) (p1 p2:x = y), p1 = p2.
You will have then to prove that equalities of booleans are decidable (i.e. that you can write a function which says whether two given booleans are equal or not) which you should also be able to find in the standard library but which should be easily provable by hand as well.
This is a different question but since you asked: bool_dec exists and even has that name!
The easy way to find it is to use the command
Search sumbool bool.
It will turn up several lemmata, including pretty early:
Bool.bool_dec: forall b1 b2 : bool, {b1 = b2} + {b1 <> b2}
Why did I search sumbool? sumbool is the type which is written above:
{ A } + { B } := sumbool A B
You can find it using the very nice Locate command:
Locate "{".
will turn up
"{ A } + { B }" := sumbool A B : type_scope (default interpretation)
(and other notations involving "{").

Z_3: left id proof

I am close to ending the proof for Z_3 left id. Here is what I have so far
Require Import Coq.Arith.PeanoNat.
Require Import Coq.Bool.Bool.
Require Import Coq.Logic.Eqdep_dec.
Record Z_3 : Type := Z3
{
n :> nat;
proof : (Nat.ltb n 3) = true
}.
Proposition lt_0_3 : (0 <? 3) = true.
Proof.
simpl. reflexivity.
Qed.
Definition z3_0 : Z_3 := (Z3 0 lt_0_3).
Proposition lt_1_3 : (1 <? 3) = true.
Proof.
reflexivity.
Qed.
Definition z3_1 : Z_3 := (Z3 1 lt_1_3).
Proposition lt_2_3 : (2 <? 3) = true.
Proof.
reflexivity.
Qed.
Definition z3_2 : Z_3 := (Z3 2 lt_2_3).
Proposition three_ne_0 : 3 <> 0.
Proof.
discriminate.
Qed.
Lemma mod_upper_bound_bool : forall (a b : nat), b <> O -> (a mod b <? b) = true.
Proof.
intros a b H. apply (Nat.mod_upper_bound a b) in H. case Nat.ltb_spec0.
- reflexivity.
- intros Hcontr. contradiction.
Qed.
Definition Z3_op (x y: Z_3) : Z_3 :=
let a := (x + y) mod 3 in
Z3 a (mod_upper_bound_bool _ 3 three_ne_0).
Lemma Z3_eq n m p q : n = m -> Z3 n p = Z3 m q.
Proof.
intros H. revert p q. rewrite H. clear H. intros. apply f_equal. apply UIP_dec. apply bool_dec.
Qed.
Proposition Z3_left_id' : forall x: Z_3, (Z3_op z3_0 x) = x.
Proof.
intro. unfold Z3_op. destruct x as [n proof]. apply Z3_eq.
Result:
1 subgoal (ID 46)
n : nat
proof : (n <? 3) = true
============================
(z3_0 + {| n := n; proof := proof |}) mod 3 = n
I found the following theorems that could be useful:
Nat.ltb_spec0
: forall x y : nat, reflect (x < y) (x <? y)
Nat.mod_small: forall a b : nat, a < b -> a mod b = a
Is it possible to get rid of profs in the goal, convert proof from bool to Prop, and then use Nat.mod_small?
Update
Proposition Z3_left_id' : forall x: Z_3, (Z3_op z3_0 x) = x.
Proof.
intro. unfold Z3_op. destruct x as [vx proof]. apply Z3_eq. unfold n, z3_0. rewrite plus_O_n. apply Nat.mod_small.
1 subgoal (ID 67)
vx : nat
proof : (vx <? 3) = true
============================
vx < 3
You need the coercion to execute. Unfortunately,
by naming the bound variable of your proof n and the projection from Z_3 to nat n, you painted yourself in a corner.
Here are four solutions:
1/ this one I mention just for the record: you can talk about the constant n that was defined in this file by using the file name as a module qualifier.
unfold user4035_oct_16.n.
user4035_oct_16 is the name of the current file, this is ugly.
2/ you could call a computation function that computes everything, however computation of modulo leaves unsightly terms in the goal, so you could decide to not compute that particular part.
cbn -[Nat.modulo].
I like this one, but it requires that you spend sometime learning how to use cbn.
3/ You can avoid the name clash by renaming variables in the goal.
rename n into m.
unfold n, Z3_0.
Not very nice either.
4/ Just go back in your script and replace destruct x as [n proof] with destruct x as [vx proof], then you can type:
unfold n, z3_0.
you will be able to use the lemmas you suggest.
Proof:
Proposition Z3_left_id : forall x: Z_3, (Z3_op z3_0 x) = x.
Proof.
intro. unfold Z3_op. destruct x as [vx proof]. apply Z3_eq. unfold n, z3_0. rewrite plus_O_n. apply Nat.mod_small. apply Nat.ltb_lt in proof. assumption.
Qed.

IndProp: prove that Prop is not provable

The task.
Suppose we give Coq the following definition:
Inductive R2 : nat -> list nat -> Prop :=
| c1 : R2 0 []
| c2 : forall n l, R2 n l -> R2 (S n) (n :: l)
| c3 : forall n l, R2 (S n) l -> R2 n l.
Which of the following propositions are provable?
I proved 2 out of 3.
Example Example_R21 : R2 2 [1;0].
Proof.
apply c2. apply c2. apply c1.
Qed.
Example Example_R22 : R2 1 [1;2;1;0].
Proof.
repeat constructor.
Qed.
The 3-rd is not provable, because c3 will only increase n, and it will never be equal to the head of list + 1. But how to formally prove that it is not provable?
Example Example_R23 : not (R2 6 [3;2;1;0]).
Proof.
Qed.
Update 1
Fixpoint gen (n: nat) : list nat :=
match n with
| 0 => []
| S n' => (n' :: gen n')
end.
Lemma R2_gen : forall (n : nat) (l : list nat), R2 n l -> l = gen n.
Proof.
intros n l H. induction H.
- simpl. reflexivity.
- simpl. rewrite IHR2. reflexivity.
- simpl in IHR2. ?
You have to proceed by induction on the R2. Basically, if you have R2 6 (3 :: _), then it must be a c3 (no other constructor fits), so it contains an R2 7 (3 :: _), which must also be c3, which contains R2 8 (3 :: _), etc. This chain is infinite, so you'll never reach the end. Therefore, you can use False as the goal of the induction and you will never reach the base case where you actually have to produce False. It is not enough to just use inversion. Inversion is really just one step of the needed induction, and induction on any of the other things in the context doesn't help.
During the induction, the first parameter will vary. Specifically, it will always be more than S 3 (that's what lets us rule out the other constructors), so we need to generalize with respect to k where the first parameter is always 5 + k (starting with k = 1 for our case where we have 6).
Example Example_R23 : not (R2 6 [3;2;1;0]).
Proof.
set (xs := [2; 1; 0]).
change 6 with (5 + 1).
set (x := 3). (* sets are not strictly needed, but help clean things up *)
generalize 1 as k.
intros k.
(* Everything up to here is just generalizing over k *)
remember (S (S x) + k) as n eqn:prf_n.
remember (x :: xs) as l eqn:prf_l.
intros no.
revert k prf_n prf_l.
induction no as [ | n' l' _ _ | n' l' _ rec_no]
; intros k prf_n prf_l.
- discriminate.
- injection prf_l as -> ->.
discriminate.
- subst.
(* Everything up to here is combined inversion and induction *)
eapply rec_no.
+ apply plus_n_Sm.
+ reflexivity.
Defined.
We can reduce this proof immensely by using the experimental dependent induction tactic, which replaces the middle, inversiony part.
Example Example_R23 : not (R2 6 [3;2;1;0]).
Proof.
set (xs := [2; 1; 0]).
change 6 with (5 + 1).
set (x := 3).
generalize 1 as k.
intros k no.
dependent induction no generalizing k.
eapply IHno.
- apply plus_n_Sm.
- reflexivity.
Defined.
Another form of cleanup would be extracting the generalized proof out into a lemma:
Lemma R2_head x k xs : ~R2 (S (S x) + k) (x :: xs).
Proof.
intros no.
dependent induction no generalizing k.
- clear no IHno. (* Another "infinite chain" contradiction *)
rename x into prf_x, x0 into x.
induction x as [ | x rec_x].
+ discriminate.
+ injection prf_x.
apply rec_x.
- eapply IHno.
+ apply plus_n_Sm.
+ reflexivity.
Defined.
Example Example_R232 : not (R2 6 [3;2;1;0]) := R2_head 3 _ _.
Here is a simple proof that uses the goal generalization technique.
First, we prove a more general property than we actually are posed with.
From Coq Require Import Lia.
Lemma R2_len n l : R2 n l -> n <= length l.
Proof. induction 1; simpl; lia. Qed.
Now our example is a simple concrete instance of the more general property.
Example Example_R23 : not (R2 6 [3;2;1;0]).
Proof. intros H%R2_len; simpl in H; lia. Qed.
This is equivalent to #HTNW's proof
Lemma R2_head' {a n l}: R2 a (n::l) -> a <= S n.
intros H; dependent induction H;
try pose proof (IHR2 _ _ eq_refl); lia.
Qed.
Example Example_R23 : not (R2 6 [3;2;1;0]).
Proof. intros C; pose proof (R2_head' C); lia. Qed.
not A is A -> False. You should introduce the absurd hypothesis and reason by cases on it (see the inversion tactic).
You could write a function to generate the list from the nat parameter (let's call it gen) and prove R2 n l -> l = gen n. From that, you can prove your proposition by showing that l <> gen n.

How to deal with a function with an exists on the right side?

I am not sure whether I am using the right words in the question title, so here is the code:
Lemma In_map_iff :
forall (A B : Type) (f : A -> B) (l : list A) (y : B),
In y (map f l) <->
exists x, f x = y /\ In x l.
Proof.
intros A B f l y.
split.
- intros.
induction l.
+ intros. inversion H.
+ exists x.
simpl.
simpl in H.
destruct H.
* split.
{ apply H. }
{ left. reflexivity. }
* split.
A : Type
B : Type
f : A -> B
x : A
l : list A
y : B
H : In y (map f l)
IHl : In y (map f l) -> exists x : A, f x = y /\ In x l
============================
f x = y
Basically, there is not much to go on with this proof, I can only really use induction on l and after substituting for x in the goal I get the above form. If IHl had a forall instead of exists maybe I could substitute something there, but I am not sure at all what to do here.
I've been stuck on this one for a while now, but unlike the other problems where that has happened, I could not find the solution online for this one. This is a problem as I am going through the book on my own, so have nobody to ask except in places like SO.
I'd appreciate a few hints. Thank you.
Lemma In_map_iff :
forall (A B : Type) (f : A -> B) (l : list A) (y : B),
In y (map f l) <->
exists x, f x = y /\ In x l.
Proof.
intros A B f l y.
split.
- intros.
induction l.
+ intros. inversion H.
+ simpl.
simpl in H.
destruct H.
* exists x.
split.
{ apply H. }
{ left. reflexivity. }
* destruct IHl.
-- apply H.
-- exists x0.
destruct H0.
++ split.
** apply H0.
** right. apply H1.
- intros.
inversion H.
induction l.
+ intros.
inversion H.
inversion H1.
inversion H3.
+ simpl.
right.
apply IHl.
* inversion H.
inversion H0.
inversion H2.
exists x.
split.
-- reflexivity.
-- destruct H3.
A : Type
B : Type
f : A -> B
x0 : A
l : list A
y : B
H : exists x : A, f x = y /\ In x (x0 :: l)
x : A
H0 : f x = y /\ In x (x0 :: l)
IHl : (exists x : A, f x = y /\ In x l) ->
f x = y /\ In x l -> In y (map f l)
x1 : A
H1 : f x1 = y /\ In x1 (x0 :: l)
H2 : f x = y
H3 : x0 = x
H4 : f x = y
============================
In x l
I managed to do one case, but am now stuck in the other. To be honest, since I've already spent 5 hours on a problem that should need like 15 minutes, I am starting to think that maybe I should consider genetic programming at this point.
H can be true on two different ways, try destruct H. From that, the proof follows easily I think, but be careful on the order you destruct H and instantiate the existential thou.
Here is a proof that has the same structure as would have a pen-and-paper proof (at least the first -> part). When you see <tactic>... it means ; intuition (because of Proof with intuition. declaration), i.e. apply the intuition tactic to all the subgoals generated by <tactic>. intuition enables us not to do tedious logical deductions and can be replaced by a sequence of apply and rewrite tactics, utilizing some logical lemmas.
As #ejgallego pointed out the key here is that while proving you can destruct existential hypotheses and get inhabitants of some types out of them. Which is crucial when trying to prove existential goals.
Require Import Coq.Lists.List.
Lemma some_SF_lemma :
forall (A B : Type) (f : A -> B) (l : list A) (y : B),
In y (map f l) <->
exists x, f x = y /\ In x l.
Proof with intuition.
intros A B f l y. split; intro H.
- (* -> *)
induction l as [ | h l'].
+ (* l = [] *)
contradiction.
+ (* l = h :: l' *)
destruct H.
* exists h...
* destruct (IHl' H) as [x H'].
exists x...
- (* <- *)
admit.
Admitted.

How to simplify A + 0 > 0 into A > 0?

I'm just a beginner with Coq, and I've been trying to prove a few elementary theorems about natural numbers. I've done a few already, not very elegantly, but completed nether the less. However I'm totally stuck on completing this theorem:
Theorem add_increase: (forall a b: nat, a > 0 -> a + b > b).
Proof.
intros A.
intros B.
intros H.
case B.
Entering this in, I get this output:
2 subgoals
A, B : nat
H : A > 0
______________________________________(1/2)
A + 0 > 0
______________________________________(2/2)
forall n : nat, A + S n > S n
Obviously, the first goal is pretty trivial to simplify to hypothesis H. However, I just can't figure out how to make this straightforward simplification.
One way to simplify this is to use a rather boring lemma
Lemma add_zero_r : forall n, n + 0 = n.
Proof.
intros n. induction n. reflexivity.
simpl. rewrite IHn. reflexivity.
Qed.
and next use this to rewrite your goal:
Theorem add_increase: (forall a b: nat, a > 0 -> a + b > b).
Proof.
intros A.
intros B.
intros H.
case B.
rewrite (add_zero_r A).
assumption.
To finish the other proof case I've used a little lemma and a tactic that eases the task of proving stuff with inequalities over naturals.
First, I've imported Omega library.
Require Import Omega.
Prove another boring fact.
Lemma add_succ_r : forall n m, n + (S m) = S (n + m).
Proof.
intros n m. induction n. reflexivity.
simpl. rewrite IHn. reflexivity.
Qed.
and going back to add_increase prove we have the following goal:
A, B : nat
H : A > 0
============================
forall n : nat, A + S n > S n
That can be solved by:
intros C.
rewrite (add_succ_r A C).
omega.
Again, I've used the previous proved lemma to rewrite the goal. The omega tactic is a very useful one since it is a complete decision procedure for the so called quantifier free Presburger arithmetic, and based on your context, it can solve the goal automagically.
Here's the complete solution to your proof:
Require Import Omega.
Lemma add_zero_r : forall n, n + 0 = n.
Proof.
intros n. induction n. reflexivity.
simpl. rewrite IHn. reflexivity.
Qed.
Lemma add_succ_r : forall n m, n + (S m) = S (n + m).
Proof.
intros n m. induction n. reflexivity.
simpl. rewrite IHn. reflexivity.
Qed.
Theorem add_increase: (forall a b: nat, a > 0 -> a + b > b).
Proof.
intros A.
intros B.
intros H.
case B.
rewrite (add_zero_r A).
assumption.
intros C.
rewrite (add_succ_r A C).
omega.
Qed.
Several common lemmas such as a + 0 = a etc. are put in the hint database arith. With them, auto can usually solve many simple goals of this kind, so use auto with arith.
Require Import Arith.
Theorem add_increase: (forall a b: nat, a > 0 -> a + b > b).
destruct a; intros b H.
- inversion H. (* base case, H: 0 > 0 *)
- simpl. auto with arith.
Qed.
To see which lemmas auto used, you can Print add_increase. In this case, auto used three lemmas, and they can alternatively be given explicitly to auto by auto using gt_le_S, le_lt_n_Sm, le_plus_r.
In general, when you need a lemma that you think ought to have already been proven, you can search for it with SearchAbout. Use _ as a wild card, or ?a as a named wild-card. In your case above you wanted something about adding a zero on the right, so
SearchAbout ( _ + 0 = _ ).
returns
plus_0_r: forall n : nat, n + 0 = n
NPeano.Nat.add_0_r: forall n : nat, n + 0 = n
You can even find a lemma in the library that is close to what you want to prove.
SearchAbout ( _ > _ -> _ + _ > _ ).
finds
plus_gt_compat_l: forall n m p : nat, n > m -> p + n > p + m
which is pretty close to add_increase.
Theorem add_increase: (forall a b: nat, a > 0 -> a + b > b).
intros.
pose (plus_gt_compat_l a 0 b H) as A.
repeat rewrite (plus_comm b) in A.
apply A.
Qed.
Another solution using a different natural numbers library ssrnat and the ssreflect proof language (which is needed by the library):
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.
Theorem add_increase a b : 0 < a -> b < a + b.
Proof. by rewrite -{1}[b]add0n ltn_add2r. Qed.
The ltn_add2r : (m + p < n + p) = (m < n) lemma is proved by induction on p, directly by induction on p plus commutativity and other easy properties of addition.
Note that if we're invoking the omega tactic, we could've just done:
Theorem add_increase : forall a b: nat, a > 0 -> a + b > b.
Proof. intros a b. omega. Qed.