Zulip Chat Archive

Stream: new members

Topic: Finishing off induction for pigeonhole


Adeeb K (Apr 21 2020 at 01:15):

Hello everyone! I am working on implementing the pigeonhole principle in lean for a school project. I have the following formulation for a finite subset of n elements:

def finite_subset (n : ) := Σ' k, k < n

From this, I have a definition that lifts finite subsets of m elements to any finite subset of more elements:

def lift_finite (m n : ) (p : m < n) : finite_subset m  finite_subset n
    := λ k, k.1, lt.trans k.2 p

and finally a small lemma:

lemma succ_greater_than_nat (n : ) : nat.succ n > n

My formulation for pigeonhole is the following:

theorem pigeonhole_principle
    (n m : )
    (f : finite_subset n  finite_subset m)
: (n > m)  ¬(injective f)

I proceeded by induction and was able to prove the base case but am stuck on the next step. I have this:

intros n_gt_m f_injective,
induction n with d hd,
...  --base case, done
let g := f  (lift_finite d (d+1) (succ_greater_than_nat d)),
let hd' := hd g,

It is enough to show that d > m to get that g cannot be injective, but I have that d + 1 > m, which means that d ≥ m, which is where I'm stuck. Does anybody have any idea how to proceed? Thank you!

Adeeb K (Apr 21 2020 at 01:24):

Oh shoot, I forgot to send the corresponding lean goal at the last line:

m d :  ,
hd :  (f : finite_subset d  finite_subset m), d > m  injective f  false,
f : finite_subset (nat.succ d)  finite_subset m,
n_gt_m : nat.succ d > m
f_injective: injective f
g: finite_subset d  finite_subset m
hd' : d > m  injective g  false := hd g

Bryan Gin-ge Chen (Apr 21 2020 at 01:32):

It'll be easier for us to help you if you include something we can directly copy+paste into our editors (a "minimum working example" or MWE).

Adeeb K (Apr 21 2020 at 01:37):

Sure!

import tactic

def injective {X Y} (f : X  Y)
    :=  x₁ x₂, f x₁ = f x₂  x₁ = x₂

def range {X Y} (f : X  Y)
    := { y |  x, f x = y }

/--
Type of pairs (k,p) where k
is a natural number and p is a witness to the proof that k < n.
-/
def finite_subset (n : ) := Σ' k, k < n

def lift_finite (m n : ) (p : m < n) : finite_subset m  finite_subset n
    := λ k, k.1, lt.trans k.2 p

lemma pred_exists (n : ) (p: n > 0) : exists k, nat.succ k = n
:=
begin
induction n with d hd,
{linarith,},
{
    existsi d,
  refl}
end

lemma succ_greater_than_nat (n : ) : nat.succ n > n
:=
begin
rw nat.succ_eq_add_one,
linarith,
end


/--
Pigeonhole principle, induction on n
-/
theorem pigeonhole_principle
    (n m : )
    (f : finite_subset n  finite_subset m)
: (n > m)  ¬(injective f)
:= begin
    intros n_gt_m f_injective,

    induction n with d hd,

    linarith, -- case d=0

    let g := f  (lift_finite d (d+1) (succ_greater_than_nat d)),

    let hd' := hd g,
    /-
    induction m with d hd,
    {
         cases pred_exists n n_gt_m with k hk,
         let n_gt_k := succ_greater_than_nat k,
         rw hk at n_gt_k,
         let fk := f ⟨k, n_gt_k⟩,
         let fk2 := fk.2,
         linarith,
    },
    {
        let n_gt_d : n>d :=
        begin
            exact lt.trans (succ_greater_than_nat d)  n_gt_m,
        end,
        sorry
    },

    -/
end

Mario Carneiro (Apr 21 2020 at 01:55):

By the way, finite_subset already exists in lean, by the name fin

Mario Carneiro (Apr 21 2020 at 01:56):

similarly with function.injective and set.range

Mario Carneiro (Apr 21 2020 at 01:58):

succ_greater_than_nat is nat.lt_succ_self

Adeeb K (Apr 21 2020 at 01:59):

@Mario Carneiro thanks, got it!

Mario Carneiro (Apr 21 2020 at 01:59):

lift_finite is fin.cast_le (with a different precondition)

Mario Carneiro (Apr 21 2020 at 02:01):

pred_exists is nat.exists_eq_succ_of_ne_zero although the precondition is slightly different

Adeeb K (Apr 21 2020 at 02:05):

thanks again haha!
I guess I have a long ways to go to being acquainted with the libraries.
Is there any library function that would help me resolve my issue with d in the induction step? I can't tell if the problem thus far has to do with a lack of vocabulary of a deeper error into the formulation of the proof

