Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(data/fintype/card_embedding): the birthday problem (#7363)
Co-authored-by: Eric <37984851+ericrbg@users.noreply.github.com>
- Loading branch information
Showing
9 changed files
with
292 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/- | ||
Copyright (c) 2021 Eric Rodriguez. All rights reserved. | ||
Released under Apache 2.0 license as described in the file LICENSE. | ||
Authors: Eric Rodriguez | ||
-/ | ||
import data.fintype.card_embedding | ||
|
||
/-! | ||
# Birthday Problem | ||
This file proves Theorem 93 from the [100 Theorems List](https://www.cs.ru.nl/~freek/100/). | ||
As opposed to the standard probabilistic statement, we instead state the birthday problem | ||
in terms of injective functions. The general result about `fintype.card (α ↪ β)` which this proof | ||
uses is `fintype.card_embedding`. | ||
-/ | ||
|
||
local notation `‖` x `‖` := fintype.card x | ||
|
||
theorem birthday : | ||
2 * ‖fin 23 ↪ fin 365‖ < ‖fin 23 → fin 365‖ ∧ 2 * ‖fin 22 ↪ fin 365‖ > ‖fin 22 → fin 365‖ := | ||
by split; norm_num [nat.desc_fac] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/- | ||
Copyright (c) 2021 Eric Rodriguez. All rights reserved. | ||
Released under Apache 2.0 license as described in the file LICENSE. | ||
Authors: Eric Rodriguez | ||
-/ | ||
import logic.embedding | ||
import data.set.lattice | ||
|
||
/-! | ||
# Equivalences on embeddings | ||
This file shows some advanced equivalences on embeddings, useful for constructing larger | ||
embeddings from smaller ones. | ||
-/ | ||
|
||
open function.embedding | ||
|
||
namespace equiv | ||
|
||
/-- Embeddings from a sum type are equivalent to two separate embeddings with disjoint ranges. -/ | ||
def sum_embedding_equiv_prod_embedding_disjoint {α β γ : Type*} : | ||
((α ⊕ β) ↪ γ) ≃ {f : (α ↪ γ) × (β ↪ γ) // disjoint (set.range f.1) (set.range f.2)} := | ||
{ to_fun := λ f, ⟨(inl.trans f, inr.trans f), | ||
begin | ||
rintros _ ⟨⟨a, h⟩, ⟨b, rfl⟩⟩, | ||
simp only [trans_apply, inl_apply, inr_apply] at h, | ||
have : sum.inl a = sum.inr b := f.injective h, | ||
simp only at this, | ||
assumption | ||
end⟩, | ||
inv_fun := λ ⟨⟨f, g⟩, disj⟩, | ||
⟨λ x, match x with | ||
| (sum.inl a) := f a | ||
| (sum.inr b) := g b | ||
end, | ||
begin | ||
rintros (a₁|b₁) (a₂|b₂) f_eq; | ||
simp only [equiv.coe_fn_symm_mk, sum.elim_inl, sum.elim_inr] at f_eq, | ||
{ rw f.injective f_eq }, | ||
{ simp! only at f_eq, exfalso, exact disj ⟨⟨a₁, by simp⟩, ⟨b₂, by simp [f_eq]⟩⟩ }, | ||
{ simp! only at f_eq, exfalso, exact disj ⟨⟨a₂, by simp⟩, ⟨b₁, by simp [f_eq]⟩⟩ }, | ||
{ rw g.injective f_eq } | ||
end⟩, | ||
left_inv := λ f, by { dsimp only, ext, cases x; simp! }, | ||
right_inv := λ ⟨⟨f, g⟩, _⟩, by { simp only [prod.mk.inj_iff], split; ext; simp! } } | ||
|
||
/-- Embeddings whose range lies within a set are equivalent to embeddings to that set. | ||
This is `function.embedding.cod_restrict` as an equiv. -/ | ||
def cod_restrict (α : Type*) {β : Type*} (bs : set β) : | ||
{f : α ↪ β // ∀ a, f a ∈ bs} ≃ (α ↪ bs) := | ||
{ to_fun := λ f, (f : α ↪ β).cod_restrict bs f.prop, | ||
inv_fun := λ f, ⟨f.trans (function.embedding.subtype _), λ a, (f a).prop⟩, | ||
left_inv := λ x, by ext; refl, | ||
right_inv := λ x, by ext; refl } | ||
|
||
/-- Pairs of embeddings with disjoint ranges are equivalent to a dependent sum of embeddings, | ||
in which the second embedding cannot take values in the range of the first. -/ | ||
def prod_embedding_disjoint_equiv_sigma_embedding_restricted {α β γ : Type*} : | ||
{f : (α ↪ γ) × (β ↪ γ) // disjoint (set.range f.1) (set.range f.2)} ≃ | ||
(Σ f : α ↪ γ, β ↪ ↥((set.range f)ᶜ)) := | ||
(subtype_prod_equiv_sigma_subtype $ | ||
λ (a : α ↪ γ) (b : β ↪ _), disjoint (set.range a) (set.range b)).trans $ | ||
equiv.sigma_congr_right $ λ a, | ||
(subtype_equiv_prop begin | ||
ext f, | ||
rw [←set.range_subset_iff, set.subset_compl_iff_disjoint], | ||
exact disjoint.comm.trans disjoint_iff, | ||
end).trans (cod_restrict _ _) | ||
|
||
/-- A combination of the above results, allowing us to turn one embedding over a sum type | ||
into two dependent embeddings, the second of which avoids any members of the range | ||
of the first. This is helpful for constructing larger embeddings out of smaller ones. -/ | ||
def sum_embedding_equiv_sigma_embedding_restricted {α β γ : Type*} : | ||
((α ⊕ β) ↪ γ) ≃ (Σ f : α ↪ γ, β ↪ ↥((set.range f)ᶜ)) | ||
:= equiv.trans sum_embedding_equiv_prod_embedding_disjoint | ||
prod_embedding_disjoint_equiv_sigma_embedding_restricted | ||
|
||
/-- Embeddings from a single-member type are equivalent to members of the target type. -/ | ||
def unique_embedding_equiv_result {α β : Type*} [unique α] : (α ↪ β) ≃ β := | ||
{ to_fun := λ f, f (default α), | ||
inv_fun := λ x, ⟨λ _, x, λ _ _ _, subsingleton.elim _ _⟩, | ||
left_inv := λ _, by { ext, simp_rw [function.embedding.coe_fn_mk], congr }, | ||
right_inv := λ _, by simp } | ||
|
||
end equiv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/- | ||
Copyright (c) 2021 Eric Rodriguez. All rights reserved. | ||
Released under Apache 2.0 license as described in the file LICENSE. | ||
Authors: Eric Rodriguez | ||
-/ | ||
import data.fintype.card | ||
import data.equiv.fin | ||
import data.equiv.embedding | ||
|
||
/-! | ||
# Birthday Problem | ||
This file establishes the cardinality of `α ↪ β` in full generality. | ||
-/ | ||
|
||
local notation `|` x `|` := finset.card x | ||
local notation `‖` x `‖` := fintype.card x | ||
|
||
open_locale nat | ||
|
||
namespace fintype | ||
|
||
-- We need the separate `fintype α` instance as it contains data, | ||
-- and may not match definitionally with the instance coming from `unique.fintype`. | ||
lemma card_embedding_of_unique | ||
{α β : Type*} [unique α] [fintype α] [fintype β] [decidable_eq α] [decidable_eq β]: | ||
‖α ↪ β‖ = ‖β‖ := card_congr equiv.unique_embedding_equiv_result | ||
|
||
private lemma card_embedding_aux (n : ℕ) (β) [fintype β] [decidable_eq β] (h : n ≤ ‖β‖) : | ||
‖fin n ↪ β‖ = nat.desc_fac (‖β‖ - n) n := | ||
begin | ||
induction n with n hn, | ||
{ nontriviality (fin 0 ↪ β), | ||
rw [nat.desc_fac_zero, fintype.card_eq_one_iff], | ||
refine ⟨nonempty.some nontrivial.to_nonempty, λ x, function.embedding.ext fin.elim0⟩ }, | ||
|
||
rw [nat.succ_eq_add_one, ←card_congr (equiv.embedding_congr fin_sum_fin_equiv (equiv.refl β))], | ||
rw card_congr equiv.sum_embedding_equiv_sigma_embedding_restricted, | ||
-- these `rw`s create goals for instances, which it doesn't infer for some reason | ||
all_goals { try { apply_instance } }, -- however, this needs to be done here instead of at the end | ||
-- else, a later `simp`, which depends on the `fintype` instance, won't work. | ||
|
||
have : ∀ (f : fin n ↪ β), ‖fin 1 ↪ ↥((set.range f)ᶜ)‖ = ‖β‖ - n, | ||
{ intro f, | ||
rw card_embedding_of_unique, | ||
rw card_of_finset' (finset.map f finset.univ)ᶜ, | ||
{ rw [finset.card_compl, finset.card_map, finset.card_fin] }, | ||
{ simp } }, | ||
|
||
-- putting `card_sigma` in `simp` causes it not to fully simplify | ||
rw card_sigma, | ||
simp only [this, finset.sum_const, finset.card_univ, nsmul_eq_mul, nat.cast_id], | ||
|
||
replace h := nat.lt_of_succ_le h, | ||
rw [hn h.le, mul_comm, nat.desc_fac_of_sub h] | ||
end | ||
|
||
variables {α β : Type*} [fintype α] [fintype β] [decidable_eq α] [decidable_eq β] | ||
|
||
/- Establishes the cardinality of the type of all injections, if any exist. -/ | ||
@[simp] theorem card_embedding (h : ‖α‖ ≤ ‖β‖) : ‖α ↪ β‖ = (nat.desc_fac (‖β‖ - ‖α‖) ‖α‖) := | ||
begin | ||
trunc_cases fintype.trunc_equiv_fin α with eq, | ||
rw fintype.card_congr (equiv.embedding_congr eq (equiv.refl β)), | ||
exact card_embedding_aux _ _ h, | ||
end | ||
|
||
/-- If `‖β‖ < ‖α‖` there are no embeddings `α ↪ β`. | ||
This is a formulation of the pigeonhole principle. -/ | ||
@[simp] theorem card_embedding_eq_zero (h : ‖β‖ < ‖α‖) : ‖α ↪ β‖ = 0 := | ||
card_eq_zero_iff.mpr $ function.embedding.is_empty_of_card_lt h | ||
|
||
theorem card_embedding_eq_if : ‖α ↪ β‖ = if ‖α‖ ≤ ‖β‖ then nat.desc_fac (‖β‖ - ‖α‖) ‖α‖ else 0 := | ||
begin | ||
split_ifs with h, | ||
{ exact card_embedding h }, | ||
{ exact card_embedding_eq_zero (not_le.mp h) } | ||
end | ||
|
||
lemma card_embedding_eq_infinite {α β} [infinite α] [fintype β] : ‖α ↪ β‖ = 0 := | ||
by rw card_eq_zero_iff; apply_instance | ||
|
||
end fintype |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters