/-- **The Schröder–Bernstein theorem**, by the proof in the lesson. Given injections
`f : α → β` and `g : β → α`, the map `F(S) = α \ g[β \ f[S]]` on subsets of `α` is monotone, so
it has a fixed point `S` (Knaster–Tarski: Mathlib's `OrderHom.lfp`). Then `α \ S = g[β \ f[S]]`,
and `h = f` on `S`, `h = g⁻¹` off `S` is a bijection `α → β`. -/
theorem schroeder_bernstein {α : Type u} {β : Type v} {f : α → β} {g : β → α}
(hf : Function.Injective f) (hg : Function.Injective g) :
∃ h : α → β, Function.Bijective h := by
classical
rcases isEmpty_or_nonempty β with hβ | hβ
· -- If `β` is empty, so is `α`, and the empty function is a bijection.
have : IsEmpty α := Function.isEmpty f
exact ⟨f, fun a => isEmptyElim a, fun b => isEmptyElim b⟩
-- The monotone operator `F(S) = α \ g[β \ f[S]]`.
let F : Set α →o Set α :=
{ toFun := fun S => (g '' (f '' S)ᶜ)ᶜ
monotone' := fun S T hST =>
Set.compl_subset_compl.mpr
(Set.image_mono (Set.compl_subset_compl.mpr (Set.image_mono hST))) }
-- Knaster–Tarski: a fixed point `S = F(S)`.
set S : Set α := OrderHom.lfp F with hSdef
have hS : (g '' (f '' S)ᶜ)ᶜ = S := OrderHom.map_lfp F
-- Off `S`, every point is `g y` for some `y` outside `f[S]`.
have hSc : g '' (f '' S)ᶜ = Sᶜ := (compl_compl _).symm.trans (congrArg compl hS)
have off : ∀ a, a ∉ S → ∃ y, y ∉ f '' S ∧ g y = a := by
intro a ha
have : a ∈ g '' (f '' S)ᶜ := by rw [hSc]; exact ha
obtain ⟨y, hy, rfl⟩ := this
exact ⟨y, hy, rfl⟩
-- `g'` undoes `g`.
let g' : α → β := Function.invFun g
have hg' : ∀ y, g' (g y) = y := Function.leftInverse_invFun hg
let h : α → β := fun a => if a ∈ S then f a else g' a
refine ⟨h, ?_, ?_⟩
· -- `h` is injective.
intro a b hab
by_cases ha : a ∈ S <;> by_cases hb : b ∈ S
· simp only [h, ha, hb, ↓reduceIte] at hab
exact hf hab
· simp only [h, ha, hb, ↓reduceIte] at hab
obtain ⟨y, hy, rfl⟩ := off b hb
rw [hg'] at hab
exact absurd ⟨a, ha, hab⟩ hy
· simp only [h, ha, hb, ↓reduceIte] at hab
obtain ⟨y, hy, rfl⟩ := off a ha
rw [hg'] at hab
exact absurd ⟨b, hb, hab.symm⟩ hy
· simp only [h, ha, hb, ↓reduceIte] at hab
obtain ⟨y, -, rfl⟩ := off a ha
obtain ⟨z, -, rfl⟩ := off b hb
rw [hg', hg'] at hab
rw [hab]
· -- `h` is surjective.
intro y
by_cases hy : y ∈ f '' S
· obtain ⟨a, ha, rfl⟩ := hy
exact ⟨a, by simp only [h, ha, ↓reduceIte]⟩
· have hgy : g y ∉ S := by
have : g y ∈ g '' (f '' S)ᶜ := ⟨y, hy, rfl⟩
rw [hSc] at this
exact this
exact ⟨g y, by simp only [h, hgy, ↓reduceIte, hg']⟩