Mario Carneiro (Apr 21 2020 at 02:05):

Unfortunately I'm not a lint but a decent approximation is by library_search, which will find theorems from the library by type

Adeeb K (Apr 21 2020 at 02:06):

oh nice, that's really useful

Adeeb K (Apr 21 2020 at 02:07):

wait, could you give me an example of using library_search?

Mario Carneiro (Apr 21 2020 at 02:08):

What is the role of your commented out block? If I uncomment it I get an error about n not found

Mario Carneiro (Apr 21 2020 at 02:09):

import tactic

lemma pred_exists (n : ) (p: n  0) : exists k, n = nat.succ k := by library_search

Adeeb K (Apr 21 2020 at 02:14):

It was my original attempt at induction on m, but I got stuck with that, so I switch to induction on n

Mario Carneiro (Apr 21 2020 at 02:14):

In your setup you tried to prove d > m from d + 1 > m, which isn't going to work. You can't always rely on the inductive hypothesis because then there would be nothing to the proof. Without thinking too hard about the theorem itself, here you should probably split into cases: either d > m or d = m. In the first case, you can use the inductive hypothesis. In the second case there is something to prove

Adeeb K (Apr 21 2020 at 02:17):

I'm not sure how to split into cases from what I have

Adeeb K (Apr 21 2020 at 02:17):

I mean, I see why, but I'm at a loss at how to do it given my existing work

Mario Carneiro (Apr 21 2020 at 02:19):

theorem pigeonhole_principle (n m : ) (f : finite_subset n  finite_subset m) :
  n > m  ¬ injective f :=
begin
  intros n_gt_m f_injective,
  induction n with d hd,
  { linarith, /- case d=0 -/ },
  let g := f  (lift_finite d (d+1) (succ_greater_than_nat d)),
  let hd' := hd g,
  rcases lt_or_eq_of_le (nat.lt_succ_iff.1 n_gt_m) with h | rfl,
  { apply hd' h,
    sorry /- injective g -/ },
  { sorry /- prove f : finite_subset (nat.succ m) → finite_subset m is not injective -/ }
end

Mario Carneiro (Apr 21 2020 at 02:21):

here lt_or_eq_of_le (nat.lt_succ_iff.1 n_gt_m) is a proof that d > m \/ d = m, and rcases does the case split and replaces d with m in the second branch

Adeeb K (Apr 21 2020 at 02:22):

Also, so d > m means that d + 1 > m by transitivity, so I'm done
for d = m, I'm not sure how to proceed, but my idea is this: there is a clear identity injection from finite_subset d to finite_subset m when d = m. Suppose towards contradiction there is an injection from finite_subset (d + 1) to finite_subset m. We replace d with m, meaning there is an injection from finite_subset (m + 1) to finite_subset m...and I'm stuck from there

Mario Carneiro (Apr 21 2020 at 02:23):

you don't want to prove d + 1 > m from d > m, the proof is going the other way around

Mario Carneiro (Apr 21 2020 at 02:23):

you need d > m and you have d + 1 > m

Adeeb K (Apr 21 2020 at 02:24):

ah I see

Mario Carneiro (Apr 21 2020 at 02:25):

As for proving that there is no injection from m+1 to m, this is indeed the core of the proof, and here you have to step back from the code and ask what the maths proof is

Adeeb K (Apr 21 2020 at 02:27):

what do you mean with rcases replaces d with m in the second branch?

Mario Carneiro (Apr 21 2020 at 02:27):

you will notice in the second branch that d does not exist anymore

Mario Carneiro (Apr 21 2020 at 02:27):

and everywhere there used to be d there is now an m

Mario Carneiro (Apr 21 2020 at 02:28):

which is why f is an injection from m+1 to m instead of d+1 to m

Adeeb K (Apr 21 2020 at 02:29):

I see, but I'm still having a hard time understanding this all. What is the

with h | rfl

Bryan Gin-ge Chen (Apr 21 2020 at 02:30):

You can read more about rcases (and most other tactics) in the mathlib docs here.

Mario Carneiro (Apr 21 2020 at 02:30):

that's a pattern, that describes what kind of case split to do. the | means to do a split on the or, producing an assumption on the left that is being named h, and on the right the rfl means "case split on the equality", doing the replacement of d for m that I mentioned

Adeeb K (Apr 21 2020 at 02:32):

I see. I'll have to take some time to get comfortable with that, but that makes enough sense

Adeeb K (Apr 21 2020 at 02:33):

what does

apply hd' h

do here?

Mario Carneiro (Apr 21 2020 at 02:34):

hd' h is a proof of injection g -> false, so since the goal is false, apply hd' h changes the goal to injection g

