1-- Continuous maps: constant maps, inclusions, restrictions and2-- corestrictions, closed sets of a closed subspace, the pasting lemma,3-- open and closed maps, homeomorphisms as an equivalence, and a4-- continuous bijection from a compact space onto a Hausdorff space as a5-- homeomorphism6-- Part of Cumulus, the Grace17 mathematics library.7-- Copyright (c) 2026 Grant Passmore.8-- Released under the Apache License 2.0. See LICENSE in the repository root.9-- Authors: Grant Passmore1011module Grace.Cumulus.Topology.Maps12import CompactMore13import CompactImage1415-- Constant maps and inclusions are continuous.1617theorem ContinuousMap.constant (X T Y S y : Set)18requires topology : IsTopology(X, T)19requires hy : y ∈ Y20shows ContinuousMap(constantFunction(X, Y, y), X, T, Y, S)21proof22have function := constantFunction.function at X, Y, y with hy23constructor24 . exact function25 . intros V hV26havesplit : y ∈ V ∨¬y ∈ V bytauto27casessplitwith inV | outside28 . have equal : functionPreimage(constantFunction(X, Y, y), X, V) = X29apply Subset.antisymmetric30 . exact functionPreimage.subset at constantFunction(X, Y, y), X, V31 . intros x hx32have value := constantFunction.apply with hx, hy33apply functionPreimage.membership.backward34rw value35exact⟨hx, inV⟩36rw equal37exact IsTopology.whole with topology38 . have equal : functionPreimage(constantFunction(X, Y, y), X, V) =∅39apply Subset.empty_iff.forward40intros x hx41have parts := functionPreimage.membership.forward with hx42have value := constantFunction.apply with parts.left, hy43rw value at parts44exfalso45exact outside with parts.right46rw equal47exact IsTopology.empty with topology4849theorem ContinuousMap.inclusion (X T A : Set)50requires topology : IsTopology(X, T)51requires hA : A ⊆ X52shows ContinuousMap(inclusionMap(A, X), A, subspaceTopology(T, A), X, T)53proof54have function := inclusionMap.function at A, X with hA55constructor56 . exact function57 . intros V hV58have equal : functionPreimage(inclusionMap(A, X), A, V) = V ∩ A59ext x60constructor61 . intro hx62have parts := functionPreimage.membership.forward with hx63have value := inclusionMap.value at A, X, x with hA, parts.left64rw value at parts65exact intersection.membership.backward with⟨parts.right, parts.left⟩66 . intro hx67have parts := intersection.membership.forward with hx68have value := inclusionMap.value at A, X, x with hA, parts.right69apply functionPreimage.membership.backward70rw value71exact⟨parts.right, parts.left⟩72rw equal73exact subspaceTopology.membership.backward with⟨V, hV, rfl⟩7475-- Restriction to a subspace and corestriction to a subspace of the76-- codomain.7778theorem restrict.preimage (f X Y A V : Set)79requires function : f : X → Y80requires hA : A ⊆ X81shows functionPreimage(restrict(f, A), A, V) = functionPreimage(f, X, V) ∩ A82proof83ext x84constructor85 . intro hx86have parts := functionPreimage.membership.forward with hx87have value := restrict.domain_apply with function, hA, parts.left88rw value at parts89have hxX := hA with x, parts.left90exact intersection.membership.backward with⟨(functionPreimage.membership.backward with⟨hxX, parts.right⟩), parts.left⟩91 . intro hx92have parts := intersection.membership.forward with hx93have inner := functionPreimage.membership.forward with parts.left94have value := restrict.domain_apply with function, hA, parts.right95apply functionPreimage.membership.backward96rw value97exact⟨parts.right, inner.right⟩9899theorem ContinuousMap.restrict (f X T Y S A : Set)100requires continuous : ContinuousMap(f, X, T, Y, S)101requires hA : A ⊆ X102shows ContinuousMap(restrict(f, A), A, subspaceTopology(T, A), Y, S)103proof104have function := continuous.left105constructor106 . exact restrict.domain_function with function, hA107 . intros V hV108have equal := restrict.preimage at f, X, Y, A, V with function, hA109rw equal110have isOpen := continuous.right with V, hV111exact subspaceTopology.membership.backward with⟨functionPreimage(f, X, V), isOpen, rfl⟩112113theorem ContinuousMap.corestrict (f X T Y S B : Set)114requires continuous : ContinuousMap(f, X, T, Y, S)115requires hB : B ⊆ Y116requires values : ∀ x ∈ X, f(x) ∈ B117shows ContinuousMap(f, X, T, B, subspaceTopology(S, B))118proof119have function := continuous.left120constructor121 . exact FunctionBetween.codomain_of_values with function, values122 . intros W hW123obtain⟨V, hV, shape⟩:= subspaceTopology.membership.forward with hW124have equal : functionPreimage(f, X, W) = functionPreimage(f, X, V)125ext x126constructor127 . intro hx128have parts := functionPreimage.membership.forward with hx129rw← shape at parts130have inner := intersection.membership.forward with parts.right131exact functionPreimage.membership.backward with⟨parts.left, inner.left⟩132 . intro hx133have parts := functionPreimage.membership.forward with hx134apply functionPreimage.membership.backward135refine⟨parts.left, ?_⟩136rw← shape137exact intersection.membership.backward with⟨parts.right, (values with x, parts.left)⟩138rw equal139exact continuous.right with V, hV140141theorem ContinuousMap.into_image (f X T Y S : Set)142requires continuous : ContinuousMap(f, X, T, Y, S)143shows ContinuousMap(f, X, T, functionImage(f, X, Y), subspaceTopology(S, functionImage(f, X, Y)))144proof145have function := continuous.left146apply ContinuousMap.corestrict with continuous, (functionImage.subset at f, X, Y)147intros x hx148exact functionImage.value with function, hx149150-- Closed sets of a subspace: traces of closed sets, and closed sets of a151-- closed subspace are closed in the whole space.152153theorem IsClosed.subspace_trace (X T A C : Set)154requires topology : IsTopology(X, T)155requires hA : A ⊆ X156requires closed : IsClosed(X, T, C)157shows IsClosed(A, subspaceTopology(T, A), C ∩ A)158proof159constructor160 . exact intersection.subset_right at C, A161 . have equal : complement(A, C ∩ A) = complement(X, C) ∩ A162ext x163constructor164 . intro hx165have parts := complement.membership.forward with hx166have hxX := hA with x, parts.left167apply intersection.membership.backward168refine⟨?_, parts.left⟩169apply complement.membership.backward170refine⟨hxX, ?_⟩171intro inC172apply parts.right173exact intersection.membership.backward with⟨inC, parts.left⟩174 . intro hx175have parts := intersection.membership.forward with hx176have away := complement.membership.forward with parts.left177apply complement.membership.backward178refine⟨parts.right, ?_⟩179intro inBoth180have inner := intersection.membership.forward with inBoth181exact away.right with inner.left182rw equal183exact subspaceTopology.membership.backward with⟨complement(X, C), closed.right, rfl⟩184185theorem IsClosed.of_closed_subspace (X T A C : Set)186requires topology : IsTopology(X, T)187requires closedA : IsClosed(X, T, A)188requires closed : IsClosed(A, subspaceTopology(T, A), C)189shows IsClosed(X, T, C)190proof191have hA := closedA.left192have hCA := closed.left193obtain⟨U, hU, shape⟩:= subspaceTopology.membership.forward with closed.right194have equal : C = A ∩ complement(X, U)195ext x196constructor197 . intro hx198have hxA := hCA with x, hx199apply intersection.membership.backward200refine⟨hxA, ?_⟩201apply complement.membership.backward202refine⟨(hA with x, hxA), ?_⟩203intro inU204have inTrace : x ∈ U ∩ A := intersection.membership.backward with⟨inU, hxA⟩205rw shape at inTrace206have away := complement.membership.forward with inTrace207exact away.right with hx208 . intro hx209have parts := intersection.membership.forward with hx210have away := complement.membership.forward with parts.right211by_contra outside212have inComplement : x ∈ complement(A, C) := complement.membership.backward with⟨parts.left, outside⟩213rw← shape at inComplement214have inner := intersection.membership.forward with inComplement215exact away.right with inner.left216rw equal217exact IsClosed.intersection2 with topology, closedA, (Open.complement_closed with topology, hU)218219-- The pasting lemma: a map continuous on each of two closed pieces220-- covering the space is continuous.221theorem ContinuousMap.pasting (f X T Y S C D : Set)222requires topologyX : IsTopology(X, T)223requires topologyY : IsTopology(Y, S)224requires function : f : X → Y225requires closedC : IsClosed(X, T, C)226requires closedD : IsClosed(X, T, D)227requires whole : C ∪ D = X228requires onC : ContinuousMap(restrict(f, C), C, subspaceTopology(T, C), Y, S)229requires onD : ContinuousMap(restrict(f, D), D, subspaceTopology(T, D), Y, S)230shows ContinuousMap(f, X, T, Y, S)231proof232have hC := closedC.left233have hD := closedD.left234apply ContinuousMap.of_closed_preimages with topologyX, topologyY, function235intros K closedK236have preimageC := ContinuousMap.closed_preimage with onC, closedK237have preimageD := ContinuousMap.closed_preimage with onD, closedK238have equalC := restrict.preimage at f, X, Y, C, K with function, hC239have equalD := restrict.preimage at f, X, Y, D, K with function, hD240rw equalC at preimageC241rw equalD at preimageD242have closedInC := IsClosed.of_closed_subspace with topologyX, closedC,243 preimageC244have closedInD := IsClosed.of_closed_subspace with topologyX, closedD,245 preimageD246have below := functionPreimage.subset at f, X, K247havesplit : functionPreimage(f, X, K) = functionPreimage(f, X, K) ∩ C ∪ functionPreimage(f, X, K) ∩ D248rw [← intersection.union2_distrib, whole]249 symm250exact intersection.eq_left_of_subset with below251rwsplit252exact IsClosed.union2 with topologyX, closedInC, closedInD253254-- Open maps, closed maps, and homeomorphisms.255256predicate OpenMap (f X T Y S : Set) :=257 FunctionBetween(f, X, Y) ∧ (∀ U ∈ T, functionImage(f, U, Y) ∈ S)258259predicate ClosedMap (f X T Y S : Set) :=260 FunctionBetween(f, X, Y) ∧261 (∀ C, IsClosed(X, T, C) → IsClosed(Y, S, functionImage(f, C, Y)))262263-- Under a bijection the image of U is the preimage of U under the inverse.264theorem Bijective.image_eq_preimage (f X Y U : Set)265requires bijective : BijectiveBetween(f, X, Y)266requires hU : U ⊆ X267shows functionImage(f, U, Y) = functionPreimage(converse(f, X, Y), Y, U)268proof269ext y270constructor271 . intro hy272have parts := functionImage.membership.forward with hy273obtain⟨hyY, x, hx, shape⟩:= parts274have back := Bijective.inverse_apply with bijective, (hU with x, hx)275have back2 : converse(f, X, Y)(y) = x276rw shape277exact back278apply functionPreimage.membership.backward279rw back2280exact⟨hyY, hx⟩281 . intro hy282have parts := functionPreimage.membership.forward with hy283have forward := Bijective.apply_inverse with bijective, parts.left284apply functionImage.membership.backward285refine⟨parts.left, converse(f, X, Y)(y), parts.right, ?_⟩286rw forward287rfl288289theorem IsHomeomorphism.open_map (f X T Y S : Set)290requires topology : IsTopology(X, T)291requires homeomorphism : IsHomeomorphism(f, X, T, Y, S)292shows OpenMap(f, X, T, Y, S)293proof294obtain⟨bijective, continuous, inverse⟩:= homeomorphism295constructor296 . exact continuous.left297 . intros U hU298have equal := Bijective.image_eq_preimage with bijective, (IsTopology.subset with topology, hU)299rw equal300exact inverse.right with U, hU301302theorem IsHomeomorphism.closed_map (f X T Y S : Set)303requires homeomorphism : IsHomeomorphism(f, X, T, Y, S)304shows ClosedMap(f, X, T, Y, S)305proof306obtain⟨bijective, continuous, inverse⟩:= homeomorphism307constructor308 . exact continuous.left309 . intros C closed310have equal := Bijective.image_eq_preimage with bijective, closed.left311rw equal312exact ContinuousMap.closed_preimage with inverse, closed313314theorem IsHomeomorphism.of_open_bijection (f X T Y S : Set)315requires topology : IsTopology(X, T)316requires bijective : BijectiveBetween(f, X, Y)317requires continuous : ContinuousMap(f, X, T, Y, S)318requires openMap : OpenMap(f, X, T, Y, S)319shows IsHomeomorphism(f, X, T, Y, S)320proof321refine⟨bijective, continuous, ?_⟩322constructor323 . exact converse.function_of_bijective with bijective324 . intros U hU325have equal := Bijective.image_eq_preimage with bijective, (IsTopology.subset with topology, hU)326rw← equal327exact openMap.right with U, hU328329theorem IsHomeomorphism.of_closed_bijection (f X T Y S : Set)330requires topologyX : IsTopology(X, T)331requires topologyY : IsTopology(Y, S)332requires bijective : BijectiveBetween(f, X, Y)333requires continuous : ContinuousMap(f, X, T, Y, S)334requires closedMap : ClosedMap(f, X, T, Y, S)335shows IsHomeomorphism(f, X, T, Y, S)336proof337refine⟨bijective, continuous, ?_⟩338have inverse := converse.function_of_bijective with bijective339apply ContinuousMap.of_closed_preimages with topologyY, topologyX, inverse340intros C closed341have equal := Bijective.image_eq_preimage with bijective, closed.left342rw← equal343exact closedMap.right with C, closed344345theorem IsHomeomorphism.identity (X T : Set)346requires topology : IsTopology(X, T)347shows IsHomeomorphism(identity(X), X, T, X, T)348proof349have openMap : OpenMap(identity(X), X, T, X, T)350constructor351 . exact identity.function at X352 . intros U hU353have equal := functionImage.identity_of_subset with (IsTopology.subset with topology, hU)354 rwa equal355exact IsHomeomorphism.of_open_bijection with topology, (identity.bijective at X), (ContinuousMap.identity with topology), openMap356357theorem OpenMap.compose (g f X T Y S Z R : Set)358requires topology : IsTopology(X, T)359requires first : OpenMap(f, X, T, Y, S)360requires second : OpenMap(g, Y, S, Z, R)361shows OpenMap(compose(g, f, X, Y, Z), X, T, Z, R)362proof363have fFunction := first.left364have gFunction := second.left365constructor366 . exact compose.function with fFunction, gFunction367 . intros U hU368have hUX := IsTopology.subset with topology, hU369have equal := functionImage.compose with fFunction, gFunction, hUX370rw equal371exact second.right with functionImage(f, U, Y), (first.right with U, hU)372373theorem ClosedMap.compose (g f X T Y S Z R : Set)374requires first : ClosedMap(f, X, T, Y, S)375requires second : ClosedMap(g, Y, S, Z, R)376shows ClosedMap(compose(g, f, X, Y, Z), X, T, Z, R)377proof378have fFunction := first.left379have gFunction := second.left380constructor381 . exact compose.function with fFunction, gFunction382 . intros C closed383have equal := functionImage.compose with fFunction, gFunction, closed.left384rw equal385exact second.right with functionImage(f, C, Y), (first.right with C, closed)386387theorem IsHomeomorphism.compose (g f X T Y S Z R : Set)388requires topologyX : IsTopology(X, T)389requires topologyY : IsTopology(Y, S)390requires first : IsHomeomorphism(f, X, T, Y, S)391requires second : IsHomeomorphism(g, Y, S, Z, R)392shows IsHomeomorphism(compose(g, f, X, Y, Z), X, T, Z, R)393proof394have openF := IsHomeomorphism.open_map with topologyX, first395have openG := IsHomeomorphism.open_map with topologyY, second396have openMap := OpenMap.compose with topologyX, openF, openG397obtain⟨bijectiveF, continuousF, inverseF⟩:= first398obtain⟨bijectiveG, continuousG, inverseG⟩:= second399have bijective := compose.bijective with bijectiveF, bijectiveG400have continuous := ContinuousMap.compose with continuousF, continuousG401exact IsHomeomorphism.of_open_bijection with topologyX, bijective, continuous, openMap402403-- A continuous map from a compact space to a Hausdorff space is closed,404-- so a continuous bijection between them is a homeomorphism.405406theorem IsCompact.continuous_closed_map (f X T Y S : Set)407requires topologyX : IsTopology(X, T)408requires topologyY : IsTopology(Y, S)409requires compact : IsCompact(X, T, X)410requires hausdorff : IsHausdorff(Y, S)411requires continuous : ContinuousMap(f, X, T, Y, S)412shows ClosedMap(f, X, T, Y, S)413proof414constructor415 . exact continuous.left416 . intros C closed417have compactC := IsCompact.closed_subset with topologyX, compact, closed, closed.left418have compactImage := IsCompact.image with continuous, compactC419exact IsCompact.hausdorff_closed with topologyY, hausdorff, compactImage420421theorem IsHomeomorphism.compact_hausdorff (f X T Y S : Set)422requires topologyX : IsTopology(X, T)423requires topologyY : IsTopology(Y, S)424requires compact : IsCompact(X, T, X)425requires hausdorff : IsHausdorff(Y, S)426requires bijective : BijectiveBetween(f, X, Y)427requires continuous : ContinuousMap(f, X, T, Y, S)428shows IsHomeomorphism(f, X, T, Y, S)429proof430have closedMap := IsCompact.continuous_closed_map with topologyX, topologyY, compact, hausdorff, continuous431exact IsHomeomorphism.of_closed_bijection with topologyX, topologyY, bijective, continuous, closedMap432433-- Topological properties carried along maps.434435theorem IsCompact.of_surjection (f X T Y S : Set)436requires continuous : ContinuousMap(f, X, T, Y, S)437requires surjective : SurjectiveBetween(f, X, Y)438requires compact : IsCompact(X, T, X)439shows IsCompact(Y, S, Y)440proof441have function := continuous.left442have image := IsCompact.image with continuous, compact443have whole : functionImage(f, X, Y) = Y444apply Subset.antisymmetric445 . exact functionImage.subset at f, X, Y446 . intros y hy447obtain⟨x, hx, edge⟩:= surjective.right with y, hy448have value := FunctionBetween.apply_value with function, hx, edge449rw← value450exact functionImage.value with function, hx451 rwa whole at image452453theorem IsDense.image (f X T Y S A : Set)454requires topologyX : IsTopology(X, T)455requires topologyY : IsTopology(Y, S)456requires continuous : ContinuousMap(f, X, T, Y, S)457requires surjective : SurjectiveBetween(f, X, Y)458requires hA : A ⊆ X459requires dense : IsDense(X, T, A)460shows IsDense(Y, S, functionImage(f, A, Y))461proof462have function := continuous.left463have equal : closure(X, T, A) = X := dense464have inclusion := ContinuousMap.image_closure with topologyX, topologyY, continuous, hA465rw equal at inclusion466have whole : functionImage(f, X, Y) = Y467apply Subset.antisymmetric468 . exact functionImage.subset at f, X, Y469 . intros y hy470obtain⟨x, hx, edge⟩:= surjective.right with y, hy471have value := FunctionBetween.apply_value with function, hx, edge472rw← value473exact functionImage.value with function, hx474rw whole at inclusion475have inside := closure.subset with topologyY, (functionImage.subset at f, A, Y)476exact Subset.antisymmetric with inside, inclusion477478theorem IsHausdorff.of_homeomorphism (f X T Y S : Set)479requires topologyX : IsTopology(X, T)480requires topologyY : IsTopology(Y, S)481requires homeomorphism : IsHomeomorphism(f, X, T, Y, S)482requires hausdorff : IsHausdorff(X, T)483shows IsHausdorff(Y, S)484proof485have openMap := IsHomeomorphism.open_map with topologyX, homeomorphism486obtain⟨bijective, continuous, inverse⟩:= homeomorphism487have injective := Bijective.injective with bijective488have inverseFunction := converse.function_of_bijective with bijective489intros y1 hy1 y2 hy2 distinct490have hx1 := FunctionBetween.apply_closed with inverseFunction, hy1491have hx2 := FunctionBetween.apply_closed with inverseFunction, hy2492have forward1 := Bijective.apply_inverse with bijective, hy1493have forward2 := Bijective.apply_inverse with bijective, hy2494have distinctX : converse(f, X, Y)(y1) ≠ converse(f, X, Y)(y2)495intro same496apply distinct497rw [← forward1, ← forward2, same]498rfl499obtain⟨U, hU, V, hV, inU, inV, disjoint⟩:= hausdorff with converse(f, X, Y)(y1), hx1, converse(f, X, Y)(y2), hx2, distinctX500have separated := Disjoint.iff.forward with disjoint501have hUX := IsTopology.subset with topologyX, hU502have hVX := IsTopology.subset with topologyX, hV503refine⟨functionImage(f, U, Y), (openMap.right with U, hU), functionImage(f, V, Y), (openMap.right with V, hV), ?_, ?_, ?_⟩504 . apply functionImage.membership.backward505refine⟨hy1, converse(f, X, Y)(y1), inU, ?_⟩506rw forward1507rfl508 . apply functionImage.membership.backward509refine⟨hy2, converse(f, X, Y)(y2), inV, ?_⟩510rw forward2511rfl512 . apply Disjoint.iff.backward513intros z hzU hzV514have partsU := functionImage.membership.forward with hzU515have partsV := functionImage.membership.forward with hzV516obtain⟨hzY, a, ha, shapeA⟩:= partsU517obtain⟨hzY2, b, hb, shapeB⟩:= partsV518have same : f(a) = f(b)519rw [← shapeA, ← shapeB]520rfl521have equal := Injective.apply_cancel with injective, (hUX with a, ha), (hVX with b, hb), same522rw equal at ha523exact separated with b, ha, hb524