Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
Try doing some basic maths questions in the Lean Theorem Prover. Functions, real numbers, equivalence relations and groups. Click on README.md and then on "Open in CoCalc with one click".
Project: Xena
Views: 18536License: APACHE
/- Copyright (c) 2018 Reid Barton. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Reid Barton -/ import topology.bases topology.dense_embedding /-! # Stone-Čech compactification Construction of the Stone-Čech compactification using ultrafilters. Parts of the formalization are based on "Ultrafilters and Topology" by Marius Stekelenburg, particularly section 5. -/ noncomputable theory open filter lattice set open_locale topological_space universes u v section ultrafilter /- The set of ultrafilters on α carries a natural topology which makes it the Stone-Čech compactification of α (viewed as a discrete space). -/ /-- Basis for the topology on `ultrafilter α`. -/ def ultrafilter_basis (α : Type u) : set (set (ultrafilter α)) := {t | ∃ (s : set α), t = {u | s ∈ u.val}} variables {α : Type u} instance : topological_space (ultrafilter α) := topological_space.generate_from (ultrafilter_basis α) lemma ultrafilter_basis_is_basis : topological_space.is_topological_basis (ultrafilter_basis α) := ⟨begin rintros _ ⟨a, rfl⟩ _ ⟨b, rfl⟩ u ⟨ua, ub⟩, refine ⟨_, ⟨a ∩ b, rfl⟩, u.val.inter_sets ua ub, assume v hv, ⟨_, _⟩⟩; apply v.val.sets_of_superset hv; simp end, eq_univ_of_univ_subset $ subset_sUnion_of_mem $ ⟨univ, eq.symm (eq_univ_of_forall (λ u, u.val.univ_sets))⟩, rfl⟩ /-- The basic open sets for the topology on ultrafilters are open. -/ lemma ultrafilter_is_open_basic (s : set α) : is_open {u : ultrafilter α | s ∈ u.val} := topological_space.is_open_of_is_topological_basis ultrafilter_basis_is_basis ⟨s, rfl⟩ /-- The basic open sets for the topology on ultrafilters are also closed. -/ lemma ultrafilter_is_closed_basic (s : set α) : is_closed {u : ultrafilter α | s ∈ u.val} := begin change is_open (- _), convert ultrafilter_is_open_basic (-s), ext u, exact (ultrafilter_iff_compl_mem_iff_not_mem.mp u.property s).symm end /-- Every ultrafilter `u` on `ultrafilter α` converges to a unique point of `ultrafilter α`, namely `mjoin u`. -/ lemma ultrafilter_converges_iff {u : ultrafilter (ultrafilter α)} {x : ultrafilter α} : u.val ≤ 𝓝 x ↔ x = mjoin u := begin rw [eq_comm, ultrafilter.eq_iff_val_le_val], change u.val ≤ 𝓝 x ↔ x.val.sets ⊆ {a | {v : ultrafilter α | a ∈ v.val} ∈ u.val}, simp only [topological_space.nhds_generate_from, lattice.le_infi_iff, ultrafilter_basis, le_principal_iff], split; intro h, { intros a ha, exact h _ ⟨ha, a, rfl⟩ }, { rintros _ ⟨xi, a, rfl⟩, exact h xi } end instance ultrafilter_compact : compact_space (ultrafilter α) := ⟨compact_iff_ultrafilter_le_nhds.mpr $ assume f uf _, ⟨mjoin ⟨f, uf⟩, trivial, ultrafilter_converges_iff.mpr rfl⟩⟩ instance ultrafilter.t2_space : t2_space (ultrafilter α) := t2_iff_ultrafilter.mpr $ assume f x y u fx fy, have hx : x = mjoin ⟨f, u⟩, from ultrafilter_converges_iff.mp fx, have hy : y = mjoin ⟨f, u⟩, from ultrafilter_converges_iff.mp fy, hx.trans hy.symm lemma ultrafilter_comap_pure_nhds (b : ultrafilter α) : comap pure (𝓝 b) ≤ b.val := begin rw topological_space.nhds_generate_from, simp only [comap_infi, comap_principal], intros s hs, rw ←le_principal_iff, refine lattice.infi_le_of_le {u | s ∈ u.val} _, refine lattice.infi_le_of_le ⟨hs, ⟨s, rfl⟩⟩ _, exact principal_mono.2 (λ a, id) end section embedding lemma ultrafilter_pure_injective : function.injective (pure : α → ultrafilter α) := begin intros x y h, have : {x} ∈ (pure x : ultrafilter α).val := singleton_mem_pure_sets, rw h at this, exact (mem_singleton_iff.mp (mem_pure_sets.mp this)).symm end open topological_space /-- `pure : α → ultrafilter α` defines a dense inducing of `α` in `ultrafilter α`. -/ lemma dense_inducing_pure : @dense_inducing _ _ ⊥ _ (pure : α → ultrafilter α) := by letI : topological_space α := ⊥; exact dense_inducing.mk' pure continuous_bot (assume x, mem_closure_iff_ultrafilter.mpr ⟨x.map ultrafilter.pure, range_mem_map, ultrafilter_converges_iff.mpr (bind_pure x).symm⟩) (assume a s as, ⟨{u | s ∈ u.val}, mem_nhds_sets (ultrafilter_is_open_basic s) (mem_of_nhds as : a ∈ s), assume b hb, mem_pure_sets.mp hb⟩) -- The following refined version will never be used /-- `pure : α → ultrafilter α` defines a dense embedding of `α` in `ultrafilter α`. -/ lemma dense_embedding_pure : @dense_embedding _ _ ⊥ _ (pure : α → ultrafilter α) := by letI : topological_space α := ⊥ ; exact { inj := ultrafilter_pure_injective, ..dense_inducing_pure } end embedding section extension /- Goal: Any function `α → γ` to a compact Hausdorff space `γ` has a unique extension to a continuous function `ultrafilter α → γ`. We already know it must be unique because `α → ultrafilter α` is a dense embedding and `γ` is Hausdorff. For existence, we will invoke `dense_embedding.continuous_extend`. -/ variables {γ : Type*} [topological_space γ] /-- The extension of a function `α → γ` to a function `ultrafilter α → γ`. When `γ` is a compact Hausdorff space it will be continuous. -/ def ultrafilter.extend (f : α → γ) : ultrafilter α → γ := by letI : topological_space α := ⊥; exact dense_inducing_pure.extend f variables [t2_space γ] lemma ultrafilter_extend_extends (f : α → γ) : ultrafilter.extend f ∘ pure = f := begin letI : topological_space α := ⊥, letI : discrete_topology α := ⟨rfl⟩, exact funext (dense_inducing_pure.extend_eq_of_cont continuous_of_discrete_topology) end variables [compact_space γ] lemma continuous_ultrafilter_extend (f : α → γ) : continuous (ultrafilter.extend f) := have ∀ (b : ultrafilter α), ∃ c, tendsto f (comap ultrafilter.pure (𝓝 b)) (𝓝 c) := assume b, -- b.map f is an ultrafilter on γ, which is compact, so it converges to some c in γ. let ⟨c, _, h⟩ := compact_iff_ultrafilter_le_nhds.mp compact_univ (b.map f).val (b.map f).property (by rw [le_principal_iff]; exact univ_mem_sets) in ⟨c, le_trans (map_mono (ultrafilter_comap_pure_nhds _)) h⟩, begin letI : topological_space α := ⊥, letI : normal_space γ := normal_of_compact_t2, exact dense_inducing_pure.continuous_extend this end /-- The value of `ultrafilter.extend f` on an ultrafilter `b` is the unique limit of the ultrafilter `b.map f` in `γ`. -/ lemma ultrafilter_extend_eq_iff {f : α → γ} {b : ultrafilter α} {c : γ} : ultrafilter.extend f b = c ↔ b.val.map f ≤ 𝓝 c := ⟨assume h, begin -- Write b as an ultrafilter limit of pure ultrafilters, and use -- the facts that ultrafilter.extend is a continuous extension of f. let b' : ultrafilter (ultrafilter α) := b.map pure, have t : b'.val ≤ 𝓝 b, from ultrafilter_converges_iff.mpr (bind_pure _).symm, rw ←h, have := (continuous_ultrafilter_extend f).tendsto b, refine le_trans _ (le_trans (map_mono t) this), change _ ≤ map (ultrafilter.extend f ∘ pure) b.val, rw ultrafilter_extend_extends, exact le_refl _ end, assume h, by letI : topological_space α := ⊥; exact dense_inducing_pure.extend_eq (le_trans (map_mono (ultrafilter_comap_pure_nhds _)) h)⟩ end extension end ultrafilter section stone_cech /- Now, we start with a (not necessarily discrete) topological space α and we want to construct its Stone-Čech compactification. We can build it as a quotient of `ultrafilter α` by the relation which identifies two points if the extension of every continuous function α → γ to a compact Hausdorff space sends the two points to the same point of γ. -/ variables (α : Type u) [topological_space α] instance stone_cech_setoid : setoid (ultrafilter α) := { r := λ x y, ∀ (γ : Type u) [topological_space γ], by exactI ∀ [t2_space γ] [compact_space γ] (f : α → γ) (hf : continuous f), ultrafilter.extend f x = ultrafilter.extend f y, iseqv := ⟨assume x γ tγ h₁ h₂ f hf, rfl, assume x y xy γ tγ h₁ h₂ f hf, by exactI (xy γ f hf).symm, assume x y z xy yz γ tγ h₁ h₂ f hf, by exactI (xy γ f hf).trans (yz γ f hf)⟩ } /-- The Stone-Čech compactification of a topological space. -/ def stone_cech : Type u := quotient (stone_cech_setoid α) variables {α} instance : topological_space (stone_cech α) := by unfold stone_cech; apply_instance instance [inhabited α] : inhabited (stone_cech α) := by unfold stone_cech; apply_instance /-- The natural map from α to its Stone-Čech compactification. -/ def stone_cech_unit (x : α) : stone_cech α := ⟦pure x⟧ /-- The image of stone_cech_unit is dense. (But stone_cech_unit need not be an embedding, for example if α is not Hausdorff.) -/ lemma stone_cech_unit_dense : closure (range (@stone_cech_unit α _)) = univ := begin convert quotient_dense_of_dense (eq_univ_iff_forall.mp dense_inducing_pure.closure_range), rw [←range_comp], refl end section extension variables {γ : Type u} [topological_space γ] [t2_space γ] [compact_space γ] variables {f : α → γ} (hf : continuous f) local attribute [elab_with_expected_type] quotient.lift /-- The extension of a continuous function from α to a compact Hausdorff space γ to the Stone-Čech compactification of α. -/ def stone_cech_extend : stone_cech α → γ := quotient.lift (ultrafilter.extend f) (λ x y xy, xy γ f hf) lemma stone_cech_extend_extends : stone_cech_extend hf ∘ stone_cech_unit = f := ultrafilter_extend_extends f lemma continuous_stone_cech_extend : continuous (stone_cech_extend hf) := continuous_quot_lift _ (continuous_ultrafilter_extend f) end extension lemma convergent_eqv_pure {u : ultrafilter α} {x : α} (ux : u.val ≤ 𝓝 x) : u ≈ pure x := assume γ tγ h₁ h₂ f hf, begin resetI, transitivity f x, swap, symmetry, all_goals { refine ultrafilter_extend_eq_iff.mpr (le_trans (map_mono _) (hf.tendsto _)) }, { apply pure_le_nhds }, { exact ux } end lemma continuous_stone_cech_unit : continuous (stone_cech_unit : α → stone_cech α) := continuous_iff_ultrafilter.mpr $ λ x g u gx, let g' : ultrafilter α := ⟨g, u⟩ in have (g'.map ultrafilter.pure).val ≤ 𝓝 g', by rw ultrafilter_converges_iff; exact (bind_pure _).symm, have (g'.map stone_cech_unit).val ≤ 𝓝 ⟦g'⟧, from (continuous_at_iff_ultrafilter g').mp (continuous_quotient_mk.tendsto g') _ (ultrafilter_map u) this, by rwa (show ⟦g'⟧ = ⟦pure x⟧, from quotient.sound $ convergent_eqv_pure gx) at this instance stone_cech.t2_space : t2_space (stone_cech α) := begin rw t2_iff_ultrafilter, rintros g ⟨x⟩ ⟨y⟩ u gx gy, apply quotient.sound, intros γ tγ h₁ h₂ f hf, resetI, let ff := stone_cech_extend hf, change ff ⟦x⟧ = ff ⟦y⟧, have lim : ∀ z : ultrafilter α, g ≤ 𝓝 ⟦z⟧ → tendsto ff g (𝓝 (ff ⟦z⟧)) := assume z gz, calc map ff g ≤ map ff (𝓝 ⟦z⟧) : map_mono gz ... ≤ 𝓝 (ff ⟦z⟧) : (continuous_stone_cech_extend hf).tendsto _, exact tendsto_nhds_unique u.1 (lim x gx) (lim y gy) end instance stone_cech.compact_space : compact_space (stone_cech α) := quotient.compact_space end stone_cech