Adeeb K (Apr 21 2020 at 02:35):

ah, so my goal here is to show that g is injective?

Mario Carneiro (Apr 21 2020 at 02:35):

yes, and that should be easy enough

Mario Carneiro (Apr 21 2020 at 02:36):

In fact, if you use function.injective and fin.cast_le you will find the theorem already exists :)

Adeeb K (Apr 21 2020 at 02:38):

what if I want to put it in terms of what I've already written though? (just as an exercise in being comfortable with using my own definitions haha)

Mario Carneiro (Apr 21 2020 at 02:38):

It's still an easy proof. Go ahead and try it

Adeeb K (Apr 21 2020 at 02:40):

I'm just sort of confused having all of the hypotheses in front of me. I have that f is injective, and that already takes finite_subset (d + 1) to finite_subset m

Adeeb K (Apr 21 2020 at 02:41):

I'm not sure what tactics I'd use to introduce two variables x1 and x2 and show that if g x1 = g x2, then x1 = x2

Mario Carneiro (Apr 21 2020 at 02:42):

None of that matters

Mario Carneiro (Apr 21 2020 at 02:42):

You can prove that g is injective without anything about f

Mario Carneiro (Apr 21 2020 at 02:42):

theorem lift_finite_injective (m n : ) (p : m < n) : injective (lift_finite m n p) := sorry

Mario Carneiro (Apr 21 2020 at 02:43):

when proving a forall statement, the tactic to introduce variables is intro or intros

Adeeb K (Apr 21 2020 at 02:46):

okay, so here into this new theorem, I'd introduce x1 and x2 right? the arguments are two naturals m, n, and a proof that m < n.

Adeeb K (Apr 21 2020 at 02:47):

so I let f := lift_finite m n p

Adeeb K (Apr 21 2020 at 02:48):

and I have to introduce the proposition that f x1 = f x2?

Adeeb K (Apr 21 2020 at 02:51):

okay, this is what I have so far:

theorem lift_finite_injective (m n : ) (p : m < n) : injective (lift_finite m n p)
:= begin

introv x1 f,
sorry
end

Mario Carneiro (Apr 21 2020 at 04:24):

Does anyone know why the first argument in the introv application here is x1 rather than the equality argument? That seems to go against the documentation of introv

Mario Carneiro (Apr 21 2020 at 04:25):

If you unfold injective first it works correctly

Adeeb K (Apr 21 2020 at 04:28):

my current plan is this:

/- pf sketch

--  suppose f x1 = f x2 = < k, pf: k < n >

--  we know x1 = < l , pf: k < m > and x2 = < j , pf: j < m >

--  note that (f x1).1 = (f x2).1 = k

--  furthermore, k < m < n

--  then x1 = < k, pf: k < m > = x2

--  done
-/

Adeeb K (Apr 21 2020 at 04:28):

I'm just not sure how to translate that into tactics

Mario Carneiro (Apr 21 2020 at 04:34):

you can do this with just cases and refl

Mario Carneiro (Apr 21 2020 at 04:34):

to do this step -- we know x1 = < l , pf: k < m > and x2 = < j , pf: j < m > use cases x1

Adeeb K (Apr 21 2020 at 04:36):

okay, so I do cases x1 and cases x2?

Adeeb K (Apr 21 2020 at 04:37):

how do I note that x1_fst = (f x1).1?

Mario Carneiro (Apr 21 2020 at 04:38):

that's true by definition (it won't be x1 after the cases, it will be <x1_fst, x1_snd>)

Mario Carneiro (Apr 21 2020 at 04:38):

so you don't have to say anything

Adeeb K (Apr 21 2020 at 04:45):

oh so then how can I conclude that x1_fst = x2_fst? I see that clearly x1_fst = (f x1).1 = (f x2).2 = x2_fst but I'm not sure how to type it out

Mario Carneiro (Apr 21 2020 at 04:47):

the easiest way is actually cases on the equality you have

Mario Carneiro (Apr 21 2020 at 04:47):

which is in fact <x1_fst, ...> = <x2_fst, ...>

Adeeb K (Apr 21 2020 at 04:57):

what do you mean with cases here?

Mario Carneiro (Apr 21 2020 at 04:58):

cases f

Mario Carneiro (Apr 21 2020 at 04:59):

the fact that you can do "case analysis" on an equality is one of the more mind bending things you can do in type theory but it's super useful

Adeeb K (Apr 21 2020 at 04:59):

ahhhh I see I see

Adeeb K (Apr 21 2020 at 05:02):

so now I have < x1_fst, x1_snd> = <x1_fst, x2_snd>, and I want to make it so that I have a match

