Skip to content

Commit 81e24ed

Browse files
committed
feat(Topology/CWComplex): 1-skeleton Graph of CWComplex (#37915)
This PR introduces `CWComplex.OneSkeletonGraph`, a graph with 0-dim cells as vertices and 1-dim cells as edges.
1 parent 6230489 commit 81e24ed

3 files changed

Lines changed: 136 additions & 1 deletion

File tree

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7433,6 +7433,7 @@ public import Mathlib.Topology.Bornology.Real
74337433
public import Mathlib.Topology.CWComplex.Abstract.Basic
74347434
public import Mathlib.Topology.CWComplex.Classical.Basic
74357435
public import Mathlib.Topology.CWComplex.Classical.Finite
7436+
public import Mathlib.Topology.CWComplex.Classical.Graph
74367437
public import Mathlib.Topology.CWComplex.Classical.Subcomplex
74377438
public import Mathlib.Topology.Category.Born
74387439
public import Mathlib.Topology.Category.CompHaus.Basic

Mathlib/Topology/CWComplex/Classical/Basic.lean

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ together.
7474

7575
noncomputable section
7676

77-
open Metric Set
77+
open Metric Set Function
7878

7979
namespace Topology
8080

@@ -357,6 +357,60 @@ lemma RelCWComplex.cellFrontier_zero_eq_empty [RelCWComplex C D] {j : cell C 0}
357357
cellFrontier 0 j = ∅ := by
358358
simp [cellFrontier, sphere_eq_empty_of_subsingleton]
359359

360+
lemma RelCWComplex.nonempty_cellFrontier [CWComplex C] {n : ℕ} (hn : n ≠ 0) (j : cell C n) :
361+
(cellFrontier n j).Nonempty := by
362+
letI : NeZero n := ⟨hn⟩
363+
use map n j (Pi.single 0 1)
364+
simp only [cellFrontier, mem_image, mem_sphere_iff_norm, sub_zero]
365+
use Pi.single 0 1, by simp [Pi.norm_single]
366+
367+
/-- If two 0-cells have the same characteristic image point, they are equal. -/
368+
lemma RelCWComplex.injective_map_zero (C : Set X) [RelCWComplex C D] :
369+
Injective ((map 0 · ![]) : cell C 0 → X) := by
370+
rintro x z h
371+
by_contra hne
372+
exact not_disjoint_iff.mpr ⟨map 0 x ![], by simp [openCell_zero_eq_singleton, h]⟩
373+
<| disjoint_openCell_of_ne (by grind : (⟨0, x⟩ : Σ n, cell C n) ≠ ⟨0, z⟩)
374+
375+
@[simp]
376+
lemma RelCWComplex.map_zero_eq_self_iff (C : Set X) [RelCWComplex C D] {x z : cell C 0} :
377+
map 0 x ![] = map 0 z ![] ↔ x = z :=
378+
fun h ↦ injective_map_zero C h, fun h ↦ h ▸ rfl⟩
379+
380+
lemma RelCWComplex.closedCell_zero_injective (C : Set X) [RelCWComplex C D] :
381+
Injective (closedCell 0 : cell C 0 → _) := by
382+
intro x y h
383+
rw [closedCell_zero_eq_singleton, closedCell_zero_eq_singleton, singleton_eq_singleton_iff] at h
384+
exact injective_map_zero C h
385+
386+
lemma RelCWComplex.openCell_zero_injective (C : Set X) [RelCWComplex C D] :
387+
Injective (openCell 0 : cell C 0 → _) := by
388+
intro x y h
389+
rw [openCell_zero_eq_singleton, openCell_zero_eq_singleton, singleton_eq_singleton_iff] at h
390+
exact injective_map_zero C h
391+
392+
lemma RelCWComplex.cellFrontier_one_eq [RelCWComplex C D] (e : cell C 1) :
393+
cellFrontier 1 e = map 1 e '' {-1, 1} := by
394+
rw [cellFrontier]
395+
congr 1
396+
ext f
397+
simp only [mem_sphere_iff_norm, sub_zero, Pi.norm_def, Finset.univ_unique, Fin.default_eq_zero,
398+
Fin.isValue, Finset.sup_singleton, coe_nnnorm, Real.norm_eq_abs, abs_eq (zero_le_one' ℝ),
399+
mem_insert_iff, mem_singleton_iff]
400+
rw [eq_const_of_unique (f := f), ← funext_iff_of_subsingleton (x := 0) (y := 0)]
401+
simp [const_apply, or_comm]
402+
403+
lemma CWComplex.exists_cellFrontier_one_eq [CWComplex C] (e : cell C 1) :
404+
∃ x y : cell C 0, cellFrontier 1 e = closedCell 0 x ∪ closedCell 0 y := by
405+
obtain ⟨f, h⟩ := cellFrontier_subset_finite_closedCell 1 e
406+
simp only [RelCWComplex.cellFrontier_one_eq, image_pair, Order.lt_one_iff, iUnion_iUnion_eq_left,
407+
RelCWComplex.closedCell_zero_eq_singleton, pair_subset_iff, mem_iUnion, mem_singleton_iff,
408+
exists_prop] at h
409+
obtain ⟨⟨u, hu, hun1⟩, v, hv, hv1⟩ := h
410+
use u, v
411+
simp [RelCWComplex.cellFrontier_one_eq, image_pair, RelCWComplex.closedCell_zero_eq_singleton,
412+
hun1, hv1, pair_comm]
413+
360414
lemma RelCWComplex.base_subset_complex [RelCWComplex C D] : D ⊆ C := by
361415
simp_rw [← union]
362416
exact subset_union_left
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/-
2+
Copyright (c) 2026 Jun Kwon. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Jun Kwon
5+
-/
6+
module
7+
8+
public import Mathlib.Topology.CWComplex.Classical.Finite
9+
public import Mathlib.Combinatorics.Graph.Basic
10+
11+
/-!
12+
# 1-skeletons of CW complexes as graphs
13+
14+
In this file we define the 1-skeleton of a CW complex as a graph.
15+
16+
## Main definitions
17+
* `CWComplex.OneSkeletonGraph`: the 1-skeleton of a CW complex as a graph.
18+
19+
-/
20+
21+
public section
22+
23+
open Metric Set Graph
24+
25+
namespace Topology
26+
27+
variable {X : Type*} [TopologicalSpace X]
28+
29+
/-- The 1-skeleton of a CW complex as a graph. -/
30+
@[expose, simps]
31+
def CWComplex.OneSkeletonGraph (C : Set X) [CWComplex C] : Graph (cell C 0) (cell C 1) where
32+
vertexSet := univ
33+
edgeSet := univ
34+
IsLink e x y := cellFrontier 1 e = closedCell 0 x ∪ closedCell 0 y
35+
isLink_symm _ _ x y h := by grind
36+
eq_or_eq_of_isLink_of_isLink e x y z w h1 h2 := by
37+
simp_rw [closedCell_zero_eq_singleton] at h1 h2
38+
rw [h1] at h2
39+
simp only [(RelCWComplex.injective_map_zero C).eq_iff, union_singleton, pair_eq_pair_iff] at h2
40+
tauto
41+
left_mem_of_isLink _ _ _ _ := mem_univ _
42+
edge_mem_iff_exists_isLink e := by
43+
simp only [mem_univ, true_iff]
44+
exact exists_cellFrontier_one_eq e
45+
46+
namespace CWComplex.OneSkeletonGraph
47+
48+
variable {C : Set X} [CWComplex C]
49+
50+
lemma isLink_iff_pair (e : cell C 1) (x y : cell C 0) :
51+
(OneSkeletonGraph C).IsLink e x y ↔ cellFrontier 1 e = {map 0 x ![], map 0 y ![]} := by
52+
rw [OneSkeletonGraph_isLink, closedCell_zero_eq_singleton, closedCell_zero_eq_singleton,
53+
singleton_union]
54+
55+
lemma exists_isLoopAt_iff (e : cell C 1) : (∃ x : cell C 0, (OneSkeletonGraph C).IsLoopAt e x) ↔
56+
∃ x : cell C 0, cellFrontier 1 e = closedCell 0 x := by
57+
refine exists_congr fun x ↦ ?_
58+
change cellFrontier 1 e = closedCell 0 x ∪ closedCell 0 x ↔ _
59+
rw [union_self]
60+
61+
lemma exists_isLoopAt_iff_subsingleton (e : cell C 1) :
62+
(∃ x : cell C 0, (OneSkeletonGraph C).IsLoopAt e x) ↔ (cellFrontier 1 e).Subsingleton := by
63+
rw [exists_isLoopAt_iff]
64+
refine ⟨fun ⟨x, hx⟩ => by simp [closedCell_zero_eq_singleton, hx], fun h => ?_⟩
65+
obtain ⟨x, y, hxy⟩ := exists_cellFrontier_one_eq e
66+
simp only [closedCell_zero_eq_singleton, union_singleton] at hxy
67+
obtain rfl : x = y := RelCWComplex.injective_map_zero C <| (hxy ▸ h) (by simp) (by simp)
68+
exact ⟨x, by simp [hxy, closedCell_zero_eq_singleton]⟩
69+
70+
lemma not_exists_isLoopAt_iff_nontrivial (e : cell C 1) :
71+
¬(∃ x : cell C 0, (OneSkeletonGraph C).IsLoopAt e x) ↔ (cellFrontier 1 e).Nontrivial :=
72+
(exists_isLoopAt_iff_subsingleton e).not.trans not_subsingleton_iff
73+
74+
@[simp]
75+
lemma adj_iff (x y : cell C 0) : (OneSkeletonGraph C).Adj x y ↔
76+
∃ e : cell C 1, cellFrontier 1 e = closedCell 0 x ∪ closedCell 0 y := Iff.rfl
77+
78+
end CWComplex.OneSkeletonGraph
79+
80+
end Topology

0 commit comments

Comments
 (0)