1-- Spaces built from spaces and the properties of a space: subspaces,2-- products, the real line and the plane as values; compactness, the3-- Hausdorff and T1 properties, connectedness, and their laws, with the4-- tube lemma, Heine–Borel, compact subsets of Hausdorff spaces, and the5-- uniqueness of limits in their textbook statements6-- 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.Spaces12import Continuous13import Plane1415-- The subspace on a subset, the product of two spaces, the real line, and16-- the plane, each a constructed space whose projections are the carrier17-- and topology over separate pieces.18def subspace (X A : Set) : Set:=19 TopologicalSpace.mk(A, subspaceTopology(TopologicalSpace.opens(X), A))20def productSpace (X Y : Set) : Set:=21 TopologicalSpace.mk(22 TopologicalSpace.carrier(X) × TopologicalSpace.carrier(Y),23 productTopology(TopologicalSpace.carrier(X), TopologicalSpace.opens(X),24 TopologicalSpace.carrier(Y), TopologicalSpace.opens(Y)))25def realLine : Set:= TopologicalSpace.mk(ℝ, realTopology)26def plane : Set:= TopologicalSpace.mk(ℝ × ℝ, planeTopology)2728theorem subspace.carrier (X A : Set)29shows TopologicalSpace.carrier(subspace(X, A)) = A30proof31unfold subspace32 topology_projections3334theorem subspace.opens (X A : Set)35shows TopologicalSpace.opens(subspace(X, A)) =36 subspaceTopology(TopologicalSpace.opens(X), A)37proof38unfold subspace39 topology_projections4041theorem productSpace.carrier (X Y : Set)42shows TopologicalSpace.carrier(productSpace(X, Y)) =43 TopologicalSpace.carrier(X) × TopologicalSpace.carrier(Y)44proof45unfold productSpace46 topology_projections4748theorem productSpace.opens (X Y : Set)49shows TopologicalSpace.opens(productSpace(X, Y)) =50 productTopology(TopologicalSpace.carrier(X), TopologicalSpace.opens(X),51 TopologicalSpace.carrier(Y), TopologicalSpace.opens(Y))52proof53unfold productSpace54 topology_projections5556theorem realLine.carrier57shows TopologicalSpace.carrier(realLine) = ℝ58proof59unfold realLine60 topology_projections6162theorem realLine.opens63shows TopologicalSpace.opens(realLine) = realTopology64proof65unfold realLine66 topology_projections6768theorem plane.carrier69shows TopologicalSpace.carrier(plane) = ℝ × ℝ70proof71unfold plane72 topology_projections7374theorem plane.opens75shows TopologicalSpace.opens(plane) = planeTopology76proof77unfold plane78 topology_projections7980-- Each construction is a space; these are instances, so the hypothesis on81-- a constructed space is synthesized from those on its pieces.82instance subspace.space (X A : Set)83requires space : TopologicalSpace(X)84requires hA : A ⊆ X85shows TopologicalSpace(subspace(X, A))86proof87have parts := TopologicalSpace.parts with space88have topology := subspaceTopology.topology with parts, hA89unfold subspace90exact TopologicalSpace.of_parts with topology9192instance productSpace.space (X Y : Set)93requires spaceX : TopologicalSpace(X)94requires spaceY : TopologicalSpace(Y)95shows TopologicalSpace(productSpace(X, Y))96proof97have partsX := TopologicalSpace.parts with spaceX98have partsY := TopologicalSpace.parts with spaceY99have topology := productTopology.topology with partsX, partsY100unfold productSpace101exact TopologicalSpace.of_parts with topology102103instance realLine.space104shows TopologicalSpace(realLine)105proof106unfold realLine107exact TopologicalSpace.of_parts with realTopology.topology108109instance plane.space110shows TopologicalSpace(plane)111proof112unfold plane113exact TopologicalSpace.of_parts with planeTopology.topology114115theorem plane.eq_product116shows plane = productSpace(realLine, realLine)117proof118unfold plane119unfold productSpace120unfold planeTopology121rw [realLine.carrier, realLine.opens]122rfl123124section CompactLaws125variable (X : Set)126hypothesis space : TopologicalSpace(X)127128theorem Compact.subset_carrier (A : Set)129requires compact : Compact(X, A)130shows A ⊆ X131proof132have pieces := Compact.parts with compact133exact Compact.IsCompact.subset with pieces134135instance Compact.empty_set136shows Compact(X, ∅)137proof138exact Compact.of_parts with (Compact.IsCompact.empty at X.carrier, X.opens)139140instance Compact.point (x : X)141shows Compact(X, {x})142proof143have xIn : x ∈ X byassumption144have point := Compact.IsCompact.singleton at X.carrier, X.opens, x with xIn145exact Compact.of_parts with point146147instance Compact.union (A B : Set)148requires compactA : Compact(X, A)149requires compactB : Compact(X, B)150shows Compact(X, A ∪ B)151proof152have piecesA := Compact.parts with compactA153have piecesB := Compact.parts with compactB154exact Compact.of_parts with (Compact.IsCompact.union2 with piecesA, piecesB)155156theorem Compact.of_finite (A : Set)157requires finite : Finite(A)158requires hA : A ⊆ X159shows Compact(X, A)160proof161have engine := CompactMore.IsCompact.finite at X.carrier, X.opens, A with*162exact Compact.of_parts with engine163164-- A closed subset of a compact set is compact.165theorem Compact.of_closed_subset (A C : Set)166requires compact : Compact(X, A)167requires closed : Closed(X, C)168requires hCA : C ⊆ A169shows Compact(X, C)170proof171have parts := TopologicalSpace.parts with space172have piecesA := Compact.parts with compact173have piecesC := Closed.parts with closed174have engine := Compact.IsCompact.closed_subset with parts, piecesA, piecesC,175 hCA176exact Compact.of_parts with engine177178theorem Compact.space_iff179shows Compact(X) ↔ Compact(X, X.carrier)180proof181constructor182 . intro compact183exact Compact.of_parts with (Compact.space_parts with compact)184 . intro compact185exact Compact.of_space_parts with (Compact.parts with compact)186187theorem Compact.space_of_finite188requires finite : Finite(X.carrier)189shows Compact(X)190proof191apply Compact.of_space_parts192exact IsCompact.whole_of_finite at X.carrier, X.opens with finite193194end CompactLaws195196section HausdorffLaws197variable (X : Set)198hypothesis space : TopologicalSpace(X)199hypothesis hausdorff : Hausdorff(X)200201-- Distinct points have disjoint open neighborhoods.202theorem Hausdorff.separate (x y : X)203requires distinct : x ≠ y204shows∃ U ∈ X.opens, ∃ V ∈ X.opens,205 x ∈ U ∧ y ∈ V ∧ Disjoint(U, V)206proof207have parts := Hausdorff.parts with hausdorff208have xIn : x ∈ X byassumption209have yIn : y ∈ X byassumption210exact parts with x, xIn, y, yIn, distinct211212instance Hausdorff.point_closed (x : X)213shows Closed(X, {x})214proof215have parts := TopologicalSpace.parts with space216have pieces := Hausdorff.parts with hausdorff217have xIn : x ∈ X byassumption218have engine := Subspace.IsHausdorff.singleton_closed with parts, pieces, xIn219exact Closed.of_parts with engine220221theorem Hausdorff.t1_space222shows T1Space(X)223proof224have pieces := Hausdorff.parts with hausdorff225apply T1Space.of_parts226exact Separation.IsHausdorff.t1 with pieces227228-- A compact subset of a Hausdorff space is closed.229theorem Compact.closed_of_hausdorff (K : Set)230requires compact : Compact(X, K)231shows Closed(X, K)232proof233have parts := TopologicalSpace.parts with space234have pieces := Hausdorff.parts with hausdorff235have compactK := Compact.parts with compact236have engine := IsCompact.hausdorff_closed with parts, pieces, compactK237exact Closed.of_parts with engine238239-- In a compact Hausdorff space the compact subsets are the closed ones.240theorem Compact.iff_closed (K : Set)241requires compact : Compact(X)242shows Compact(X, K) ↔ Closed(X, K)243proof244constructor245 . intro compactK246exact Compact.closed_of_hausdorff with*247 . intro closed248have whole := Compact.of_parts with (Compact.space_parts with compact)249have inside := Closed.subset with closed250exact Compact.of_closed_subset with whole, closed, inside251252-- A sequence has at most one limit.253theorem Converges.unique (u : Set) (x y : X)254requires first : u ⇝ x255requires second : u ⇝ y256shows x = y257proof258by_contra distinct259obtain⟨U, hU, V, hV, hxU, hyV, disjoint⟩:= Hausdorff.separate with*260have separated := Disjoint.iff.forward with disjoint261have openU := Open.of_mem with hU262have openV := Open.of_mem with hV263obtain⟨N, hN, tailU⟩:= Converges.eventually with first, openU, hxU264obtain⟨M, hM, tailV⟩:= Converges.eventually with second, openV, hyV265have order := LessEqual.total at N, M266cases order with below | above267 . have inU := tailU with M, hM, below268have inV := tailV with M, hM, (LessEqual.reflexive at M)269exact separated with u(M), inU, inV270 . have inU := tailU with N, hN, (LessEqual.reflexive at N)271have inV := tailV with N, hN, above272exact separated with u(N), inU, inV273274end HausdorffLaws275276section ConnectedLaws277variable (X : Set)278hypothesis space : TopologicalSpace(X)279280theorem Connected.clopen_trivial (U : Set)281requires connected : Connected(X)282requiresopen : Open(X, U)283requires closed : Closed(X, U)284shows U =∅∨ U = X.carrier285proof286have parts := TopologicalSpace.parts with space287have pieces := Connected.parts with connected288have member := Open.mem withopen289have closedU := Closed.parts with closed290exact Connected.IsConnected.clopen with parts, pieces, member, closedU291292theorem Connected.iff_clopen_trivial293shows Connected(X) ↔294∀ U, Open(X, U) → Closed(X, U) → U =∅∨ U = X.carrier295proof296have parts := TopologicalSpace.parts with space297have characterization := Connected.IsConnected.iff_clopen with parts298constructor299 . intros connected U open closed300exact Connected.clopen_trivial with*301 . intro trivial302have pieces : ∀ U ∈ X.opens, IsClosed(X.carrier, X.opens, U) →303 U =∅∨ U = X.carrier304intros U hU closedU305have openU := Open.of_mem with hU306have closedB := Closed.of_parts with closedU307exact trivial with U, openU, closedB308exact Connected.of_parts with (characterization.backward with pieces)309310theorem ConnectedSubset.subset_carrier (A : Set)311requires connected : ConnectedSubset(X, A)312shows A ⊆ X313proof314have pieces := ConnectedSubset.parts with connected315exact Connected.IsConnectedSubset.subset with pieces316317-- A subset is connected exactly when it is connected as a subspace.318theorem ConnectedSubset.iff_subspace_connected (A : Set)319requires hA : A ⊆ X320shows ConnectedSubset(X, A) ↔ Connected(subspace(X, A))321proof322have parts := TopologicalSpace.parts with space323have characterization := Connected.IsConnectedSubset.iff_subspace with parts,324 hA325constructor326 . intro connected327have pieces := ConnectedSubset.parts with connected328unfold subspace329exact Connected.of_mk with (characterization.forward with pieces)330 . intro connected331have pieces := Connected.parts with connected332rw [subspace.carrier, subspace.opens] at pieces333exact ConnectedSubset.of_parts with (characterization.backward with pieces)334335end ConnectedLaws336337-- The continuous image of a connected space is connected.338theorem Connected.continuous_image (f X Y : Set)339requires continuous : f : X ⇒ Y340requires connected : Connected(X)341shows ConnectedSubset(Y, functionImage(f, X.carrier, Y.carrier))342proof343have parts := TopologicalSpace.parts with (Continuous.source with continuous)344have engine := Continuous.parts with continuous345have pieces := Connected.parts with connected346have target := Continuous.target with continuous347have image := Connected.IsConnected.image with parts, engine, pieces348exact ConnectedSubset.of_parts with target, image349350theorem ConnectedSubset.continuous_image (f X Y A : Set)351requires continuous : f : X ⇒ Y352requires connected : ConnectedSubset(X, A)353shows ConnectedSubset(Y, functionImage(f, A, Y.carrier))354proof355have engine := Continuous.parts with continuous356have pieces := ConnectedSubset.parts with connected357have target := Continuous.target with continuous358have image := Connected.IsConnectedSubset.image with engine, pieces359exact ConnectedSubset.of_parts with target, image360361-- Subspaces: the inclusion and restrictions are continuous, and the362-- Hausdorff and T1 properties pass to subspaces.363theorem Continuous.inclusion (X A : Set)364requires space : TopologicalSpace(X)365requires hA : A ⊆ X366shows inclusionMap(A, X.carrier) : subspace(X, A) ⇒ X367proof368have parts := TopologicalSpace.parts with space369have engine := ContinuousMap.inclusion with parts, hA370have spaceA : TopologicalSpace(subspace(X, A)) := subspace.space with*371have shifted : ContinuousMap(inclusionMap(A, X.carrier),372 TopologicalSpace.carrier(subspace(X, A)),373 TopologicalSpace.opens(subspace(X, A)), X.carrier, X.opens)374rw [subspace.carrier, subspace.opens]375exact engine376exact Continuous.of_projections with spaceA, space, shifted377378theorem Continuous.restrict (f X Y A : Set)379requires continuous : f : X ⇒ Y380requires hA : A ⊆ X381shows restrict(f, A) : subspace(X, A) ⇒ Y382proof383have spaceX := Continuous.source with continuous384have spaceY := Continuous.target with continuous385have engine := Continuous.parts with continuous386have restricted := ContinuousMap.restrict with engine, hA387have spaceA : TopologicalSpace(subspace(X, A)) := subspace.space with*388have shifted : ContinuousMap(restrict(f, A),389 TopologicalSpace.carrier(subspace(X, A)),390 TopologicalSpace.opens(subspace(X, A)), Y.carrier, Y.opens)391rw [subspace.carrier, subspace.opens]392exact restricted393exact Continuous.of_projections with spaceA, spaceY, shifted394395instance Hausdorff.subspace_of (X A : Set)396requires space : TopologicalSpace(X)397requires hausdorff : Hausdorff(X)398requires hA : A ⊆ X399shows Hausdorff(subspace(X, A))400proof401have pieces := Hausdorff.parts with hausdorff402unfold subspace403exact Hausdorff.of_mk with (Separation.IsHausdorff.subspace with pieces, hA)404405theorem T1Space.subspace_of (X A : Set)406requires space : TopologicalSpace(X)407requires t1 : T1Space(X)408requires hA : A ⊆ X409shows T1Space(subspace(X, A))410proof411have pieces := T1Space.parts with t1412unfold subspace413exact T1Space.of_mk with (Separation.IsT1Space.subspace with pieces, hA)414415-- Products: boxes are open, the projections are continuous, the product416-- of Hausdorff spaces is Hausdorff, and the product of compact sets is417-- compact (the tube lemma).418theorem Open.box (X Y U V : Set)419requires spaceX : TopologicalSpace(X)420requires spaceY : TopologicalSpace(Y)421requires openU : Open(X, U)422requires openV : Open(Y, V)423shows Open(productSpace(X, Y), U × V)424proof425have partsX := TopologicalSpace.parts with spaceX426have partsY := TopologicalSpace.parts with spaceY427have memberU := Open.mem with openU428have memberV := Open.mem with openV429have box := productTopology.box with partsX, partsY, memberU, memberV430unfold productSpace431exact Open.of_mk with (productTopology.topology with partsX, partsY), box432433theorem Continuous.fst (X Y : Set)434requires spaceX : TopologicalSpace(X)435requires spaceY : TopologicalSpace(Y)436shows firstProjection(X.carrier, Y.carrier) : productSpace(X, Y) ⇒ X437proof438have partsX := TopologicalSpace.parts with spaceX439have partsY := TopologicalSpace.parts with spaceY440have engine := Product.firstProjection.continuous with partsX, partsY441have spaceP := productSpace.space with spaceX, spaceY442have shifted : ContinuousMap(firstProjection(X.carrier, Y.carrier),443 TopologicalSpace.carrier(productSpace(X, Y)),444 TopologicalSpace.opens(productSpace(X, Y)), X.carrier, X.opens)445rw [productSpace.carrier, productSpace.opens]446exact engine447exact Continuous.of_projections with spaceP, spaceX, shifted448449theorem Continuous.snd (X Y : Set)450requires spaceX : TopologicalSpace(X)451requires spaceY : TopologicalSpace(Y)452shows secondProjection(X.carrier, Y.carrier) : productSpace(X, Y) ⇒ Y453proof454have partsX := TopologicalSpace.parts with spaceX455have partsY := TopologicalSpace.parts with spaceY456have engine := Product.secondProjection.continuous with partsX, partsY457have spaceP := productSpace.space with spaceX, spaceY458have shifted : ContinuousMap(secondProjection(X.carrier, Y.carrier),459 TopologicalSpace.carrier(productSpace(X, Y)),460 TopologicalSpace.opens(productSpace(X, Y)), Y.carrier, Y.opens)461rw [productSpace.carrier, productSpace.opens]462exact engine463exact Continuous.of_projections with spaceP, spaceY, shifted464465instance Hausdorff.prod (X Y : Set)466requires spaceX : TopologicalSpace(X)467requires spaceY : TopologicalSpace(Y)468requires hausdorffX : Hausdorff(X)469requires hausdorffY : Hausdorff(Y)470shows Hausdorff(productSpace(X, Y))471proof472have partsX := TopologicalSpace.parts with spaceX473have partsY := TopologicalSpace.parts with spaceY474have piecesX := Hausdorff.parts with hausdorffX475have piecesY := Hausdorff.parts with hausdorffY476unfold productSpace477have product := Separation.IsHausdorff.product with partsX, partsY, piecesX, piecesY478exact Hausdorff.of_mk with product479480theorem Compact.prod (X Y A B : Set)481requires spaceX : TopologicalSpace(X)482requires spaceY : TopologicalSpace(Y)483requires compactA : Compact(X, A)484requires compactB : Compact(Y, B)485shows Compact(productSpace(X, Y), A × B)486proof487have partsX := TopologicalSpace.parts with spaceX488have partsY := TopologicalSpace.parts with spaceY489have piecesA := Compact.parts with compactA490have piecesB := Compact.parts with compactB491have product := Tube.IsCompact.product with partsX, partsY, piecesA, piecesB492unfold productSpace493have topology := productTopology.topology with partsX, partsY494exact Compact.of_mk with topology, product495496-- The real line: Hausdorff, with closed intervals closed and compact497-- (Heine–Borel), closed rectangles compact in the plane, and ε–δ498-- continuity the continuity of the line into itself.499instance realLine.hausdorff500shows Hausdorff(realLine)501proof502unfold realLine503exact Hausdorff.of_mk with realTopology.hausdorff504505instance Closed.interval (A B : Real)506shows Closed(realLine, closedInterval(A, B))507proof508unfold realLine509exact Closed.of_mk with realTopology.topology, (closedInterval.closed at A, B)510511theorem Compact.interval (A B : Real)512requiresordered : A ≤ B513shows Compact(realLine, closedInterval(A, B))514proof515unfold realLine516have compact := closedInterval.compact withordered517exact Compact.of_mk with realTopology.topology, compact518519theorem Compact.rectangle (A B C D : Real)520requires orderedX : A ≤ B521requires orderedY : C ≤ D522shows Compact(plane, closedInterval(A, B) × closedInterval(C, D))523proof524unfold plane525have compact := closedRectangle.compact with orderedX, orderedY526exact Compact.of_mk with planeTopology.topology, compact527528theorem Continuous.iff_real_line (f : Set)529shows Continuous(f) ↔ f : realLine ⇒ realLine530proof531have characterization := Continuous.continuous_map at f532constructor533 . intro continuous534have engine := characterization.forward with continuous535unfold realLine536have topology := realTopology.topology537exact Continuous.of_parts with*538 . intro continuous539have engine := Continuous.parts with continuous540rw [realLine.carrier, realLine.opens] at engine541exact characterization.backward with engine542