No git information available.

Some circle equivalences

This is a work in progress jointly with Marc Bezem. Some of the following proofs are collapsed or hidden to reduce the size of the document. Nevertheless, the reader can click on them to open the full description. Pictures are also clickable.

In this entry, we want to show some equivalences between the circle and other higher inductive types.

{-# OPTIONS --without-K #-}
open import Agda.Primitive using ( Level ; lsuc; lzero; _⊔_ )

open import MiniHoTT hiding (;base;loop;S¹-rec;S¹-βrec;S¹-ind;S¹-βind;neg)
module _ where

type

The circle is the higher inductive type with one point and one no trivial path called path as we can see in the following picture.

path Figure 1. The circle type .

Definition

-- Definition of the Circle S¹ using an Agda hack.
module _ where
  private
    data !S¹ : Type₀ where
      !base : !S¹

   : Type₀
   = !S¹

  base : 
  base = !base

  -- Nontrivial path on the circle.
  postulate
    loop : base == base
  -- Def. loop^2
  
    :  {} {A : Type } {a : A}
     a == a
    --------
     a == a

  p ² = p · p

Recursion principle

Recursion principle on points:

  -- Def.
  S¹-rec
    :  {}
     (A : Type )
     (a : A)
     (p : a == a)
    --------------
     (  A)

  S¹-rec A a p !base = a

Recursion on paths:

  -- Postulate.
  postulate
    S¹-βrec
      :  {}
       (A : Type )
       (a : A)
       (p : a == a)
      -----------------------------
       ap (S¹-rec A a p) loop == p

Induction principle

Induction principle on points:

  -- Def.
  S¹-ind
    :  {} (P :   Type )
     (x : P base)
     (x == x [ P  loop ])
    ------------------------
     ((t : )  P t)

  S¹-ind P x p !base = x

Induction principle on paths:

  -- Postulate.
  postulate
    S¹-βind
      :  {} (P :   Type )
       (x : P base)
       (p : x == x [ P  loop ])
      -------------------------------
       apd (S¹-ind P x p) loop == p

pS type

The pS type as the figure below shows, it is a circle with two edges in opposite direction between two points. Notice this HIT is just different form the suspension of booleans (Σ 2) by reversing one arrow.

path Figure 2. pS Type.

-- Definition of pS type using an Agda hack.
module _ where
  private
    data #!pS : Type lzero where
      #!pS₀ : #!pS
      #!pS₁ : #!pS

    data !pS : Type lzero where
      !ps : #!pS  (Unit  Unit)  !pS

  pS : Type₀
  pS = !pS

  pS₀ : pS
  pS₀ = !ps #!pS₀ _

  pS₁ : pS
  pS₁ = !ps #!pS₁ _

  postulate
    p₀₁ : pS₀ == pS₁
    p₁₀ : pS₁ == pS₀

Recursion principle

Recursion principle on points:

  -- Def.
  pS-rec
    : (C : Type₀)
     (c₀ c₁ : C)
     (p₀₁'  : c₀ == c₁)
     (p₁₀'  : c₁ == c₀)
    --------------------
     (pS  C)

  pS-rec C c₀ c₁ p₀₁' p₁₀' (!ps #!pS₀ x₁) = c₀
  pS-rec C c₀ c₁ p₀₁' p₁₀' (!ps #!pS₁ x₁) = c₁

Recursion principle on paths:

  -- Postulate.
  postulate
    pS-βrec₀₁
      : (C : Type₀)
       (c₀ c₁ : C)
       (p₀₁'  : c₀ == c₁)
       (p₁₀'  : c₁ == c₀)
      -------------------------------------------
       ap (pS-rec C c₀ c₁ p₀₁' p₁₀') p₀₁ == p₀₁'

    pS-βrec₁₀
      : (C : Type₀)
       (c₀ c₁ : C)
       (p₀₁'  : c₀ == c₁)
       (p₁₀'  : c₁ == c₀)
      --------------------------------------------
        ap (pS-rec C c₀ c₁ p₀₁' p₁₀') p₁₀ == p₁₀'

Induction principle

Induction principle on points:

  -- Def.
  pS-ind
    :  {} (C : pS  Type )
     (c₀ : C pS₀)
     (c₁ : C pS₁)
     (q₁ : c₀ == c₁ [ C  p₀₁ ])
     (q₂ : c₁ == c₀ [ C  p₁₀ ])
    -----------------------------
     ((t : pS)  C t)

  pS-ind C c₀ c₁ q₁ q₂ (!ps #!pS₀ x₁) = c₀
  pS-ind C c₀ c₁ q₁ q₂ (!ps #!pS₁ x₁) = c₁

Induction principle on paths:

  -- Postulate.
  postulate
    pS-βind₀₁
      :  {} (C : pS  Type )
       (c₀   : C pS₀)
       (c₁   : C pS₁)
       (p₀₁' : c₀ == c₁ [ C  p₀₁ ])
       (p₁₀' : c₁ == c₀ [ C  p₁₀ ])
       ((t : pS)  C t)
      --------------------------------------------
       apd (pS-ind C c₀ c₁ p₀₁' p₁₀') p₀₁ == p₀₁'

    pS-βind₁₀
      :  {} (C : pS  Type )
       (c₀   : C pS₀)
       (c₁   : C pS₁)
       (p₀₁' : c₀ == c₁ [ C  p₀₁ ])
       (p₁₀' : c₁ == c₀ [ C  p₁₀ ])
       ((t : pS)  C t)
      -------------------------------------------
       apd (pS-ind C c₀ c₁ p₀₁' p₁₀') p₁₀ == p₁₀'

S¹ ≃ pS

Lemma 1 .

Proof. We proceed as usual. Defining the outgoing functions and proving the homotopies. We prove the equivalence by quasiinverse equivalence.

For this equivalence, we need to find a proper candidate to correspond with the loop path of . Our propose is p₀₀, the path p₀₁ · p₁₀. This choice makes sense because p₀₀ suggests a loop, closing the circuit with the arrows.

p₀₀ : pS₀ == pS₀
p₀₀ = p₀₁ · p₁₀

Outgoing functions

We define the function f that goes from to pS type. Which it means we need to use the recursion principle of the circle. We map base to pS₀ and the action on loop to (tr (λ p → pS₀ == pS₀) loop p₀₀).

module Lemma₁ where

  private
    f :   pS
    f = S¹-rec pS pS₀ (tr  p  pS₀ == pS₀) loop p₀₀)

For the inverse function of f we have g which goes from pS to . g is defined by the recursion principle of pS type. The correspondence in this case maps all the points to base in S¹, and the arrows p₀₁ and p₁₀ to loop ² and loop ⁻¹ respectively. The reason for these last choices is because their concatenation gives a loop which is exactly the correspondence that we want to have. Another possible choices would be if we take instead loop and refl base but that would give us a different proof and p₀₀ could be something else.

  -- Inverse
    g : pS  
    g = pS-rec  base base (loop ²) (loop ⁻¹)

Now, let’s prove the respective homotopies to show the equivalence.

f ∘ g ~ id

To prove the homotopy , we also need recursion principle of pS type as it follows.

  • Case pS₁:
  -- Def.
  q₁ : f (g pS₁) == pS₁
  q₁ = ! p₀₀ · ! p₀₀ · p₀₁

Case on paths:

  -- Def.
  dpath₀ :  refl pS₀ == q₁ [  z  (f  g) z == id z)  p₀₁ ]
  dpath₀ =
    begin
      transport  z  (f  g) z == id z) p₀₁ idp
        ==⟨ transport-eq-fun (f  g) id p₀₁ idp 
      ! ap (f  g) p₀₁ · idp · ap id p₀₁
        ==⟨ ·-assoc _ idp (ap id p₀₁) 
      ! ap (f  g) p₀₁ · (idp · ap id p₀₁)
        ==⟨ ap  r  ! ap (f  g) p₀₁ · r) (·-lunit (ap id p₀₁)) 
      ! ap (f  g) p₀₁  · (ap id p₀₁)
        ==⟨ ap  r  ! ap (f  g) p₀₁ · r) (ap-id p₀₁) 
      ! ap (f  g) p₀₁ · p₀₁
        ==⟨ ap  r  ! r · p₀₁) (! (ap-comp g f p₀₁)) 
      ! ap f (ap g p₀₁) · p₀₁
        ==⟨ ap  r  ! ap f r · p₀₁) (pS-βrec₀₁  base base (loop · loop) idp) 
      ! ap f (loop ²) · p₀₁
        ==⟨ ap  r  ! r · p₀₁) (ap-· f loop loop) 
      ! (ap f loop · ap f loop) · p₀₁
        ==⟨ ap  r  ! (r · ap f loop) · p₀₁)
          (S¹-βrec pS pS₀ (transport  _  pS₀ == pS₀) loop p₀₀)) 
      ! (transport  p  pS₀ == pS₀) loop p₀₀ · ap f loop) · p₀₁
        ==⟨ ap  r  ! (r · ap f loop) · p₀₁) (transport-const loop p₀₀) 
      ! (p₀₀ · ap f loop) · p₀₁
        ==⟨ ap  r  ! (p₀₀ · r) · p₀₁)
               (S¹-βrec pS pS₀ (transport  _  pS₀ == pS₀) loop p₀₀)) 
      ! (p₀₀ · transport  p  pS₀ == pS₀) loop p₀₀) · p₀₁
        ==⟨ ap  r  ! (p₀₀ · r) · p₀₁)(transport-const loop p₀₀) 
      ! (p₀₀ · p₀₀) · p₀₁
        ==⟨ ap ( p₀₁) (!-· p₀₀ p₀₀) 
      q₁
    
  -- Def.
  dpath₁ : q₁ == refl pS₀ [  z  (f  g) z == id z)  p₁₀ ]
  dpath₁ =
    begin
      transport   z  (f  g) z == id z) p₁₀ q₁
        ==⟨ transport-eq-fun (f  g) id p₁₀ q₁ 
      ! ap (f  g) p₁₀ · q₁ · ap id p₁₀
        ==⟨ ap  r  ! ap (f  g) p₁₀ · q₁ · r) (ap-id p₁₀) 
      ! ap (f  g) p₁₀ · q₁ · p₁₀
        ==⟨ ap  r  ! r · q₁ · p₁₀) (! (ap-comp g f p₁₀)) 
      ! ap f (ap g p₁₀) · q₁ · p₁₀
        ==⟨ ap  r  ! ap f r · q₁ · p₁₀) (pS-βrec₁₀  base base idp (! loop)) 
      ! ap f (! loop) · q₁ · p₁₀
        ==⟨ ap  r  ! r · q₁ · p₁₀) (ap-inv f loop) 
      (! ! ap f loop) · q₁ · p₁₀
        ==⟨ ap  r  r · q₁ · p₁₀) (involution {p = ap f loop}) 
      ap f loop · q₁ · p₁₀
        ==⟨ ap  r  r · q₁ · p₁₀)
               (S¹-βrec pS pS₀
               (transport  _  pS₀ == pS₀) loop (p₀₁ · p₁₀))) 
      (transport  p  pS₀ == pS₀) loop p₀₀) · q₁ · p₁₀
        ==⟨ ap  r  r · q₁ · p₁₀) (transport-const loop p₀₀) 
      p₀₀ · q₁ · p₁₀
        ==⟨ idp 
      p₀₀ · (! p₀₀ · ! p₀₀ · p₀₁) · p₁₀
        ==⟨ ap  r  p₀₀ · r · p₁₀) (·-assoc (! p₀₀) (! p₀₀) p₀₁) 
      p₀₀ · (! p₀₀ · (! p₀₀ · p₀₁)) · p₁₀
        ==⟨ ap  r  r · p₁₀) (! (·-assoc p₀₀ (! p₀₀) (! p₀₀ · p₀₁))) 
      (p₀₀ · ! p₀₀ ) · (! p₀₀ · p₀₁) · p₁₀
        ==⟨ ap  r  r · (! p₀₀ · p₀₁) · p₁₀)  (·-rinv p₀₀) 
      idp · (! p₀₀ · p₀₁) · p₁₀
        ==⟨ ap ( p₁₀) ( ! ·-lunit ((! p₀₀ · p₀₁))) 
      (! p₀₀ · p₀₁) · p₁₀
        ==⟨ ·-assoc (! p₀₀) p₀₁ p₁₀ 
      ! p₀₀ · (p₀₁ · p₁₀)
        ==⟨⟩
      ! p₀₀ · p₀₀
        ==⟨ ·-linv p₀₀ 
      idp
        ==⟨⟩
      refl pS₀
    

