Skip to content

Commit b1e3b32

Browse files
committed
feat: a few misc results about open (quotient) maps (leanprover-community#40715)
In particular, we upgrade `IsOpen[Quotient]Map.prodMap` to an `iff` when both factors are nonempty.
1 parent eeee791 commit b1e3b32

4 files changed

Lines changed: 69 additions & 4 deletions

File tree

Mathlib/Topology/Constructions/SumProd.lean

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Authors: Johannes Hölzl, Mario Carneiro, Patrick Massot
66
module
77

88
public import Mathlib.Topology.Homeomorph.Defs
9-
public import Mathlib.Topology.Maps.Basic
9+
public import Mathlib.Topology.Maps.OpenQuotient
1010
public import Mathlib.Topology.Separation.SeparatedNhds
1111

1212
/-!
@@ -358,6 +358,16 @@ theorem ContinuousAt.prodMap' {f : X → Z} {g : Y → W} {x : X} {y : Y} (hf :
358358
(hg : ContinuousAt g y) : ContinuousAt (Prod.map f g) (x, y) :=
359359
hf.prodMap hg
360360

361+
@[simp]
362+
theorem continuousAt_prodMap_iff {f : X → Z} {g : Y → W} {x : X} {y : Y} :
363+
ContinuousAt (Prod.map f g) (x, y) ↔ ContinuousAt f x ∧ ContinuousAt g y := by
364+
simp [ContinuousAt, nhds_prod_eq, tendsto_iff_comap, comap_prodMap_prod]
365+
366+
@[simp]
367+
theorem continuous_prodMap_iff [Nonempty Z] [Nonempty W] {f : Z → X} {g : W → Y} :
368+
Continuous (Prod.map f g) ↔ Continuous f ∧ Continuous g := by
369+
simp [continuous_iff_continuousAt, forall_and]
370+
361371
theorem ContinuousAt.comp₂ {f : Y × Z → W} {g : X → Y} {h : X → Z} {x : X}
362372
(hf : ContinuousAt f (g x, h x)) (hg : ContinuousAt g x) (hh : ContinuousAt h x) :
363373
ContinuousAt (fun x ↦ f (g x, h x)) x :=
@@ -494,11 +504,17 @@ theorem isOpen_prod_iff' {s : Set X} {t : Set Y} :
494504
simp only [st.1.ne_empty, st.2.ne_empty, or_false] at H
495505
exact H.1.prod H.2
496506

507+
theorem isOpenQuotientMap_fst [Nonempty Y] : IsOpenQuotientMap (Prod.fst : X × Y → X) :=
508+
⟨Prod.fst_surjective, continuous_fst, isOpenMap_fst⟩
509+
510+
theorem isOpenQuotientMap_snd [Nonempty X] : IsOpenQuotientMap (Prod.snd : X × Y → Y) :=
511+
⟨Prod.snd_surjective, continuous_snd, isOpenMap_snd⟩
512+
497513
theorem isQuotientMap_fst [Nonempty Y] : IsQuotientMap (Prod.fst : X × Y → X) :=
498-
isOpenMap_fst.isQuotientMap continuous_fst Prod.fst_surjective
514+
isOpenQuotientMap_fst.isQuotientMap
499515

500516
theorem isQuotientMap_snd [Nonempty X] : IsQuotientMap (Prod.snd : X × Y → Y) :=
501-
isOpenMap_snd.isQuotientMap continuous_snd Prod.snd_surjective
517+
isOpenQuotientMap_snd.isQuotientMap
502518

503519
theorem closure_prod_eq {s : Set X} {t : Set Y} : closure (s ×ˢ t) = closure s ×ˢ closure t :=
504520
ext fun ⟨a, b⟩ => by
@@ -589,6 +605,15 @@ protected theorem IsOpenMap.prodMap {f : X → Y} {g : Z → W} (hf : IsOpenMap
589605
rw [nhds_prod_eq, nhds_prod_eq, ← Filter.prod_map_map_eq']
590606
exact Filter.prod_mono (hf.nhds_le a) (hg.nhds_le b)
591607

608+
@[simp]
609+
theorem isOpenMap_prodMap_iff [Nonempty X] [Nonempty Z] {f : X → Y} {g : Z → W} :
610+
IsOpenMap (Prod.map f g) ↔ IsOpenMap f ∧ IsOpenMap g := by
611+
refine ⟨fun h ↦ ⟨?_, ?_⟩, fun ⟨hf, hg⟩ ↦ hf.prodMap hg⟩
612+
· rw [(isOpenQuotientMap_fst (Y := Z)).isOpenMap_iff]
613+
exact isOpenMap_fst.comp h
614+
· rw [(isOpenQuotientMap_snd (X := X)).isOpenMap_iff]
615+
exact isOpenMap_snd.comp h
616+
592617
protected lemma Topology.IsOpenEmbedding.prodMap {f : X → Y} {g : Z → W} (hf : IsOpenEmbedding f)
593618
(hg : IsOpenEmbedding g) : IsOpenEmbedding (Prod.map f g) :=
594619
.of_isEmbedding_isOpenMap (hf.1.prodMap hg.1) (hf.isOpenMap.prodMap hg.isOpenMap)
@@ -612,6 +637,13 @@ theorem IsOpenQuotientMap.prodMap {f : X → Y} {g : Z → W} (hf : IsOpenQuotie
612637
(hg : IsOpenQuotientMap g) : IsOpenQuotientMap (Prod.map f g) :=
613638
⟨.prodMap hf.1 hg.1, .prodMap hf.2 hg.2, .prodMap hf.3 hg.3
614639

640+
@[simp]
641+
theorem isOpenQuotientMap_prodMap_iff [Nonempty X] [Nonempty Z] {f : X → Y} {g : Z → W} :
642+
IsOpenQuotientMap (Prod.map f g) ↔ IsOpenQuotientMap f ∧ IsOpenQuotientMap g := by
643+
have : Nonempty Y := .map f inferInstance
644+
have : Nonempty W := .map g inferInstance
645+
grind [isOpenQuotientMap_iff, continuous_prodMap_iff, isOpenMap_prodMap_iff, Prod.map_surjective]
646+
615647
theorem TopologicalSpace.prod_mono {α β : Type*} {σ₁ σ₂ : TopologicalSpace α}
616648
{τ₁ τ₂ : TopologicalSpace β} (hσ : σ₁ ≤ σ₂) (hτ : τ₁ ≤ τ₂) :
617649
@instTopologicalSpaceProd α β σ₁ τ₁ ≤ @instTopologicalSpaceProd α β σ₂ τ₂ :=

Mathlib/Topology/Homeomorph/Defs.lean

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Authors: Johannes Hölzl, Patrick Massot, Sébastien Gouëzel, Zhouhang Zhou, Re
66
module
77

88
public import Mathlib.Topology.ContinuousMap.Defs
9-
public import Mathlib.Topology.Maps.Basic
9+
public import Mathlib.Topology.Maps.OpenQuotient
1010

1111
/-!
1212
# Homeomorphisms
@@ -342,6 +342,20 @@ theorem comp_isOpenMap_iff' (h : X ≃ₜ Y) {f : Y → Z} : IsOpenMap (f ∘ h)
342342
rw [← Function.comp_id f, ← h.self_comp_symm, ← Function.comp_assoc]
343343
exact hf.comp h.symm.isOpenMap
344344

345+
/-- Open quotient maps are preserved by precomposing with a homeomorphism. -/
346+
@[simp]
347+
theorem isOpenQuotient_comp_iff (e : X ≃ₜ Y) {f : Y → Z} :
348+
IsOpenQuotientMap (f ∘ e) ↔ IsOpenQuotientMap f :=
349+
fun h ↦ by simpa [Function.comp_assoc] using h.comp e.symm.isOpenQuotientMap,
350+
fun hf ↦ hf.comp e.isOpenQuotientMap⟩
351+
352+
/-- Open quotient maps are preserved by postcomposing with a homeomorphism. -/
353+
@[simp]
354+
theorem comp_isOpenQuotientMap_iff (e : Y ≃ₜ Z) {f : X → Y} :
355+
IsOpenQuotientMap (e ∘ f) ↔ IsOpenQuotientMap f :=
356+
fun h ↦ by simpa [← Function.comp_assoc] using e.symm.isOpenQuotientMap.comp h,
357+
fun hf ↦ e.isOpenQuotientMap.comp hf⟩
358+
345359
variable (X Y) in
346360
/-- If both `X` and `Y` have a unique element, then `X ≃ₜ Y`. -/
347361
@[simps!]

Mathlib/Topology/Maps/Basic.lean

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,12 @@ protected theorem id : IsOpenMap (@id X) := fun s hs => by rwa [image_id]
369369
protected theorem comp (hg : IsOpenMap g) (hf : IsOpenMap f) :
370370
IsOpenMap (g ∘ f) := fun s hs => by rw [image_comp]; exact hg _ (hf _ hs)
371371

372+
/-- If `g ∘ f` is open, where `f` is continuous and surjective, then `g` is open. -/
373+
theorem of_comp (hf : Continuous f) (f_surj : Surjective f) (h : IsOpenMap (g ∘ f)) :
374+
IsOpenMap g := fun s hs => by
375+
rw [← f_surj.image_preimage s, ← image_comp]
376+
exact h _ (hs.preimage hf)
377+
372378
theorem isOpen_range (hf : IsOpenMap f) : IsOpen (range f) := by
373379
rw [← image_univ]
374380
exact hf _ isOpen_univ

Mathlib/Topology/Maps/OpenQuotient.lean

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ theorem comp {g : Y → Z} (hg : IsOpenQuotientMap g) (hf : IsOpenQuotientMap f)
4949
IsOpenQuotientMap (g ∘ f) :=
5050
⟨.comp hg.1 hf.1, .comp hg.2 hf.2, .comp hg.3 hf.3
5151

52+
theorem of_comp {g : Y → Z} (hf : Continuous f) (f_surj : Surjective f) (hg : Continuous g)
53+
(h : IsOpenQuotientMap (g ∘ f)) : IsOpenQuotientMap g :=
54+
⟨.of_comp h.surjective, hg, .of_comp hf f_surj h.isOpenMap ⟩
55+
56+
theorem of_comp_iff {g : Y → Z} (hf : IsOpenQuotientMap f) :
57+
IsOpenQuotientMap (g ∘ f) ↔ IsOpenQuotientMap g :=
58+
fun h ↦ .of_comp hf.continuous hf.surjective
59+
(hf.isQuotientMap.continuous_iff.mpr h.continuous) h, fun hg ↦ hg.comp hf⟩
60+
5261
theorem map_nhds_eq (h : IsOpenQuotientMap f) (x : X) : map f (𝓝 x) = 𝓝 (f x) :=
5362
le_antisymm h.continuous.continuousAt <| h.isOpenMap.nhds_le _
5463

@@ -60,6 +69,10 @@ theorem continuousAt_comp_iff (h : IsOpenQuotientMap f) {g : Y → Z} {x : X} :
6069
ContinuousAt (g ∘ f) x ↔ ContinuousAt g (f x) := by
6170
simp only [ContinuousAt, ← h.map_nhds_eq, tendsto_map'_iff, comp_def]
6271

72+
theorem isOpenMap_iff (hf : IsOpenQuotientMap f) {g : Y → Z} :
73+
IsOpenMap g ↔ IsOpenMap (g ∘ f) :=
74+
fun hg ↦ hg.comp hf.isOpenMap, fun h ↦ .of_comp hf.continuous hf.surjective h⟩
75+
6376
theorem dense_preimage_iff (h : IsOpenQuotientMap f) {s : Set Y} : Dense (f ⁻¹' s) ↔ Dense s :=
6477
fun hs ↦ h.surjective.denseRange.dense_of_mapsTo h.continuous hs (mapsTo_preimage _ _),
6578
fun hs ↦ hs.preimage h.isOpenMap⟩

0 commit comments

Comments
 (0)