{- Set quotients: -} {-# OPTIONS --cubical --no-import-sorts --safe #-} module Cubical.HITs.SetQuotients.Properties where open import Cubical.HITs.SetQuotients.Base open import Cubical.Core.Everything open import Cubical.Foundations.Prelude open import Cubical.Foundations.Isomorphism open import Cubical.Foundations.Equiv open import Cubical.Foundations.HLevels open import Cubical.Foundations.Equiv.HalfAdjoint open import Cubical.Foundations.Univalence open import Cubical.Functions.FunExtEquiv open import Cubical.Data.Sigma open import Cubical.Relation.Nullary open import Cubical.Relation.Binary.Base open import Cubical.HITs.PropositionalTruncation as PropTrunc using (∥_∥; ∣_∣; squash) open import Cubical.HITs.SetTruncation as SetTrunc using (∥_∥₂; ∣_∣₂; squash₂) -- Type quotients private variable : Level A : Type R : A A Type B : A / R Type C : A / R A / R Type D : A / R A / R A / R Type elimEq/ : (Bprop : (x : A / R ) isProp (B x)) {x y : A / R} (eq : x y) (bx : B x) (by : B y) PathP i B (eq i)) bx by elimEq/ {B = B} Bprop {x = x} = J y eq bx by PathP i B (eq i)) bx by) bx by Bprop x bx by) elimProp : ((x : A / R ) isProp (B x)) ((a : A) B ( [ a ])) (x : A / R) B x elimProp Bprop f [ x ] = f x elimProp Bprop f (squash/ x y p q i j) = isOfHLevel→isOfHLevelDep 2 x isProp→isSet (Bprop x)) (g x) (g y) (cong g p) (cong g q) (squash/ x y p q) i j where g = elimProp Bprop f elimProp Bprop f (eq/ a b r i) = elimEq/ Bprop (eq/ a b r) (f a) (f b) i elimProp2 : ((x y : A / R ) isProp (C x y)) ((a b : A) C [ a ] [ b ]) (x y : A / R) C x y elimProp2 Cprop f = elimProp x isPropΠ y Cprop x y)) x elimProp y Cprop [ x ] y) (f x)) elimProp3 : ((x y z : A / R ) isProp (D x y z)) ((a b c : A) D [ a ] [ b ] [ c ]) (x y z : A / R) D x y z elimProp3 Dprop f = elimProp x isPropΠ2 y z Dprop x y z)) x elimProp2 y z Dprop [ x ] y z) (f x)) -- lemma 6.10.2 in hott book []surjective : (x : A / R) ∃[ a A ] [ a ] x []surjective = elimProp x squash) a a , refl ) elim : {B : A / R Type } ((x : A / R) isSet (B x)) (f : (a : A) (B [ a ])) ((a b : A) (r : R a b) PathP i B (eq/ a b r i)) (f a) (f b)) (x : A / R) B x elim Bset f feq [ a ] = f a elim Bset f feq (eq/ a b r i) = feq a b r i elim Bset f feq (squash/ x y p q i j) = isOfHLevel→isOfHLevelDep 2 Bset (g x) (g y) (cong g p) (cong g q) (squash/ x y p q) i j where g = elim Bset f feq rec : {B : Type } (Bset : isSet B) (f : A B) (feq : (a b : A) (r : R a b) f a f b) A / R B rec Bset f feq [ a ] = f a rec Bset f feq (eq/ a b r i) = feq a b r i rec Bset f feq (squash/ x y p q i j) = Bset (g x) (g y) (cong g p) (cong g q) i j where g = rec Bset f feq rec2 : {B : Type } (Bset : isSet B) (f : A A B) (feql : (a b c : A) (r : R a b) f a c f b c) (feqr : (a b c : A) (r : R b c) f a b f a c) A / R A / R B rec2 Bset f feql feqr = rec (isSetΠ _ Bset)) a rec Bset (f a) (feqr a)) a b r funExt (elimProp _ Bset _ _) c feql a b c r))) setQuotUniversalIso : {B : Type } (Bset : isSet B) Iso (A / R B) (Σ[ f (A B) ] ((a b : A) R a b f a f b)) Iso.fun (setQuotUniversalIso Bset) g = a g [ a ]) , λ a b r i g (eq/ a b r i) Iso.inv (setQuotUniversalIso Bset) h = elim x Bset) (fst h) (snd h) Iso.rightInv (setQuotUniversalIso Bset) h = refl Iso.leftInv (setQuotUniversalIso Bset) g = funExt x PropTrunc.elim sur Bset (out (intro g) x) (g x)) sur cong (out (intro g)) (sym (snd sur)) (cong g (snd sur))) ([]surjective x)) where intro = Iso.fun (setQuotUniversalIso Bset) out = Iso.inv (setQuotUniversalIso Bset) setQuotUniversal : {B : Type } (Bset : isSet B) (A / R B) (Σ[ f (A B) ] ((a b : A) R a b f a f b)) setQuotUniversal Bset = isoToEquiv (setQuotUniversalIso Bset) open BinaryRelation -- characterisation of binary functions/operations on set-quotients setQuotUniversal2Iso : {B : Type } (Bset : isSet B) isRefl R Iso (A / R A / R B) (Σ[ _∗_ (A A B) ] ((a a' b b' : A) R a a' R b b' a b a' b')) Iso.fun (setQuotUniversal2Iso {A = A} {R = R} {B = B} Bset isReflR) _∗/_ = _∗_ , h where _∗_ = λ a b [ a ] ∗/ [ b ] h : (a a' b b' : A) R a a' R b b' a b a' b' h a a' b b' ra rb = cong (_∗/ [ b ]) (eq/ _ _ ra) cong ([ a' ] ∗/_) (eq/ _ _ rb) Iso.inv (setQuotUniversal2Iso {A = A} {R = R} {B = B} Bset isReflR) (_∗_ , h) = rec2 Bset _∗_ hleft hright where hleft : a b c R a b (a c) (b c) hleft _ _ c r = h _ _ _ _ r (isReflR c) hright : a b c R b c (a b) (a c) hright a _ _ r = h _ _ _ _ (isReflR a) r Iso.rightInv (setQuotUniversal2Iso {A = A} {R = R} {B = B} Bset isReflR) (_∗_ , h) = Σ≡Prop _ isPropΠ4 λ _ _ _ _ isPropΠ2 λ _ _ Bset _ _) refl Iso.leftInv (setQuotUniversal2Iso {A = A} {R = R} {B = B} Bset isReflR) _∗/_ = funExt₂ (elimProp2 _ _ Bset _ _) λ _ _ refl) setQuotUniversal2 : {B : Type } (Bset : isSet B) isRefl R (A / R A / R B) (Σ[ _∗_ (A A B) ] ((a a' b b' : A) R a a' R b b' a b a' b')) setQuotUniversal2 Bset isReflR = isoToEquiv (setQuotUniversal2Iso Bset isReflR) -- corollary for binary operations -- TODO: prove truncated inverse for effective relations setQuotBinOp : isRefl R (_∗_ : A A A) (∀ a a' b b' R a a' R b b' R (a b) (a' b')) (A / R A / R A / R) setQuotBinOp isReflR _∗_ h = Iso.inv (setQuotUniversal2Iso squash/ isReflR) ((λ a b [ a b ]) , λ _ _ _ _ ra rb eq/ _ _ (h _ _ _ _ ra rb)) setQuotSymmBinOp : isRefl R isTrans R (_∗_ : A A A) (∀ a b a b b a) (∀ a a' b R a a' R (a b) (a' b)) (A / R A / R A / R) setQuotSymmBinOp {A = A} {R = R} isReflR isTransR _∗_ ∗-symm h = setQuotBinOp isReflR _∗_ h' where h' : a a' b b' R a a' R b b' R (a b) (a' b') h' a a' b b' ra rb = isTransR _ _ _ (h a a' b ra) (transport i R (∗-symm b a' i) (∗-symm b' a' i)) (h b b' a' rb)) effective : (Rprop : isPropValued R) (Requiv : isEquivRel R) (a b : A) [ a ] [ b ] R a b effective {A = A} {R = R} Rprop (equivRel R/refl R/sym R/trans) a b p = transport aa≡ab (R/refl _) where helper : A / R hProp _ helper = rec isSetHProp c (R a c , Rprop a c)) c d cd Σ≡Prop _ isPropIsProp) (hPropExt (Rprop a c) (Rprop a d) ac R/trans _ _ _ ac cd) ad R/trans _ _ _ ad (R/sym _ _ cd)))) aa≡ab : R a a R a b aa≡ab i = helper (p i) .fst isEquivRel→effectiveIso : isPropValued R isEquivRel R (a b : A) Iso ([ a ] [ b ]) (R a b) Iso.fun (isEquivRel→effectiveIso {R = R} Rprop Req a b) = effective Rprop Req a b Iso.inv (isEquivRel→effectiveIso {R = R} Rprop Req a b) = eq/ a b Iso.rightInv (isEquivRel→effectiveIso {R = R} Rprop Req a b) _ = Rprop a b _ _ Iso.leftInv (isEquivRel→effectiveIso {R = R} Rprop Req a b) _ = squash/ _ _ _ _ isEquivRel→isEffective : isPropValued R isEquivRel R isEffective R isEquivRel→isEffective Rprop Req a b = isoToIsEquiv (invIso (isEquivRel→effectiveIso Rprop Req a b)) discreteSetQuotients : Discrete A isPropValued R isEquivRel R (∀ a₀ a₁ Dec (R a₀ a₁)) Discrete (A / R) discreteSetQuotients {A = A} {R = R} Adis Rprop Req Rdec = elim a₀ isSetΠ a₁ isProp→isSet (isPropDec (squash/ a₀ a₁)))) discreteSetQuotients' discreteSetQuotients'-eq where discreteSetQuotients' : (a : A) (y : A / R) Dec ([ a ] y) discreteSetQuotients' a₀ = elim a₁ isProp→isSet (isPropDec (squash/ [ a₀ ] a₁))) dis dis-eq where dis : (a₁ : A) Dec ([ a₀ ] [ a₁ ]) dis a₁ with Rdec a₀ a₁ ... | (yes p) = yes (eq/ a₀ a₁ p) ... | (no ¬p) = no λ eq ¬p (effective Rprop Req a₀ a₁ eq ) dis-eq : (a b : A) (r : R a b) PathP i Dec ([ a₀ ] eq/ a b r i)) (dis a) (dis b) dis-eq a b ab = J b ab k PathP i Dec ([ a₀ ] ab i)) (dis a) k) k isPropDec (squash/ _ _) _ _) (eq/ a b ab) (dis b) discreteSetQuotients'-eq : (a b : A) (r : R a b) PathP i (y : A / R) Dec (eq/ a b r i y)) (discreteSetQuotients' a) (discreteSetQuotients' b) discreteSetQuotients'-eq a b ab = J b ab k PathP i (y : A / R) Dec (ab i y)) (discreteSetQuotients' a) k) k funExt x isPropDec (squash/ _ _) _ _)) (eq/ a b ab) (discreteSetQuotients' b) -- Quotienting by the truncated relation is equivalent to quotienting by untruncated relation truncRelIso : Iso (A / R) (A / a b R a b )) Iso.fun truncRelIso = rec squash/ [_] λ _ _ r eq/ _ _ r Iso.inv truncRelIso = rec squash/ [_] λ _ _ PropTrunc.rec (squash/ _ _) λ r eq/ _ _ r Iso.rightInv truncRelIso = elimProp _ squash/ _ _) λ _ refl Iso.leftInv truncRelIso = elimProp _ squash/ _ _) λ _ refl truncRelEquiv : A / R A / a b R a b ) truncRelEquiv = isoToEquiv truncRelIso -- Using this we can obtain a useful characterization of -- path-types for equivalence relations (not prop-valued) -- and their quotients isEquivRel→TruncIso : isEquivRel R (a b : A) Iso ([ a ] [ b ]) R a b isEquivRel→TruncIso {A = A} {R = R} Req a b = compIso (isProp→Iso (squash/ _ _) (squash/ _ _) (cong (Iso.fun truncRelIso)) (cong (Iso.inv truncRelIso))) (isEquivRel→effectiveIso _ _ PropTrunc.propTruncIsProp) ∥R∥eq a b) where open isEquivRel ∥R∥eq : isEquivRel λ a b R a b reflexive ∥R∥eq a = reflexive Req a symmetric ∥R∥eq a b = PropTrunc.map (symmetric Req a b) transitive ∥R∥eq a b c = PropTrunc.map2 (transitive Req a b c)