1-- The product of two topological spaces: a set is open when every point2-- has an open box inside it. The coordinate projections are continuous,3-- and open boxes are open4-- Part of Cumulus, the Grace17 mathematics library.5-- Copyright (c) 2026 Grant Passmore.6-- Released under the Apache License 2.0. See LICENSE in the repository root.7-- Authors: Grant Passmore89module Grace.Cumulus.Topology.Product10import Subspace1112-- The product topology.13def productTopology (X T Y S : Set) : Set:=14 { W ∈𝒫(X × Y) |∀ p ∈ W, ∃ U ∈ T, ∃ V ∈ S, p ∈ U × V ∧ U × V ⊆ W }1516theorem productTopology.box (X T Y S U V : Set)17requires topologyX : IsTopology(X, T)18requires topologyY : IsTopology(Y, S)19requires hU : U ∈ T20requires hV : V ∈ S21shows U × V ∈ productTopology(X, T, Y, S)22proof23apply productTopology.membership.backward24have inside := product.monotone with (IsTopology.subset with topologyX, hU), (IsTopology.subset with topologyY, hV)25refine⟨(powerset.membership_iff.backward with inside), ?_⟩26intros p hp27refine⟨U, hU, V, hV, hp, (Subset.reflexive at U × V)⟩2829theorem productTopology.topology (X T Y S : Set)30requires topologyX : IsTopology(X, T)31requires topologyY : IsTopology(Y, S)32shows IsTopology(X × Y, productTopology(X, T, Y, S))33proof34constructor35 . intros W hW36have parts := productTopology.membership.forward with hW37exact parts.left38 . constructor39 . exact productTopology.box with topologyX, topologyY, (IsTopology.whole with topologyX), (IsTopology.whole with topologyY)40 . constructor41 . intros F hF42apply productTopology.membership.backward43constructor44 . apply powerset.membership_iff.backward45apply union.subset46intros W hW47have parts := productTopology.membership.forward with (hF with W, hW)48exact powerset.membership_iff.forward with parts.left49 . intros p hp50obtain⟨W, hW, hpW⟩:= union.membership.forward with hp51have parts := productTopology.membership.forward with (hF with W, hW)52obtain⟨U, hU, V, hV, inBox, boxInside⟩:= parts.right with p, hpW53refine⟨U, hU, V, hV, inBox, ?_⟩54exact Subset.transitive with boxInside, (union.subset_of_member with hW)55 . intros W1 hW1 W2 hW256have parts1 := productTopology.membership.forward with hW157have parts2 := productTopology.membership.forward with hW258have inside1 := powerset.membership_iff.forward with parts1.left59apply productTopology.membership.backward60constructor61 . apply powerset.membership_iff.backward62exact Subset.transitive with (intersection.subset_left at W1, W2), inside163 . intros p hp64have both := intersection.membership.forward with hp65obtain⟨U1, hU1, V1, hV1, inBox1, boxInside1⟩:= parts1.right with p, both.left66obtain⟨U2, hU2, V2, hV2, inBox2, boxInside2⟩:= parts2.right with p, both.right67have boxes := product.intersection at U1, U2, V1, V268refine⟨U1 ∩ U2, (IsTopology.intersection2 with topologyX, hU1, hU2), V1 ∩ V2, (IsTopology.intersection2 with topologyY, hV1, hV2), ?_, ?_⟩69 . rw boxes70exact intersection.membership.backward with⟨inBox1, inBox2⟩71 . rw boxes72exact intersection.monotone with boxInside1, boxInside27374-- Projections are continuous: the preimage of U is the box U × Y.75theorem firstProjection.continuous (X T Y S : Set)76requires topologyX : IsTopology(X, T)77requires topologyY : IsTopology(Y, S)78shows ContinuousMap(firstProjection(X, Y), X × Y, productTopology(X, T, Y, S), X, T)79proof80have function := firstProjection.function at X, Y81constructor82 . exact function83 . intros U hU84have inside := IsTopology.subset with topologyX, hU85have same : functionPreimage(firstProjection(X, Y), X × Y, U) = U × Y86ext p87constructor88 . intro hp89have parts := functionPreimage.membership.forward with hp90obtain⟨bound, x, hx, y, hy, shape⟩:= product.membership.forward with parts.left91have value := firstProjection.pair with hx, hy92rw [shape, value] at parts93rw shape94exact product.pair with parts.right, hy95 . intro hp96obtain⟨bound, x, hx, y, hy, shape⟩:= product.membership.forward with hp97have hxX := inside with x, hx98have value := firstProjection.pair with hxX, hy99apply functionPreimage.membership.backward100rw [shape, value]101exact⟨(product.pair with hxX, hy), hx⟩102rw same103exact productTopology.box with topologyX, topologyY, hU, (IsTopology.whole with topologyY)104105theorem secondProjection.continuous (X T Y S : Set)106requires topologyX : IsTopology(X, T)107requires topologyY : IsTopology(Y, S)108shows ContinuousMap(secondProjection(X, Y), X × Y, productTopology(X, T, Y, S), Y, S)109proof110have function := secondProjection.function at X, Y111constructor112 . exact function113 . intros V hV114have inside := IsTopology.subset with topologyY, hV115have same : functionPreimage(secondProjection(X, Y), X × Y, V) = X × V116ext p117constructor118 . intro hp119have parts := functionPreimage.membership.forward with hp120obtain⟨bound, x, hx, y, hy, shape⟩:= product.membership.forward with parts.left121have value := secondProjection.pair with hx, hy122rw [shape, value] at parts123rw shape124exact product.pair with hx, parts.right125 . intro hp126obtain⟨bound, x, hx, y, hy, shape⟩:= product.membership.forward with hp127have hyY := inside with y, hy128have value := secondProjection.pair with hx, hyY129apply functionPreimage.membership.backward130rw [shape, value]131exact⟨(product.pair with hx, hyY), hy⟩132rw same133exact productTopology.box with topologyX, topologyY, (IsTopology.whole with topologyX), hV134