Skip to content

Commit 9e49057

Browse files
urkudb-mehta
authored andcommitted
feat(Sheaves/EtaleSpace): new file (leanprover-community#39630)
Written for the Cauchy integral theorem project at ICERM.
1 parent a914648 commit 9e49057

3 files changed

Lines changed: 168 additions & 1 deletion

File tree

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7983,6 +7983,7 @@ public import Mathlib.Topology.Sheaves.Abelian
79837983
public import Mathlib.Topology.Sheaves.AddCommGrpCat
79847984
public import Mathlib.Topology.Sheaves.Alexandrov
79857985
public import Mathlib.Topology.Sheaves.CommRingCat
7986+
public import Mathlib.Topology.Sheaves.EtaleSpace
79867987
public import Mathlib.Topology.Sheaves.Flasque
79877988
public import Mathlib.Topology.Sheaves.Forget
79887989
public import Mathlib.Topology.Sheaves.Functors

Mathlib/Topology/Order.lean

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,10 @@ instance : DiscreteTopology ℤ := ⟨rfl⟩
576576
instance {n} : TopologicalSpace (Fin n) := ⊥
577577
instance {n} : DiscreteTopology (Fin n) := ⟨rfl⟩
578578

579-
instance : DiscreteTopology (WithTopology α ⊥) where
579+
/-- A copy of a type equipped with the discrete topology. -/
580+
abbrev WithDiscreteTopology (α : Type*) := WithTopology α ⊥
581+
582+
instance : DiscreteTopology (WithDiscreteTopology α) where
580583
eq_bot := coinduced_bot
581584

582585
instance : IndiscreteTopology (WithTopology α ⊤) where
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/-
2+
Copyright (c) 2026 Yury Kudryashov. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Yury Kudryashov
5+
-/
6+
module
7+
8+
public import Mathlib.Topology.Covering.Basic
9+
public import Mathlib.Topology.Sheaves.Stalks
10+
11+
/-!
12+
# Etale space of a presheaf
13+
14+
Given a presheaf `F` on a topological space `X`,
15+
its *etale space* is the space of pairs `(base, germ)`,
16+
where `base` is a point of `X`, and `germ` is an element of the stalk of `F` at `base`.
17+
18+
This space is equipped with the following topology.
19+
For each open set `U` and a section `s` of `F` over `U`,
20+
the set of germs of `s` at points `x ∈ U` is an open set in the etale space.
21+
22+
## Main results
23+
24+
- `TopCat.Presheaf.EtaleSpace.eventually_nhds`. If `s` is a section of `F` over `U`
25+
with germ at `g.base` equal to `g.germ`,
26+
then a neighborhood of `g` consists of germs of `s` at points `x ∈ U`.
27+
28+
- `TopCat.Presheaf.EtaleSpace.isCoveringMap_base`.
29+
Let `F` be a presheaf with the following property.
30+
31+
For each `x`, there exists an open neighborhood `U ∋ x` such that for each `y ∈ U`,
32+
the map `Presheaf.germ F U y hyU` from sections of `F` over `U` to the stalk at `y`
33+
is bijective.
34+
35+
Then the projection from the etale space of `F` to the base is a covering map.
36+
-/
37+
38+
public section
39+
40+
open Function Set CategoryTheory TopologicalSpace Opposite Filter
41+
open scoped Topology
42+
43+
namespace TopCat.Presheaf
44+
45+
universe v u w
46+
variable {X : TopCat.{v}} {C : Type u} [Category.{v} C] {CC : C → Type v} {FC : C → C → Type w}
47+
[∀ X Y, FunLike (FC X Y) (CC X) (CC Y)] [ConcreteCategory C FC] [Limits.HasColimits.{v} C]
48+
49+
/-- Etale space of a presheaf. -/
50+
structure EtaleSpace (F : Presheaf C X) where
51+
/-- The base point. -/
52+
base : X
53+
/-- A germ at `base` (formally, an element of the stalk of `F` at `base`). -/
54+
germ : ToType (F.stalk base)
55+
56+
namespace EtaleSpace
57+
58+
instance (F : Presheaf C X) : TopologicalSpace F.EtaleSpace :=
59+
.generateFrom
60+
{{g | ∃ h, g.germ = F.germ U g.base h f} | (U : Opens X) (f : ToType (F.obj <| op U))}
61+
62+
variable {F : Presheaf C X}
63+
64+
/-- If `s` is a section of a presheaf `F` over `U` with germ at `g.base` equal to `g.germ`,
65+
then a neighborhood of `g` consists of germs of `s` at points `x ∈ U`. -/
66+
protected theorem eventually_nhds (g : EtaleSpace F) {U : Opens X} (h : g.base ∈ U)
67+
(s : ToType (F.obj (op U))) (hs : F.germ U g.base h s = g.germ) :
68+
∀ᶠ g' : EtaleSpace F in 𝓝 g, ∃ hgU : g'.base ∈ U, g'.germ = F.germ U g'.base hgU s := by
69+
simp only [nhds_generateFrom, Filter.Eventually, mem_setOf_eq, iInf_and, iInf_exists]
70+
refine mem_iInf_of_mem _ <| mem_iInf_of_mem ?_ <| mem_iInf_of_mem U <| mem_iInf_of_mem s <|
71+
mem_iInf_of_mem rfl <| mem_principal_self _
72+
simp [*]
73+
74+
variable [Limits.PreservesFilteredColimits (forget C)]
75+
76+
variable (F) in
77+
@[fun_prop]
78+
theorem continuous_base : Continuous (base (F := F)) := by
79+
rw [continuous_iff_continuousAt]
80+
intro x
81+
rw [ContinuousAt, (nhds_basis_opens _).tendsto_right_iff]
82+
rintro U ⟨hxU, hUo⟩
83+
lift U to Opens X using hUo
84+
rcases F.exists_le_germ_eq x.germ hxU with ⟨V, hVU, hxV, f, hf⟩
85+
refine x.eventually_nhds hxV f hf |>.mono ?_
86+
aesop
87+
88+
theorem exists_section_of_tendsto {α : Type*} {l : Filter α} {g : α → F.EtaleSpace}
89+
{g₀ : F.EtaleSpace} (h : Tendsto g l (𝓝 g₀)) :
90+
∃ (U : Opens X), g₀.base ∈ U ∧ ∃ (f : ToType (F.obj (op U))),
91+
∀ᶠ a in l, ∃ ha : (g a).base ∈ U, (g a).germ = F.germ U (g a).base ha f := by
92+
rcases F.exists_germ_eq g₀.germ with ⟨U, hU, s, hs⟩
93+
use U, hU, s
94+
exact h.eventually <| g₀.eventually_nhds hU s hs
95+
96+
/-- Let `F` be a `C`-valued presheaf on `X`.
97+
Let `U` be an open set on `X` such that for each `x ∈ U`, the `germ` map is bijective, i.e.,
98+
every germ can be extended to a unique section over `U`.
99+
100+
Then for each `x ∈ U`, the preimage of `U` under `EtaleSpace.base`
101+
is homeomorphic to the product of `U` and the stalk of `F` at `x` with discrete topology.
102+
-/
103+
@[expose, simps apply_fst]
104+
noncomputable def homeomorph (U : Opens X)
105+
(hF_bij : ∀ (x : X) (hx : x ∈ U), Bijective (F.germ U x hx))
106+
(x : X) (hx : x ∈ U) :
107+
(base (F := F) ⁻¹' U) ≃ₜ U × WithDiscreteTopology (ToType (F.stalk x)) where
108+
toFun s := (⟨s.1.base, s.2⟩,
109+
.toTopology ⊥ <| F.germ U x hx <| surjInv (hF_bij s.1.base s.2).surjective s.1.germ)
110+
invFun
111+
| (⟨y, hy⟩, .toTopology _ g) => ⟨⟨y, F.germ U y hy <| surjInv (hF_bij x hx).surjective g⟩, hy⟩
112+
left_inv := by
113+
rintro ⟨⟨base, s⟩, hs⟩
114+
simp only
115+
congr 2
116+
rw [leftInverse_surjInv (hF_bij _ _), surjInv_eq (hF_bij _ _).surjective]
117+
right_inv := by
118+
rintro ⟨⟨y, hy⟩, ⟨g⟩⟩
119+
simp only
120+
congr
121+
rw [leftInverse_surjInv (hF_bij _ _), surjInv_eq (hF_bij _ _).surjective]
122+
continuous_toFun := by
123+
refine .prodMk (by fun_prop) ?_
124+
simp_rw [continuous_iff_continuousAt, ContinuousAt, nhds_discrete, tendsto_pure, nhds_subtype,
125+
eventually_comap]
126+
rintro ⟨g, hg⟩
127+
rcases hF_bij _ hg |>.surjective g.germ with ⟨f, hf⟩
128+
filter_upwards [g.eventually_nhds hg f hf]
129+
rintro _ ⟨hgU, hgf⟩ g' rfl
130+
congr 1
131+
rw [hgf, ← hf, leftInverse_surjInv (hF_bij _ _), leftInverse_surjInv (hF_bij _ _)]
132+
continuous_invFun := by
133+
simp_rw [continuous_iff_continuousAt, continuousAt_prod_of_discrete_right]
134+
rintro ⟨y, ⟨g⟩⟩
135+
simp only [ContinuousAt, nhds_subtype_eq_comap, tendsto_comap_iff, comp_def,
136+
nhds_generateFrom, tendsto_iInf, mem_setOf_eq, tendsto_principal]
137+
rintro _ ⟨hmem, V, f, rfl⟩
138+
simp only [mem_setOf_eq] at hmem
139+
rcases hmem with ⟨hyV, hgf⟩
140+
rcases F.germ_eq _ _ _ _ _ hgf with ⟨W, hyW, ιWU, ιWV, hW⟩
141+
filter_upwards [W.isOpen.preimage continuous_subtype_val |>.mem_nhds hyW] with z hz
142+
use ιWV.le hz
143+
rw [← F.germ_res_apply ιWU z hz, hW, F.germ_res_apply]
144+
145+
/-- Let `F` be a presheaf with the following property.
146+
147+
For each `x`, there exists an open neighborhood `U ∋ x` such that for each `y ∈ U`,
148+
the map `Presheaf.germ F U y hyU` from sections of `F` over `U` to the stalk at `y`
149+
is bijective.
150+
151+
Then the projection from the etale space of `F` to the base is a covering map. -/
152+
theorem isCoveringMap_base
153+
(hF_bij : ∀ x, ∃ (U : Opens X), x ∈ U ∧ ∀ y (hyU : y ∈ U), Bijective (F.germ U y hyU)) :
154+
IsCoveringMap (base (F := F)) := by
155+
refine fun x ↦ .to_isEvenlyCovered_preimage (I := WithDiscreteTopology (ToType (F.stalk x))) ?_
156+
use inferInstance
157+
rcases hF_bij x with ⟨U, hxU, hU_bij⟩
158+
use U, hxU, U.isOpen, U.isOpen.preimage (continuous_base F), homeomorph U hU_bij x hxU
159+
simp
160+
161+
end EtaleSpace
162+
163+
end TopCat.Presheaf

0 commit comments

Comments
 (0)