Finally, by path induction on pS type, we got the homotopy.

  -- Homotopy.
  H₁ : f  g  id
  H₁ = pS-ind _ (refl pS₀) q₁ dpath₀ dpath₁

g ∘ f ~ id

To prove the homotopy , we proceed by induction on the circle. For the base case, refl base works since g (f base) is definitionally equal to base.

  -- Def.
  H₂-base : g (f base) == base
  H₂-base = refl base

Action on loop case:

  -- Def.
  H₂-loop : refl base == refl base [  z  (g  f) z == id z)  loop ]
  H₂-loop =
    (begin
      transport  z  (g  f) z == id z) loop idp
        ==⟨ transport-eq-fun (g  f) id loop idp 
      ! (ap (g  f) loop) · idp · ap id loop
        ==⟨ ap  r  ! (ap (g  f) loop) · idp · r) (ap-id loop) 
      ! (ap (g  f) loop) · idp · loop
        ==⟨ ·-assoc _ idp loop 
      ! (ap (g  f) loop) · (idp · loop)
        ==⟨ ap  r  ! (ap (g  f) loop) · r) (·-lunit loop) 
      ! (ap (g  f) loop) · loop
        ==⟨ ap   r  ! r · loop) (! (ap-comp f g loop)) 
      ! ap g (ap f loop) · loop
        ==⟨ ap {A = pS₀ == pS₀}  r  ( ! (ap g r)) · loop)
                                (S¹-βrec pS pS₀ _) 
      ! ap g (transport  p  pS₀ == pS₀) loop p₀₀) · loop
        ==⟨ ap {A = pS₀ == pS₀}  r  ! ap g r · loop)
                (transport-const loop p₀₀) 
      ! ap g p₀₀ · loop
        ==⟨ ap  r  ! r · loop)  (ap-· g p₀₁ p₁₀) 
      ! (ap g p₀₁ · ap g p₁₀) · loop
        ==⟨ ap {A = base == base}  r  ! (r · ap g p₁₀) · loop)
               (pS-βrec₀₁  base base (loop · loop) idp) 
      ! ((loop ²) · ap g p₁₀) · loop
        ==⟨ ap {A = base == base}  r  ! ( loop · loop · r) · loop)
               (pS-βrec₁₀  base base idp (inv loop)) 
      ! ((loop ²) · ! loop) · loop
        ==⟨ ap  r   ! r · loop) aux-path 
      ! loop · loop
        ==⟨ ·-linv loop 
       idp
    )
    where
      aux-path : (loop ²) · (loop ⁻¹) == loop
      aux-path =
        begin
          (loop ²) · (loop ⁻¹)
            ==⟨ ·-assoc loop loop (! loop) 
          loop · (loop · ! loop)
            ==⟨ ap (loop ·_) (·-rinv loop) 
          loop · idp
            ==⟨ ! (·-runit loop) 
          loop
        
  -- Homotopy
  H₂ : g  f  id
  H₂ = S¹-ind _ H₂-base H₂-loop

