Minimum in non-empty, finite set
Asked Answered
L

3

5

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.

Lamprey answered 21/5, 2018 at 9:42 Comment(0)
L
0

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.
Lamprey answered 23/5, 2018 at 16:19 Comment(0)
T
3
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.
Tetragon answered 21/5, 2018 at 13:2 Comment(1)
I am sorry, but this is a part of the proof I did. What I cannot do is, proving, that your f (my f') exists, that has the same values as my old f.Lamprey
D
3

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.
Delight answered 21/5, 2018 at 15:39 Comment(2)
Your proof works, but my Coq-skills are way too low, to map your solution onto mine. I guess 'I_n.+1 is semantically the same as {m : nat | m < n /\ n > 0} (the Coq-notation I know). Is there a way to show this?Lamprey
First note that the proof is just an application of the natural-numbers lemma ex_minnP, in the ssrnat library. As for the notation, 'I_n is indeed { x | x < n }, but in this case < is a boolean less-than operator. Thus, 'I_n.+1 is notation for { x | x < S n } that guarantees that the type is not empty as x := 0 is a solution.Delight
L
0

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.
Lamprey answered 23/5, 2018 at 16:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.