Minimum in non-empty, finite set - coq

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.

Related

Check less or equal natural number in coq

I have function (beq_nat_refl) which determines the equality of two natural numbers and gives a boolean. But now I want to prove a lemma stating that a natural number x is less or equal to x.
May I use the above function (beq_nat_refl)?
Theorem beq_nat_refl :
forall n : nat,
true = beq_nat n n.
Theorem leq_nat :
forall x:nat,
x <= x.
That would work if you would define x <= y as x < y || x == y; however this is not the definition, so usually the proof of x <= x tends to be induction [on the computational case] or by applying the base constructor if using a witness.
Here is a straightforward path to proving leq_nat from similar definitions:
Fixpoint leb (n m : nat) : bool :=
match n, m with
| 0 , _ => true
| _ , 0 => false
| S n, S m => leb n m
end.
Lemma leb_nat_refl : forall (n : nat), leb n n = true.
Proof.
induction n; simpl.
+ reflexivity.
+ assumption.
Qed.
Lemma leb_nat_reflect : forall (n : nat), leb n n = true <-> n <= n.
Proof.
induction n; simpl; split; intros.
+ constructor.
+ reflexivity.
+ constructor.
+ apply IHn. constructor.
Qed.
Theorem leq_nat : forall (n : nat), n <= n.
Proof.
intros.
apply leb_nat_reflect.
apply leb_nat_refl.
Qed.

I want to prove some properties about list, but am stuck at induction

I tried following proof,
Require Import List Omega.
Import ListNotations.
Variable X : Type.
Lemma length_n_nth_app_error_same : forall (n:nat) (x:X) (l:list X),
n <= length l -> 0 < n -> nth_error l n = nth_error (l ++ [x]) n .
Proof.
intros.
induction l eqn:eqHl.
- unfold length in H. omega.
-
but I'm stuck, as what I have is only
1 subgoal
n : nat
x : X
l : list X
a : X
l0 : list X
eqHl : l = a :: l0
H : n <= length (a :: l0)
H0 : 0 < n
IHl0 : l = l0 ->
n <= length l0 ->
nth_error l0 n = nth_error (l0 ++ [x]) n
______________________________________(1/1)
nth_error (a :: l0) n = nth_error ((a :: l0) ++ [x]) n
I've met some similar cases also for other proofs on lists.
I don't know if the usual induction would be useful here.
How should I prove this?
Should I use generalize?
Your theorem is wrong. Maybe your understanding of nth_error is incorrect.
Specifically, when n = length l, nth_error l n returns None while nth_error (l ++ [x]) n returns Some x.
Require Import List Omega.
Import ListNotations.
Lemma length_n_nth_app_error_not_always_same :
(forall (n:nat) (X:Type) (x:X) (l:list X),
n <= length l -> 0 < n -> nth_error l n = nth_error (l ++ [x]) n)
-> False.
Proof.
intros.
assert (1 <= 1) by omega. assert (0 < 1) by omega.
specialize (H 1 nat 2 [1] H0 H1). simpl in H. inversion H. Qed.
On the other hand, proving a similar theorem with fixed inequality is easy:
Lemma length_n_nth_app_error_same : forall (n:nat) (X:Type) (x:X) (l:list X),
n < length l -> nth_error l n = nth_error (l ++ [x]) n .
Proof.
induction n; intros.
- simpl. destruct l; simpl in *.
+ omega.
+ reflexivity.
- simpl. destruct l; simpl in *.
+ omega.
+ apply IHn. omega. Qed.
Note that I used induction n instead of induction l. It is mainly because nth_error does recursive calls on decreasing n.
Also, if you felt like an induction hypothesis is not general enough, it is probably because your order of intros and induction was wrong. The rule of thumb is to start the proof by induction, and then intros the variables. If it is still not enough, you can revert dependent all the variables other than the one to do induction, and then induction x; intros.

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.

Stuck proving lemma with unprovable subgoals

