{-# OPTIONS --lossy-unification #-}
open import GpdCont.Prelude
open import Cubical.Algebra.Group.Base using (GroupStr ; Group)
open import Cubical.Algebra.Group.Properties using (module GroupTheory)
open import Cubical.Algebra.Group.Morphisms using (GroupHom ; IsGroupHom ; GroupEquiv)
open import Cubical.Algebra.Group.MorphismProperties using (isPropIsGroupHom ; makeIsGroupHom ; invGroupEquiv ; GroupEquiv→GroupHom)
open import Cubical.Algebra.Group.GroupPath using (uaGroup)
open import Cubical.Algebra.SymmetricGroup using (Symmetric-Group)
module GpdCont.Delooping.Properties {ℓ} (G : Group ℓ) where
open import GpdCont.Group.Solve using (solveGroup)
private
module G where
open GroupStr (str G) public
open GroupTheory G public
reassoc : (g g′ h : ⟨ G ⟩) → g · (g′ · h · g) · g′ ≡ (g · g′) · h · (g · g′)
reassoc = solveGroup G
·IdLR : (h : ⟨ G ⟩) → 1g · h · 1g ≡ h
·IdLR h = cong (1g ·_) (·IdR h) ∙ ·IdL h
open G using (_·_ ; inv)
open import GpdCont.Experimental.Groups.Base using () renaming (GroupStr to hGroupStr)
open import GpdCont.Delooping.Base G as Delooping using (𝔹)
open import GpdCont.Connectivity using (isPathConnected ; isPathConnected→merePath)
open import GpdCont.Univalence using (ua→)
import GpdCont.Group.FundamentalGroup as FundamentalGroup
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Equiv.Properties hiding (conjugatePathEquiv)
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.GroupoidLaws
open import Cubical.Foundations.Path using (compPath→Square)
open import Cubical.Foundations.Univalence hiding (elimIso ; ua→)
open import Cubical.Data.Sigma
open import Cubical.HITs.SetTruncation as ST using (∥_∥₂)
open import Cubical.HITs.PropositionalTruncation as PT using (∥_∥₁)
open import Cubical.Functions.FunExtEquiv
open import Cubical.Functions.Embedding
isPropSetTruncDelooping : isProp ∥ 𝔹 ∥₂
isPropSetTruncDelooping = ST.elim2 (λ s t → ST.isSetPathImplicit) conn-lemma where
conn-lemma : (s t : 𝔹) → ST.∣ s ∣₂ ≡ ST.∣ t ∣₂
conn-lemma = Delooping.elimProp {B = λ s → (t : 𝔹) → ST.∣ s ∣₂ ≡ ST.∣ t ∣₂}
(λ s → isPropΠ λ t → ST.isSetSetTrunc _ _)
(Delooping.elimProp (λ t → ST.isSetSetTrunc _ _) $ refl {x = ST.∣ Delooping.⋆ ∣₂})
isConnectedDelooping : isContr ∥ 𝔹 ∥₂
isConnectedDelooping = inhProp→isContr ST.∣ 𝔹.⋆ ∣₂ isPropSetTruncDelooping
merePath : (x y : 𝔹) → ∥ x ≡ y ∥₁
merePath = isPathConnected→merePath isConnectedDelooping
deloopingGroupStr : hGroupStr 𝔹
deloopingGroupStr .hGroupStr.is-connected = isConnectedDelooping
deloopingGroupStr .hGroupStr.is-groupoid = Delooping.isGroupoid𝔹
deloopingGroupStr .hGroupStr.pt = Delooping.⋆
coerceLoopCompSquareFiller : ∀ {g h r}
→ g · h ≡ r
→ compSquareFiller (𝔹.loop g) (𝔹.loop h) (𝔹.loop r)
coerceLoopCompSquareFiller {g} {h} {r} p i j = hcomp {φ = i ∨ ~ i ∨ j ∨ ~ j}
(λ where
k (i = i0) → Delooping.loop g j
k (i = i1) → Delooping.loop (p k) j
k (j = i0) → Delooping.⋆
k (j = i1) → Delooping.loop h i
)
(𝔹.loop-comp g h i j)
isPropDeloopingSquare :
{x₀₀ x₀₁ : 𝔹} {x₀₋ : x₀₀ ≡ x₀₁}
{x₁₀ x₁₁ : 𝔹} {x₁₋ : x₁₀ ≡ x₁₁}
{x₋₀ : x₀₀ ≡ x₁₀} {x₋₁ : x₀₁ ≡ x₁₁}
→ isProp (Square x₀₋ x₁₋ x₋₀ x₋₁)
isPropDeloopingSquare = isGroupoid→isPropSquare Delooping.isGroupoid𝔹
private
conjugate : (g : ⟨ G ⟩) → ⟨ G ⟩ → ⟨ G ⟩
conjugate g h = inv g · h · g
conjugateIso : (g : ⟨ G ⟩) → Iso ⟨ G ⟩ ⟨ G ⟩
conjugateIso g .Iso.fun = conjugate g
conjugateIso g .Iso.inv = conjugate (inv g)
conjugateIso g .Iso.rightInv h =
inv g · (inv (inv g) · h · inv g) · g ≡[ i ]⟨ inv g · (G.invInv g i · h · inv g) · g ⟩
inv g · (g · (h · inv g)) · g ≡⟨ G.reassoc (inv g) g h ⟩
(inv g · g) · h · (inv g · g) ≡⟨ cong (λ - → - · h · -) (G.·InvL g) ⟩
G.1g · h · G.1g ≡⟨ G.·IdLR h ⟩
h ∎
conjugateIso g .Iso.leftInv h =
inv (inv g) · (inv g · h · g) · inv g ≡⟨ cong (_· (inv g · h · g) · inv g) (G.invInv g) ⟩
g · (inv g · h · g) · inv g ≡⟨ G.reassoc g (inv g) h ⟩
(g · inv g) · h · (g · inv g) ≡⟨ cong (λ - → - · h · -) (G.·InvR g) ⟩
G.1g · h · G.1g ≡⟨ G.·IdLR h ⟩
h ∎
conjugateEquiv : (g : ⟨ G ⟩) → ⟨ G ⟩ ≃ ⟨ G ⟩
conjugateEquiv g = isoToEquiv $ conjugateIso g
conjugatePath : (g : ⟨ G ⟩) → ⟨ G ⟩ ≡ ⟨ G ⟩
conjugatePath g = ua $ conjugateEquiv g
conjugatePathFiller : ∀ g h → compSquareFiller (conjugatePath g) (conjugatePath h) (conjugatePath $ g · h)
conjugatePathFiller g h = coerceCompSquareFiller $
ua (conjugateEquiv g) ∙ ua (conjugateEquiv h) ≡⟨ sym (uaCompEquiv _ _) ⟩
ua (conjugateEquiv g ∙ₑ conjugateEquiv h) ≡⟨ cong ua $ equivEq $ funExt shuffle ⟩
ua (conjugateEquiv $ g · h) ∎
where
shuffle : ∀ x → inv h · (inv g · x · g) · h ≡ inv (g · h) · x · g · h
shuffle x =
inv h · (inv g · x · g) · h ≡⟨ lemma₁ (inv h) (inv g) x g h ⟩
(inv h · inv g) · x · g · h ≡⟨ cong (λ - → - · x · g · h) (sym $ G.invDistr g h) ⟩
inv (g · h) · x · g · h ∎
where
lemma₁ : (h⁻¹ g⁻¹ x g h : ⟨ G ⟩) → h⁻¹ · (g⁻¹ · x · g) · h ≡ (h⁻¹ · g⁻¹) · x · g · h
lemma₁ = solveGroup G
mulRightIso : (g : ⟨ G ⟩) → Iso ⟨ G ⟩ ⟨ G ⟩
mulRightIso g .Iso.fun = _· g
mulRightIso g .Iso.inv = _· (inv g)
mulRightIso g .Iso.rightInv h = sym (G.·Assoc h (inv g) g) ∙ cong (h ·_) (G.·InvL g) ∙ G.·IdR h
mulRightIso g .Iso.leftInv h = sym (G.·Assoc h g (inv g)) ∙ cong (h ·_) (G.·InvR g) ∙ G.·IdR h
mulRightEquiv : (g : ⟨ G ⟩) → ⟨ G ⟩ ≃ ⟨ G ⟩
mulRightEquiv g = isoToEquiv $ mulRightIso g
mulRightPath : (g : ⟨ G ⟩) → ⟨ G ⟩ ≡ ⟨ G ⟩
mulRightPath g = ua $ mulRightEquiv g
opaque
mulRightPathFiller : ∀ g h → compSquareFiller (mulRightPath g) (mulRightPath h) (mulRightPath $ g · h)
mulRightPathFiller g h = coerceCompSquareFiller $
ua (mulRightEquiv g) ∙ ua (mulRightEquiv h) ≡⟨ sym (uaCompEquiv _ _) ⟩
ua (mulRightEquiv g ∙ₑ mulRightEquiv h) ≡⟨ cong ua $ equivEq $ funExt (λ k → sym (G.·Assoc k g h)) ⟩
ua (mulRightEquiv $ g · h) ∎
Code : 𝔹 → hSet ℓ
Code = Delooping.rec isGroupoidHSet Code[⋆≡⋆] Code[⋆≡_] filler where
Code[⋆≡⋆] : hSet ℓ
Code[⋆≡⋆] .fst = ⟨ G ⟩
Code[⋆≡⋆] .snd = G.is-set
Code[⋆≡_] : ⟨ G ⟩ → Code[⋆≡⋆] ≡ Code[⋆≡⋆]
Code[⋆≡_] g = TypeOfHLevel≡ 2 (mulRightPath g)
filler : ∀ g h → compSquareFiller Code[⋆≡ g ] Code[⋆≡ h ] Code[⋆≡ g · h ]
filler g h = ΣSquareSet (λ _ → isProp→isSet isPropIsSet) (mulRightPathFiller g h)
isSetCode : ∀ x → isSet ⟨ Code x ⟩
isSetCode = str ∘ Code
encode : ∀ {y} → 𝔹.⋆ ≡ y → ⟨ Code y ⟩
encode = J (λ y p → ⟨ Code y ⟩) G.1g
encodeRefl : encode refl ≡ G.1g
encodeRefl = JRefl (λ y p → ⟨ Code y ⟩) G.1g
decode : ∀ {y} → ⟨ Code y ⟩ → 𝔹.⋆ ≡ y
decode {y} = decode' y where
decode' : ∀ y → ⟨ Code y ⟩ → 𝔹.⋆ ≡ y
decode' = Delooping.elimSet (λ x → isSet→ (𝔹.isGroupoid𝔹 𝔹.⋆ x))
𝔹.loop
λ { g → ua→ λ h → 𝔹.loop-comp h g }
decode-encode : ∀ {y} (p : 𝔹.⋆ ≡ y) → decode (encode p) ≡ p
decode-encode = J (λ y p → decode (encode p) ≡ p) $
decode (encode refl) ≡⟨ cong decode encodeRefl ⟩
decode G.1g ≡⟨ Delooping.loop-1 ⟩
refl ∎
encode-decode : ∀ y (c : ⟨ Code y ⟩) → encode (decode c) ≡ c
encode-decode = Delooping.elimProp (λ _ → isPropΠ λ c → isSetCode _ _ _) λ g →
transport refl (G.1g · g) ≡⟨ transportRefl _ ⟩
G.1g · g ≡⟨ G.·IdL g ⟩
g ∎
encodeDecodeIso : ∀ {y} → Iso (𝔹.⋆ ≡ y) ⟨ Code y ⟩
encodeDecodeIso .Iso.fun = encode
encodeDecodeIso .Iso.inv = decode
encodeDecodeIso .Iso.rightInv = encode-decode _
encodeDecodeIso .Iso.leftInv = decode-encode
encodeDecode : ∀ {y} → (𝔹.⋆ ≡ y) ≃ ⟨ Code y ⟩
encodeDecode = isoToEquiv encodeDecodeIso
ΩDelooping≃ : (𝔹.⋆ ≡ 𝔹.⋆) ≃ ⟨ G ⟩
ΩDelooping≃ = encodeDecode {y = 𝔹.⋆}
unloop : 𝔹.⋆ ≡ 𝔹.⋆ → ⟨ G ⟩
unloop = equivFun ΩDelooping≃
loopEquiv : ⟨ G ⟩ ≃ (𝔹.⋆ ≡ 𝔹.⋆)
loopEquiv = invEquiv ΩDelooping≃
isEquivLoop : isEquiv 𝔹.loop
isEquivLoop = equivIsEquiv loopEquiv
π₁ : (x₀ : 𝔹) → Group _
π₁ = FundamentalGroup.π₁ (𝔹 , 𝔹.isGroupoid𝔹)
private
π₁𝔹 : Group _
π₁𝔹 = π₁ 𝔹.⋆
conjugatePathEquiv : {x₀ x₁ : 𝔹} → x₀ ≡ x₁ → GroupEquiv (π₁ x₀) (π₁ x₁)
conjugatePathEquiv = FundamentalGroup.conjugateGroupEquiv (𝔹 , 𝔹.isGroupoid𝔹)
conjugatePathHom : {x₀ x₁ : 𝔹} → x₀ ≡ x₁ → GroupHom (π₁ x₀) (π₁ x₁)
conjugatePathHom p = GroupEquiv→GroupHom $ conjugatePathEquiv p
loopHom : GroupHom G π₁𝔹
loopHom .fst = 𝔹.loop
loopHom .snd .IsGroupHom.pres· g h = sym $ Delooping.loop-∙ g h
loopHom .snd .IsGroupHom.pres1 = Delooping.loop-1
loopHom .snd .IsGroupHom.presinv = Delooping.loop-inv
loopGroupEquiv : GroupEquiv G π₁𝔹
loopGroupEquiv .fst = loopEquiv
loopGroupEquiv .snd = loopHom .snd
unloopGroupEquiv : GroupEquiv π₁𝔹 G
unloopGroupEquiv = invGroupEquiv loopGroupEquiv
unloopGroupHom : GroupHom π₁𝔹 G
unloopGroupHom = GroupEquiv→GroupHom unloopGroupEquiv
_ : unloopGroupHom .fst ≡ unloop
_ = refl
elimSetIso : ∀ {ℓB} {B : 𝔹 → Type ℓB}
→ (∀ x → isSet (B x))
→ Iso (Σ[ b₀ ∈ B 𝔹.⋆ ] (∀ g → PathP (λ i → B (𝔹.loop g i)) b₀ b₀)) (∀ x → B x)
elimSetIso is-set-B .Iso.fun = uncurry $ Delooping.elimSet is-set-B
elimSetIso is-set-B .Iso.inv b = b 𝔹.⋆ , cong b ∘ 𝔹.loop
elimSetIso is-set-B .Iso.rightInv b = funExt (Delooping.elimProp (λ _ → isOfHLevelPathP' 1 (is-set-B _) _ _) refl)
elimSetIso is-set-B .Iso.leftInv (b₀ , p) = refl
elimSetEquiv : ∀ {ℓB} {B : 𝔹 → Type ℓB}
→ (∀ x → isSet (B x))
→ (Σ[ b₀ ∈ B 𝔹.⋆ ] (∀ g → PathP (λ i → B (𝔹.loop g i)) b₀ b₀)) ≃ (∀ x → B x)
elimSetEquiv = isoToEquiv ∘ elimSetIso
elimPropIso : ∀ {ℓB} {B : 𝔹 → Type ℓB}
→ (∀ x → isProp (B x))
→ Iso (B 𝔹.⋆) (∀ x → B x)
elimPropIso is-prop-B .Iso.fun = Delooping.elimProp is-prop-B
elimPropIso is-prop-B .Iso.inv f = f 𝔹.⋆
elimPropIso is-prop-B .Iso.rightInv f = funExt λ x → is-prop-B _ _ (f x)
elimPropIso is-prop-B .Iso.leftInv _ = refl
elimPropEquiv : ∀ {ℓB} {B : 𝔹 → Type ℓB}
→ (∀ x → isProp (B x))
→ (B 𝔹.⋆) ≃ (∀ x → B x)
elimPropEquiv = isoToEquiv ∘ elimPropIso
recEquiv : ∀ {ℓX} {X : hGroupoid ℓX}
→ (Σ[ x₀ ∈ ⟨ X ⟩ ] Σ[ φ ∈ (⟨ G ⟩ → x₀ ≡ x₀) ] ∀ g h → compSquareFiller (φ g) (φ h) (φ $ g · h)) ≃ (𝔹 → ⟨ X ⟩)
recEquiv {X = (X , is-gpd-X)} = rec-equiv , is-equiv where
open IsGroupHom using (pres·)
rec-equiv : _ → _
rec-equiv (x₀ , φ , φ-hom) = Delooping.rec is-gpd-X x₀ φ φ-hom
rec-inv : (𝔹 → X) → (Σ[ x₀ ∈ X ] Σ[ φ ∈ (⟨ G ⟩ → x₀ ≡ x₀) ] ∀ g h → compSquareFiller (φ g) (φ h) (φ $ g · h))
rec-inv f .fst = f 𝔹.⋆
rec-inv f .snd .fst = cong f ∘ 𝔹.loop
rec-inv f .snd .snd = λ g h i j → f (Delooping.loop-comp g h i j)
recIso : Iso _ _
recIso .Iso.fun = rec-equiv
recIso .Iso.inv = rec-inv
recIso .Iso.rightInv f = funExt (Delooping.elim (λ _ → isSet→isGroupoid (is-gpd-X _ _)) refl (λ g i j → f (𝔹.loop g i)) λ g h i j k → f (𝔹.loop-comp g h i j))
recIso .Iso.leftInv (x₀ , φ , φ-comp) = refl
is-equiv : isEquiv rec-equiv
is-equiv = isoToIsEquiv recIso
recEquivHom : ∀ {ℓX} {X : hGroupoid ℓX}
→ (Σ[ x₀ ∈ ⟨ X ⟩ ] GroupHom G (FundamentalGroup.π₁ X x₀)) ≃ (𝔹 → ⟨ X ⟩)
recEquivHom {X} = Σ-cong-equiv-snd (λ x₀ → Σ-cong-equiv-snd $ lemma x₀) ∙ₑ recEquiv where
lemma : ∀ x₀ (φ : ⟨ G ⟩ → x₀ ≡ x₀) →
IsGroupHom (str G) φ (FundamentalGroup.π₁ X x₀ .snd)
≃
((g h : ⟨ G ⟩) → compSquareFiller (φ g) (φ h) (φ $ g · h))
lemma x₀ φ = propBiimpl→Equiv (isPropIsGroupHom _ _) (isPropΠ2 (λ g h → isGroupoid→isPropSquare (str X)))
(λ is-hom g h → coerceCompSquareFiller (sym $ is-hom .IsGroupHom.pres· g h))
(λ mk-comp-sq → makeIsGroupHom λ g h → sym (compSquareFillerUnique (mk-comp-sq g h)))
module _ {ℓ'} {B : 𝔹 → Type ℓ'} where
cong⋆ : {f g : ∀ x → B x} (p : f ≡ g) → PathP (λ i → B 𝔹.⋆) (f 𝔹.⋆) (g 𝔹.⋆)
cong⋆ = cong (λ f → f 𝔹.⋆)
cong⋆-∙ : {f g h : ∀ x → B x} (p : f ≡ g) (q : g ≡ h) → cong⋆ (p ∙ q) ≡ cong⋆ p ∙ cong⋆ q
cong⋆-∙ = cong-∙ (λ f → f 𝔹.⋆)