\import Category
\import Category.Limit
\import Equiv
\import Function.Meta
\import Logic
\import Logic.Meta
\import Logic.Unique
\import Order.Lattice
\import Order.PartialOrder
\import Paths
\import Paths.Meta
\import Relation.Equivalence
\open PrecatWithBprod
\type Subobj {C : Precat} (obj : C)
=> Quotient {Mono {C} { | cod => obj }} \lam m1 m2 => \Sigma (f : Hom m1.dom m2.dom) (m2.f ∘ f = m1.f) (g : Hom m2.dom m1.dom) (m1.f ∘ g = m2.f)
\func inso~ {C : Precat} {obj : C} (m : Mono {C} { | cod => obj }) : Subobj m.cod
=> in~ m
\instance SubobjPoset {C : Precat} (obj : C) : Poset (Subobj obj)
| <= (s1 s2 : Subobj obj) : \Prop \with {
| in~ m1, in~ m2 => ∃ (f : Hom m1.dom m2.dom) (m2.f ∘ f = m1.f)
| in~ m, ~-equiv x y r => propExt (\lam (inP (f,xf=m)) => inP (r.1 ∘ f, inv o-assoc *> pmap (∘ _) r.2 *> xf=m))
(\lam (inP (f,yf=m)) => inP (r.3 ∘ f, inv o-assoc *> pmap (∘ _) r.4 *> yf=m))
| ~-equiv x y r, in~ m => propExt (\lam (inP (f,mf=x)) => inP (f ∘ r.3, inv o-assoc *> pmap (∘ _) mf=x *> r.4))
(\lam (inP (f,mf=y)) => inP (f ∘ r.1, inv o-assoc *> pmap (∘ _) mf=y *> r.2))
}
| <=-refl {x} => \case \elim x \with {
| in~ m => inP (id, id-right)
}
| <=-transitive {x} {y} {z} => \case \elim x, \elim y, \elim z, \elim __, \elim __ \with {
| in~ m1, in~ m2, in~ m3, inP p, inP q => inP (q.1 ∘ p.1, inv o-assoc *> pmap (∘ _) q.2 *> p.2)
}
| <=-antisymmetric {x} {y} => \case \elim x, \elim y, \elim __, \elim __ \with {
| in~ m1, in~ m2, inP p, inP q => path \lam i => ~-equiv m1 m2 (p.1,p.2,q.1,q.2) i
}
\where {
\lemma extractMap {obj : C} {f g : Mono {C} { | cod => obj }} (f<=g : inso~ f <= inso~ g) : \Sigma (h : Hom f.dom g.dom) (g.f ∘ h = f)
=> TruncP.remove (\lam p q => ext $ g.isMono $ p.2 *> inv q.2) f<=g
\func subobj-iso {obj : C} {f g : Mono {C} { | cod => obj }}
(f<=g : inso~ f <= inso~ g) (g<=f : inso~ g <= inso~ f) : Iso {C} {f.dom} {g.dom} \cowith
| f => (SubobjPoset.extractMap f<=g).1
| hinv => (SubobjPoset.extractMap g<=f).1
| hinv_f => f.isMono $ inv o-assoc *> pmap (∘ _) (SubobjPoset.extractMap g<=f).2 *> (SubobjPoset.extractMap f<=g).2 *> inv id-right
| f_hinv => g.isMono $ inv o-assoc *> pmap (∘ _) (SubobjPoset.extractMap f<=g).2 *> (SubobjPoset.extractMap g<=f).2 *> inv id-right
}
\lemma ~-unsoequiv {C : Precat} {obj : C} {m1 m2 : Mono {C} { | cod => obj }} (p : inso~ m1 = inso~ m2)
: ∃ (f : Hom m1.dom m2.dom) (m2.f ∘ f = m1.f) (g : Hom m2.dom m1.dom) (m1.f ∘ g = m2.f)
=> \case =_<= p, =_<= (inv p) \with {
| inP r1, inP r2 => inP (r1.1,r1.2,r2.1,r2.2)
}
\where {
\lemma left-right=id (r : \Sigma (f : Hom m1.dom m2.dom) (m2.f ∘ f = m1.f) (g : Hom m2.dom m1.dom) (m1.f ∘ g = m2.f)) : r.3 ∘ r.1 = id
=> m1.isMono $ inv o-assoc *> pmap (∘ _) r.4 *> r.2 *> inv id-right
\lemma right-left=id (r : \Sigma (f : Hom m1.dom m2.dom) (m2.f ∘ f = m1.f) (g : Hom m2.dom m1.dom) (m1.f ∘ g = m2.f)) : r.1 ∘ r.3 = id
=> m2.isMono $ inv o-assoc *> pmap (∘ _) r.2 *> r.4 *> inv id-right
}
\sfunc subobjTop {C : Precat} {obj : C} : Subobj obj
=> inso~ idIso
\instance SubobjectSemilattice {C : PrecatWithPullbacks} (obj : C) : TopMeetSemilattice
| Poset => SubobjPoset obj
| meet (x y : Subobj obj) : Subobj obj \with {
| in~ m1, in~ m2 => inso~ $ Mono.comp m1 $ Mono_pullback (pullback m1.f m2.f) m2
| in~ m, ~-equiv x y r => <=-antisymmetric
(inP (pbMap pbProj1 (r.1 ∘ pbProj2) $ pbCoh *> pmap (∘ _) (inv r.2) *> o-assoc, o-assoc *> pmap (_ ∘) pbBeta1))
(inP (pbMap pbProj1 (r.3 ∘ pbProj2) $ pbCoh *> pmap (∘ _) (inv r.4) *> o-assoc, o-assoc *> pmap (_ ∘) pbBeta1))
| ~-equiv x y r, in~ m => <=-antisymmetric
(inP (pbMap (r.1 ∘ pbProj1) pbProj2 $ inv o-assoc *> pmap (∘ _) r.2 *> pbCoh, o-assoc *> pmap (_ ∘) pbBeta1 *> inv o-assoc *> pmap (∘ _) r.2))
(inP (pbMap (r.3 ∘ pbProj1) pbProj2 $ inv o-assoc *> pmap (∘ _) r.4 *> pbCoh, o-assoc *> pmap (_ ∘) pbBeta1 *> inv o-assoc *> pmap (∘ _) r.4))
}
| meet-left {x} {y} => \case \elim x, \elim y \with {
| in~ m1, in~ m2 => inP (pbProj1, idp)
}
| meet-right {x} {y} => \case \elim x, \elim y \with {
| in~ m1, in~ m2 => inP (pbProj2, inv pbCoh)
}
| meet-univ {x} {y} {z} => \case \elim x, \elim y, \elim z, \elim __, \elim __ \with {
| in~ xm, in~ ym, in~ zm, inP z<=x, inP z<=y => inP (pbMap z<=x.1 z<=y.1 $ z<=x.2 *> inv z<=y.2, o-assoc *> pmap (_ ∘) pbBeta1 *> z<=x.2)
}
| top => subobjTop
| top-univ {x} => rewrite (\peval subobjTop {_} {obj}) \case \elim x \with {
| in~ m => inP (m, id-left)
}
\func subobjLifts {C : Precat} {x y : C} (f : Hom x y) (s : Subobj y) : \Prop \elim s
| in~ m => ∃ (g : Hom x m.dom) (m.f ∘ g = f)
| ~-equiv m1 m2 r => propExt
(\lam (inP (g,p)) => inP (r.1 ∘ g, inv o-assoc *> pmap (∘ _) r.2 *> p))
(\lam (inP (g,p)) => inP (r.3 ∘ g, inv o-assoc *> pmap (∘ _) r.4 *> p))
\where {
\func toMap {s : Subobj y} {m : Mono {C} { | cod => y}} (p : s = inso~ m) (l : subobjLifts f s) : \Sigma (g : Hom x m.dom) (m.f ∘ g = f) \elim p
| idp => TruncP.remove (\lam s s' => ext $ m.isMono $ s.2 *> inv s'.2) l
}
\lemma subobjLifts_id_top {C : Precat} {x : C} {s : Subobj x} : subobjLifts id s <-> (s = subobjTop) \elim s
| in~ m => rewrite (\peval subobjTop {_} {x}) (<=-antisymmetric $ inP (m, id-left), \lam r => =_<= (inv r))
\sfunc subobjEq {C : PrecatWithBprod} (c : C) : Subobj (Bprod c c)
=> inso~ diagonal-splitMono
\lemma subobjEq-lifts {C : PrecatWithBprod} {x c : C} {f g : Hom x c} : subobjLifts (pair f g) (subobjEq c) <-> (f = g)
=> rewrite (\peval subobjEq c)
(\lam (inP (h,p)) => inv beta1 *> pmap (proj1 ∘) (inv p) *> inv o-assoc *> pmap (∘ h) (beta1 *> inv beta2) *> o-assoc *> pmap (proj2 ∘) p *> beta2,
\lam p => inP (f, pair-unique (inv o-assoc *> pmap (∘ _) beta1 *> id-left *> inv beta1) (inv o-assoc *> pmap (∘ _) beta2 *> id-left *> p *> inv beta2)))
\func subobjPullback {C : PrecatWithPullbacks} {x y : C} (h : Hom x y) (s : Subobj y) : Subobj x \elim s
| in~ m => inso~ $ Mono_pullback (pullback h m.f) m
| ~-equiv m1 m2 r => <=-antisymmetric
(inP (pbMap pbProj1 (r.1 ∘ pbProj2) $ pbCoh *> pmap (∘ _) (inv r.2) *> o-assoc, pbBeta1))
(inP (pbMap pbProj1 (r.3 ∘ pbProj2) $ pbCoh *> pmap (∘ _) (inv r.4) *> o-assoc, pbBeta1))
\lemma subobjPullback-char {C : PrecatWithPullbacks} {s m : Mono {C}} {sub : Subobj s.cod} (p : sub = inso~ s) {h : Hom m.cod s.cod} (q : subobjPullback h sub = inso~ m)
: Contr (Pullback h s.f m.dom m) \elim p
| idp => \case ~-unsoequiv {_} {_} {Mono_pullback _ s} q \with {
| inP r => \new Contr {
| center => \new Pullback {
| pbProj2 => pbProj2 ∘ r.3
| pbCoh => pmap (h ∘) (inv r.4) *> inv o-assoc *> pmap (∘ _) pbCoh *> o-assoc
| pbMap p1 p2 c => r.1 ∘ pbMap p1 p2 c
| pbBeta1 => inv o-assoc *> pmap (∘ _) r.2 *> pbBeta1
| pbBeta2 => o-assoc *> pmap (_ ∘) (inv o-assoc *> pmap (∘ _) (~-unsoequiv.left-right=id {_} {_} {Mono_pullback _ s} r) *> id-left) *> pbBeta2
| pbEta e _ => m.isMono e
}
| contraction P => exts (s.isMono $ inv o-assoc *> pmap (∘ _) (inv pbCoh) *> o-assoc *> pmap (_ ∘) r.4 *> pbCoh,
\lam p1 p2 c => m.isMono $ inv o-assoc *> pmap (∘ _) r.2 *> pbBeta1 *> inv P.pbBeta1)
}
}
\lemma subobjPullback-lifts {C : PrecatWithPullbacks} {x y z : C} {f : Hom x y} {g : Hom y z} {s : Subobj z}
: subobjLifts f (subobjPullback g s) <-> subobjLifts (g ∘ f) s \elim s
| in~ m => (\lam (inP (h,p)) => inP (pbProj2 ∘ h, inv o-assoc *> pmap (∘ h) (inv pbCoh) *> o-assoc *> pmap (g ∘) p),
\lam (inP (h,p)) => inP (pbMap f h (inv p), pbBeta1))
\lemma subobjLifts_top {C : PrecatWithPullbacks} {x y : C} {f : Hom x y} {s : Subobj y}
: subobjLifts f s <-> (subobjPullback f s = subobjTop)
=> transport (subobjLifts __ _ <-> _) id-right $ <->trans (<->sym subobjPullback-lifts) subobjLifts_id_top
\lemma subobjPullback_id {C : PrecatWithPullbacks} {x : C} {s : Subobj x}
: subobjPullback id s = s \elim s
| in~ m => <=-antisymmetric (inP (pbProj2, inv pbCoh *> id-left)) (inP (pbMap m id $ id-left *> inv id-right, pbBeta1))
\lemma subobjPullback_o {C : PrecatWithPullbacks} {x y z : C} {f : Hom x y} {g : Hom y z} {s : Subobj z}
: subobjPullback (g ∘ f) s = subobjPullback f (subobjPullback g s) \elim s
| in~ m => <=-antisymmetric
(inP (pbMap pbProj1 (pbMap (f ∘ pbProj1) pbProj2 (inv o-assoc *> pbCoh)) (inv pbBeta1), pbBeta1))
(inP (pbMap pbProj1 (pbProj2 ∘ pbProj2) $ o-assoc *> pmap (g ∘) pbCoh *> inv o-assoc *> pmap (∘ _) pbCoh *> o-assoc, pbBeta1))
\lemma subobjPullback-top {C : PrecatWithPullbacks} {x y : C} {f : Hom x y} {s : Subobj y} (p : s = inso~ idIso) : subobjPullback f s = inso~ idIso \elim p
| idp => <=-antisymmetric (inP (pbProj1, id-left)) (inP (pbMap id f (id-right *> inv id-left), pbBeta1))
\lemma subobjPullback_top {C : PrecatWithPullbacks} {x y : C} {f : Hom x y} : subobjPullback f subobjTop = subobjTop
=> subobjPullback-top (\peval subobjTop {_} {y}) *> inv (\peval subobjTop {_} {x})
\lemma subobjPullback-self {C : PrecatWithPullbacks} {h : Mono {C}} {s : Subobj h.cod} (p : s = inso~ h) : subobjPullback h.f s = inso~ idIso \elim p
| idp => <=-antisymmetric (inP (pbProj1, id-left)) (inP (pbMap id id idp, pbBeta1))
\func subobjPullback_Iso-equiv {C : PrecatWithPullbacks} (h : Iso {C}) : QEquiv {Subobj h.cod} {Subobj h.dom} \cowith
| f => subobjPullback h.f
| ret => subobjPullback h.hinv
| ret_f s => inv subobjPullback_o *> pmap (subobjPullback __ s) h.f_hinv *> subobjPullback_id
| f_sec s => inv subobjPullback_o *> pmap (subobjPullback __ s) h.hinv_f *> subobjPullback_id
\func subobjPullback_Iso {C : PrecatWithPullbacks} (h : Iso {C}) {s : Subobj h.cod} {m : Mono {C} { | cod => h.cod }} (p : s = inso~ m)
: subobjPullback h.f s = inso~ (Mono.comp h.reverse m) \elim p
| idp => <=-antisymmetric
(inP (pbProj2, o-assoc *> pmap (_ ∘) (inv pbCoh) *> inv o-assoc *> pmap (∘ _) h.hinv_f *> id-left))
(inP (pbMap (h.hinv ∘ m) id $ inv o-assoc *> pmap (∘ _) h.f_hinv *> id-left *> inv id-right, pbBeta1))