Adeeb K (Apr 21 2020 at 05:02):

would I apply a rw or apply tactic here?

Johan Commelin (Apr 21 2020 at 05:05):

@Adeeb K I haven't been following along... Is that your goal or a hypothesis?

Adeeb K (Apr 21 2020 at 05:06):

I think I got it - I just applied a simple refl and it finished off the proof. Seems I need practice applying the basics. That...and reading more through the HoTT book.

Johan Commelin (Apr 21 2020 at 05:06):

Have you played the natural number game?

Johan Commelin (Apr 21 2020 at 05:07):

It's a great way of practicing the simple tactics

Adeeb K (Apr 21 2020 at 05:07):

only up to the third world

Adeeb K (Apr 21 2020 at 05:16):

now I'm showing composition of injective functions is injective. Not sure how to unpack that, but I'll try it with cases

Adeeb K (Apr 21 2020 at 05:21):

wait, so I still have stuff to finish for pigeonhole

Adeeb K (Apr 21 2020 at 05:22):

what tactic / proof is there to show that (g ∘ f) x = g (f x)?

Kenny Lau (Apr 21 2020 at 05:22):

refl

Adeeb K (Apr 21 2020 at 05:22):

no but like

Adeeb K (Apr 21 2020 at 05:23):

Right now I have:
(g ∘ f) x1 = (g ∘ f) x2

Kenny Lau (Apr 21 2020 at 05:23):

change g (f x1) = g (f x2)

Adeeb K (Apr 21 2020 at 05:23):

How do I rewrite this as:
g (f x1) = g (f x2)?

Adeeb K (Apr 21 2020 at 05:23):

lemme try that

Johan Commelin (Apr 21 2020 at 05:24):

Kenny answers before you write your question.... C'est la vie.

Adeeb K (Apr 21 2020 at 05:24):

I'm getting an error

Adeeb K (Apr 21 2020 at 05:24):

tactic.change failed, given type
  g (f x) = g (f x₂)
is not definitionally equal to
  x = x₂

Johan Commelin (Apr 21 2020 at 05:24):

change allows you to change your goal to anything that is equal to the old goal by definition.

Johan Commelin (Apr 21 2020 at 05:25):

Aah but those two are certainly not the same goals

Johan Commelin (Apr 21 2020 at 05:25):

You need something like g \circ f is injective to do that

Kenny Lau (Apr 21 2020 at 05:25):

change g (f x1) = g (f x2) at H

Adeeb K (Apr 21 2020 at 05:26):

ah nice that worked!

Adeeb K (Apr 21 2020 at 05:27):

okay so now I want to use the injectivity of g to say f x1 = f x2

Johan Commelin (Apr 21 2020 at 05:28):

apply hg

Johan Commelin (Apr 21 2020 at 05:28):

Where hg : injective g

Adeeb K (Apr 21 2020 at 05:28):

error:

invalid apply tactic, failed to unify
  x = x₂
with
  ?m_1 = ?m_2

Johan Commelin (Apr 21 2020 at 05:29):

Aah, right, same problem again...

Adeeb K (Apr 21 2020 at 05:29):

wait

Adeeb K (Apr 21 2020 at 05:29):

one sec

Johan Commelin (Apr 21 2020 at 05:29):

have foo : f x1 = f x2 := hg H

Adeeb K (Apr 21 2020 at 05:30):

I got it

Adeeb K (Apr 21 2020 at 05:30):

I applied injectivity in reverse order and got it

Adeeb K (Apr 21 2020 at 05:30):

p3 : g (f x) = g (f x₂)
 x = x₂

Adeeb K (Apr 21 2020 at 05:31):

I did apply p1 which is injective f

Adeeb K (Apr 21 2020 at 05:31):

Then I got

p3 : g (f x) = g (f x₂)
 f x = f x₂

Adeeb K (Apr 21 2020 at 05:31):

then apply p2 which is injective g

Adeeb K (Apr 21 2020 at 05:31):

p3 : g (f x) = g (f x₂)
 g (f x) = g (f x₂)

Adeeb K (Apr 21 2020 at 05:32):

to which I finally just applied p3 and got my desired result for the lemma

Adeeb K (Apr 21 2020 at 05:32):

with this, the first part of the induction step for pigeonhole is done

Adeeb K (Apr 21 2020 at 05:39):

so uh

Adeeb K (Apr 21 2020 at 05:40):

suppose I have

g :=  f  lift,
inj : injective (f  lift)

Adeeb K (Apr 21 2020 at 05:41):

how do I conclude

inj : injective (g)

?

Mario Carneiro (Apr 21 2020 at 05:42):

I think you want inj : injective (f ∘ lift)?