Now, everything we needed to prove the equivalence is and the equivalence is by quasiinverse equivalence.

  -- Equivalence.
  S¹-≃-pS :   pS
  S¹-≃-pS = qinv-≃ f (g , H₁ , H₂)

Σ S¹ P ≃ pS

Lemma 3. where and .

P is a type family defined by the recursion principle of the circle. When it is the base case, P base is definitionally equal to the booleans Bool. When P is acting on loop, a path of type Bool == Bool is given by Univalence Axiom and the equivalence neg, the negation function for booleans.

path Figure 3. P type family.

Let’s define this type family formally.

module Lemma₃ where

  -- Def.
  neg : Bool  Bool
  neg true  = false
  neg false = true

  -- Equiv.
  neg-eq : Bool  Bool
  neg-eq = qinv-≃ neg (neg , h , h)
    where
      h : neg  neg  id
      h true  = idp
      h false = idp

The type family P : S¹ → Type₀.

  -- Def
  P :   Type₀
  P = S¹-rec Type₀ Bool (ua neg-eq)

As we saw in the Fig. 3, the paths γ₀₁ and γ₁₀ are defined as pathovers.

  -- Defs.
  γ₀₁ : tr P loop false == true
  γ₀₁ = transport-ua P loop neg-eq (S¹-βrec Type₀ Bool (ua neg-eq)) false

  γ₁₀ : tr P loop true == false
  γ₁₀ = transport-ua P loop neg-eq (S¹-βrec Type₀ Bool (ua neg-eq)) true

Proof. We proceed as usual to show the equivalence. We define the outgoing functions f : Σ S¹ P → pS, g : pS → Σ S¹ P and the homotopies f ∘ g ~ id and g ∘ f ∼ id. Let’s start defining the function f.

f : Σ S¹ P → pS

