-
Notifications
You must be signed in to change notification settings - Fork 251
/
AlexandrovDiscrete.lean
269 lines (192 loc) · 12 KB
/
AlexandrovDiscrete.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
/-
Copyright (c) 2023 Yaël Dillies. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yaël Dillies
-/
import Mathlib.Data.Set.Image
import Mathlib.Topology.Bases
import Mathlib.Topology.Inseparable
import Mathlib.Topology.Compactness.Compact
/-!
# Alexandrov-discrete topological spaces
This file defines Alexandrov-discrete spaces, aka finitely generated spaces.
A space is Alexandrov-discrete if the (arbitrary) intersection of open sets is open. As such,
the intersection of all neighborhoods of a set is a neighborhood itself. Hence every set has a
minimal neighborhood, which we call the *exterior* of the set.
## Main declarations
* `AlexandrovDiscrete`: Prop-valued typeclass for a topological space to be Alexandrov-discrete
* `exterior`: Intersection of all neighborhoods of a set. When the space is Alexandrov-discrete,
this is the minimal neighborhood of the set.
## Notes
The "minimal neighborhood of a set" construction is not named in the literature. We chose the name
"exterior" with analogy to the interior. `interior` and `exterior` have the same properties up to
## TODO
Finite product of Alexandrov-discrete spaces is Alexandrov-discrete.
## Tags
Alexandroff, discrete, finitely generated, fg space
-/
open Filter Set TopologicalSpace
open scoped Topology
/-- A topological space is **Alexandrov-discrete** or **finitely generated** if the intersection of
a family of open sets is open. -/
class AlexandrovDiscrete (α : Type*) [TopologicalSpace α] : Prop where
/-- The intersection of a family of open sets is an open set. Use `isOpen_sInter` in the root
namespace instead. -/
protected isOpen_sInter : ∀ S : Set (Set α), (∀ s ∈ S, IsOpen s) → IsOpen (⋂₀ S)
variable {ι : Sort*} {κ : ι → Sort*} {α β : Type*} [TopologicalSpace α] [TopologicalSpace β]
instance DiscreteTopology.toAlexandrovDiscrete [DiscreteTopology α] : AlexandrovDiscrete α where
isOpen_sInter _ _ := isOpen_discrete _
instance Finite.toAlexandrovDiscrete [Finite α] : AlexandrovDiscrete α where
isOpen_sInter S := (toFinite S).isOpen_sInter
section AlexandrovDiscrete
variable [AlexandrovDiscrete α] {S : Set (Set α)} {f : ι → Set α}
lemma isOpen_sInter : (∀ s ∈ S, IsOpen s) → IsOpen (⋂₀ S) := AlexandrovDiscrete.isOpen_sInter _
lemma isOpen_iInter (hf : ∀ i, IsOpen (f i)) : IsOpen (⋂ i, f i) :=
isOpen_sInter <| forall_mem_range.2 hf
lemma isOpen_iInter₂ {f : ∀ i, κ i → Set α} (hf : ∀ i j, IsOpen (f i j)) :
IsOpen (⋂ i, ⋂ j, f i j) :=
isOpen_iInter fun _ ↦ isOpen_iInter <| hf _
lemma isClosed_sUnion (hS : ∀ s ∈ S, IsClosed s) : IsClosed (⋃₀ S) := by
simp only [← isOpen_compl_iff, compl_sUnion] at hS ⊢; exact isOpen_sInter <| forall_mem_image.2 hS
lemma isClosed_iUnion (hf : ∀ i, IsClosed (f i)) : IsClosed (⋃ i, f i) :=
isClosed_sUnion <| forall_mem_range.2 hf
lemma isClosed_iUnion₂ {f : ∀ i, κ i → Set α} (hf : ∀ i j, IsClosed (f i j)) :
IsClosed (⋃ i, ⋃ j, f i j) :=
isClosed_iUnion fun _ ↦ isClosed_iUnion <| hf _
lemma isClopen_sInter (hS : ∀ s ∈ S, IsClopen s) : IsClopen (⋂₀ S) :=
⟨isClosed_sInter fun s hs ↦ (hS s hs).1, isOpen_sInter fun s hs ↦ (hS s hs).2⟩
lemma isClopen_iInter (hf : ∀ i, IsClopen (f i)) : IsClopen (⋂ i, f i) :=
⟨isClosed_iInter fun i ↦ (hf i).1, isOpen_iInter fun i ↦ (hf i).2⟩
lemma isClopen_iInter₂ {f : ∀ i, κ i → Set α} (hf : ∀ i j, IsClopen (f i j)) :
IsClopen (⋂ i, ⋂ j, f i j) :=
isClopen_iInter fun _ ↦ isClopen_iInter <| hf _
lemma isClopen_sUnion (hS : ∀ s ∈ S, IsClopen s) : IsClopen (⋃₀ S) :=
⟨isClosed_sUnion fun s hs ↦ (hS s hs).1, isOpen_sUnion fun s hs ↦ (hS s hs).2⟩
lemma isClopen_iUnion (hf : ∀ i, IsClopen (f i)) : IsClopen (⋃ i, f i) :=
⟨isClosed_iUnion fun i ↦ (hf i).1, isOpen_iUnion fun i ↦ (hf i).2⟩
lemma isClopen_iUnion₂ {f : ∀ i, κ i → Set α} (hf : ∀ i j, IsClopen (f i j)) :
IsClopen (⋃ i, ⋃ j, f i j) :=
isClopen_iUnion fun _ ↦ isClopen_iUnion <| hf _
lemma interior_iInter (f : ι → Set α) : interior (⋂ i, f i) = ⋂ i, interior (f i) :=
(interior_maximal (iInter_mono fun _ ↦ interior_subset) <| isOpen_iInter fun _ ↦
isOpen_interior).antisymm' <| subset_iInter fun _ ↦ interior_mono <| iInter_subset _ _
lemma interior_sInter (S : Set (Set α)) : interior (⋂₀ S) = ⋂ s ∈ S, interior s := by
simp_rw [sInter_eq_biInter, interior_iInter]
lemma closure_iUnion (f : ι → Set α) : closure (⋃ i, f i) = ⋃ i, closure (f i) :=
compl_injective <| by
simpa only [← interior_compl, compl_iUnion] using interior_iInter fun i ↦ (f i)ᶜ
lemma closure_sUnion (S : Set (Set α)) : closure (⋃₀ S) = ⋃ s ∈ S, closure s := by
simp_rw [sUnion_eq_biUnion, closure_iUnion]
end AlexandrovDiscrete
variable {s t : Set α} {a x y : α}
/-- The *exterior* of a set is the intersection of all its neighborhoods. In an Alexandrov-discrete
space, this is the smallest neighborhood of the set.
Note that this construction is unnamed in the literature. We choose the name in analogy to
`interior`. -/
def exterior (s : Set α) : Set α := (𝓝ˢ s).ker
lemma exterior_singleton_eq_ker_nhds (a : α) : exterior {a} = (𝓝 a).ker := by simp [exterior]
lemma exterior_def (s : Set α) : exterior s = ⋂₀ {t : Set α | IsOpen t ∧ s ⊆ t} :=
(hasBasis_nhdsSet _).ker.trans sInter_eq_biInter.symm
lemma mem_exterior : a ∈ exterior s ↔ ∀ U, IsOpen U → s ⊆ U → a ∈ U := by simp [exterior_def]
lemma subset_exterior_iff : s ⊆ exterior t ↔ ∀ U, IsOpen U → t ⊆ U → s ⊆ U := by
simp [exterior_def]
lemma subset_exterior : s ⊆ exterior s := subset_exterior_iff.2 fun _ _ ↦ id
lemma exterior_minimal (h₁ : s ⊆ t) (h₂ : IsOpen t) : exterior s ⊆ t := by
rw [exterior_def]; exact sInter_subset_of_mem ⟨h₂, h₁⟩
lemma IsOpen.exterior_eq (h : IsOpen s) : exterior s = s :=
(exterior_minimal Subset.rfl h).antisymm subset_exterior
lemma IsOpen.exterior_subset_iff (ht : IsOpen t) : exterior s ⊆ t ↔ s ⊆ t :=
⟨subset_exterior.trans, fun h ↦ exterior_minimal h ht⟩
@[mono] lemma exterior_mono : Monotone (exterior : Set α → Set α) :=
fun _s _t h ↦ ker_mono <| nhdsSet_mono h
@[simp] lemma exterior_empty : exterior (∅ : Set α) = ∅ := isOpen_empty.exterior_eq
@[simp] lemma exterior_univ : exterior (univ : Set α) = univ := isOpen_univ.exterior_eq
@[simp] lemma exterior_eq_empty : exterior s = ∅ ↔ s = ∅ :=
⟨eq_bot_mono subset_exterior, by rintro rfl; exact exterior_empty⟩
variable [AlexandrovDiscrete α] [AlexandrovDiscrete β]
@[simp] lemma isOpen_exterior : IsOpen (exterior s) := by
rw [exterior_def]; exact isOpen_sInter fun _ ↦ And.left
lemma exterior_mem_nhdsSet : exterior s ∈ 𝓝ˢ s := isOpen_exterior.mem_nhdsSet.2 subset_exterior
@[simp] lemma exterior_eq_iff_isOpen : exterior s = s ↔ IsOpen s :=
⟨fun h ↦ h ▸ isOpen_exterior, IsOpen.exterior_eq⟩
@[simp] lemma exterior_subset_iff_isOpen : exterior s ⊆ s ↔ IsOpen s := by
simp only [exterior_eq_iff_isOpen.symm, Subset.antisymm_iff, subset_exterior, and_true]
lemma exterior_subset_iff : exterior s ⊆ t ↔ ∃ U, IsOpen U ∧ s ⊆ U ∧ U ⊆ t :=
⟨fun h ↦ ⟨exterior s, isOpen_exterior, subset_exterior, h⟩,
fun ⟨_U, hU, hsU, hUt⟩ ↦ (exterior_minimal hsU hU).trans hUt⟩
lemma exterior_subset_iff_mem_nhdsSet : exterior s ⊆ t ↔ t ∈ 𝓝ˢ s :=
exterior_subset_iff.trans mem_nhdsSet_iff_exists.symm
lemma exterior_singleton_subset_iff_mem_nhds : exterior {a} ⊆ t ↔ t ∈ 𝓝 a := by
simp [exterior_subset_iff_mem_nhdsSet]
lemma IsOpen.exterior_subset (ht : IsOpen t) : exterior s ⊆ t ↔ s ⊆ t :=
⟨subset_exterior.trans, fun h ↦ exterior_minimal h ht⟩
lemma gc_exterior_interior : GaloisConnection (exterior : Set α → Set α) interior :=
fun s t ↦ by simp [exterior_subset_iff, subset_interior_iff]
@[simp] lemma exterior_exterior (s : Set α) : exterior (exterior s) = exterior s :=
isOpen_exterior.exterior_eq
@[simp] lemma exterior_union (s t : Set α) : exterior (s ∪ t) = exterior s ∪ exterior t :=
gc_exterior_interior.l_sup
@[simp] lemma nhdsSet_exterior (s : Set α) : 𝓝ˢ (exterior s) = 𝓝ˢ s := by
ext t; simp_rw [← exterior_subset_iff_mem_nhdsSet, exterior_exterior]
@[simp] lemma principal_exterior (s : Set α) : 𝓟 (exterior s) = 𝓝ˢ s := by
rw [← nhdsSet_exterior, isOpen_exterior.nhdsSet_eq]
@[simp] lemma exterior_subset_exterior : exterior s ⊆ exterior t ↔ 𝓝ˢ s ≤ 𝓝ˢ t := by
refine ⟨?_, fun h ↦ ker_mono h⟩
simp_rw [le_def, ← exterior_subset_iff_mem_nhdsSet]
exact fun h u ↦ h.trans
lemma specializes_iff_exterior_subset : x ⤳ y ↔ exterior {x} ⊆ exterior {y} := by
simp [Specializes]
lemma isOpen_iff_forall_specializes : IsOpen s ↔ ∀ x y, x ⤳ y → y ∈ s → x ∈ s := by
refine ⟨fun hs x y hxy ↦ hxy.mem_open hs, fun hs ↦ ?_⟩
simp_rw [specializes_iff_exterior_subset] at hs
simp_rw [isOpen_iff_mem_nhds, mem_nhds_iff]
rintro a ha
refine ⟨_, fun b hb ↦ hs _ _ ?_ ha, isOpen_exterior, subset_exterior <| mem_singleton _⟩
rwa [isOpen_exterior.exterior_subset, singleton_subset_iff]
lemma Set.Finite.isCompact_exterior (hs : s.Finite) : IsCompact (exterior s) := by
classical
refine isCompact_of_finite_subcover fun f hf hsf ↦ ?_
choose g hg using fun a (ha : a ∈ exterior s) ↦ mem_iUnion.1 (hsf ha)
refine ⟨hs.toFinset.attach.image fun a ↦
g a.1 <| subset_exterior <| (Finite.mem_toFinset _).1 a.2,
(isOpen_iUnion fun i ↦ isOpen_iUnion ?_).exterior_subset.2 ?_⟩
· exact fun _ ↦ hf _
refine fun a ha ↦ mem_iUnion₂.2 ⟨_, ?_, hg _ <| subset_exterior ha⟩
simp only [Finset.mem_image, Finset.mem_attach, true_and, Subtype.exists, Finite.mem_toFinset]
exact ⟨a, ha, rfl⟩
lemma Inducing.alexandrovDiscrete {f : β → α} (h : Inducing f) : AlexandrovDiscrete β where
isOpen_sInter S hS := by
simp_rw [h.isOpen_iff] at hS ⊢
choose U hU htU using hS
refine ⟨_, isOpen_iInter₂ hU, ?_⟩
simp_rw [preimage_iInter, htU, sInter_eq_biInter]
lemma alexandrovDiscrete_coinduced {β : Type*} {f : α → β} :
@AlexandrovDiscrete β (coinduced f ‹_›) :=
@AlexandrovDiscrete.mk β (coinduced f ‹_›) fun S hS ↦ by
rw [isOpen_coinduced, preimage_sInter]; exact isOpen_iInter₂ hS
lemma AlexandrovDiscrete.sup {t₁ t₂ : TopologicalSpace α} (_ : @AlexandrovDiscrete α t₁)
(_ : @AlexandrovDiscrete α t₂) :
@AlexandrovDiscrete α (t₁ ⊔ t₂) :=
@AlexandrovDiscrete.mk α (t₁ ⊔ t₂) fun _S hS ↦
⟨@isOpen_sInter _ t₁ _ _ fun _s hs ↦ (hS _ hs).1, isOpen_sInter fun _s hs ↦ (hS _ hs).2⟩
lemma alexandrovDiscrete_iSup {t : ι → TopologicalSpace α} (_ : ∀ i, @AlexandrovDiscrete α (t i)) :
@AlexandrovDiscrete α (⨆ i, t i) :=
@AlexandrovDiscrete.mk α (⨆ i, t i)
fun _S hS ↦ isOpen_iSup_iff.2
fun i ↦ @isOpen_sInter _ (t i) _ _
fun _s hs ↦ isOpen_iSup_iff.1 (hS _ hs) _
instance AlexandrovDiscrete.toFirstCountable : FirstCountableTopology α where
nhds_generated_countable a := ⟨{exterior {a}}, countable_singleton _, by simp⟩
instance AlexandrovDiscrete.toLocallyCompactSpace : LocallyCompactSpace α where
local_compact_nhds a _U hU := ⟨exterior {a},
isOpen_exterior.mem_nhds <| subset_exterior <| mem_singleton _,
exterior_singleton_subset_iff_mem_nhds.2 hU, (finite_singleton _).isCompact_exterior⟩
instance Subtype.instAlexandrovDiscrete {p : α → Prop} : AlexandrovDiscrete {a // p a} :=
inducing_subtype_val.alexandrovDiscrete
instance Quotient.instAlexandrovDiscrete {s : Setoid α} : AlexandrovDiscrete (Quotient s) :=
alexandrovDiscrete_coinduced
instance Sum.instAlexandrovDiscrete : AlexandrovDiscrete (α ⊕ β) :=
alexandrovDiscrete_coinduced.sup alexandrovDiscrete_coinduced
instance Sigma.instAlexandrovDiscrete {ι : Type*} {π : ι → Type*} [∀ i, TopologicalSpace (π i)]
[∀ i, AlexandrovDiscrete (π i)] : AlexandrovDiscrete (Σ i, π i) :=
alexandrovDiscrete_iSup fun _ ↦ alexandrovDiscrete_coinduced