I'm trying to prove a lemma that's based on the following definitions.
Section lemma.
Variable A : Type.
Variable P : A -> Prop.
Variable P_dec : forall x, {P x}+{~P x}.
Inductive vector : nat -> Type :=
| Vnil : vector O
| Vcons : forall {n}, A -> vector n -> vector (S n).
Arguments Vcons {_} _ _.
Fixpoint countPV {n: nat} (v : vector n): nat :=
match v with
| Vnil => O
| Vcons x v' => if P_dec x then S (countPV v') else countPV v'
end.
The lemma I'm trying to prove is as follows
Lemma lem: forall (n:nat) (a:A) (v:vector n),
S n = countPV (Vcons a v) -> (P a /\ n = countPV v).
I've tried a lot of things and currently I'm at this point.
Proof.
intros n a v.
unfold not in P_dec.
simpl.
destruct P_dec.
- intros.
split.
* exact p.
* apply eq_add_S.
exact H.
- intros.
split.
The context at this point:
2 subgoals
A : Type
P : A -> Prop
P_dec : forall x : A, {P x} + {P x -> False}
n : nat
a : A
v : vector n
f : P a -> False
H : S n = countPV v
______________________________________(1/2)
P a
______________________________________(2/2)
n = countPV v
My issue is that I seem to be stuck with two subgoals that I can not prove and the available context does not seem to be helpful. Can anyone provide me with some pointers to move on?
EDIT:
I've proven the lemma by contradicting H:
assert (countPV v <= n).
* apply countNotBiggerThanConstructor.
* omega.
Qed.
where countNotBiggerThanConstructor is:
Lemma countNotBiggerThanConstructor: forall {n : nat} (v: vector n), countPV v <= n.
Proof.
intros n v.
induction v.
- reflexivity.
- simpl.
destruct P_dec.
+ apply le_n_S in IHv.
assumption.
+ apply le_S.
assumption.
Qed.
Notice that H can't possibly be true. That is a good thing, if you can prove False, you can prove anything. So I would do contradict H next (and you don't need that last split).
Overall your proof seems a little messy to me. I suggest thinking about how you would prove this lemma on paper and trying to do that in Coq. I am not an expert in Coq, but I think it would also help you realize, that you need to use contradiction in this case.
(Edit: BTW other answers suggesting that this lemma does not hold are wrong, but I can't comment with my 1 reputation)

How to do induction differently?

I am doing an exercise in Coq and trying to prove if a list equals to its reverse, it's a palindrome. Here is how I define palindromes:
Inductive pal {X : Type} : list X -> Prop :=
| emptypal : pal []
| singlpal : forall x, pal [x]
| inducpal : forall x l, pal l -> pal (x :: l ++ [x]).
Here is the theorem:
Theorem palindrome3 : forall {X : Type} (l : list X),
l = rev l -> pal l.
According to my definition, I will need to do the induction my extracting the front and tail element but apparently coq won't let me do it, and if I force it to do so, it gives an induction result that definitely doesn't make any sense:
Proof.
intros X l H. remember (rev l) as rl. induction l, rl.
- apply emptypal.
- inversion H.
- inversion H.
- (* stuck *)
context:
1 subgoals
X : Type
x : X
l : list X
x0 : X
rl : list X
Heqrl : x0 :: rl = rev (x :: l)
H : x :: l = x0 :: rl
IHl : x0 :: rl = rev l -> l = x0 :: rl -> pal l
______________________________________(1/1)
pal (x :: l)
aparently the inductive context is terribly wrong. is there any way I can fix the induction?
The solution I propose here is probably not the shortest one, but I think it is rather natural.
My solution consists in defining an induction principle on list specialized to your problem.
Consider natural numbers. There is not only the standard induction nat_ind where you prove P 0 and forall n, P n -> P (S n). But there are other induction schemes, e.g., the strong induction lt_wf_ind, or the two-step induction where you prove P 0, P 1 and forall n, P n -> P (S (S n)). If the standard induction scheme is not strong enough to prove the property you want, you can try another one.
We can do the same for lists. If the standard induction scheme list_ind is not enough, we can write another one that works. In this idea, we define for lists an induction principle similar to the two-step induction on nat (and we will prove the validity of this induction scheme using the two-step induction on nat), where we need to prove three cases: P [], forall x, P [x] and forall x l x', P l -> P (x :: l ++ [x']). The proof of this scheme is the difficult part. Applying it to deduce your theorem is quite straightforward.
I don't know if the two-step induction scheme is part of the standard library, so I introduce it as an axiom.
Axiom nat_ind2 : forall P : nat -> Prop, P 0 -> P 1 ->
(forall n : nat, P n -> P (S (S n))) -> forall n : nat, P n.
Then we prove the induction scheme we want.
Lemma list_ind2 : forall {A} (P : list A -> Prop) (P_nil : P [])
(P_single : forall x, P [x])
(P_cons_snoc : forall x l x', P l -> P (x :: l ++ [x'])),
forall l, P l.
Proof.
intros. remember (length l) as n. symmetry in Heqn. revert dependent l.
induction n using nat_ind2; intros.
- apply length_zero_iff_nil in Heqn. subst l. apply P_nil.
- destruct l; [discriminate|]. simpl in Heqn. inversion Heqn; subst.
apply length_zero_iff_nil in H0. subst l. apply P_single.
- destruct l; [discriminate|]. simpl in Heqn.
inversion Heqn; subst. pose proof (rev_involutive l) as Hinv.
destruct (rev l). destruct l; discriminate. simpl in Hinv. subst l.
rewrite app_length in H0.
rewrite PeanoNat.Nat.add_comm in H0. simpl in H0. inversion H0.
apply P_cons_snoc. apply IHn. assumption.
Qed.
You should be able to conclude quite easily using this induction principle.
Theorem palindrome3 : forall {X : Type} (l : list X),
l = rev l -> pal l.