To define f we need to use the recursor principle of Sigma types which gives a pair (b , x) in order to provide a definition for the uncurried version of f, f̰ : (b : S¹) → P b → pS. Since is a dependent function, we define it using induction principle on the circle. In this case, we maps base to ct and as evidence of the pathover of ct and ct along the loop in the family (λ z → P z → pS).

  -- Def.
  ct : P base  pS
  ct true  = pS₁
  ct false = pS₀
  -- Def.
   : ct == ct [  z  P z  pS)  loop ]
   =
    (begin
      transport  z  P z  pS) loop ct
        ==⟨ transport-fun loop ct 
      ff
        ==⟨ funext  x  (ff-gg' x) · (gg-hh' x)) 
      hh
        ==⟨ funext helper₂ 
      ct
     )
     where

     open import UnivalenceLemmas

     helper₁ : (x : P base)  x == neg x [ P  ! loop ]
     helper₁ x =
       let
         apP!loop :  ap P (! loop) == ua (invEqv neg-eq)
         apP!loop =
           begin
             ap P (! loop)
               ==⟨ ap-inv P loop 
             ! ap P loop
               ==⟨ ap (!_) (S¹-βrec Type₀ Bool (ua (neg-eq))) 
             ! ua (neg-eq)
               ==⟨ ! (UnivalenceLemmas.ua-inv neg-eq) 
             ua (invEqv neg-eq)
           
       in
       begin
         transport P (! loop) x
           ==⟨ transport-ua P (! loop) (invEqv neg-eq) apP!loop x 
         fun≃ (invEqv (neg-eq)) x
           ==⟨⟩
         fun≃ (neg-eq) x
           ==⟨⟩
         neg x
       

     helper₂ : (x : P base)  ct (neg x) == ct x
     helper₂ true  = p₀₁
     helper₂ false = p₁₀

     ff : (x : P base)  pS
     ff =  (x : P base)  transport  z  pS) loop
                          (ct (transport  z  P z) (! loop) x)))

     gg : (x : P base)  pS
     gg =  (x : P base)  (ct (transport  z  P z) (! loop) x)))

     ff-gg' : (x : P base)  ff x == gg x
     ff-gg' =  (pb : P base)  transport-const loop
                       (ct (transport  z  P z) (! loop) pb)))

     ff-gg : ff == gg
     ff-gg = funext ff-gg'

     hh : (x : P base)  pS
     hh = λ (x : P base)  ct (neg x)

     gg-hh' : (x : P base)  gg x == hh x
     gg-hh' =  (pb : P base)  ap ct (helper₁ pb))

     gg-hh : gg == hh
     gg-hh = funext gg-hh'
  -- Def.
   : (b : )  P b  pS
   = S¹-ind  z  P z  pS) ct 
  -- Def.
  f :  Σ  P  pS
  f (b , x) =  b x

g : pS → Σ S¹ P

We define g as the inverse function of f by recursion on pS type. Since pS and Σ S¹ P both have two points, two arrows and their graphs are actually isomorphic, g entitled such a correspond as it is expected. false maps to (base , false), true maps to (base, true). For the paths, the subindexes will suggest the correspondence: p₀₁ maps to (base , false) == (base , true ), and p₁₀ maps to (base , true) == (base, false). For these last paths, we use Theorem 2.9.7 in (Univalent Foundations Program, 2013) to get the respective dependent pair equalities, this is by using the pair= function.

-- Def.
  ctp : P base  Σ  P
  ctp b = base , b

  ptp : (y : P base)  ctp y == ctp (neg y)
  ptp false = pair= (loop , γ₀₁)
  ptp true  = pair= (loop , γ₁₀)

  g : pS  Σ  P
  g = pS-rec (Σ  P)
            (ctp false)  -- false ↦ (base , false)
            (ctp true)   -- true ↦ (base , true)
            (ptp false)  -- p₀₁ ↦ (base , false) = (base , true)
            (ptp true)   -- p₁₀ ↦ (base , true ) = (base , false)

f ∘ g ∼ id

