I am learning Coq right now and in a larger proof I have become stumped by the following sub-proof:
Theorem sub : ∀ n m : nat, n ≤ m → n ≠ m → n < m.
Or, once unfolded:
Theorem sub : ∀ n m : nat, n ≤ m → n ≠ m → S n ≤ m.
Here, "n ≤ m" is inductively defined as follows:
Inductive le : nat → nat → Prop :=
| le_n : ∀ n : nat, le n n
| le_S : ∀ n m : nat, (le n m) → (le n (S m)).
I have not gotten very far, but my attempt looks like this:
Theorem sub : ∀ n m : nat, n ≤ m → n ≠ m → n < m.
Proof.
unfold lt.
intro n.
induction n.
- induction m.
+ intros. exfalso. contradiction.
+ admit.
- admit.
Admitted.
In the first inductive step (marked by the first admit), the inductive hypothesis shows the following :
1 subgoal
m : nat
IHm : 0 ≤ m → 0 ≠ m → 1 ≤ m
______________________________________(1/1)
0 ≤ S m → 0 ≠ S m → 1 ≤ S m
I am not sure how I can leverage this hypothesis to prove the subgoal. I would appreciate any guidance in the right direction.
Since le is defined as an inductive predicate, it makes more sense to do the induction on that, rather than n. le doesn't make any references to 0 or even S n (it does have S m), so induction on n is probably not the way to go. Induction on m might work, but it's probably harder than necessary.
Before starting a formal proof, it can often be helpful to think about how you would prove this informally (still using the same definitions, though). If you assume that n ≤ m, then by the inductive definition of lt, this means that either n and m are the same, or m is the successor of some number m' and n is less than or equal to m' (can you see why the definition of lt implies this?). In the first case, we'll have to use the additional hypothesis that n ≠ m to derive a contradiction. In the second case, we won't even need that. n ≤ m' implies that S n ≤ S m', so since m = S m', S n ≤ m, i.e., n < m.
For the formalization, we'll have to prove that assumption on the last line that n ≤ m implies S n ≤ S m. You should try a similar informal analysis to prove it. Other than that, the informal proof should be straightforward to formalize. Case analysis on H: n ≤ m is just destruct H..
One more thing. This isn't essential, but can often help in the long run. When defining an inductive type (or predicate), if you can factor out a parameter that's used the same way in each constructor, it can make the induction principle more powerful. The way you have it with le, n is universally quantified and used the same way for both constructors. Every instance of le starts with le n.
Inductive le : nat → nat → Prop :=
| le_n : ∀ n : nat, le n n
| le_S : ∀ n m : nat, (le n m) → (le n (S m)).
That means that we can factor out that index into a parameter.
Inductive le' (n: nat) : nat → Prop :=
| le_n' : le' n n
| le_S' : ∀ m : nat, (le' n m) → (le' n (S m)).
This gives you a slightly simpler/better induction principle.
le'_ind
: forall (n : nat) (P : nat -> Prop),
P n ->
(forall m : nat, le' n m -> P m -> P (S m)) ->
forall n0 : nat, le' n n0 -> P n0
Compare this to le_ind.
le_ind
: forall P : nat -> nat -> Prop,
(forall n : nat, P n n) ->
(forall n m : nat, le n m -> P n m -> P n (S m)) ->
forall n n0 : nat, le n n0 -> P n n0
Basically what's happening here is that with le_ind, you have to prove everything for every n. With le'_ind, you only need to prove it for the particular n that you're using. This can sometimes simplify proofs, though it's not necessary for the proof of your theorem. It's a good exercise to prove that these two predicates are equivalent.
Related
I am trying to complete the series of exercises le_exercises from Logical Foundations' chapter on inductive propositions.
This series is mostly based on the inductive relation le, defined thusly:
Inductive le : nat -> nat -> Prop :=
| le_n (n : nat) : le n n
| le_S (n m : nat) (H : le n m) : le n (S m).
Notation "n <= m" := (le n m).
The particular theorem I am stuck at is the following:
Theorem add_le_cases : forall n m p q,
n + m <= p + q -> n <= p \/ m <= q.
The previous theorems in these series that I managed to prove so far are:
Lemma le_trans : ∀ m n o, m ≤ n → n ≤ o → m ≤ o.
Theorem O_le_n : ∀ n, 0 ≤ n.
Theorem n_le_m__Sn_le_Sm : ∀ n m, n ≤ m → S n ≤ S m.
Theorem Sn_le_Sm__n_le_m : ∀ n m, S n ≤ S m → n ≤ m.
Theorem lt_ge_cases : ∀ n m, n < m ∨ n ≥ m.
Theorem le_plus_l : ∀ a b, a ≤ a + b.
Theorem plus_le : ∀ n1 n2 m, n1 + n2 ≤ m → n1 ≤ m ∧ n2 ≤ m.
The book gives a hint stating that the theorem add_le_cases may be "easier to prove by induction on n" which I tried in various ways, but can't seem to go anywhere.
Theorem add_le_cases : forall n m p q,
n + m <= p + q -> n <= p \/ m <= q.
Proof.
intros n. induction n.
- intros. left. apply O_le_n.
- intros. inversion H.
+ destruct m.
* right. apply O_le_n.
* (* stuck *)
I have considered using the plus_le theorem but can't seem to get anything useful from it. I feel there must be something crucial missing from my understanding but you can't know what you don't know.
Well, I would not do inversion H and destruct m. I would just destruct p and after solving the O case, then massage H a bit to be able to apply the induction hypothesis.
I am facing a pretty strange problem: coq doesn't want to move forall variable into the context.
In the old times it did:
Example and_exercise :
forall n m : nat, n + m = 0 -> n = 0 /\ m = 0.
Proof.
intros n m.
It generates:
n, m : nat
============================
n + m = 0 -> n = 0 /\ m = 0
But when we have forall inside forall, it doesn't work:
(* Auxilliary definition *)
Fixpoint All {T : Type} (P : T -> Prop) (l : list T) : Prop :=
(* ... *)
Lemma All_In :
forall T (P : T -> Prop) (l : list T),
(forall x, In x l -> P x) <->
All P l.
Proof.
intros T P l. split.
- intros H.
After this we get:
T : Type
P : T -> Prop
l : list T
H : forall x : T, In x l -> P x
============================
All P l
But how to move x outside of H and destruct it into smaller pieces? I tried:
destruct H as [x H1].
But it gives an error:
Error: Unable to find an instance for the variable x.
What is it? How to fix?
The problem is that forall is nested to the left of an implication rather than the right. It does not make sense to introduce x from a hypothesis of the form forall x, P x, just like it wouldn't make sense to introduce the n in plus_comm : forall n m, n + m = m + n into the context of another proof. Instead, you need to use the H hypothesis by applying it at the right place. I can't give you the answer to this question, but you might want to refer to the dist_not_exists exercise in the same chapter.
With the following definitions I want to prove lemma without_P
Variable n : nat.
Definition mnnat := {m : nat | m < n}.
Variable f : mnnat -> nat.
Lemma without_P : (exists x : mnnat, True) -> (exists x, forall y, f x <= f y).
Lemma without_P means: if you know (the finite) set mnnat is not empty, then there must exist an element in mnnat, that is the smallest of them all, after mapping f onto mnnat.
We know mnnat is finite, as there are n-1 numbers in it and in the context of the proof of without_P we also know mnnat is not empty, because of the premise (exists x : mnnat, True).
Now mnnat being non-empty and finite "naturally/intuitively" has some smallest element (after applying f on all its elements).
At the moment I am stuck at the point below, where I thought to proceed by induction over n, which is not allowed.
1 subgoal
n : nat
f : mnnat -> nat
x : nat
H' : x < n
______________________________________(1/1)
exists (y : nat) (H0 : y < n),
forall (y0 : nat) (H1 : y0 < n),
f (exist (fun m : nat => m < n) y H0) <= f (exist (fun m : nat => m < n) y0 H1)
My only idea here is to assert the existance of a function f' : nat -> nat like this: exists (f' : nat -> nat), forall (x : nat) (H0: x < n), f' (exist (fun m : nat => m < n) x H0) = f x, after solving this assertion I have proven the lemma by induction over n. How can I prove this assertion?
Is there a way to prove "non-empty, finite sets (after applying f to each element) have a minimum" more directly? My current path seems too hard for my Coq-skills.
Require Import Psatz Arith. (* use lia to solve the linear integer arithmetic. *)
Variable f : nat -> nat.
This below is essentially your goal, modulo packing of the statement into some dependent type. (It doesn't say that mi < n, but you can extend the proof statement to also contain that.)
Goal forall n, exists mi, forall i, i < n -> f mi <= f i.
induction n; intros.
- now exists 0; inversion 1. (* n cant be zero *)
- destruct IHn as [mi IHn]. (* get the smallest pos mi, which is < n *)
(* Is f mi still smallest, or is f n the smallest? *)
(* If f mi < f n then mi is the position of the
smallest value, otherwise n is that position,
so consider those two cases. *)
destruct (lt_dec (f mi) (f n));
[ exists mi | exists n];
intros.
+ destruct (eq_nat_dec i n).
subst; lia.
apply IHn; lia.
+ destruct (eq_nat_dec i n).
subst; lia.
apply le_trans with(f mi).
lia.
apply IHn.
lia.
Qed.
Your problem is an specific instance of a more general result which is proven for example in math-comp. There, you even have a notation for denoting "the minimal x such that it meets P", where P must be a decidable predicate.
Without tweaking your statement too much, we get:
From mathcomp Require Import all_ssreflect.
Variable n : nat.
Variable f : 'I_n.+1 -> nat.
Lemma without_P : exists x, forall y, f x <= f y.
Proof.
have/(_ ord0)[] := arg_minP (P:=xpredT) f erefl => i _ P.
by exists i => ?; apply/P.
Qed.
I found a proof to my assertion (exists (f' : nat -> nat), forall (x : nat) (H0: x < n), f (exist (fun m : nat => m < n) x H0) = f' x). by proving the similar assertion (exists (f' : nat -> nat), forall x : mnnat, f x = f' (proj1_sig x)). with Lemma f'exists. The first assertion then follows almost trivially.
After I proved this assertion I can do a similar proof to user larsr, to prove Lemma without_P.
I used the mod-Function to convert any nat to a nat smaller then n, apart from the base case of n = 0.
Lemma mod_mnnat : forall m,
n > 0 -> m mod n < n.
Proof.
intros.
apply PeanoNat.Nat.mod_upper_bound.
intuition.
Qed.
Lemma mod_mnnat' : forall m,
m < n -> m mod n = m.
Proof.
intros.
apply PeanoNat.Nat.mod_small.
auto.
Qed.
Lemma f_proj1_sig : forall x y,
proj1_sig x = proj1_sig y -> f x = f y.
Proof.
intros.
rewrite (sig_eta x).
rewrite (sig_eta y).
destruct x. destruct y as [y H0].
simpl in *.
subst.
assert (l = H0).
apply proof_irrelevance. (* This was tricky to find.
It means two proofs of the same thing are equal themselves.
This makes (exist a b c) (exist a b d) equal,
if c and d prove the same thing. *)
subst.
intuition.
Qed.
(* Main Lemma *)
Lemma f'exists :
exists (ff : nat -> nat), forall x : mnnat, f x = ff (proj1_sig x).
Proof.
assert (n = 0 \/ n > 0).
induction n.
auto.
intuition.
destruct H.
exists (fun m : nat => m).
intuition. destruct x. assert (l' := l). rewrite H in l'. inversion l'.
unfold mnnat in *.
(* I am using the mod-function to map (m : nat) -> {m | m < n} *)
exists (fun m : nat => f (exist (ltn n) (m mod n) (mod_mnnat m H))).
intros.
destruct x.
simpl.
unfold ltn.
assert (l' := l).
apply mod_mnnat' in l'.
assert (proj1_sig (exist (fun m : nat => m < n) x l) = proj1_sig (exist (fun m : nat => m < n) (x mod n) (mod_mnnat x H))).
simpl. rewrite l'.
auto.
apply f_proj1_sig in H0.
auto.
Qed.
I'm trying to prove the following toy theorem about the ordering of the naturals:
Inductive Le: nat -> nat -> Prop :=
| le_n: forall n, Le n n
| le_S: forall n m, Le n m -> Le n (S m).
Theorem le_Sn_m: forall n m,
Le (S n) m -> Le n m.
On paper, this is a simple induction on Le (S n) m. In particular, the base case of le_n is trivial.
In Coq though, beginning my proof with induction gives me the following:
Proof.
intros n m H. induction H.
1 subgoal
n, n0 : nat
______________________________________(1/1)
Le n n0
...in which case I am blocked.
How should I proceed instead?
This is happening because Coq treats differently indices and parameters (see the accepted answer to this question for a very nice explanation).
Your Le relation uses indices only, whereas the standard definition makes the first argument a parameter:
Inductive le (n : nat) : nat -> Prop :=
| le_n : n <= n
| le_S : forall m : nat, n <= m -> n <= S m
I can recommend reading this blog post by James Wilcox. Here is a relevant excerpt:
When Coq performs a case analysis, it first abstracts over all indices. You may have seen this manifest as a loss of information when using destruct on predicates
So you can either (1) change your Le relation so it would use a parameter, or (2) use the remember tactic as was suggested by #Zimm i48, or (3) use the dependent induction tactic mentioned by #Vinz:
Require Import Coq.Program.Equality. (* for `dependent induction` *)
Inductive Le: nat -> nat -> Prop :=
| le_n: forall n, Le n n
| le_S: forall n m, Le n m -> Le n (S m).
Hint Constructors Le. (* so `auto` will work *)
Theorem le_Sn_m: forall n m,
Le (S n) m -> Le n m.
Proof. intros n m H. dependent induction H; auto. Qed.
This is due to a limitation of Coq, when using induction on term that are not made only of variables. By doing your induction, Coq forgets about the fact that the first argument was a S of some n.
You can do the following instead:
Theorem le_Sn_m_: forall X m,
Le X m -> forall n, X = S n -> Le n m.
I think there is a dependent induction somewhere that could save you this intermediate lemma but I can't recall where.
Similar to #Vinz suggestion, but without changing the statement you are proving:
Proof.
intros n m H.
remember (S n) as p.
induction H.
Using the remember tactic will introduce an equality in your context which will avoid losing this critical information.
Assume the following:
Inductive bin : Set := Z | O.
Fixpoint fib (n : nat) : list bin :=
match n with
| 0 => [Z]
| S k => match k with
| 0 => [O]
| S k' => fib k' ++ fib k
end
end.
I would like to show:
Theorem fib_first : forall n,
Nat.Even n -> n > 3 -> exists w, fib n = Z :: w.
However, by performing induction on n, I get a really useless inductive
hypothesis fixing n, stating that IH : Nat.Even n -> n > 3 -> exists w : list bin, fib n = Z :: w.
What I would ideally have is the following: IH : forall n : nat, Nat.Even n -> n > 3 -> exists w : list bin, fib n = Z :: w. Naturally I cannot assume the original proposition, but it feels like I need to prove something stronger perhaps?
My idea for the inductive reasoning would be made possible by expanding F n = F n-2 . F n-1, we know F n-2 is even iff F n is even, and since neither of F n-2 or F n-1 is empty, we can show the substring is shorter, therefore sufficient for the inductive hypothesis - how does one express this in Coq?
The trick is to unfold the definition of Nat.Even and do induction on n / 2 instead of n:
Theorem fib_first : forall n,
Nat.Even n -> exists w, fib n = Z :: w.
Proof.
intros n [m ->].
induction m as [|m IH].
- now exists nil.
- rewrite <- mult_n_Sm, plus_comm.
generalize (2 * m) IH. clear m IH. simpl.
intros n [w ->].
simpl. eauto.
Qed.
Note that your n > 3 hypothesis is not actually needed.