COQ gets wrong by proving "forall n:nat, ( n <= 0) -> n=0" - coq

Can someone explain me the following - apparently wrong - COQ derivation?
Theorem test: forall n:nat, ( n <= 0) -> n=0.
intros n H.
elim H.
auto.
COQ answer:
1 subgoal
n : nat
H : n <= 0
=================
forall m : nat, n <= m -> n = m -> n = S m

le (<=) has two constructors. In n <= 0 both (somehow) could apply:
Inductive le (n : nat) : nat -> Prop :=
le_n : n <= n
| le_S : forall m : nat, n <= m -> n <= S m
auto in your proof solves the first goal / case. The second is unprovable. You should do induction on n to prove the theorem:
Theorem test: forall n, n <= 0 -> n = 0.
intros n H.
induction n.
reflexivity.
inversion H. Qed.
or you could use inversion H tactic (not elim):
Theorem test: forall n, n <= 0 -> n = 0.
intros n H.
inversion H.
auto. Qed.

When using induction on a predicate, you usually need to make sure the arguments to the predicate are variables and not terms. You do so by adding some equations. You also usually need to make sure those variables are distinct and that there aren't any unnecessary hypotheses or quantifiers before the predicate.
Goal forall n1, n1 <= 0 -> n1 = 0.
assert (H1 : forall n1 n2, n1 <= n2 -> n2 = 0 -> n1 = 0).
induction 1 as [| n2 H1 H2].
intros H1.
eapply H1.
intros H3.
discriminate.
intros n1 H2.
eapply H1.
eapply H2.
eapply eq_refl.
Qed.

It's the other way around: your original goal doesn't imply the unprovable goal; it's the unprovable goal that implies the original.
The goal
A : B
_____
C
is equivalent to the sequent
A : B |- C.
When proving something interactively in Coq, you are building a sequent tree from bottom to top. Here's an example.
-------------------- apply H
P : Prop, H : P |- P
-------------------- intro H
P : Prop |- P -> P
-------------------------- intro P
|- forall P : Prop, P -> P
Of course, when moving backwards to a proof, you can make a wrong move.
?
------------- ?
P : Prop |- P
-------------------- clear H
P : Prop, H : P |- P
-------------------- intro H
P : Prop |- P -> P
-------------------------- intro P
|- forall P : Prop, P -> P
You can learn more about sequent calculus from all over the internet.

Related

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.

Rev.v le_antisymmetric