To show that this homotopy holds, we proceed by induction principle of pS type. This means we need to show the identity types (f ∘ g) pS₀ == id pS₀ and (f ∘ g) pS₁ == id pS₁ are inhabited but also the pathovers along p₀₁ and p₁₀ respectively. These are the terms q₀, q₁, pover₁, and pover₂ in the following. To define pover₁ and pover₂ we need the following lemmas based on Lemma 6.12.8 in (missing reference) and postulated here because of its complexity.

  -- Lemma 6.12.8
  -- postulate
  --   lemma-ap-f-γ₀₁ : ap f (ptp false) == p₀₁
  --   lemma-ap-f-γ₁₀ : ap f (ptp true) == p₁₀
  -- Def.
  -- q₀ : (f ∘ g) pS₀ == id pS₀
  -- q₀ = p₀₁ · p₁₀
  -- Def.
  -- q₁ : (f ∘ g) pS₁ == id pS₁
  -- q₁ = p₁₀ · p₀₁
  -- Def.
  -- pover₁ : q₀ == q₁ [ (λ z → (f ∘ g) z == id z) ↓ p₀₁ ]
  -- pover₁ =
  --   (begin
  --     transport (λ z → (f ∘ g) z == id z) p₀₁ q₀
  --       ==⟨ transport-eq-fun (f ∘ g) id p₀₁ q₀ ⟩
  --     ! ap (f ∘ g) p₀₁ · q₀ · ap id p₀₁
  --       ==⟨ ap (! ap (f ∘ g) p₀₁ · q₀ ·_) (ap-id p₀₁) ⟩
  --     ! ap (f ∘ g) p₀₁ · q₀ · p₀₁
  --       ==⟨ ap (λ r → ! r · q₀ · p₀₁) (! ap-comp g f p₀₁) ⟩
  --     ! ap f (ap g p₀₁) · q₀ · p₀₁
  --       ==⟨ ap (λ r → ! ap f r · q₀ · p₀₁) (pS-βrec₀₁ (Σ S¹ (λ b → P b)) (ctp false) (ctp true) (ptp false) (ptp true)) ⟩
  --     ! ap f (ptp false) · q₀ · p₀₁
  --       ==⟨ ap (λ r → ! r · q₀ · p₀₁) lemma-ap-f-γ₀₁ ⟩
  --     ! p₀₁ · q₀ · p₀₁
  --       ==⟨ idp ⟩
  --     ! p₀₁ · (p₀₁ · p₁₀) · p₀₁
  --       ==⟨ ! (·-assoc (! p₀₁) p₀₁ p₁₀) |in-ctx (_· p₀₁) ⟩
  --     (! p₀₁ · p₀₁) · p₁₀ · p₀₁
  --       ==⟨ ·-linv p₀₁ |in-ctx (λ r → r · p₁₀ · p₀₁) ⟩
  --     idp · p₁₀ · p₀₁
  --       ==⟨⟩
  --     q₁
  --   ∎)
  -- Def.
  -- pover₂ : q₁ == q₀ [ (λ z → (f ∘ g) z == id z) ↓ p₁₀ ]
  --
  -- pover₂ =
  --   (begin
  --     transport (λ z → (f ∘ g) z == id z) p₁₀ q₁
  --       ==⟨ transport-eq-fun (f ∘ g) id p₁₀ q₁ ⟩
  --     ! ap (f ∘ g) p₁₀ · q₁ · ap id p₁₀
  --       ==⟨ ap (! ap (f ∘ g) p₁₀ · q₁ ·_) (ap-id p₁₀) ⟩
  --     ! ap (f ∘ g) p₁₀ · q₁ · p₁₀
  --       ==⟨ ap (λ r → ! r · q₁ · p₁₀) (! ap-comp g f p₁₀) ⟩
  --     ! ap f (ap g p₁₀) · q₁ · p₁₀
  --       ==⟨ ap (λ r → ! ap f r · q₁ · p₁₀)
  --              (pS-βrec₁₀ (Σ S¹ (λ b → P b)) (ctp false) (ctp true) (ptp false) (ptp true)) ⟩
  --     ! ap f (ptp true) · q₁ · p₁₀
  --       ==⟨ ap (λ r → ! r · q₁ · p₁₀) lemma-ap-f-γ₁₀ ⟩
  --     ! p₁₀ · q₁ · p₁₀
  --       ==⟨⟩
  --     ! p₁₀ · (p₁₀ · p₀₁) · p₁₀
  --       ==⟨ ! (·-assoc (! p₁₀) p₁₀ p₀₁) |in-ctx (_· p₁₀) ⟩
  --     (! p₁₀ · p₁₀) · p₀₁ · p₁₀
  --       ==⟨ ·-linv p₁₀ |in-ctx (λ r → r · p₀₁ · p₁₀) ⟩
  --     idp ·  p₀₁ · p₁₀
  --       ==⟨⟩
  --     q₀
  --   ∎)

Finally, our homotopy holds:

  -- Homotopy
  -- f-g : f ∘ g ∼ id
  -- f-g = pS-ind (λ ps → (f ∘ g) ps == id ps) q₀ q₁ pover₁ pover₂

g ∘ f ∼ id

This homotopy is a very more complex. To show that for all x : S¹ it holds g (f x) == id x we must proceed by induction three times. We perform this in the following order: Sigma induction, Circle induction and pS induction.

Since the last two cases are induction on HITs, these inductions take into account the action on their path constructors. We have taken inspiration to finish this proof from Flattening lemma’s proof in Section 6 in (Univalent Foundations Program, 2013).