Mario Carneiro (Apr 21 2020 at 05:42):

If so, then inj : injective g and you don't have to say anything

Adeeb K (Apr 21 2020 at 05:42):

really? right now I'm not sure if I have that

Mario Carneiro (Apr 21 2020 at 05:43):

those two are the same to lean

Adeeb K (Apr 21 2020 at 05:43):

how do I conclude injective g then? refl?

Mario Carneiro (Apr 21 2020 at 05:43):

just pretend it says injective g already

Mario Carneiro (Apr 21 2020 at 05:43):

if your goal is injective g, then exact inj will work

Adeeb K (Apr 21 2020 at 05:44):

ah, yeah it worked

Adeeb K (Apr 21 2020 at 05:44):

now the nontrivial case lol

Adeeb K (Apr 21 2020 at 05:45):

where d = m

Adeeb K (Apr 21 2020 at 06:18):

I'm not exactly sure how to start this part of the proof

Adeeb K (Apr 21 2020 at 06:37):

basically, all classical proofs to show that there's no injection from a set of m + 1 elements to one of m elements I recall end up using the contrapositive

Adeeb K (Apr 21 2020 at 06:38):

well, not all

Johan Commelin (Apr 21 2020 at 06:40):

So... formalise a classical proof...

Adeeb K (Apr 21 2020 at 06:52):

I'm not sure how that'd help me here

Johan Commelin (Apr 21 2020 at 06:52):

Why not? What are you trying to do?

Adeeb K (Apr 21 2020 at 06:55):

suppose towards contradiction that there exists such an injective functionL: call it f
let M be the set of m + 1 elements and N be the set of m elements. We see that |f(M)| = m +1 but |N| = m
it is not possible for f to be injective, since each f(x) \in N for x \in M, but there are fewer possible values for f(x) than there are x

Adeeb K (Apr 21 2020 at 06:55):

So I feel like I'm going in circles restating what I'm out to prove in the first place

Johan Commelin (Apr 21 2020 at 06:58):

Can you post a copy-pasteble chunk of code (include import and variables statements)? AKA an MWE

Adeeb K (Apr 21 2020 at 07:05):

yeah sure

Adeeb K (Apr 21 2020 at 07:05):

import tactic


def injective {X Y} (f : X  Y)
    :=  x₁ x₂, f x₁ = f x₂  x₁ = x₂


def range {X Y} (f : X  Y)
    := { y |  x, f x = y }


/--
Type of pairs (k,p) where k
is a natural number and p is a witness to the proof that k < n.
-/
def finite_subset (n : ) := Σ' k, k < n


def lift_finite (m n : ) (p : m < n) : finite_subset m  finite_subset n
    := λ k, k.1, lt.trans k.2 p


lemma pred_exists (n : ) (p: n > 0) : exists k, nat.succ k = n
:=
begin
induction n with d hd,
{linarith,},
{
    existsi d,
  refl
}
end


lemma succ_greater_than_nat (n : ) : nat.succ n > n
:=
begin
rw nat.succ_eq_add_one,
linarith
end


/--
The lifting function is injective
-/
theorem lift_finite_injective (m n : ) (p : m < n) : injective (lift_finite m n p)
:= begin


/- pf sketch

--  suppose f x1 = f x2 = < k, pf: k < n >

--  we know x1 = < l , pf: k < m > and x2 = < j , pf: j < m >

--  note that (f x1).1 = (f x2).1 = k

--  furthermore, k < m < n

--  then x1 = < k, pf: k < m > = x2

--  done
-/

introv x p2,
cases x,
cases x₂,
cases p2,
refl
end


theorem comp_inj_is_inj
{X Y Z} (f : X  Y) (g : Y  Z)
(p1 : injective f)
(p2 : injective g)
:  injective (g  f)
:= begin

introv x p3,
change g (f x) = g (f x₂) at p3,
apply p1,
apply p2,
apply p3,
end

/--
Pigeonhole principle, induction on n
-/
theorem pigeonhole_principle
    (n m : )
    (f : finite_subset n  finite_subset m)
: (n > m)  ¬(injective f)
:= begin

  intros n_gt_m f_injective,
  induction n with d hd,
  { linarith, /- case d = 0 -/ },

  let succ_for_lift := (succ_greater_than_nat d),
  let lift := (lift_finite d (d+1) succ_for_lift),
  let g := f  lift,
  let hd' := hd g,

  rcases lt_or_eq_of_le (nat.lt_succ_iff.1 n_gt_m) with h | rfl,

  {   /- case where d > m -/
      /- prove injective g -/
    apply hd' h,
    let lift_injective := (lift_finite_injective d (d+1) succ_for_lift),
    let g_injective := comp_inj_is_inj lift f lift_injective f_injective,
    exact g_injective,
  },

  {   /- case where d = m -/
      /- prove f : finite_subset (nat.succ m) → finite_subset m is not injective -/

    sorry
  }

