\import Function.Meta
\import Logic
\import Logic.Meta
\import Meta
\import Operations
\import Order.Directed
\import Order.Lattice
\import Order.PartialOrder
\import Paths.Meta
\import Set.Subset
\import Topology.TopSpace
\instance TopSpaceHasProduct : HasProduct TopSpace
| Product => ProductTopSpace
\instance ProductTopSpace (X Y : TopSpace) : TopSpace (\Sigma X Y)
| isOpen W => ∀ {s : W} ∃ (U : X.isOpen) (U s.1) (V : Y.isOpen) (V s.2) ∀ {x : U} {y : V} (W (x,y))
| open-top _ => inP (top, open-top, (), top, open-top, (), \lam _ _ => ())
| open-inter {W} {W'} f g (Ws,W's) => \case f Ws, g W's \with {
| inP (U,Uo,Ux,V,Vo,Vy,h), inP (U',U'o,U'x,V',V'o,V'y,h') => inP (U ∧ U', open-inter Uo U'o, (Ux,U'x), V ∧ V', open-inter Vo V'o, (Vy,V'y), \lam (Ux,U'x) (Vy,V'y) => (h Ux Vy, h' U'x V'y))
}
| open-Union So (inP (W,SW,Ws)) => \case So SW Ws \with {
| inP (U,Uo,Ux,V,Vo,Vy,h) => inP (U, Uo, Ux, V, Vo, Vy, \lam Ux Vy => inP (W, SW, h Ux Vy))
}
\where {
\open ContMap
\func proj1 {X Y : TopSpace} : ContMap (X ⨯ Y) X \cowith
| func s => s.1
| func-cont Uo => \lam Ux => inP (_, Uo, Ux, top, open-top, (), \lam Ux _ => Ux)
\func proj2 {X Y : TopSpace} : ContMap (X ⨯ Y) Y \cowith
| func s => s.2
| func-cont Uo => \lam Uy => inP (top, open-top, (), _, Uo, Uy, \lam _ Uy => Uy)
\func tuple {X Y Z : TopSpace} (f : ContMap X Y) (g : ContMap X Z) : ContMap X (Y ⨯ Z) \cowith
| func x => (f x, g x)
| func-cont {W} Wo => X.cover-open \lam w => \case Wo w \with {
| inP (U,Uo,Ufx,V,Vo,Vgx,h) => inP (_, open-inter (f.func-cont Uo) (g.func-cont Vo), (Ufx,Vgx), \lam (Ufx,Vgx) => h Ufx Vgx)
}
\func prod {X X' Y Y' : TopSpace} (f : ContMap X Y) (f' : ContMap X' Y') : ContMap (X ⨯ X') (Y ⨯ Y')
=> tuple (f ∘ proj1) (f' ∘ proj2)
\where {
\lemma isDense {X X' Y Y' : TopSpace} {f : ContMap X Y} {g : ContMap X' Y'} (fd : f.IsDense) (gd : g.IsDense) : ContMap.IsDense {prod f g}
=> \lam Uo Ux => \case Uo Ux \with {
| inP (U1,U1o,U1x,U2,U2o,U2y,h) => \case fd U1o U1x, gd U2o U2y \with {
| inP (_, inP (x',idp), U1fx'), inP (_, inP (y',idp), U2gy') => inP (_, inP ((x',y'), idp), h U1fx' U2gy')
}
}
\lemma isWeaklyDense {X X' Y Y' : TopSpace} {f : ContMap X Y} {g : ContMap X' Y'} (fd : f.IsWeaklyDense) (gd : g.IsWeaklyDense) : ContMap.IsWeaklyDense {prod f g}
=> \lam Uo c (y,Uy) => \case Uo Uy \with {
| inP (U1,U1o,U1y,U2,U2o,U2y,h) => fd U1o (\lam (_, inP (x1,idp), U1fx1) => gd U2o (\lam (_, inP (x2,idp), U2gx2) => c (_, inP ((x1,x2), idp), h U1fx1 U2gx2)) (y.2,U2y)) (y.1,U1y)
}
\lemma isEmbedding {X X' Y Y' : TopSpace} {f : ContMap X Y} {g : ContMap X' Y'} (fd : f.IsTopEmbedding) (gd : g.IsTopEmbedding) : ContMap.IsTopEmbedding {prod f g}
=> (topEmbedding-char {prod f g}).2 \lam Uo Uxy => \case Uo Uxy \with {
| inP (U1,U1o,U1x,U2,U2o,U2y,h) => \case f.topEmbedding-char.1 fd U1o U1x, g.topEmbedding-char.1 gd U2o U2y \with {
| inP (V1,V1o,V1fx,p1), inP (V2,V2o,V2gy,p2) => inP (Set.Prod V1 V2, Prod-open V1o V2o, (V1fx,V2gy), \lam (q1,q2) => h (p1 q1) (p2 q2))
}
}
\lemma isDenseEmbedding {X X' Y Y' : TopSpace} {f : ContMap X Y} {g : ContMap X' Y'} (fd : f.IsDenseTopEmbedding) (gd : g.IsDenseTopEmbedding) : ContMap.IsDenseTopEmbedding {prod f g}
=> (isDense fd.1 gd.1, isEmbedding fd.2 gd.2)
}
}
\lemma Prod-open {X Y : TopSpace} {U : Set X} (Uo : isOpen U) {V : Set Y} (Vo : isOpen V) : isOpen (Set.Prod U V)
=> \lam {s} (Us,Vs) => inP (U, Uo, Us, V, Vo, Vs, \lam Ux Vy => (Ux,Vy))
\lemma contAt-tuple {X Y Z : TopSpace} {f : X -> Y} {g : X -> Z} {x : X} (fc : IsContAt f x) (gc : IsContAt g x) : IsContAt (\lam x => (f x, g x)) x
=> \lam {W} Wo W0 => \case Wo W0 \with {
| inP (U,Uo,Ufx,V,Vo,Vgx,g) => \case fc Uo Ufx, gc Vo Vgx \with {
| inP (U',U'o,U'x,p), inP (V',V'o,V'x,q) => inP (U' ∧ V', open-inter U'o V'o, (U'x,V'x), MeetSemilattice.meet-monotone p q <=∘ \lam s => g s.1 s.2)
}
}
\lemma limit-tuple {I : DirectedSet} {X Y : TopSpace} {f : I -> X} {x : X} (fl : X.IsLimit f x) {g : I -> Y} {y : Y} (gl : Y.IsLimit g y)
: TopSpace.IsLimit (\lam n => (f n, g n)) (x,y)
=> \lam Wo Wxy => \case Wo Wxy \with {
| inP (U,Uo,Ux,V,Vo,Vy,e) => \case fl Uo Ux, gl Vo Vy \with {
| inP (N,Ne), inP (M,Me) => \case isDirected N M \with {
| inP (K,N<=K,M<=K) => inP (K, \lam K<=n => e (Ne $ N<=K <=∘ K<=n) (Me $ M<=K <=∘ K<=n))
}
}
}
\lemma cont2-limit {I : DirectedSet} {X Y Z : TopSpace} {f : I -> X} {g : I -> Y} {lx : X} {ly : Y}
(px : X.IsLimit f lx) (py : Y.IsLimit g ly) (h : ContMap (X ⨯ Y) Z) : Z.IsLimit (\lam n => h (f n, g n)) (h (lx,ly))
=> cont-limit (limit-tuple px py) h
\lemma denseSet_<= {X : TopSpace} {Y : HausdorffTopSpace} {P : JoinSemilattice Y} (jc : ContMap (Y ⨯ Y) Y \lam s => s.1 ∨ s.2)
{S : Set X} (Sd : IsDenseSet S) (f g : ContMap X Y) (p : \Pi {x : X} -> S x -> f x <= g x) {x : X} : f x <= g x
=> join-left <=∘ =_<= (denseSet-lift-unique Sd (jc ContMap.∘ ProductTopSpace.tuple f g) g \lam Sx => <=-antisymmetric (join-univ (p Sx) <=-refl) join-right)
\lemma dense_<= {X Y : TopSpace} {Z : HausdorffTopSpace} {P : JoinSemilattice Z} (jc : ContMap (Z ⨯ Z) Z \lam s => s.1 ∨ s.2)
(f : ContMap X Y) (fd : f.IsDense) (g h : ContMap Y Z) (p : \Pi (x : X) -> g (f x) <= h (f x)) (y : Y) : g y <= h y
=> denseSet_<= jc fd g h \lam (inP (x,q)) => rewriteI q (p x)
\lemma weaklyDenseSet_<= {X : TopSpace} {Y : StronglyHausdorffTopSpace} {P : JoinSemilattice Y} (jc : ContMap (Y ⨯ Y) Y \lam s => s.1 ∨ s.2)
{S : Set X} (Sd : IsWeaklyDenseSet S) (f g : ContMap X Y) (p : \Pi {x : X} -> S x -> f x <= g x) {x : X} : f x <= g x
=> join-left <=∘ =_<= (weaklyDenseSet-lift-unique Sd (jc ContMap.∘ ProductTopSpace.tuple f g) g \lam Sx => <=-antisymmetric (join-univ (p Sx) <=-refl) join-right)
\lemma weaklyDense_<= {X Y : TopSpace} {Z : StronglyHausdorffTopSpace} {P : JoinSemilattice Z} (jc : ContMap (Z ⨯ Z) Z \lam s => s.1 ∨ s.2)
(f : ContMap X Y) (fd : f.IsWeaklyDense) (g h : ContMap Y Z) (p : \Pi (x : X) -> g (f x) <= h (f x)) (y : Y) : g y <= h y
=> weaklyDenseSet_<= jc fd g h \lam (inP (x,q)) => rewriteI q (p x)
\lemma hausdorff-char {X : TopSpace} : (\Pi {x y : X} -> ∀ {U V : isOpen} (U x) (V y) ∃ (U ∧ V) -> x = y) <-> (ProductTopSpace X X).IsClosed (\lam s => s.1 = s.2)
=> (\lam f {s} sl => f \lam Uo Vo Us Vs => TruncP.map (sl (Prod-open Uo Vo) (Us,Vs)) \lam (t,p,(Ut,Vt)) => (t.1, (Ut, rewrite p Vt)),
\lam f {x} {y} c => f {x,y} \lam {W} Wo Wxy => \case Wo Wxy \with {
| inP (U,Uo,Ux,V,Vo,Vy,h) => \case c Uo Vo Ux Vy \with {
| inP (z,(Uz,Vz)) => inP ((z,z), idp, h Uz Vz)
}
})