Skip to content

Commit c54f3c8

Browse files
feat(Topology/CWComplex/Classical): discrete spaces are CW complexes (#38943)
as well as some useful lemmas This is partly based on code by @scholzhannah I think this is notable to include, since it is pretty much the only (easy) "topological" sufficient condition for something being a CW complex there is. Co-authored-by: Batixx <s59fpern@uni-bonn.de>
1 parent cd4c002 commit c54f3c8

5 files changed

Lines changed: 92 additions & 5 deletions

File tree

Mathlib/Algebra/Group/Fin/Tuple.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ variable [Zero α]
103103

104104
@[simp] lemma zero_empty : (0 : Fin 0 → α) = ![] := empty_eq _
105105

106+
@[simp] lemma finZeroElim_eq_zero : (@finZeroElim fun _ ↦ α) = 0 := by
107+
rw [Matrix.empty_eq finZeroElim, Matrix.zero_empty]
108+
106109
@[simp] lemma cons_zero_zero : vecCons (0 : α) (0 : Fin n → α) = 0 := by
107110
ext i; exact i.cases rfl (by simp)
108111

Mathlib/Topology/CWComplex/Classical/Basic.lean

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,20 @@ lemma RelCWComplex.map_zero_mem_closedCell [RelCWComplex C D] (n : ℕ) (i : cel
289289
map n i 0 ∈ closedCell n i :=
290290
openCell_subset_closedCell _ _ (map_zero_mem_openCell _ _)
291291

292+
lemma RelCWComplex.openCell_nonempty [RelCWComplex C D] (n : ℕ) (j : cell C n) :
293+
(openCell n j).Nonempty :=
294+
⟨(map n j) 0, map_zero_mem_openCell n j⟩
295+
296+
lemma RelCWComplex.closedCell_nonempty [RelCWComplex C D] (n : ℕ) (j : cell C n) :
297+
(closedCell n j).Nonempty :=
298+
⟨(map n j) 0, map_zero_mem_closedCell n j⟩
299+
300+
/-- If two open cells are equal, so are the underlying cells. -/
301+
lemma RelCWComplex.openCell_congr [RelCWComplex C D] (n : ℕ) {s t : cell C n}
302+
(st : openCell n s = openCell n t) : s = t := by
303+
contrapose! st
304+
exact (disjoint_openCell_of_ne (by simpa)).ne (openCell_nonempty n s).ne_empty
305+
292306
/-- This is an auxiliary lemma used to prove `RelCWComplex.eq_of_eq_union_iUnion`. -/
293307
private lemma RelCWComplex.subset_of_eq_union_iUnion [RelCWComplex C D] (I J : Π n, Set (cell C n))
294308
(hIJ : D ∪ ⋃ (n : ℕ) (j : I n), openCell (C := C) n j =
@@ -1061,4 +1075,45 @@ lemma RelCWComplex.disjoint_interior_base_iUnion_closedCell [T2Space X] [RelCWCo
10611075
simp_rw [disjoint_iff_inter_eq_empty, inter_iUnion, disjoint_interior_base_closedCell.inter_eq,
10621076
iUnion_empty]
10631077

1078+
/-- A closed discrete subset of a space is a CW complex. -/
1079+
@[reducible, simps -isSimp]
1080+
def CWComplex.OfDiscreteClosed (hD : IsDiscrete D) (Dc : IsClosed D) : CWComplex D where
1081+
cell n := match n with
1082+
| 0 => D
1083+
| (_ + 1) => PEmpty
1084+
map n i := match n with
1085+
| 0 => PartialEquiv.single ![] i
1086+
| (_ + 1) => i.elim
1087+
source_eq n i := match n with
1088+
| 0 => by simp [ball, Matrix.empty_eq, eq_univ_iff_forall]
1089+
| (_ + 1) => i.elim
1090+
continuousOn n i := match n with
1091+
| 0 => continuousOn_const
1092+
| (_ + 1) => i.elim
1093+
continuousOn_symm n i := match n with
1094+
| 0 => continuousOn_const
1095+
| (_ + 1) => i.elim
1096+
pairwiseDisjoint' := by
1097+
simp_rw [PairwiseDisjoint, Set.Pairwise, Function.onFun]
1098+
rintro ⟨_|n, j⟩ _ ⟨_|m, i⟩ _ ne
1099+
· simp_all [Subtype.coe_injective.ne]
1100+
· exact i.elim
1101+
· tauto
1102+
· exact i.elim
1103+
mapsTo' n i := match n with
1104+
| 0 => by simp [Matrix.zero_empty, sphere_eq_empty_of_subsingleton]
1105+
| (_ + 1) => i.elim
1106+
closed' A AD _ := isClosed_of_subset_discrete_closed AD hD Dc
1107+
union' := by
1108+
apply subset_antisymm (iUnion₂_subset_iff.mpr fun n ↦ by cases n <;> simp)
1109+
intro x xD
1110+
simp only [mem_iUnion, mem_image, mem_closedBall, dist_zero_right]
1111+
refine ⟨0, ?_⟩
1112+
simpa [-Matrix.zero_empty]
1113+
1114+
/-- A discrete space is a CW complex. -/
1115+
instance CWComplex.ofDiscreteTopology {X : Type*} [TopologicalSpace X] [DiscreteTopology X] :
1116+
CWComplex (univ : Set X) :=
1117+
CWComplex.OfDiscreteClosed IsDiscrete.univ isClosed_univ
1118+
10641119
end Topology

Mathlib/Topology/Covering/Basic.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ variable (f) in
497497
theorem IsDiscrete.of_openPartialHomeomorph {t : Set E} {x : X}
498498
(htx : t ⊆ f ⁻¹' {x}) (hf : ∀ e ∈ t, ∃ φ : OpenPartialHomeomorph E X, e ∈ φ.source ∧ φ = f) :
499499
IsDiscrete t :=
500-
isDiscrete_iff_forall_exists_isOpen.mpr fun e he ↦ by
500+
isDiscrete_iff_forall_mem_exists_isOpen.mpr fun e he ↦ by
501501
obtain ⟨φ, hφ, rfl⟩ := hf e he
502502
exact ⟨_, φ.open_source, subset_antisymm (fun e' he' ↦ φ.injOn he'.1 hφ <|
503503
(htx he'.2).trans (htx he).symm) <| Set.singleton_subset_iff.mpr ⟨hφ, he⟩⟩

Mathlib/Topology/DiscreteSubset.lean

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,39 @@ lemma discreteTopology_subtype_iff' {S : Set Y} :
6565
simp [discreteTopology_iff_isOpen_singleton, isOpen_induced_iff, Set.ext_iff]
6666
grind
6767

68-
theorem isDiscrete_iff_forall_exists_isOpen {S : Set Y} :
69-
IsDiscrete S ↔ ∀ y ∈ S, ∃ U, IsOpen U ∧ U ∩ S = {y} := by
68+
/-- A set `s` is discrete iff for every `y ∈ s` there is an open `u` with `u ∩ s = {y}`.
69+
See `isDiscrete_iff_forall_subset_exists_isOpen'` for a related version of this with subsets. -/
70+
theorem isDiscrete_iff_forall_mem_exists_isOpen {s : Set Y} :
71+
IsDiscrete s ↔ ∀ y ∈ s, ∃ u, IsOpen u ∧ u ∩ s = {y} := by
7072
rw [isDiscrete_iff_discreteTopology, discreteTopology_subtype_iff']
7173

74+
@[deprecated (since := "2026-06-24")]
75+
alias isDiscrete_iff_forall_exists_isOpen := isDiscrete_iff_forall_mem_exists_isOpen
76+
77+
/-- A set `s` is discrete iff for every `t ⊆ s` there is an open `u` with `u ∩ s = t`.
78+
See `isDiscrete_iff_forall_mem_exists_isOpen` for a similar version of this with singletons. -/
79+
theorem isDiscrete_iff_forall_subset_exists_isOpen {s : Set X} :
80+
IsDiscrete s ↔ ∀ t ⊆ s, ∃ u, IsOpen u ∧ u ∩ s = t := by
81+
simp_rw [isDiscrete_iff_discreteTopology, discreteTopology_iff_forall_isOpen,
82+
isOpen_induced_iff, ← image_eq_image (Subtype.val_injective), Subtype.image_preimage_coe,
83+
Subtype.forall_set_subtype (p := fun t ↦ ∃ u, IsOpen u ∧ s ∩ u = t), inter_comm]
84+
85+
/-- A set `s` is discrete iff for every `t ⊆ s` there is a closed `u` with `u ∩ s = t`. -/
86+
theorem isDiscrete_iff_forall_mem_exists_isClosed {S : Set X} :
87+
IsDiscrete S ↔ ∀ s ⊆ S, ∃ U, IsClosed U ∧ U ∩ S = s := by
88+
rw [isDiscrete_iff_forall_subset_exists_isOpen]
89+
constructor <;> intro h s sS
90+
· obtain ⟨U, Uo, Us⟩ := h (sᶜ ∩ S) inter_subset_right
91+
exact ⟨Uᶜ, isClosed_compl_iff.mpr Uo, by rw [left_eq_inter.mpr sS]; simp_all [Set.ext_iff]⟩
92+
· obtain ⟨U, Uo, Us⟩ := h (sᶜ ∩ S) inter_subset_right
93+
exact ⟨Uᶜ, isOpen_compl_iff.mpr Uo, by rw [left_eq_inter.mpr sS]; simp_all [Set.ext_iff]⟩
94+
95+
theorem isClosed_of_subset_discrete_closed {s t : Set X} (sd : s ⊆ t)
96+
(ht : IsDiscrete t) (tc : IsClosed t) : IsClosed s := by
97+
obtain ⟨_, rp, rt⟩ := isDiscrete_iff_forall_mem_exists_isClosed.mp ht s sd
98+
rw [← rt]
99+
exact rp.inter tc
100+
72101
lemma Set.Subsingleton.isDiscrete (hs : s.Subsingleton) : IsDiscrete s :=
73102
have : Subsingleton s := (Set.subsingleton_coe s).mpr hs
74103
⟨inferInstance⟩

Mathlib/Topology/Irreducible.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,8 @@ end
524524
lemma IsDiscrete.subsingleton_of_isPreirreducible (hs : IsDiscrete s) (hs' : IsPreirreducible s) :
525525
s.Subsingleton := by
526526
intro x hxs y hys
527-
obtain ⟨U, hU, hUx⟩ := isDiscrete_iff_forall_exists_isOpen.mp hs x hxs
528-
obtain ⟨V, hV, hVy⟩ := isDiscrete_iff_forall_exists_isOpen.mp hs y hys
527+
obtain ⟨U, hU, hUx⟩ := isDiscrete_iff_forall_mem_exists_isOpen.mp hs x hxs
528+
obtain ⟨V, hV, hVy⟩ := isDiscrete_iff_forall_mem_exists_isOpen.mp hs y hys
529529
obtain ⟨z, hz⟩ := hs' _ _ hU hV ⟨x, by grind⟩ ⟨y, by grind⟩
530530
exact (hUx.le (by grind)).symm.trans (b := z) (hVy.le (by grind))
531531

0 commit comments

Comments
 (0)