end

Kenny Lau (Apr 21 2020 at 07:06):

first come up with a math proof

Kenny Lau (Apr 21 2020 at 07:06):

then formalize it

Adeeb K (Apr 21 2020 at 07:09):

alright
It's pretty late where I am, so I'll be heading to bed for now. Thank you everyone for your help!

Adeeb K (Apr 21 2020 at 07:09):

I'll be back in a few hours probably

Patrick Stevens (Apr 21 2020 at 07:44):

Adeeb K said:

basically, all classical proofs to show that there's no injection from a set of m + 1 elements to one of m elements I recall end up using the contrapositive

I wrote a constructive one in Agda a while back. Hint for the maths proof: if you have an injection f: [m+1] -> [m], consider that f sends 1 somewhere, and note that you must use induction because it's a constructively-true thing about the natural numbers. State the inductive hypothesis, and try to use it.

Adeeb K (Apr 21 2020 at 17:54):

I see

Adeeb K (Apr 21 2020 at 17:55):

I am already using induction here, and this is the second case that I'm handling
I'll send what I currently have

Adeeb K (Apr 21 2020 at 17:56):

import tactic


def injective {X Y} (f : X  Y)
    :=  x₁ x₂, f x₁ = f x₂  x₁ = x₂


def range {X Y} (f : X  Y)
    := { y |  x, f x = y }


/--
Type of pairs (k,p) where k
is a natural number and p is a witness to the proof that k < n.
-/
def finite_subset (n : ) := Σ' k, k < n


def lift_finite (m n : ) (p : m < n) : finite_subset m  finite_subset n
    := λ k, k.1, lt.trans k.2 p


lemma pred_exists (n : ) (p: n > 0) : exists k, nat.succ k = n
:=
begin
induction n with d hd,
{linarith,},
{
    existsi d,
  refl
}
end


lemma succ_greater_than_nat (n : ) : nat.succ n > n
:=
begin
rw nat.succ_eq_add_one,
linarith
end


/--
The lifting function is injective
-/
theorem lift_finite_injective (m n : ) (p : m < n) : injective (lift_finite m n p)
:= begin


/- pf sketch

--  suppose f x1 = f x2 = < k, pf: k < n >

--  we know x1 = < l , pf: k < m > and x2 = < j , pf: j < m >

--  note that (f x1).1 = (f x2).1 = k

--  furthermore, k < m < n

--  then x1 = < k, pf: k < m > = x2

--  done
-/

introv x p2,
cases x,
cases x₂,
cases p2,
refl
end


theorem comp_inj_is_inj
{X Y Z} (f : X  Y) (g : Y  Z)
(p1 : injective f)
(p2 : injective g)
:  injective (g  f)
:= begin

introv x p3,
change g (f x) = g (f x₂) at p3,
apply p1,
apply p2,
apply p3,
end

/--
Pigeonhole principle, induction on n
-/
theorem pigeonhole_principle
    (n m : )
    (f : finite_subset n  finite_subset m)
: (n > m)  ¬(injective f)
:= begin

  intros n_gt_m f_injective,
  induction n with d hd,
  { linarith, /- case d = 0 -/ },

  let succ_for_lift := (succ_greater_than_nat d),
  let lift := (lift_finite d (d+1) succ_for_lift),
  let g := f  lift,
  let hd' := hd g,

  rcases lt_or_eq_of_le (nat.lt_succ_iff.1 n_gt_m) with h | rfl,

  {   /- case where d > m -/
      /- prove injective g -/
    apply hd' h,
    let lift_injective := (lift_finite_injective d (d+1) succ_for_lift),
    let g_injective := comp_inj_is_inj lift f lift_injective f_injective,
    exact g_injective,
  },

  {   /- case where d = m -/
      /- prove f : finite_subset (nat.succ m) → finite_subset m is not injective -/

    sorry
  }

end

Adeeb K (Apr 21 2020 at 18:08):

So going off @Patrick Stevens 's advice, I have injective f : [m + 1] → [m]. I have set up finite sets finite_subset m to be all pairs <k, pf: k < m>. We consider f([m + 1]). Since f is injective, we know that for distinct x1, x2 : finite_subset (m + 1)``, if f x1 = f x2 then x1 = x2```.

Adeeb K (Apr 21 2020 at 18:11):

We consider the image of f. By my current inductive hypothesis, I have

hd :  (f : finite_subset m  finite_subset m), m > m  injective f  false,

