← back to lean navigator

Pigeonhole.lean

ghView source on GitHub

Proves the pigeonhole principle from scratch: you cannot injectively map n+1 items into n slots, so at least two must collide.

compress

A helper that removes one element from Fin (n+1), compressing the remaining elements into Fin n. Elements below the removed value keep their index; elements above shift down by 1.

private def compress {n : Nat} (v x : Fin (n + 1)) (h : x ≠ v) : Fin n :=
  if hlt : x.val < v.val then
    ⟨x.val, by omega⟩
  else
    ⟨x.val - 1, by ...⟩

Fin.no_injection

There is no injective function from Fin (n+1) to Fin n. Proved by induction on n with element removal at each step.

theorem Fin.no_injection (n : Nat)
    : ∀ g : Fin (n + 1) → Fin n, ¬ Function.Injective g

Base case: Fin 1 → Fin 0 is impossible since Fin 0 is empty. Inductive step: given g : Fin (k+2) → Fin (k+1), remove the image of the last element from the codomain. The compressed function g' : Fin (k+1) → Fin k inherits injectivity, contradicting the induction hypothesis.

pigeonhole

Among N+1 values in Fin N, at least two must collide. The collision gives specific indices i < j where f i = f j.

theorem pigeonhole {N : Nat} (f : Fin (N + 1) → Fin N)
    : &exists; i j : Fin (N + 1), i < j ∧ f i = f j

Uses Fin.no_injection by contradiction: if no collision existed, f would be injective, which is impossible.

Python

pigeonhole_nat

A convenience wrapper for Nat-indexed sequences: among values f(0), ..., f(N), at least two in Fin N must collide.

Connections

Neighbors