1-- Continuous maps between bundled spaces: the guard f : X ⇒ Y, the2-- identity, composition, constants, and restrictions, preimages of open and3-- closed sets, the closure inclusion, convergent sequences under a4-- continuous map, compact images, and homeomorphisms5-- Part of Cumulus, the Grace17 mathematics library.6-- Copyright (c) 2026 Grant Passmore.7-- Released under the Apache License 2.0. See LICENSE in the repository root.8-- Authors: Grant Passmore910module Grace.Cumulus.Topology.Continuous11import Structure1213-- f : X ⇒ Y: a function between the carriers of two spaces under which the14-- preimage of every open set is open. The form is a transparent guard, so15-- a hypothesis f : X ⇒ Y also supplies the spaces X and Y and the binders16-- (x : X) and (y : Y). ContinuousMap(f, A, T, B, S) remains the form over17-- separate pieces, bridged below.18predicate Continuous (f X Y : Set) :=19 TopologicalSpace(X) ∧ TopologicalSpace(Y) ∧20 ContinuousMap(f, X.carrier, X.opens, Y.carrier, Y.opens)2122notationguard"_ : _ ⇒ _"=> Continuous2324theorem Continuous.mk (f X Y : Set)25requires source : TopologicalSpace(X)26requires target : TopologicalSpace(Y)27requires function : f : X.carrier → Y.carrier28requires preimages :29∀ V ∈ Y.opens, functionPreimage(f, X.carrier, V) ∈ X.opens30shows f : X ⇒ Y31proof32unfold Continuous33refine⟨source, target, ?_⟩34unfold ContinuousMap35exact⟨function, preimages⟩3637theorem Continuous.of_projections (f X Y : Set)38requires spaceX : TopologicalSpace(X)39requires spaceY : TopologicalSpace(Y)40requires continuous : ContinuousMap(f, X.carrier, X.opens, Y.carrier, Y.opens)41shows f : X ⇒ Y42proof43unfold Continuous44exact⟨spaceX, spaceY, continuous⟩4546theorem Continuous.of_parts (f A T B S : Set)47requires topologyA : IsTopology(A, T)48requires topologyB : IsTopology(B, S)49requires continuous : ContinuousMap(f, A, T, B, S)50shows f : TopologicalSpace.mk(A, T) ⇒ TopologicalSpace.mk(B, S)51proof52have spaceA := TopologicalSpace.of_parts with topologyA53have spaceB := TopologicalSpace.of_parts with topologyB54unfold Continuous55refine⟨spaceA, spaceB, ?_⟩56 topology_projections5758section ContinuityLaws59variable (f X Y : Set)60hypothesis continuous : f : X ⇒ Y6162theorem Continuous.source63shows TopologicalSpace(X)64proof65obtain⟨source, rest⟩:= continuous66exact source6768theorem Continuous.target69shows TopologicalSpace(Y)70proof71obtain⟨source, target, rest⟩:= continuous72exact target7374-- The bridge to the form over separate pieces is an instance, so `with *`75-- reads it off the guard.76instance Continuous.parts77shows ContinuousMap(f, X.carrier, X.opens, Y.carrier, Y.opens)78proof79obtain⟨source, target, engine⟩:= continuous80exact engine8182theorem Continuous.function_between83shows f : X.carrier → Y.carrier84proof85have engine := Continuous.parts with continuous86exact ContinuousMap.function with engine8788theorem Continuous.apply_mem (x : X)89shows f(x) ∈ Y90proof91have function := Continuous.function_between with continuous92have xIn : x ∈ X byassumption93exact FunctionBetween.apply_closed with function, xIn9495theorem Continuous.preimage_open (V : Set)96requiresopen : Open(Y, V)97shows Open(X, functionPreimage(f, X.carrier, V))98proof99have spaceX := Continuous.source with continuous100have engine := Continuous.parts with continuous101have member := Open.mem withopen102exact Open.of_mem with spaceX, (ContinuousMap.preimage with engine, member)103104theorem Continuous.preimage_closed (C : Set)105requires closed : Closed(Y, C)106shows Closed(X, functionPreimage(f, X.carrier, C))107proof108have spaceX := Continuous.source with continuous109have engine := Continuous.parts with continuous110have pieces := Closed.parts with closed111have closedPreimage := ContinuousMap.closed_preimage with engine, pieces112exact Closed.of_parts with spaceX, closedPreimage113114-- A continuous map sends the closure of A into the closure of its image.115theorem Continuous.image_closure (A : Set)116requires hA : A ⊆ X117shows functionImage(f, closure(X, A), Y.carrier) ⊆118 closure(Y, functionImage(f, A, Y.carrier))119proof120have engine := Continuous.parts with continuous121rw [closure.parts, closure.parts]122exact ContinuousMap.image_closure with*123124-- A continuous map carries a convergent sequence to a convergent sequence.125theorem Continuous.map_converges (u : Set) (x : X)126requires converges : u ⇝ x127shows compose(f, u, ℕ, X.carrier, Y.carrier) ⇝ f(x)128proof129have function := Continuous.function_between with continuous130have sequence := Converges.sequence with converges131have point := Converges.limit_mem with converges132have composite := compose.function with sequence, function133have image := FunctionBetween.apply_closed with function, point134have eventually : ∀ V, Open(Y, V) → f(x) ∈ V →135∃ N ∈ ℕ, ∀ n ∈ ℕ, N ≤ n →136apply(compose(f, u, ℕ, X.carrier, Y.carrier), n) ∈ V137intros V open hfx138have preimageOpen := Continuous.preimage_open with continuous, open139have inPreimage : x ∈ functionPreimage(f, X.carrier, V)140apply functionPreimage.membership.backward141exact⟨point, hfx⟩142have hit := Converges.eventually with converges, preimageOpen, inPreimage143obtain⟨N, hN, tail⟩:= hit144witness N145refine⟨hN, ?_⟩146intros n hn order147have term := tail with n, hn, order148have parts := functionPreimage.membership.forward with term149have value := compose.apply at f, u, ℕ, X.carrier, Y.carrier, n with*150rw value151exact parts.right152exact Converges.of_eventually with*153154-- The continuous image of a compact set is compact.155theorem Compact.continuous_image (A : Set)156requires compact : Compact(X, A)157shows Compact(Y, functionImage(f, A, Y.carrier))158proof159have engine := Continuous.parts with continuous160have pieces := Compact.parts with compact161exact Compact.of_parts with (IsCompact.image with engine, pieces)162163end ContinuityLaws164165theorem Continuous.id (X : Set)166requires space : TopologicalSpace(X)167shows identity(X.carrier) : X ⇒ X168proof169unfold Continuous170refine⟨space, space, ?_⟩171exact ContinuousMap.identity with*172173theorem Continuous.comp (f g X Y Z : Set)174requires first : f : X ⇒ Y175requires second : g : Y ⇒ Z176shows compose(g, f, X.carrier, Y.carrier, Z.carrier) : X ⇒ Z177proof178have engineF := Continuous.parts with first179have engineG := Continuous.parts with second180unfold Continuous181have spaceX := Continuous.source with first182have spaceZ := Continuous.target with second183refine⟨spaceX, spaceZ, ?_⟩184exact ContinuousMap.compose with engineF, engineG185186theorem Continuous.constant (X Y y : Set)187requires spaceX : TopologicalSpace(X)188requires spaceY : TopologicalSpace(Y)189requires hy : y ∈ Y190shows constantFunction(X.carrier, Y.carrier, y) : X ⇒ Y191proof192unfold Continuous193refine⟨spaceX, spaceY, ?_⟩194exact ContinuousMap.constant with*195196theorem Continuous.of_closed_preimages (f X Y : Set)197requires spaceX : TopologicalSpace(X)198requires spaceY : TopologicalSpace(Y)199requires function : f : X.carrier → Y.carrier200requires closed :201∀ C, Closed(Y, C) → Closed(X, functionPreimage(f, X.carrier, C))202shows f : X ⇒ Y203proof204have pieces : ∀ C, IsClosed(Y.carrier, Y.opens, C) →205 IsClosed(X.carrier, X.opens, functionPreimage(f, X.carrier, C))206intros C closedC207exact Closed.parts with (closed with C, (Closed.of_parts with closedC))208unfold Continuous209refine⟨spaceX, spaceY, ?_⟩210exact ContinuousMap.of_closed_preimages with*211212-- Homeomorphisms: continuous bijections with a continuous inverse.213predicate Homeomorphism (f X Y : Set) :=214 Continuous(f, X, Y) ∧ BijectiveBetween(f, X.carrier, Y.carrier) ∧215 Continuous(converse(f, X.carrier, Y.carrier), Y, X)216217theorem Homeomorphism.continuous (f X Y : Set)218requires homeomorphism : Homeomorphism(f, X, Y)219shows f : X ⇒ Y220proof221obtain⟨continuous, rest⟩:= homeomorphism222exact continuous223224theorem Homeomorphism.bijective (f X Y : Set)225requires homeomorphism : Homeomorphism(f, X, Y)226shows BijectiveBetween(f, X.carrier, Y.carrier)227proof228obtain⟨continuous, bijective, inverse⟩:= homeomorphism229exact bijective230231instance Homeomorphism.parts (f X Y : Set)232requires homeomorphism : Homeomorphism(f, X, Y)233shows IsHomeomorphism(f, X.carrier, X.opens, Y.carrier, Y.opens)234proof235obtain⟨continuous, bijective, inverse⟩:= homeomorphism236have forward := Continuous.parts with continuous237have backward := Continuous.parts with inverse238unfold IsHomeomorphism239exact⟨bijective, forward, backward⟩240241theorem Homeomorphism.of_parts (f X Y : Set)242requires spaceX : TopologicalSpace(X)243requires spaceY : TopologicalSpace(Y)244requires homeomorphism :245 IsHomeomorphism(f, X.carrier, X.opens, Y.carrier, Y.opens)246shows Homeomorphism(f, X, Y)247proof248obtain⟨bijective, forward, backward⟩:= homeomorphism249have continuous : f : X ⇒ Y250unfold Continuous251exact⟨spaceX, spaceY, forward⟩252have inverse : converse(f, X.carrier, Y.carrier) : Y ⇒ X253unfold Continuous254exact⟨spaceY, spaceX, backward⟩255unfold Homeomorphism256exact⟨continuous, bijective, inverse⟩257258theorem Homeomorphism.symm (f X Y : Set)259requires homeomorphism : Homeomorphism(f, X, Y)260shows Homeomorphism(converse(f, X.carrier, Y.carrier), Y, X)261proof262have continuous := Homeomorphism.continuous with homeomorphism263have spaceX := Continuous.source with continuous264have spaceY := Continuous.target with continuous265have engine := Homeomorphism.parts with homeomorphism266apply Homeomorphism.of_parts with spaceY, spaceX267exact Continuity.IsHomeomorphism.inverse with engine268