Adeeb K (Apr 21 2020 at 18:14):

I'm not sure if I should consider the image or the pre-image here.

Kenny Lau (Apr 21 2020 at 18:14):

m > m is false

Adeeb K (Apr 21 2020 at 18:15):

I realize that much, so what does that give me?

Reid Barton (Apr 21 2020 at 18:15):

Nothing

Kenny Lau (Apr 21 2020 at 18:16):

you should write down a maths proof first

Adeeb K (Apr 21 2020 at 18:17):

I'm just figuring out how to word a constructive proof for pigeonhole

Kenny Lau (Apr 21 2020 at 18:19):

it doesn't need to be constructive

Kenny Lau (Apr 21 2020 at 18:19):

you just need to make sure that it isn't circular

Adeeb K (Apr 21 2020 at 18:20):

Alright, makes sense

Adeeb K (Apr 21 2020 at 18:26):

quick question

Kenny Lau (Apr 21 2020 at 18:26):

quick answer

Adeeb K (Apr 21 2020 at 18:27):

just something I forgot to ask last night: is there a function in the library that lets me say a natural number is either 0 or not?

Kenny Lau (Apr 21 2020 at 18:27):

cases n

Adeeb K (Apr 21 2020 at 18:28):

gotcha thanks

Kenny Lau (Apr 21 2020 at 18:29):

how about you write down a maths proof first before touching Lean

Adeeb K (Apr 21 2020 at 18:29):

yeah I'm on that right now - this was just something I forgot

Kenny Lau (Apr 21 2020 at 18:35):

Kenny Lau (Apr 21 2020 at 18:35):

see i answered before you asked

Kenny Lau (Apr 21 2020 at 18:35):

from your point of view you'd probably say that i answered after you asked

Kenny Lau (Apr 21 2020 at 18:36):

this has been a demonstration of the relativity of simultaneity in Einstein's theory of relativity

Kenny Lau (Apr 21 2020 at 18:36):

whaddup I'm Kenny I'm (age removed) and I'm a physicist

Kenny Lau (Apr 21 2020 at 18:37):

(nobody will get this reference)

Adeeb K (Apr 21 2020 at 19:03):

Okay I believe I have something

Adeeb K (Apr 21 2020 at 19:04):

We want to show that there exists no injection f : [m + 1] → [m], where [m] here denotes the set {0, 1, ..., m - 1}.

Adeeb K (Apr 21 2020 at 19:06):

we proceed by induction. The base case m = 0 is clear since if we suppose not, we end up with f(0) = f(1) = 0, which is a contradiction.

Kenny Lau (Apr 21 2020 at 19:07):

[0] is empty, not {0}

Kevin Buzzard (Apr 21 2020 at 19:07):

The case m=0 is clear because there are no functions [1]->[0], injective or not

Adeeb K (Apr 21 2020 at 19:11):

Now, we know that there is no injective f : [m] → [m - 1] and want to show this for f : [m + 1] → [m], where [m]. Suppose not, to which we assume there exists such f. We know that f(m) = k for some k < m. Then we consider the restriction of f to [m]. By injectivity we know that if for any j in {0, ..., m}, f j = f k → j = k. So when we restrict f, the image of the function lives in [m - 1]. However, by our inductive hypothesis, there is no injective function that maps [m] to [m - 1]. Contradiction.

Adeeb K (Apr 21 2020 at 19:14):

I see a small problem.

Adeeb K (Apr 21 2020 at 19:16):

I know that f(m) = k, but I don't know if k = m - 1, which means I know that the restriction of f to [m] must necessarily map to a set of only m - 1 elements, but they may not all 'live' in [m - 1] unless I relabel them.

Adeeb K (Apr 21 2020 at 19:23):

So, does this suggest I can't use the idea of restrictions?

Kenny Lau (Apr 21 2020 at 19:23):

this suggests you relabel them

Adeeb K (Apr 21 2020 at 19:23):

That's the first thing that came to mind to use an inductive hypothesis

Adeeb K (Apr 21 2020 at 19:23):

oh

Adeeb K (Apr 21 2020 at 19:25):

I'm not exactly sure how to do that. How do I know a priori that I have a collection of size m - 1 if I only have that they are type finite_subset (m + 1)?

Adeeb K (Apr 21 2020 at 19:26):

I have some vague idea that relabelling itself is an injective function

Adeeb K (Apr 21 2020 at 19:27):

if we have some number k that sits in {0, 1, ..., m}, then my relabelling function would basically this:
for all j < k, j maps to j + 1. Otherwise, if j > k, then j maps to j.

Adeeb K (Apr 21 2020 at 19:28):

wait shoot that's backwards

Adeeb K (Apr 21 2020 at 19:28):

