Convert ~exists to forall in hypothesis - coq

I'm stuck in situation where I have hypothesis ~ (exists k, k <= n+1 /\ f k = f (n+2)) and wish to convert it into equivalent (I hope so) hypothesis forall k, k <= n+1 -> f k <> f (n+2).
Here is little example:
Require Import Coq.Logic.Classical_Pred_Type.
Require Import Omega.
Section x.
Variable n : nat.
Variable f : nat -> nat.
Hypothesis Hf : forall i, f i <= n+1.
Variable i : nat.
Hypothesis Hi : i <= n+1.
Hypothesis Hfi: f i = n+1.
Hypothesis H_nex : ~ (exists k, k <= n+1 /\ f k = f (n+2)).
Goal (f (n+2) <= n).
I tried to use not_ex_all_not from Coq.Logic.Classical_Pred_Type.
Check not_ex_all_not.
not_ex_all_not
: forall (U : Type) (P : U -> Prop),
~ (exists n : U, P n) -> forall n : U, ~ P n
apply not_ex_all_not in H_nex.
Error: Unable to find an instance for the variable n.
I don't understand what this error means, so as a random guess I tried this:
apply not_ex_all_not with (n := n) in H_nex.
It succeeds but H_nex is complete nonsense now:
H_nex : ~ (n <= n+1 /\ f n = f (n + 2))
On the other hand it is easy to solve my goal if H_nex is expressed as forall:
Hypothesis H_nex : forall k, k <= n+1 -> f k <> f (n+2).
specialize (H_nex i).
specialize (Hf (n+2)).
omega.
I found similar question but failed to apply it to my case.

If you want to use the not_ex_all_not lemma, what you want to proof needs to look like the lemma. E.g. you can proof the following first:
Lemma lma {n:nat} {f:nat->nat} : ~ (exists k, k <= n /\ f k = f (n+1)) ->
forall k, ~(k <= n /\ f k = f (n+1)).
intro H.
apply not_ex_all_not.
trivial.
Qed.
and then proof the rest:
Theorem thm (n:nat) (f:nat->nat) : ~ (exists k, k <= n /\ f k = f (n+1)) ->
forall k, k <= n -> f k <> f (n+1).
intro P.
specialize (lma P). intro Q.
intro k.
specialize (Q k).
tauto.
Qed.

I'm not quite sure what your problem is.
Here is how to show trivially that your implication holds.
Section S.
Variable n : nat.
Variable f : nat -> nat.
Hypothesis H : ~ (exists k, k <= n /\ f k = f (n+1)).
Goal forall k, k <= n -> f k <> f (n+1).
Proof.
intros k H1 H2.
apply H.
exists k.
split; assumption.
Qed.
End S.
Also your goal is provable by apply Hf., so I'm not sure but you seem to have some confusion...

Related

How can I prove `add_le_cases` (`forall n m p q, n + m <= p + q -> n <= p \/ m <= q`)

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.

Automatically specialize forall when the parameters are in scope

Consider the following simple problem:
Goal forall (R : relation nat) (a b c d e f g h : nat),
(forall m n : nat, R m n -> False) -> (R a b) -> False.
Proof.
intros ? a b c d e f g h H1 H2.
saturate H1. (* <-- TODO implement this *)
assumption.
Qed.
My current implementation of saturate instantiates H1 with every possible combination of nat hypotheses, leading to quadratic blowup in time and memory usage. Instead I would like it to inspect forall and see that it requires a R m n, so the only combination of parameters that makes sense in context is a and then b.
Is there a known solution to this? My intuition is to use evars, but if I could avoid them without sacrificing significant performance I would like to.
This might be too simplistic, the idea is to try apply H1 on every hypothesis:
Ltac saturate H :=
match goal with
(* For any hypothesis I... *)
| [ I : _ |- _ ] =>
(* 1. Clone it (to not lose information). *)
let J := fresh I in pose proof I as J;
(* 2. apply H. *)
apply H in J;
(* 3. Abort if we already knew the resulting fact. *)
let T := type of J in
match goal with
| [ I1 : T, I2 : T |- _ ] => fail 2
end + idtac;
(* 4. Keep going *)
try (saturate H)
end.
Example:
Require Setoid. (* To get [relation] in scope so the example compiles *)
(* Made the example a little less trivial to better test the backtracking logic. *)
Goal forall (R S : relation nat) (a b c d e f g h : nat),
(forall m n : nat, R m n -> S m n) -> (R a b) -> R c d -> S a b.
Proof.
intros R S a b c d e f g h H1 H2 H3.
(* --- BEFORE ---
H2: R a b
H3: R c d
*)
saturate H1.
(* --- AFTER ---
H2: R a b
H3: R c d
H0: S c d
H4: S a b
*)
assumption.
Qed.

Logic: All_In can't expand nested forall

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.

Minimum in non-empty, finite set

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.

Getting a stronger induction principle in Coq

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.