Skip to content

Commit

Permalink
feat(Cardinal): #(α ≃ β) and #(α ↪ β) in the infinite case (#9646)
Browse files Browse the repository at this point in the history
Main results:

+ If two types have the same infinite cardinality, then there are as many Equivs between them as there are functions.

+ If B has infinite cardinality no less than #A, then there are as many embeddings from A into B as there are functions.

+ If A has infinite cardinality no less than #B, then there are as many surjective functions from A to B as there are functions.



Co-authored-by: Junyan Xu <junyanxu.math@gmail.com>
  • Loading branch information
alreadydone and alreadydone committed Jan 12, 2024
1 parent 0533bf2 commit d91d679
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Mathlib/Logic/Embedding/Basic.lean
Expand Up @@ -42,6 +42,11 @@ initialize_simps_projections Embedding (toFun → apply)
-- porting note: this needs `tactic.lift`.
--instance {α β : Sort*} : CanLift (α → β) (α ↪ β) coeFn Injective where prf f hf := ⟨⟨f, hf⟩, rfl⟩

theorem exists_surjective_iff :
(∃ f : α → β, Surjective f) ↔ Nonempty (α → β) ∧ Nonempty (β ↪ α) :=
fun ⟨f, h⟩ ↦ ⟨⟨f⟩, ⟨⟨_, injective_surjInv h⟩⟩⟩, fun ⟨h, ⟨e⟩⟩ ↦ (nonempty_fun.mp h).elim
(fun _ ↦ ⟨isEmptyElim, (isEmptyElim <| e ·)⟩) fun _ ↦ ⟨_, invFun_surjective e.inj'⟩⟩

end Function

section Equiv
Expand Down Expand Up @@ -74,6 +79,9 @@ theorem Equiv.toEmbedding_apply (a : α) : f.toEmbedding a = f a :=
rfl
#align equiv.to_embedding_apply Equiv.toEmbedding_apply