it should be:
for all j > k, j maps to j - 1. Otherwise, if j < k, then it is mapped to itself.

Adeeb K (Apr 21 2020 at 19:29):

call this function relabel. We can show it is injective.

Adeeb K (Apr 21 2020 at 19:31):

and so when we restrict f to [m], and relabel, we should have an injective function relabel ∘ f : [m] → [m - 1]

Adeeb K (Apr 21 2020 at 19:32):

which is a contradiction. Is there anything I missed?

Kenny Lau (Apr 21 2020 at 19:34):

relabel itself isn't injective (let's say you send k to k)

Kenny Lau (Apr 21 2020 at 19:34):

but relabel \o f is injective

Kenny Lau (Apr 21 2020 at 19:34):

other than that, LGTM

Kenny Lau (Apr 21 2020 at 19:34):

oh and you implicitly restricted f to [m] I guess

Adeeb K (Apr 21 2020 at 19:35):

yeah I'm not exactly sure how to carry out restriction

Kenny Lau (Apr 21 2020 at 19:35):

compose it with [m] -> [m+1]

Kenny Lau (Apr 21 2020 at 19:35):

relabel o f o lift

Adeeb K (Apr 21 2020 at 19:36):

I see I see

Adeeb K (Apr 21 2020 at 19:36):

wait, so then what does relabel's function signature become?

Kenny Lau (Apr 21 2020 at 19:36):

relabel : [m] -> [m-1]

Kenny Lau (Apr 21 2020 at 19:36):

f: [m+1] -> [m]

Kenny Lau (Apr 21 2020 at 19:36):

lift: [m] -> [m+1]

Adeeb K (Apr 21 2020 at 19:37):

ah so this is exactly why I can't say relabel is injective, but relabel composed with an injective function is in fact injective?

Kenny Lau (Apr 21 2020 at 19:38):

no, it's because f o lift misses k that relabel k o f o lift is injective

Adeeb K (Apr 21 2020 at 19:39):

ah gotcha

Adeeb K (Apr 21 2020 at 19:40):

...stupid question, but how would I define this in lean?

Adeeb K (Apr 21 2020 at 19:41):

relabel, that is. I'm not sure how to give cases for j < k and j > k.

Kenny Lau (Apr 21 2020 at 19:41):

don't forget k

Kenny Lau (Apr 21 2020 at 19:41):

if j \le k then j else j-1

Adeeb K (Apr 21 2020 at 19:42):

ah gotcha gotcha.

Adeeb K (Apr 21 2020 at 19:47):

I'm getting some errors

Adeeb K (Apr 21 2020 at 19:47):

here's what I have for relabel so far

Adeeb K (Apr 21 2020 at 19:47):

def relabel_finite_set
(m k : )
(p: k < m)
: finite_subset m  finite_subset (m - 1)
:= λ j, if j.1  k then j.1, lt.trans j.1 p else j.1 - 1, lt.trans j.1 p

Adeeb K (Apr 21 2020 at 19:47):

but I have this error in both tuples:

type mismatch at application
  lt.trans j.fst
term
  j.fst
has type
   : Type
but is expected to have type
  j.fst < ?m_1 : Prop

Kenny Lau (Apr 21 2020 at 19:48):

read the error

Kevin Buzzard (Apr 21 2020 at 19:48):

Looks like lean wanted j.2

Kevin Buzzard (Apr 21 2020 at 19:49):

Or maybe it's called j.is_lt or something

Adeeb K (Apr 21 2020 at 19:49):

I have this then:

type mismatch at application
  lt.trans j.snd p
term
  p
has type
  k < m
but is expected to have type
  m < m - 1

Kevin Buzzard (Apr 21 2020 at 19:49):

It's going to be hard to come up with something of that type

Kenny Lau (Apr 21 2020 at 19:49):

if H : j.1 \le k

Adeeb K (Apr 21 2020 at 19:50):

how would I compose that with p to get j < m - 1?

Adeeb K (Apr 21 2020 at 19:54):

I'm not sure how to use H here

Adeeb K (Apr 26 2020 at 22:42):

Hello guys, and thanks for all the help from last time!

Adeeb K (Apr 26 2020 at 22:43):

I'm not sure if I should make a new topic or just get this post up to speed with my progress

Adeeb K (Apr 26 2020 at 22:44):

Basically, I've got pigeonhole done after assuming a few sorry's in my helper functions, but I am having trouble showing that (relabel m k p) ∘ f ∘ lift is an injective function

Adeeb K (Apr 26 2020 at 22:49):

ah I'll just make a new thread entirely since this is a separate issue.


Last updated: Dec 20 2023 at 11:08 UTC