By Sigma induction, we must to provide the uncurried function g-f' of g-f : g ∘ f ∼ id, that has type Π (s : S¹) Π (b : P s).(g ∘ f) (s , b) == id (s , b). Therefore, the next step is by induction on the circle. For the base case we have c defined as fallows. For acting on paths, we define a short name Q for the type family λ z → (b : P z) → (g ∘ f) (z , b) == id (z , b) in order to get a pathover between c and itself along loop in the type family Q, this path is cpath. To define cpath we require a few auxiliary lemmas that an interested reader can make them explicit by clicking on the helpers section below. The equivalence follows by showing that f defines a quasiinverse equivalence (ΣS¹P-≃-pS).

  -- Def.
  -- c : (b : P base) → (g ∘ f) (base , b) == id (base , b)
  -- c true  = refl (base , true)
  -- c false = refl (base , false)
  -- Def.
  -- Q : (s : S¹) → Type lzero
  -- Q = λ z → (b : P z) → (g ∘ f) (z , b) == id (z , b)
  -- Helpers and auxiliar lemmas

  -- Def.
  -- auxAP : ∀ {x y : P base}{p : base == base}
  --     → (q : tr (λ x → P x) p x == y)
  --     →  ap (λ w → ctp w ) q == pair= (refl base , q)
  --
  -- auxAP idp = idp
  --
  -- stepFalse1
  --   : ∀ {x y : P base}
  --   → (q : tr (λ x → P x) loop x == y)
  --   → pair= (loop , refl (tr (λ z → P z) loop x)) · pair= (refl base , q) == pair= (loop , q)
  --
  -- stepFalse1 {x = x} idp =
  --   begin
  --       pair= (loop , refl (tr (λ z → P z) loop x)) · pair= (refl base , idp)
  --   ==⟨ idp ⟩
  --       pair= (loop , refl (tr (λ z → P z) loop x)) · idp
  --   ==⟨ ! ·-runit (pair= (loop , refl (tr P loop x))) ⟩
  --       pair= (loop , refl (tr (λ z → P z) loop x))
  --   ==⟨ idp ⟩
  --       pair= (loop , idp)
  --   ∎
  --
  -- stepFalse2
  --   : c (tr (λ x → P x) loop false)
  --     == tr (λ w → (g ∘ f) w == id w) (ap (λ x → ctp x) (! γ₀₁)) (c (neg false))
  --
  -- stepFalse2 = begin
  --   c (tr (λ x → P x) loop false)
  --     ==⟨ ! (apd (λ x → c x) (! γ₀₁)) ⟩
  --   tr (λ b → (g ∘ f) (base , b) == id (base , b)) (! γ₀₁) (c (neg false))
  --     ==⟨ transport-family (! γ₀₁) (c (neg false)) ⟩
  --   tr (λ w → (g ∘ f) w == id w) (ap (λ x → ctp x) (! γ₀₁)) (c (neg false))
  --   ∎
  --
  --
  -- -- Def.
  -- p : (b : P base) → tr (λ w → (g ∘ f) w == id w) (ptp b) (c b) == c (neg b)
  --
  -- p true  =
  --   begin
  --     tr (λ w → (g ∘ f) w == id w) (ptp true) (c true)
  --       ==⟨ idp ⟩
  --     tr (λ w → (g ∘ f) w == id w) (pair= (loop , γ₁₀)) idp
  --       ==⟨ transport-eq-fun (g ∘ f) id (pair= (loop , γ₁₀)) idp ⟩
  --     ! ap (g ∘ f) (pair= (loop , γ₁₀)) · idp · ap id (pair= (loop , γ₁₀))
  --       ==⟨ ap (λ r → ! (ap (g ∘ f) (pair= (loop , γ₁₀))) · idp · r) (ap-id (pair= (loop , γ₁₀))) ⟩
  --     ! ap (g ∘ f) (pair= (loop , γ₁₀)) · idp · (pair= (loop , γ₁₀))
  --       ==⟨ ap (λ r → r · pair= (loop , γ₁₀)) (! (·-runit (! ap (g ∘ f) (pair= (loop , γ₁₀))))) ⟩
  --     ! ap (g ∘ f) (pair= (loop , γ₁₀)) · (pair= (loop , γ₁₀))
  --       ==⟨ ap (λ r → ! r · pair= (loop , γ₁₀)) (! ap-comp f g (pair= (loop , γ₁₀))) ⟩
  --     ! ap g (ap f (pair= (loop , γ₁₀))) · (pair= (loop , γ₁₀))
  --       ==⟨ ap (λ r → ! ap g r · pair= (loop , γ₁₀)) lemma-ap-f-γ₁₀ ⟩
  --     ! ap g p₁₀ · (pair= (loop , γ₁₀))
  --       ==⟨ ap (λ r → ! r · pair= (loop , γ₁₀)) (pS-βrec₁₀ (Σ S¹ P) (base , false) (base , true) (ptp false) (ptp true)) ⟩
  --     ! (ptp true) · (pair= (loop , γ₁₀))
  --       ==⟨ idp ⟩
  --     ! (pair= (loop , γ₁₀)) · (pair= (loop , γ₁₀))
  --       ==⟨ ·-linv (pair= (loop , γ₁₀)) ⟩
  --     idp
  --   ∎
  --
  -- p false =
  --   begin
  --     tr (λ w → (g ∘ f) w == id w) (ptp false) (c false)
  --       ==⟨ idp ⟩
  --     tr (λ w → (g ∘ f) w == id w) (pair= (loop , γ₀₁)) idp
  --       ==⟨ transport-eq-fun (g ∘ f) id (pair= (loop , γ₀₁)) idp ⟩
  --     ! ap (g ∘ f) (pair= (loop , γ₀₁)) · idp · ap id (pair= (loop , γ₀₁))
  --       ==⟨ ap (λ r → ! (ap (g ∘ f) (pair= (loop , γ₀₁))) · idp · r) (ap-id (pair= (loop , γ₀₁))) ⟩
  --     ! ap (g ∘ f) (pair= (loop , γ₀₁)) · idp · (pair= (loop , γ₀₁))
  --       ==⟨ ap (λ r → r · pair= (loop , γ₀₁)) (! (·-runit (! ap (g ∘ f) (pair= (loop , γ₀₁))))) ⟩
  --     ! ap (g ∘ f) (pair= (loop , γ₀₁)) · (pair= (loop , γ₀₁))
  --       ==⟨ ap (λ r → ! r · pair= (loop , γ₀₁)) (! ap-comp f g (pair= (loop , γ₀₁))) ⟩
  --     ! ap g (ap f (pair= (loop , γ₀₁))) · (pair= (loop , γ₀₁))
  --       ==⟨ ap (λ r → ! ap g r · pair= (loop , γ₀₁)) lemma-ap-f-γ₀₁ ⟩
  --     ! ap g p₀₁ · (pair= (loop , γ₀₁))
  --       ==⟨ ap (λ r → ! r · pair= (loop , γ₀₁)) (pS-βrec₀₁ (Σ S¹ P) (base , false) (base , true) (ptp false) (ptp true)) ⟩
  --     ! (ptp false) · (pair= (loop , γ₀₁))
  --       ==⟨ idp ⟩
  --     ! (pair= (loop , γ₀₁)) · (pair= (loop , γ₀₁))
  --       ==⟨ ·-linv (pair= (loop , γ₀₁)) ⟩
  --     idp
  --   ∎
  -- ------------------------------------------------------------------------------
  --
  -- -- Def.
  -- stepFalse3 :
  --   tr (λ w → (g ∘ f) w == id w)
  --      ((pair= (loop , refl (tr (λ z → P z) loop false))) · ap  (λ x → ctp x) γ₀₁ )
  --      (c false) == c (neg false)
  --
  -- stepFalse3  =
  --   begin
  --       tr (λ w → (g ∘ f) w == id w)
  --                 ( (pair= (loop , refl (tr (λ z → P z) loop false)))
  --                 · ap (λ x → ctp x) γ₀₁
  --                 )
  --                 (c false)
  --   ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) ((pair= (loop , refl (tr (λ z → P z) loop false))) · r ) (c false)) (auxAP {p = loop} γ₀₁) ⟩
  --    tr (λ w → (g ∘ f) w == id w)
  --                 ((pair= (loop , refl (tr (λ z → P z) loop false)))
  --                 ·  pair= (refl base , γ₀₁))
  --                 (c false)
  --   ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) r (c false)) (stepFalse1 γ₀₁) ⟩
  --       tr (λ w → (g ∘ f) w == id w)
  --                 (pair= (loop , γ₀₁))
  --                 (c false)
  --   ==⟨ p false ⟩
  --     c (neg false)
  --   ∎
  --
  -- -- Def.
  -- stepFalse4 :
  --   tr (λ w → (g ∘ f) w == id w)
  --     (pair= (loop , refl (tr (λ z → P z) loop false)) · (ap (λ x → ctp x) (γ₀₁)) ) (c false)
  --     ==  c (neg false)
  --   →
  --   tr (λ w → (g ∘ f) w == id w)
  --     (pair= (loop , refl (tr (λ z → P z) loop false))) (c false)
  --   == tr (λ w → (g ∘ f) w == id w) (ap (λ x → ctp x) (! γ₀₁)) (c (neg false))
  --
  -- stepFalse4 p =
  --   begin
  --     tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop false))) (c false)
  --       ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) r (c false)) (·-runit (pair= (loop , refl (tr (λ z → P z) loop false)))) ⟩
  --     tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop false)) · idp) (c false)
  --       ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop false)) · r) (c false)) (! (·-rinv (ap (λ x → ctp x) (γ₀₁)))) ⟩
  --     tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop false)) · ((ap (λ x → ctp x) (γ₀₁)) · ! (ap (λ x → ctp x) (γ₀₁)))) (c false)
  --       ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) r (c false)) (! ·-assoc (pair= (loop , refl (tr (λ z → P z) loop false))) ((ap (λ x → ctp x) (γ₀₁))) (! (ap (λ x → ctp x) (γ₀₁)))) ⟩
  --     tr (λ w → (g ∘ f) w == id w) ( (pair= (loop , refl (tr (λ z → P z) loop false)) · ((ap (λ x → ctp x) (γ₀₁))) · ! (ap (λ x → ctp x) (γ₀₁)))) (c false)
  --       ==⟨ ! (transport-comp-h (pair= (loop , refl (tr (λ z → P z) loop false)) · ap (λ x → ctp x) γ₀₁) (! (ap (λ x → ctp x) (γ₀₁))) (c false)) ⟩
  --     tr (λ w → (g ∘ f) w == id w) (! (ap (λ x → ctp x) (γ₀₁))) (tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop false)) · ((ap (λ x → ctp x) (γ₀₁)))) (c false))
  --       ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) (! (ap (λ x → ctp x) (γ₀₁))) r) p ⟩
  --     tr (λ w → (g ∘ f) w == id w) (! (ap (λ x → ctp x) (γ₀₁))) (c (neg false))
  --       ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) r (c (neg false))) (! ap-inv (λ x → ctp x) γ₀₁) ⟩
  --     tr (λ w → (g ∘ f) w == id w) (ap (λ x → ctp x) (! γ₀₁) ) (c (neg false))
  --   ∎
  --
  -- -- Def.
  -- stepFalse5 :
  --   tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop false))) (c false)
  --   == tr (λ w → (g ∘ f) w == id w) (ap (λ x → ctp x) (! γ₀₁)) (c (neg false))
  --
  -- stepFalse5 = stepFalse4 stepFalse3
  --
  -- -- Def.
  -- stepTrue1
  --   : ∀ {x y : P base}
  --   → (q : tr P loop x == y)
  --   → pair= (loop , refl (tr P loop x)) · pair= (refl base , q) == pair= (loop , q)
  --
  -- stepTrue1 {x = x} idp =
  --   begin
  --       pair= (loop , refl (tr P loop x)) · pair= (refl base , idp)
  --   ==⟨ idp ⟩
  --       pair= (loop , refl (tr P loop x)) · idp
  --   ==⟨ ! ·-runit (pair= (loop , refl (tr P loop x))) ⟩
  --       pair= (loop , refl (tr P loop x))
  --   ==⟨ idp ⟩
  --       pair= (loop , idp)
  --   ∎
  --
  -- -- Def.
  -- stepTrue2
  --   : c (tr (λ x → P x) loop true)
  --     == tr (λ w → (g ∘ f) w == id w) (ap (λ x → ctp x) (! γ₁₀)) (c (neg true))
  --
  -- stepTrue2 = begin
  --   c (tr (λ x → P x) loop true)
  --     ==⟨ ! (apd (λ x → c x) (! γ₁₀)) ⟩
  --   tr (λ b → (g ∘ f) (base , b) == id (base , b)) (! γ₁₀) (c (neg true))
  --     ==⟨ transport-family (! γ₁₀) (c (neg true)) ⟩
  --   tr (λ w → (g ∘ f) w == id w) (ap (λ x → ctp x) (! γ₁₀)) (c (neg true))
  --   ∎
  --
  -- -- Def.
  -- stepTrue3
  --   : tr (λ w → (g ∘ f) w == id w)
  --        ((pair= (loop , refl (tr (λ z → P z) loop true))) · ap  (λ x → ctp x) γ₁₀ )
  --        (c true) == c (neg true)
  --
  -- stepTrue3  =
  --   begin
  --       tr (λ w → (g ∘ f) w == id w)
  --                 ( (pair= (loop , refl (tr (λ z → P z) loop true)))
  --                 · ap (λ x → ctp x) γ₁₀
  --                 )
  --                 (c true)
  --   ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) ( (pair= (loop , refl (tr (λ z → P z) loop true))) · r ) (c true)) (auxAP {p = loop}  γ₁₀) ⟩
  --    tr (λ w → (g ∘ f) w == id w)
  --                 ((pair= (loop , refl (tr (λ z → P z) loop true)))
  --                 ·  pair= (refl base , γ₁₀))
  --                 (c true)
  --   ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) r (c true)) (stepTrue1 γ₁₀) ⟩
  --       tr (λ w → (g ∘ f) w == id w)
  --                 (pair= (loop , γ₁₀))
  --                 (c true)
  --   ==⟨ p true ⟩
  --     c (neg true)
  --   ∎
  --
  -- -- Def.
  -- stepTrue4 :
  --   tr (λ w → (g ∘ f) w == id w)
  --     (pair= (loop , refl (tr (λ z → P z) loop true)) · (ap (λ x → ctp x) (γ₁₀)) ) (c true)
  --     ==  c (neg true)
  --   →
  --   tr (λ w → (g ∘ f) w == id w)
  --     (pair= (loop , refl (tr (λ z → P z) loop true))) (c true)
  --   == tr (λ w → (g ∘ f) w == id w) (ap (λ x → ctp x) (! γ₁₀)) (c (neg true))
  --
  -- stepTrue4 p =
  --   begin
  --     tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop true))) (c true)
  --       ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) r (c true)) (·-runit (pair= (loop , refl (tr (λ z → P z) loop true)))) ⟩
  --     tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop true)) · idp) (c true)
  --       ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop true)) · r) (c true)) (! (·-rinv (ap (λ x → ctp x) (γ₁₀)))) ⟩
  --     tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop true)) · ((ap (λ x → ctp x) (γ₁₀)) · ! (ap (λ x → ctp x) (γ₁₀)))) (c true)
  --       ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) r (c true)) (! ·-assoc (pair= (loop , refl (tr (λ z → P z) loop true))) ((ap (λ x → ctp x) (γ₁₀))) (! (ap (λ x → ctp x) (γ₁₀)))) ⟩
  --     tr (λ w → (g ∘ f) w == id w) ( (pair= (loop , refl (tr (λ z → P z) loop true)) · ((ap (λ x → ctp x) (γ₁₀))) · ! (ap (λ x → ctp x) (γ₁₀)))) (c true)
  --       ==⟨ ! (transport-comp-h (pair= (loop , refl (tr (λ z → P z) loop true)) · ap (λ x → ctp x) γ₁₀) (! (ap (λ x → ctp x) (γ₁₀))) (c true)) ⟩
  --     tr (λ w → (g ∘ f) w == id w) (! (ap (λ x → ctp x) (γ₁₀))) (tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop true)) · ((ap (λ x → ctp x) (γ₁₀)))) (c true))
  --       ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) (! (ap (λ x → ctp x) (γ₁₀))) r) p ⟩
  --     tr (λ w → (g ∘ f) w == id w) (! (ap (λ x → ctp x) (γ₁₀))) (c (neg true))
  --       ==⟨ ap (λ r → tr (λ w → (g ∘ f) w == id w) r (c (neg true))) (! ap-inv (λ x → ctp x) γ₁₀) ⟩
  --     tr (λ w → (g ∘ f) w == id w) (ap (λ x → ctp x) (! γ₁₀)) (c (neg true))
  --   ∎
  --
  -- -- Def.
  -- stepTrue5
  --   : tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop true))) (c true)
  --     == tr (λ w → (g ∘ f) w == id w) (ap (λ x → ctp x) (! γ₁₀)) (c (neg true))
  --
  -- stepTrue5 = stepTrue4 stepTrue3
  --
  -- -- Def.
  -- helper
  --   : (b : P base)
  --   → tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop b)))
  --     (c b) == c (tr (λ x → P x) loop b)
  --
  -- helper false =
  --     begin
  --       tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop false))) (c false)
  --         ==⟨ stepFalse5 ⟩
  --       tr (λ w → (g ∘ f) w == id w) (ap (λ x → ctp x) (! γ₀₁)) (c (neg false))
  --         ==⟨ ! stepFalse2 ⟩
  --       c (tr (λ x → P x) loop false)
  --     ∎
  --
  -- helper true =
  --     begin
  --         tr (λ w → (g ∘ f) w == id w) (pair= (loop , refl (tr (λ z → P z) loop true))) (c true)
  --     ==⟨ stepTrue5 ⟩
  --         tr (λ w → (g ∘ f) w == id w) (ap (λ x → ctp x) (! γ₁₀)) (c (neg true))
  --     ==⟨ ! stepTrue2 ⟩
  --        c (tr (λ x → P x) loop true)
  --     ∎
  -- Def.
  -- cpath : PathOver (λ s → (b : P s) → g (f (s , b)) == s , b) loop c c
  -- cpath = funext-transport-dfun-r loop c c helper

And the homotopy is as follows:

-- Homotopy
  -- Def. by Sigma induction. Step 1.
  -- g-f : g ∘ f ∼ id
  -- g-f (s , b) = g-f' s b
  --   where
  --     -- Def. by S¹ induction. Step 2.
  --     g-f' : (s : S¹) → (b : P s) → (g ∘ f) (s , b) == id (s , b)
  --     g-f' = S¹-ind (λ s → (b : P s) → (g ∘ f) (s , b) == id (s , b)) c cpath

Finally, the equivalence:

  -- Equiv.
  -- ΣS¹P-≃-pS : Σ S¹ P ≃ pS
  -- ΣS¹P-≃-pS = qinv-≃ f (g , f-g , g-f)
  1. Univalent Foundations Program, T. (2013). Homotopy Type Theory: Univalent Foundations of Mathematics. Institute for Advanced Study. Retrieved from http://saunders.phil.cmu.edu/book/hott-online.pdf

Citation

If you want to cite the content of this post, we suggest to use the following latex bibtex entry. This is generated automatically.