theorem Equiv.toEmbedding_injective : Function.Injective (Equiv.toEmbedding : (α ≃ β) → (α ↪ β)) :=
fun _ _ h ↦ by rwa [FunLike.ext'_iff] at h ⊢

instance Equiv.coeEmbedding : Coe (α ≃ β) (α ↪ β) :=
⟨Equiv.toEmbedding⟩
#align equiv.coe_embedding Equiv.coeEmbedding
Expand Down
8 changes: 8 additions & 0 deletions Mathlib/Logic/IsEmpty.lean
Expand Up @@ -153,6 +153,14 @@ theorem isEmpty_pi {π : α → Sort*} : IsEmpty (∀ a, π a) ↔ ∃ a, IsEmpt
simp only [← not_nonempty_iff, Classical.nonempty_pi, not_forall]
#align is_empty_pi isEmpty_pi

@[simp]
theorem isEmpty_fun : IsEmpty (α → β) ↔ Nonempty α ∧ IsEmpty β := by
rw [isEmpty_pi, ← exists_true_iff_nonempty, ← exists_and_right, true_and]

@[simp]
theorem nonempty_fun : Nonempty (α → β) ↔ IsEmpty α ∨ Nonempty β :=
not_iff_not.mp <| by rw [not_or, not_nonempty_iff, not_nonempty_iff, isEmpty_fun, not_isEmpty_iff]

@[simp]
theorem isEmpty_sigma {α} {E : α → Type*} : IsEmpty (Sigma E) ↔ ∀ a, IsEmpty (E a) := by
simp only [← not_nonempty_iff, nonempty_sigma, not_exists]
Expand Down
102 changes: 102 additions & 0 deletions Mathlib/SetTheory/Cardinal/Ordinal.lean
Expand Up @@ -1042,6 +1042,108 @@ theorem powerlt_aleph0_le (c : Cardinal) : c ^< ℵ₀ ≤ max c ℵ₀ := by
/-! ### Computing cardinality of various types -/


section Function

variable {α β : Type u} {β' : Type v}

theorem mk_equiv_eq_zero_iff_lift_ne : #(α ≃ β') = 0 ↔ lift.{v} #α ≠ lift.{u} #β' := by
rw [mk_eq_zero_iff, ← not_nonempty_iff, ← lift_mk_eq']

theorem mk_equiv_eq_zero_iff_ne : #(α ≃ β) = 0 ↔ #α ≠ #β := by
rw [mk_equiv_eq_zero_iff_lift_ne, lift_id, lift_id]

/-- This lemma makes lemmas assuming `Infinite α` applicable to the situation where we have
`Infinite β` instead. -/
theorem mk_equiv_comm : #(α ≃ β') = #(β' ≃ α) :=
(ofBijective _ symm_bijective).cardinal_eq

theorem mk_embedding_eq_zero_iff_lift_lt : #(α ↪ β') = 0 ↔ lift.{u} #β' < lift.{v} #α := by
rw [mk_eq_zero_iff, ← not_nonempty_iff, ← lift_mk_le', not_le]

theorem mk_embedding_eq_zero_iff_lt : #(α ↪ β) = 0 ↔ #β < #α := by
rw [mk_embedding_eq_zero_iff_lift_lt, lift_lt]

theorem mk_arrow_eq_zero_iff : #(α → β') = 0 ↔ #α ≠ 0 ∧ #β' = 0 := by
simp_rw [mk_eq_zero_iff, mk_ne_zero_iff, isEmpty_fun]

theorem mk_surjective_eq_zero_iff_lift :
#{f : α → β' | Surjective f} = 0 ↔ lift.{v} #α < lift.{u} #β' ∨ (#α ≠ 0 ∧ #β' = 0) := by
rw [← not_iff_not, not_or, not_lt, lift_mk_le', ← Ne, not_and_or, not_ne_iff, and_comm]
simp_rw [mk_ne_zero_iff, mk_eq_zero_iff, nonempty_coe_sort,
Set.Nonempty, mem_setOf, exists_surjective_iff, nonempty_fun]

theorem mk_surjective_eq_zero_iff :
#{f : α → β | Surjective f} = 0 ↔ #α < #β ∨ (#α ≠ 0 ∧ #β = 0) := by
rw [mk_surjective_eq_zero_iff_lift, lift_lt]

variable (α β')

theorem mk_equiv_le_embedding : #(α ≃ β') ≤ #(α ↪ β') := ⟨⟨_, Equiv.toEmbedding_injective⟩⟩

theorem mk_embedding_le_arrow : #(α ↪ β') ≤ #(α → β') := ⟨⟨_, FunLike.coe_injective⟩⟩

variable [Infinite α] {α β'}

theorem mk_perm_eq_self_power : #(Equiv.Perm α) = #α ^ #α :=
((mk_equiv_le_embedding α α).trans (mk_embedding_le_arrow α α)).antisymm <| by
suffices : Nonempty ((α → Bool) ↪ Equiv.Perm (α × Bool))
· obtain ⟨e⟩ : Nonempty (α ≃ α × Bool)
· erw [← Cardinal.eq, mk_prod, lift_uzero, mk_bool,
lift_natCast, mul_two, add_eq_self (aleph0_le_mk α)]
erw [← le_def, mk_arrow, lift_uzero, mk_bool, lift_natCast 2] at this
rwa [← power_def, power_self_eq (aleph0_le_mk α), e.permCongr.cardinal_eq]
refine ⟨⟨fun f ↦ Involutive.toPerm (fun x ↦ ⟨x.1, xor (f x.1) x.2⟩) fun x ↦ ?_, fun f g h ↦ ?_⟩⟩
· simp_rw [← Bool.xor_assoc, Bool.xor_self, Bool.false_xor]
· ext a; rw [← (f a).xor_false, ← (g a).xor_false]; exact congr(($h ⟨a, false⟩).2)

theorem mk_perm_eq_two_power : #(Equiv.Perm α) = 2 ^ #α := by
rw [mk_perm_eq_self_power, power_self_eq (aleph0_le_mk α)]

variable (leq : lift.{v} #α = lift.{u} #β') (eq : #α = #β)

theorem mk_equiv_eq_arrow_of_lift_eq : #(α ≃ β') = #(α → β') := by
obtain ⟨e⟩ := lift_mk_eq'.mp leq
have e₁ := lift_mk_eq'.mpr ⟨.equivCongr (.refl α) e⟩
have e₂ := lift_mk_eq'.mpr ⟨.arrowCongr (.refl α) e⟩
rw [lift_id'.{u,v}] at e₁ e₂
rw [← e₁, ← e₂, lift_inj, mk_perm_eq_self_power, power_def]

theorem mk_equiv_eq_arrow_of_eq : #(α ≃ β) = #(α → β) :=
mk_equiv_eq_arrow_of_lift_eq congr(lift $eq)

theorem mk_equiv_of_lift_eq : #(α ≃ β') = 2 ^ lift.{v} #α := by
erw [← (lift_mk_eq'.2 ⟨.equivCongr (.refl α) (lift_mk_eq'.1 leq).some⟩).trans (lift_id'.{u,v} _),
lift_umax.{u,v}, mk_perm_eq_two_power, lift_power, lift_natCast]; rfl

theorem mk_equiv_of_eq : #(α ≃ β) = 2 ^ #α := by rw [mk_equiv_of_lift_eq (lift_inj.mpr eq), lift_id]

variable (lle : lift.{u} #β' ≤ lift.{v} #α) (le : #β ≤ #α)

theorem mk_embedding_eq_arrow_of_lift_le : #(β' ↪ α) = #(β' → α) :=
(mk_embedding_le_arrow _ _).antisymm <| by
conv_rhs => rw [← (Equiv.embeddingCongr (.refl _)
(Cardinal.eq.mp <| mul_eq_self <| aleph0_le_mk α).some).cardinal_eq]
obtain ⟨e⟩ := lift_mk_le'.mp lle
exact ⟨⟨fun f ↦ ⟨fun b ↦ ⟨e b, f b⟩, fun _ _ h ↦ e.injective congr(Prod.fst $h)⟩,
fun f g h ↦ funext fun b ↦ congr(Prod.snd <| $h b)⟩⟩

theorem mk_embedding_eq_arrow_of_le : #(β ↪ α) = #(β → α) :=
mk_embedding_eq_arrow_of_lift_le (lift_le.mpr le)

theorem mk_surjective_eq_arrow_of_lift_le : #{f : α → β' | Surjective f} = #(α → β') :=
(mk_set_le _).antisymm <|
have ⟨e⟩ : Nonempty (α ≃ α ⊕ β') := by
simp_rw [← lift_mk_eq', mk_sum, lift_add, lift_lift]; rw [lift_umax.{u,v}, eq_comm]
exact add_eq_left (aleph0_le_lift.mpr <| aleph0_le_mk α) lle
⟨⟨fun f ↦ ⟨fun a ↦ (e a).elim f id, fun b ↦ ⟨e.symm (.inr b), congr_arg _ (e.right_inv _)⟩⟩,
fun f g h ↦ funext fun a ↦ by
simpa only [e.apply_symm_apply] using congr_fun (Subtype.ext_iff.mp h) (e.symm <| .inl a)⟩⟩

theorem mk_surjective_eq_arrow_of_le : #{f : α → β | Surjective f} = #(α → β) :=
mk_surjective_eq_arrow_of_lift_le (lift_le.mpr le)

end Function

@[simp]
theorem mk_list_eq_mk (α : Type u) [Infinite α] : #(List α) = #α :=
have H1 : ℵ₀ ≤ #α := aleph0_le_mk α
Expand Down

0 comments on commit d91d679

Please sign in to comment.