/
stone_cech.lean
314 lines (257 loc) · 12 KB
/
stone_cech.lean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
/-
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
import 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 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 α)) :=
range $ λ s : set α, {u | s ∈ u}
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⟩, inter_mem ua ub, assume v hv, ⟨_, _⟩⟩;
apply mem_of_superset hv; simp [inter_subset_right a b]
end,
eq_univ_of_univ_subset $ subset_sUnion_of_mem $
⟨univ, eq_univ_of_forall (λ u, univ_mem)⟩,
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} :=
ultrafilter_basis_is_basis.is_open ⟨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} :=
begin
rw ← is_open_compl_iff,
convert ultrafilter_is_open_basic sᶜ,
ext u,
exact ultrafilter.compl_mem_iff_not_mem.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 ≤ 𝓝 x ↔ x = mjoin u :=
begin
rw [eq_comm, ← ultrafilter.coe_le_coe],
change ↑u ≤ 𝓝 x ↔ ∀ s ∈ x, {v : ultrafilter α | s ∈ v} ∈ u,
simp only [topological_space.nhds_generate_from, le_infi_iff, ultrafilter_basis,
le_principal_iff, mem_set_of_eq],
split,
{ intros h a ha, exact h _ ⟨ha, a, rfl⟩ },
{ rintros h a ⟨xi, a, rfl⟩, exact h _ xi }
end
instance ultrafilter_compact : compact_space (ultrafilter α) :=
⟨is_compact_iff_ultrafilter_le_nhds.mpr $ assume f _,
⟨mjoin f, trivial, ultrafilter_converges_iff.mpr rfl⟩⟩
instance ultrafilter.t2_space : t2_space (ultrafilter α) :=
t2_iff_ultrafilter.mpr $ assume x y f fx fy,
have hx : x = mjoin f, from ultrafilter_converges_iff.mp fx,
have hy : y = mjoin f, from ultrafilter_converges_iff.mp fy,
hx.trans hy.symm
instance : totally_disconnected_space (ultrafilter α) :=
begin
rw totally_disconnected_space_iff_connected_component_singleton,
intro A,
simp only [set.eq_singleton_iff_unique_mem, mem_connected_component, true_and],
intros B hB,
rw ← ultrafilter.coe_le_coe,
intros s hs,
rw [connected_component_eq_Inter_clopen, set.mem_Inter] at hB,
let Z := { F : ultrafilter α | s ∈ F },
have hZ : is_clopen Z := ⟨ultrafilter_is_open_basic s, ultrafilter_is_closed_basic s⟩,
exact hB ⟨Z, hZ, hs⟩,
end
lemma ultrafilter_comap_pure_nhds (b : ultrafilter α) : comap pure (𝓝 b) ≤ b :=
begin
rw topological_space.nhds_generate_from,
simp only [comap_infi, comap_principal],
intros s hs,
rw ←le_principal_iff,
refine infi_le_of_le {u | s ∈ u} _,
refine 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 α) := singleton_mem_pure,
rw h at this,
exact (mem_singleton_iff.mp (mem_pure.mp this)).symm
end
open topological_space
/-- The range of `pure : α → ultrafilter α` is dense in `ultrafilter α`. -/
lemma dense_range_pure : dense_range (pure : α → ultrafilter α) :=
λ x, mem_closure_iff_ultrafilter.mpr
⟨x.map pure, range_mem_map, ultrafilter_converges_iff.mpr (bind_pure x).symm⟩
/-- The map `pure : α → ultra_filter α` induces on `α` the discrete topology. -/
lemma induced_topology_pure :
topological_space.induced (pure : α → ultrafilter α) ultrafilter.topological_space = ⊥ :=
begin
apply eq_bot_of_singletons_open,
intros x,
use [{u : ultrafilter α | {x} ∈ u}, ultrafilter_is_open_basic _],
simp,
end
/-- `pure : α → ultrafilter α` defines a dense inducing of `α` in `ultrafilter α`. -/
lemma dense_inducing_pure : @dense_inducing _ _ ⊥ _ (pure : α → ultrafilter α) :=
by letI : topological_space α := ⊥; exact ⟨⟨induced_topology_pure.symm⟩, dense_range_pure⟩
-- 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 α := ⊥,
haveI : discrete_topology α := ⟨rfl⟩,
exact funext (dense_inducing_pure.extend_eq continuous_of_discrete_topology)
end
variables [compact_space γ]
lemma continuous_ultrafilter_extend (f : α → γ) : continuous (ultrafilter.extend f) :=
have ∀ (b : ultrafilter α), ∃ c, tendsto f (comap 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_univ.ultrafilter_le_nhds (b.map f)
(by rw [le_principal_iff]; exact univ_mem) in
⟨c, le_trans (map_mono (ultrafilter_comap_pure_nhds _)) h⟩,
begin
letI : topological_space α := ⊥,
haveI : 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.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' ≤ 𝓝 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,
rw ultrafilter_extend_extends,
exact le_rfl
end,
assume h, by letI : topological_space α := ⊥; exact
dense_inducing_pure.extend_eq_of_tendsto (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 dense_range_stone_cech_unit : dense_range (stone_cech_unit : α → stone_cech α) :=
dense_range_pure.quotient
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)
lemma unique_stone_cech_extend {g: stone_cech α → γ} (hg: continuous g)
(hfg: g ∘ stone_cech_unit = (stone_cech_extend hf) ∘ stone_cech_unit):
g = stone_cech_extend hf :=
begin
have h_eq_on: eq_on g (stone_cech_extend hf) (range stone_cech_unit) :=
begin
rw eq_on,
rintros _ ⟨a, ha⟩,
rw [← ha, ← function.comp_apply g stone_cech_unit a],
rw [← function.comp_apply (stone_cech_extend hf) stone_cech_unit a, hfg],
end,
exact continuous.ext_on dense_range_stone_cech_unit hg (continuous_stone_cech_extend hf) h_eq_on,
end
end extension
lemma convergent_eqv_pure {u : ultrafilter α} {x : α} (ux : ↑u ≤ 𝓝 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 gx,
have ↑(g.map pure) ≤ 𝓝 g,
by rw ultrafilter_converges_iff; exact (bind_pure _).symm,
have (g.map stone_cech_unit : filter (stone_cech α)) ≤ 𝓝 ⟦g⟧, from
continuous_at_iff_ultrafilter.mp (continuous_quotient_mk.tendsto g) _ 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 ⟨x⟩ ⟨y⟩ g 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 α) (gz : (g : filter (stone_cech α)) ≤ 𝓝 ⟦z⟧),
((continuous_stone_cech_extend hf).tendsto _).mono_left gz,
exact tendsto_nhds_unique (lim x gx) (lim y gy)
end
instance stone_cech.compact_space : compact_space (stone_cech α) :=
quotient.compact_space
end stone_cech