I came to this point:
Theorem le_antisymmetric :
antisymmetric le.
Proof.
unfold antisymmetric. intros a b H1 H2. generalize dependent a.
induction b as [|b' IH].
- intros. inversion H1. reflexivity.
- intros.
Output:
b' : nat
IH : forall a : nat, a <= b' -> b' <= a -> a = b'
a : nat
H1 : a <= S b'
H2 : S b' <= a
------------------------------------------------------
a = S b'
My plan was to use transitivity of le:
a <= b -> b <= c -> a <= c
And substitute a := a, b := (S b') and c := a.
So we'll get:
a <= (S b') -> (S b') <= a -> a <= a
I'll use H1 and H2 as 2 hypotheses needed and get Ha: a <= a. Then do an inversion upon it, and get the only
way construct this is a = a.
But what syntax should I use to apply transitivity with 2 my hypotheses to get Ha?
Your first induction over b here seems unnecessary. Consider le:
Inductive le (n : nat) : nat -> Prop :=
le_n : n <= n | le_S : forall m : nat, n <= m -> n <= S m
You should instead be inspecting H1 first. If it's le_n, then that's equality, and you're done. If it's le_S, then presumably that's somehow impossible.
intros a b [ | b' H1] H2.
- reflexivity.
This leaves us with
a, b, b' : nat (* b is extraneous *)
H1 : a <= b'
H2 : S b' <= a
______________________________________(1/1)
a = S b'
Now, transitivity makes sense. It can give you S b' <= b', which is impossible. You can derive a contradiction using induction (I think), or you can use an existing lemma. The whole proof is thus.
intros a b [ | b' H1] H2.
- reflexivity.
- absurd (S b' <= b').
+ apply Nat.nle_succ_diag_l.
+ etransitivity; eassumption.
That last bit is one way to use transitivity. etransitivity turns the goal R x z into R x ?y and R ?y z, for a new existential variable ?y. eassumption then finds assumptions that match that pattern. Here, specifically, you get goals S b' <= ?y and ?y <= b, filled by H2 and H1 respectively. You can also give the intermediate value explicitly, which lets you drop the existential prefix.
transitivity a; assumption.

Induction on evidence for the "less than" relation in coq

I am working on the proof of the following theorem Sn_le_Sm__n_le_m in IndProp.v of Software Foundations (Vol 1: Logical Foundations).
Theorem Sn_le_Sm__n_le_m : ∀n m,
S n ≤ S m → n ≤ m.
Proof.
intros n m HS.
induction HS as [ | m' Hm' IHm'].
- (* le_n *) (* Failed Here *)
- (* le_S *) apply IHSm'.
Admitted.
where, the definition of le (i.e., ≤) is:
Inductive le : nat → nat → Prop :=
| le_n n : le n n
| le_S n m (H : le n m) : le n (S m).
Notation "m ≤ n" := (le m n).
Before induction HS, the context as well as the goal is as follows:
n, m : nat
HS : S n <= S m
______________________________________(1/1)
n <= m
At the point of the first bullet -, the context as well as the goal is:
n, m : nat
______________________________________(1/1)
n <= m
where we have to prove n <= m without any context, which is obviously impossible.
Why does it not generate S n = S m (and then n = m) for the le_n case in induction HS?
The main problem here -I think- is it is impossible to prove the Theorem using induction on HS as there is no way to say something about n with only hypothesis about S n because non of the constructors of le do not change the value of n. But anyway the reason that after first bullet - there is no assumption is because calling induction has the effect of replacing all occurrences of the property argument by the values that correspond to each constructor and it doesn't help in this case since the term that gets replaced S n is not mentioned anywhere. There are some tricks to avoid this. for example you can replace n with pred(S n) as follows.
Theorem Sn_le_Sm__n_le_m : forall n m,
S n <= S m -> n <= m.
Proof.
intros n m HS.
assert(Hn: n=pred (S n)). reflexivity. rewrite Hn.
assert(Hm: m=pred (S m)). reflexivity. rewrite Hm.
induction HS.
- (* le_n *) apply le_n.
- (* le_S *) (* Stucks! *) Abort.
But as I mentioned above it is impossible to go further. Another way is to use inversion which is smarter but in some cases it may not help since induction hypothesis would be necessary. But it worth to know about it.
Theorem Sn_le_Sm__n_le_m : forall n m,
S n <= S m -> n <= m.
Proof.
intros n m HS.
inversion HS.
- (* le_n *) apply le_n.
- (* le_S *) (* Stucks! *) Abort.
Best way to solve the problem is use of remember tactic as follows.
Theorem Sn_le_Sm__n_le_m : forall n m,
S n <= S m -> n <= m.
Proof.
intros n m HS.
remember (S n) as Sn.
remember (S m) as Sm.
induction HS as [ n' | n' m' H IH].
- (* le_n *)
rewrite HeqSn in HeqSm. injection HeqSm as Heq.
rewrite <- Heq. apply le_n.
- (* le_S *) (* Stucks! *) Abort.
According to Software Foundations (Vol 1: Logical Foundations)
The tactic remember e as x causes Coq to (1) replace all occurrences
of the expression e by the variable x, and (2) add an equation x = e
to the context.
Anyway, although it is impossible to prove the fact using induction on HS -imo-, performing an induction on m will solve the case. (Note the use of inversion.)
Theorem Sn_le_Sm__n_le_m : forall n m,
S n <= S m -> n <= m.
Proof.
intros n.
induction m as [|m' IHm'].
- intros H. inversion H as [Hn | n' contra Hn'].
+ apply le_n.
+ inversion contra.
- intros H. inversion H as [HnSm' | n' HSnSm' Heq].
+ apply le_n.
+ apply le_S. apply IHm'. apply HSnSm'.
Qed.
Just more examples of Kamyar's answer.
Well, let's take a look of le induction scheme :
Compute le_ind.
forall (n : nat) (P : nat -> Prop),
P n ->
(forall m : nat, n <= m -> P m -> P (S m)) ->
forall n0 : nat, n <= n0 -> P n0
P is some proposition that holds one natural number, which means in the case of le_n, our preposition n <= m will be reduced to forall n, n <= m. Indeed, it's the same lemma that we want to prove, however unprovable because there is no premise.
An easy to solve this is doing induction where le_ind doesn't do.
For example :
Theorem Sn_le_Sm__n_le_m' : forall m n,
S n <= S m -> n <= m.
elim.
by intros; apply : Gt.gt_S_le .
intros; inversion H0.
by subst.
by subst; apply : le_Sn_le.
Qed.
Notice that we doing induction by m, and using inversion to generates the two possible construction of le ({x = y} + {x < y}). Optionally, you can use le decidability.
Theorem Sn_le_Sm__n_le_m : forall n m,
S n <= S m -> n <= m.
intros.
generalize dependent n.
elim.
auto with arith.
intros.
have : n <= m.
by apply : H; apply : le_Sn_le.
move => H'.
destruct m.
auto with arith.
destruct (le_lt_eq_dec _ _ H').
assumption.
subst.
(* just prove that there is no S m <= m *)
Qed.
For the sake of your time, coq has the tactic dependent induction that easily solves your goal :
Theorem Sn_le_Sm__n_le_m'' : forall n m,
S n <= S m -> n <= m.
intros.
dependent induction H.
auto.
by apply : (le_Sn_le _ _ H).
Qed.

In coq, how to do "induction n eqn: Hn" in a way that doesn't mess up the inductive hypothesis?

When using induction, I'd like to have hypotheses n = 0 and n = S n' to separate the cases.
Section x.
Variable P : nat -> Prop.
Axiom P0: P 0.
Axiom PSn : forall n, P n -> P (S n).
Theorem Pn: forall n:nat, P n.
Proof. intros n. induction n.
- (* = 0 *)
apply P0.
- (* = S n *)
apply PSn. assumption.
Qed.
In theory I could do this with induction n eqn: Hn, but that seems to mess up the inductive hypothesis:
Theorem Pn2: forall n:nat, P n.
Proof. intros n. induction n eqn: Hn.
- (* Hn : n = 0 *)
apply P0.
- (* Hn : n = S n0 *)
(*** 1 subgoals
P : nat -> Prop
n : nat
n0 : nat
Hn : n = S n0
IHn0 : n = n0 -> P n0
______________________________________(1/1)
P (S n0)
****)
Abort.
End x.
Is there an easy way to get what I want here?
Matt was almost right, you just forgot to generalize a bit your goal by reverting the remembered n:
Theorem Pn2: forall n:nat, P n.
Proof. intros n. remember n. revert n0 Heqn0.
induction n as [ | p hi]; intros m heq.
- (* heq : n = 0 *) subst. apply P0.
- (* heq : n = S n0 *)
(*
1 subgoal
P : nat -> Prop
p : nat
hi : forall n0 : nat, n0 = p -> P n0
m : nat
heq : m = S p
______________________________________(1/1)
P m
*) subst; apply (PSn p). apply hi. reflexivity.
Ooo, I think I figured it out!
Applying the inductive hypothesis changes your goal from (P n) to (P (constructor n')), so I think in general you can just match against the goal to create the equation n = construct n'.
Here's a tactic that I think does this:
(* like set (a:=b) except introduces a name and hypothesis *)
Tactic Notation
"provide_name" ident(n) "=" constr(v)
"as" simple_intropattern(H) :=
assert (exists n, n = v) as [n H] by (exists v; reflexivity).
Tactic Notation
"induction_eqn" ident(n) "as" simple_intropattern(HNS)
"eqn:" ident(Hn) :=
let PROP := fresh in (
pattern n;
match goal with [ |- ?FP _ ] => set ( PROP := FP ) end;
induction n as HNS;
match goal with [ |- PROP ?nnn ] => provide_name n = nnn as Hn end;
unfold PROP in *; clear PROP
).
It works for my example:
Theorem Pn_3: forall n:nat, P n.
Proof.
intros n.
induction_eqn n as [|n'] eqn: Hn.
- (* n: nat, Hn: n = 0; Goal: P 0 *)
apply P0.
- (* n': nat, IHn': P n';
n: nat, Hn: n = S n'
Goal: P (S n') *)
apply PSn. exact IHn'.
Qed.
I'm not sure if this is any easier, than what you have done in your second attempt, but you can first "remember" n.
Theorem Pn: forall n:nat, P n.
Proof. intro n. remember n. induction n.
- (*P : nat -> Prop
n0 : nat
Heqn0 : n0 = 0
============================
P n0
*)
subst. apply P0.
- (* P : nat -> Prop
n : nat
n0 : nat
Heqn0 : n0 = S n
IHn : n0 = n -> P n0
============================
P n0
*)

Double induction in Coq

Basically, I would like to prove that following result:
Lemma nat_ind_2 (P: nat -> Prop): P 0 -> P 1 -> (forall n, P n -> P (2+n)) ->
forall n, P n.
that is the recurrence scheme of the so called double induction.
I tried to prove it applying induction two times, but I am not sure that I will get anywhere this way. Indeed, I got stuck at that point:
Proof.
intros. elim n.
exact H.
intros. elim n0.
exact H0.
intros. apply (H1 n1).
Actually, there's a much simpler solution. A fix allows recursion (aka induction) on any subterm while nat_rect only allows recursion on the immediate subterm of a nat. nat_rect itself is defined with a fix, and nat_ind is just a special case of nat_rect.
Definition nat_rect_2 (P : nat -> Type) (f1 : P 0) (f2 : P 1)
(f3 : forall n, P n -> P (S (S n))) : forall n, P n :=
fix nat_rect_2 n :=
match n with
| 0 => f1
| 1 => f2
| S (S m) => f3 m (nat_rect_2 m)
end.
#Rui's fix solution is quite general. Here is an alternative solution that uses the following observation: when proving this lemma mentally, you use somewhat stronger induction principle. For example if P holds for two consecutive numbers it becomes easy to make it hold for the next pair:
Lemma nat_ind_2 (P: nat -> Prop): P 0 -> P 1 -> (forall n, P n -> P (2+n)) ->
forall n, P n.
Proof.
intros P0 P1 H.
assert (G: forall n, P n /\ P (S n)).
induction n as [ | n [Pn PSn]]; auto.
split; try apply H; auto.
apply G.
Qed.
Here G proves something redundant, yet calling the induction tactic for it brings sufficient context for near-trivial proof.
I think well-founded induction is necessary for that.
Require Import Arith.
Theorem nat_rect_3 : forall P,
(forall n1, (forall n2, n2 < n1 -> P n2) -> P n1) ->
forall n, P n.
Proof.
intros P H1 n1.
apply Acc_rect with (R := lt).
info_eauto.
induction n1 as [| n1 H2].
apply Acc_intro. intros n2 H3. Check lt_n_0. Check (lt_n_0 _). Check (lt_n_0 _ H3). destruct (lt_n_0 _ H3).
destruct H2 as [H2]. apply Acc_intro. intros n2 H3. apply Acc_intro. intros n3 H4. apply H2. info_eauto with *.
Defined.
Theorem nat_rect_2 : forall P,
P 0 ->
P 1 ->
(forall n, P n -> P (S (S n))) ->
forall n, P n.
Proof.
intros ? H1 H2 H3.
induction n as [n H4] using nat_rect_3.
destruct n as [| [| n]].
info_eauto with *.
info_eauto with *.
info_eauto with *.
Defined.
A fun observation: Rui's answer is the fixpoint translation of NonNumeric's answer, which is the generalization of user1861759's answer for any n, not just n = 2.
In other words, these answers are all fine, and actually deeply related to one another, by the correspondence between terminating fixpoints and generalized induction.