module QWI.ColimitsOfSizedIndexedDiagrams where

open import QWI.Size public

----------------------------------------------------------------------
-- Colimits of size-indexed diagrams (section 5.1)
----------------------------------------------------------------------
module Colim
  {l : Level}
  (Size : Set l)
  {{_ : SizeStructure Size}}
  where
  -- Diagrams in Set
  record Diag : Set (lsuc l) where
    constructor mkDiag
    field
      vtx : Size  Set l
      edg : (i : Size)  ∏ᵇ j < i , (vtx j  vtx i)
      act :  i  ∀ᵇ j < i , ∀ᵇ k < j , (∀ x 
        edg i k x == edg i j (edg j k x))
  open Diag public

  -- Cocones under the diagram
  Cocone :
    (D : Diag)
    {C : Set l}
    (f :  i   vtx D i  C)
     ----------------------
    Prop l
  Cocone D f =
     i  ∀ᵇ j < i , (∀ x  f j x == f i (edg D i j x))

  -- Colimits
  colim : Diag  Set l
  colim D = ( i  Size , vtx D i)/ 
    {- We need to define colim D as a quotient by an equivalence
    relation, because the effectiveness of quotients is needed later -}
    module _ where
    data  : (ix, iy :  i  Size , vtx D i)  Prop l where
      mk≈ :
        {i j : Size}
        {x : vtx D i}
        {y : vtx D j}
        (k : Size)
        {{_ : i <ᵇ k}}
        {{_ : j <ᵇ k}}
        (_ : edg D k i x == edg D k j y)
         ------------------------------
         (i , x) (j , y)

    ≈refl :
      {z z' :  i  Size , vtx D i}
      (_ : z == z')
       ---------------------------
       z z'
    ≈refl {i , _} refl = mk≈ (↑ˢ i) {{<ᵇ↑ˢ}} {{<ᵇ↑ˢ}} refl

    ≈symm :
      {(i , x) (j , y) :  i  Size , vtx D i}
       --------------------------------------
       (i , x) (j , y)   (j , y) (i , x)
    ≈symm (mk≈ k p) = mk≈ k (symm p)

    ≈trans :
      {(i , x) (j , y) (k , z) :  i  Size , vtx D i}
      (_ :  (j , y) (k , z))
      (_ :  (i , x) (j , y))
       ----------------------------------------------
       (i , x) (k , z)
    ≈trans {i , x} {j , y} {k , z} (mk≈ m e') (mk≈ l e) =
      let
        n : Size
        n = l ∨ˢ m
        instance
          _ : i <ᵇ n
          _ = <ᵇ<ᵇ {{q = <ᵇ∨ˢl _}}
          _ : j <ᵇ n
          _ = <ᵇ<ᵇ {{q = <ᵇ∨ˢl _}}
          _ : k <ᵇ n
          _ = <ᵇ<ᵇ {{q = <ᵇ∨ˢr _}}
      in
      mk≈ n
        (proof
          edg D n i x
        =[ act D n l {{<ᵇ∨ˢl _}} i x ]
          edg D n l {{<ᵇ∨ˢl _}} (edg D l i x)
        =[ ap (edg D n l {{<ᵇ∨ˢl _}}) e ]
          edg D n l {{<ᵇ∨ˢl _}} (edg D l j y)
        =[ symm (act D n l {{<ᵇ∨ˢl _}} j y) ]
          edg D n j y
        =[ act D n m {{<ᵇ∨ˢr _}} j y ]
          edg D n m {{<ᵇ∨ˢr _}} (edg D m j y)
        =[ ap (edg D n m {{<ᵇ∨ˢr _}}) e' ]
          edg D n m {{<ᵇ∨ˢr _}} (edg D m k z)
        =[ symm (act D n m {{<ᵇ∨ˢr _}} k z) ]
          edg D n k z
        qed)

  -- The universal cocone
  ν :
    (D : Diag)
    (i : Size)
     -------------
    vtx D i  colim D
  ν D i x = [ (i , x) ]/  D

  Coconeν : (D : Diag)  Cocone D (ν D)
  Coconeν D i j x =
    quot.eq ( D)
      (mk≈ (↑ˢ i) {{<ᵇ<ᵇ {{q = <ᵇ↑ˢ}}}} {{<ᵇ↑ˢ}}
        (act D (↑ˢ i) i {{<ᵇ↑ˢ}} j x))

  -- Universal property of the colimit
   :
    (D : Diag)
    {C : Set l}
    (f :  i  vtx D i  C)
    (Coconef : Cocone D f)
     ---------------------
    colim D  C
   D f Coconef = quot.lift {R =  D}
    (λ{(i , x)   f i x})
    λ{ {i , x} {j , y} (mk≈ k e) 
      proof
        f i x
      =[ Coconef k i x ]
        f k (edg D k i x)
      =[ ap (f k) e ]
        f k (edg D k j y)
      =[ symm (Coconef k j y) ]
        f j y
      qed}

  colimext :
    (D : Diag)
    {C : Set l}
    {f g : colim D  C}
    (_ : ∀{i} x  f (ν D i x) == g (ν D i x))
     ---------------------------------------
    f == g
  colimext D e =
    funext (quot.ind ( D) _ (λ{(_ , x)  e x}))

  νkernel :
    {D D' : Diag}
    {i i' : Size}
    {x : vtx D i}
    {x' : vtx D' i'}
    (_ : D == D')
    (_ : ν D i x === ν D' i' x')
     ---------------------------------------------
     j  Size ,  p  i <ᵇ j ,  p'  i' <ᵇ j ,
      (edg D j i {{p}} x === edg D' j i' {{p'}} x')
  νkernel {D} refl e =
    match (quot-eff.prop ( D) (≈refl D) (≈symm D) (≈trans D) e)
    λ{(mk≈ j {{p}} {{p'}} e)  ∃i j (⋀i p (⋀i p' e))}

  -- Preservation of colimits by polynomial endofunctors (Definition 5.9)
  module _
    {I : Set l}
    where
    open Slice I
    -- Preservation of colimits by taking a power (Definition 5.6)
    infix 4 _⟶ᴵ_
    _⟶ᴵ_ : Setᴵ l  (I  Diag)  Diag -- Power diagrams (5.17)
    vtx (X ⟶ᴵ D) i         =  n  X n  vtx (D n) i
    edg (X ⟶ᴵ D) i j f n x = edg (D n) i j (f n x)
    act (X ⟶ᴵ D) i j k f   =
      funext λ n  funext λ x  act (D n) i j k (f n x)

    can : -- The associated canonical function (5.18)
      (X : Setᴵ l)
      (D : I  Diag)
       ------------------------------
      colim (X ⟶ᴵ D)  (X  colim  D)
    can X D = quot.lift {R =  (X ⟶ᴵ D)}
      (λ{(i , f) n x  ν (D n) i (f n x)})
      λ{ {i , f} {j , g} (mk≈ k e)  funext λ n  funext λ x 
        proof
          ν (D n) i (f n x)
        =[ Coconeν (D n)  k i (f n x) ]
          ν (D n) k (edg (D n) k i (f n x))
        =[ ap  h  ν (D n) k (h n x)) e ]
          ν (D n) k (edg (D n) k j (g n x))
        =[ symm (Coconeν (D n) k j (g n x)) ]
          ν (D n) j (g n x)
        qed}

    module _
      {Σ : Sig}
      where
      S∘ : (I  Diag)  (I  Diag)
      S∘ D m = mkDiag V E A
        where
        V : Size  Set l
        V i = S{Σ}  n  vtx (D n) i) m

        E : (i : Size)  ∏ᵇ j < i , (V j  V i)
        E i j (a , f) = (a , λ n b  edg (D n) i j (f n b))

        A :  i  ∀ᵇ j < i , ∀ᵇ k < j , (∀ x 
            E i k x == E i j (E j k x))
        A i j k (a , f) =
          proof
            (a ,  n b  edg (D n) i k (f n b)))
          =[ ap
            {B = λ _  S{Σ}  n  vtx (D n) i) m}
             lhsrhs  (a ,  n b  lhsrhs n b)))
            (funext  n  funext  b  act (D n) i j k (f n b))))
          ]
            (a ,  n b  edg (D n) i j (edg (D n) j k (f n b))))
          qed

      canS : -- the associated canonical function (5.29)
        (D : I  Diag)
        (n : I)
         ------------------------------------
        colim (S∘ D n)  S{Σ} (colim  D) n
      canS D n =  (S∘ D n) canSf CoconecanSf
        module _ where
        canSf :  i  S{Σ}(λ m  vtx (D m) i) n  S{Σ}(colim  D) n
        canSf i = S'{Σ}  m  ν (D m) i) n

        CoconecanSf : Cocone (S∘ D n) canSf
        CoconecanSf i j s =
          ap  f  S'{Σ} f n s)
            (funext λ m  funext (Coconeν (D m) i j))

----------------------------------------------------------------------
-- Cocontinuity of taking powers (Theorem 5.7)
----------------------------------------------------------------------
module CocontinuityOfTakingPowers
  {l : Level}
  (I : Set l)
  -- (Σ : Slice.Sig I)
  (A : Set l)
  (B : A  I  Set l)
  where
  ∑B : A  Set l
  ∑B a =  I (B a)
  open Slice I
  theorem :
     Size  Set l ,
     ssz  SizeStructure Size ,
     (let open Colim Size {{ssz}} in
      (a : A)
      (D : I  Diag)
       ----------------------------
      isIso (can (B a) D)           )
  theorem
    with IWISC (mkFam A ∑B)
  ... | ∃i (mkFam C F) w
    with IWISC (mkFam ( (c , a)  C × A , (F c  ∑B a))
      λ{(_ , f)  ker f})
  ... | ∃i (mkFam C' F') w' =
    ∃i Size (∃i ssz isIsocan)
    module Inner where
    ------------------------------------------------------------------
    -- Proof of part (1) : to prove the theorem we use the size
    -- associated (as in Lemma 5.5) with the following unindexed
    -- signature
    ------------------------------------------------------------------
    private
      Σ : Unindexed.Sig{l}
      Σ = Unindexed.mkSig A ∑B

      data OpΨ : Set l where
        in₁ : C  OpΨ
        in₂ : C'  OpΨ
        in₃ : A  OpΨ

      ArΨ : OpΨ  Set l
      ArΨ (in₁ c)  = F c
      ArΨ (in₂ c') = F' c'
      ArΨ (in₃ a)  = ∑B a

      Ψ : Unindexed.Sig{l}
      Ψ = Unindexed.mkSig OpΨ ArΨ

    Size : Set l
    Size = Sz Ψ

    ssz : SizeStructure Size
    ssz = SizeStructureSize {Σ = Ψ}

    -- Size = Sz Ψ has upper bounds for arities in Σ
    module _ where
      open Plump (SizeSig Ψ)
      upperbounds : UpperBounds {Σ = Ψ} Σ
      ⋁ˢ   {{upperbounds}} a f = Unindexed.sup (ι₂ (ι₂ (in₃ a)) , f)
      <⋁ˢ  {{upperbounds}} f x = ≺sup x (≤refl (f x))
      <ᵇ⋁ˢ {{upperbounds}} f x = <inst (<⋁ˢ f x)

    open Colim Size

    module _ (a : A)(D : I  Diag) where
      qD : ( n  I ,  Size (vtx (D n)))   I (colim  D)
      qD (n , i , x) = (n , quot.mk ( (D n)) (i , x))

      surjectionqD : surjection qD
      surjectionqD (n , z) with quot.surjectionmk ( (D n)) z
      ... | ∃i i refl = ∃i (n , i) refl

      ----------------------------------------------------------------
      -- Property (5.19)
      ----------------------------------------------------------------
      injcan :
        {i j : Size}
        (f :  n  B a n  vtx (D n) i)
        (g :  n  B a n  vtx (D n) j)
        (e :  n x  ν (D n) i (f n x)) ==
           n x  ν (D n) j (g n x))      )
         ----------------------------------------
         k  Size ,  p  i <ᵇ k ,  q  j <ᵇ k ,
          (∀ n x 
            edg (D n) k i {{p}} (f n x) ==
            edg (D n) k j {{q}} (g n x))
      injcan {i} {j} f g e =
        lemma (wAC (mkFam C F) (w a)  _  Size) P Ptotal)
        where
        P :  I (B a)  Size  Prop l
        P (n , x) k =
           p  i <ᵇ k ,
           q  j <ᵇ k ,
            (edg (D n) k i {{p}} (f n x) ==
             edg (D n) k j {{q}} (g n x))

        Ptotal : (nx :  I (B a))   k  Size , P nx k
        Ptotal (n , x) = νkernel refl (ap  e'  e' n x) e)

        lemma :
          (  c  C
          ,  p  (F c   I (B a))
          ,  s  (F c  Size)
          , (surjection p   x'  P (p x')(s x')))
           ------------------------------------------
           k  Size ,  u  i <ᵇ k ,  v  j <ᵇ k ,
            (∀ n x 
             edg (D n) k i {{u}} (f n x) ==
             edg (D n) k j {{v}} (g n x))
        lemma (∃i c (∃i p (∃i s (∧i surjectionh sp-eq)))) =
          ∃i k (⋀i u (⋀i v λ n x 
            match (surjectionh (n , x)) \ where
              (∃i x' refl) 
                match (sp-eq x') \ where
                  (⋀i i<ᵇsx' (⋀i j<ᵇsx' e')) 
                    proof
                      edg (D n) k i {{u}} (f n (snd (p x')))
                    =[ act (D n) k (s x') {{_}} i {{_}} _ ]
                      edg (D n) k  (s x') {{sx'<ᵇk x'}}
                     (edg (D n) (s x') i {{i<ᵇsx'}} (f n (snd (p x'))))
                    =[ ap (edg (D n) k (s x') {{sx'<ᵇk x'}}) e' ]
                      edg (D n) k  (s x') {{sx'<ᵇk x'}}
                      (edg (D n) (s x') j {{j<ᵇsx'}} (g n (snd (p x'))))
                    =[ symm (act (D n) k (s x') {{_}} j {{_}} _) ]
                      edg (D n) k j {{v}} (g n (snd (p x')))
                    qed))
          where
          k : Size
          k = i ∨ˢ j ∨ˢ (⋁ˢ (in₁ c) s)

          u : i <ᵇ k
          u = <ᵇ∨ˢl _

          v : j <ᵇ k
          v = <ᵇ<ᵇ {{q = <ᵇ∨ˢr _}} {{<ᵇ∨ˢl _}}

          sx'<ᵇk :  x'  s x' <ᵇ k
          sx'<ᵇk x' =
            <ᵇ<ᵇ {{q =
            <ᵇ<ᵇ {{q =
              <ᵇ∨ˢr _}} {{<ᵇ∨ˢr _}}}} {{<ᵇ⋁ˢ s x'}}

      ----------------------------------------------------------------
      -- Proof of part (2): injectivity of the canonical function
      -- colim (X ⟶ D) → (X → colim D)
      ----------------------------------------------------------------
      injectioncan : injection (can (B a) D)
      injectioncan {z} {z'} =
        quot.ind₂ ( (B a ⟶ᴵ D)) ( (B a ⟶ᴵ D))
           z z'  can (B a) D z == can (B a) D z'  z == z')
          (λ{(i , f) (j , g) e  match (injcan f g e) \ where
            (∃i k (⋀i p (⋀i q e'))) 
              quot.eq ( (B a ⟶ᴵ D)) (mk≈ k {{p}} {{q}}
              (funext λ n  funext (e' n)))})
          z
          z'

      ----------------------------------------------------------------
      -- Property (5.20)
      ----------------------------------------------------------------
      surjcan :
        (f : B a  colim  D)
         ----------------------------------------------
         i  Size ,  f'  (∀ n  B a n  vtx (D n) i),
          f == λ n x  ν (D n) i (f' n x)
      surjcan f = lemma (wAC _ (w a) _ P Ptotal)
       where
        P : ((n , x) :  I (B a))  ( Size (vtx (D n)))  Prop l
        P (n , x) (i , y ) = [ (i , y) ]/  (D n) == f n x

        Ptotal :
          ((n , x) :  I (B a))
           --------------------------------------
           iy   Size (vtx (D n)) , P (n , x) iy
        Ptotal (n , x) = quot.surjectionmk ( (D n)) (f n x)

        lemma :
          ( c  C ,
           p  (F c   I (B a)),
           sg  ((z : F c)   Size (vtx (D (fst (p z))))),
          (surjection p   z  P (p z)(sg z)))
           ------------------------------------------------
           i  Size ,  f'  (∀ n  B a n  vtx (D n) i) ,
            f == λ n x  ν (D n) i (f' n x)
        lemma (∃i c (∃i p (∃i sg (∧i surjectionp u)))) =
          lemma' (wAC _ (w' _) _ P' P'total)
          where
          p₁ : F c  I
          p₁ = fst  p

          p₂ : (z : F c)  B a (p₁ z)
          p₂ = snd  p

          s : F c  Size
          s = fst  sg

          g : (z : F c)  vtx (D (p₁ z)) (s z)
          g = snd  sg

          j : Size
          j = ⋁ˢ (in₁ c) s

          s<ᵇj :  z   s z <ᵇ j
          s<ᵇj z = <ᵇ⋁ˢ s z

          fj :  z  vtx (D (p₁ z)) j
          fj z = edg (D (p₁ z)) j (s z) {{s<ᵇj z}} (g z)

          νfj=fp :  z  ν (D (p₁ z)) j (fj z) == f (p₁ z) (p₂ z)
          νfj=fp z =
            proof
              ν (D (p₁ z)) j (fj z)
            =[ symm (Coconeν (D (p₁ z)) j (s z) {{s<ᵇj z}} (g z)) ]
              ν (D (p₁ z)) (s z) (g z)
            =[ u z ]
              f (p₁ z) (p₂ z)
            qed

          P' : ker p  Size  Prop l
          P' ((z , z')  _) k =  j<ᵇk  j <ᵇ k ,
            edg (D (p₁ z )) k j {{j<ᵇk}} (fj z ) ===
            edg (D (p₁ z')) k j {{j<ᵇk}} (fj z')

          P'total :  zz'   k  Size , P' zz' k
          P'total ((z , z')  pz=pz') =
            match (νkernel e e') λ{(∃i k (⋀i j<ᵇk (⋀i _ e''))) 
            ∃i k (⋀i j<ᵇk e'')}
            where
            e : D (p₁ z) == D(p₁ z')
            e = ap (D  fst) pz=pz'

            e' :
              ν (D (p₁ z)) j (fj z) ===
              ν (D (p₁ z')) j (fj z')
            e' =
              proof
                ν (D (p₁ z)) j (fj z)
              =[ νfj=fp z ]
                f (p₁ z) (p₂ z)
              =[ ap  x  f (fst x) (snd x)) pz=pz' ]
                f (p₁ z') (p₂ z')
              =[ symm (νfj=fp z') ]
                ν (D (p₁ z')) j (fj z')
              qed

          lemma' :
            ( c'  C' ,
             p'  (F' c'  ker p),
             s'  (F' c'  Size),
            (surjection p'   z  P' (p' z) (s' z)))
             ----------------------------------------------
             i  Size ,  g'  (∀ n  B a n  vtx (D n) i),
              f == λ n x  ν (D n) i (g' n x)
          lemma' (∃i c' (∃i p' (∃i s' (∧i surjectionp' u)))) =
            ∃i i (∃i g' f=νig')
            where
            i : Size
            i = j ∨ˢ ⋁ˢ (in₂ c') s'

            j<ᵇi : j <ᵇ i
            j<ᵇi = <ᵇ∨ˢl _

            s'<ᵇi :  z'  s' z' <ᵇ i
            s'<ᵇi z' = <ᵇ<ᵇ {{q = <ᵇ∨ˢr _}}{{<ᵇ⋁ˢ s' z'}}

            fi : (z : F c)  vtx (D (p₁ z)) i
            fi z = edg (D (p₁ z)) i j {{j<ᵇi}} (fj z)

            νfi=fp :
              (z : F c)
               --------------------------------------
              ν (D (p₁ z)) i (fi z) == f (p₁ z) (p₂ z)
            νfi=fp z =
              proof
                ν (D (p₁ z)) i (fi z)
              =[ symm (Coconeν (D (p₁ z)) i j {{j<ᵇi}} (fj z)) ]
                ν (D (p₁ z)) j (fj z)
              =[ νfj=fp z ]
                f (p₁ z) (p₂ z)
              qed

            p₁' : F' c'  F c
            p₁' z' = fst (el (p' z'))

            p₂' : F' c'  F c
            p₂' z' = snd (el (p' z'))

            G' : ((n , _) :  I (B a))  vtx (D n) i  Prop l
            G' nx d =  z  F c , (p z == nx)  (fi z === d)

            instance
              ∃!G' : ∀{nx}  ∃! (vtx (D (fst nx)) i) (G' nx)
              ∃!G' {n , x} with surjectionp (n , x)
              ... | ∃i z₂ refl = ∃i (fi z₂) (∧i (∃i z₂ (∧i refl refl))
                λ{d (∃i z₁ (∧i pz₁=pz₂ fiz₁=d)) 
                match (surjectionp' ((z₁ , z₂)  pz₁=pz₂)) \ where
                  (∃i z' p'z'=z₁z₂) 
                    match (u z') \ where
                      (⋀i j<ᵇs'z' e') 
                        proof
                          fi z₂
                        =[ ap (fi  snd  el) (symm p'z'=z₁z₂) ]
                          edg (D (p₁ (p₂' z'))) i j {{j<ᵇi}} (fj (p₂' z'))
                        =[ act (D (p₁ (p₂' z'))) i (s' z') {{s'<ᵇi z'}}
                          j {{j<ᵇs'z'}} _ ]
                          edg (D (p₁ (p₂' z'))) i (s' z') {{s'<ᵇi z'}}
                          (edg (D (p₁ (p₂' z'))) (s' z') j {{j<ᵇs'z'}} (fj (p₂' z')))
                        =[ symm (ap₂  𝕛 d  edg (D 𝕛) i (s' z') {{s'<ᵇi z'}} d)
                          (ap fst (pf (p' z'))) e') ]
                          edg (D (p₁ (p₁' z'))) i (s' z') {{s'<ᵇi z'}}
                          (edg (D (p₁ (p₁' z'))) (s' z') j {{j<ᵇs'z'}} (fj (p₁' z')))
                        =[ symm (act (D (p₁ (p₁' z'))) i (s' z') {{s'<ᵇi z'}}
                          j {{j<ᵇs'z'}} _) ]
                          edg (D (p₁ (p₁' z'))) i j {{j<ᵇi}} (fj (p₁' z'))
                        =[ ap (fi  fst  el) p'z'=z₁z₂ ]
                          fi z₁
                        =[ fiz₁=d ]
                          d
                        qed})

            g' :  n  B a n  vtx (D n) i
            g' n x = the (vtx (D n) i) (G' (n , x))

            f=νig' : f == λ n x  ν (D n) i (g' n x)
            f=νig' = funext λ n  funext λ x 
              match (the-pf (vtx (D n) i) (G' (n , x))) \ where
                (∃i z (∧i pz=nx fiz=g'ix)) 
                  proof
                    f n x
                  =[ ap  x  f (fst x) (snd x)) (symm pz=nx) ]
                    f (p₁ z) (p₂ z)
                  =[ symm (νfi=fp z) ]
                    ν (D (p₁ z)) i (fi z)
                  =[ ap₂  n d  ν (D n) i d) (ap fst pz=nx) fiz=g'ix ]
                    ν (D n) i (g' n x)
                  qed

      ----------------------------------------------------------------
      -- Proof of part (3): surjectivity of the canonical function
      -- colim (X ⟶ D) → (X → colim D)
      ----------------------------------------------------------------
      surjectioncan : surjection (can (B a) D)
      surjectioncan f = match (surjcan f) \ where
        (∃i i (∃i fi refl))  ∃i ([ (i , fi) ]/  _) refl

      isIsocan =
        bijectionIsIso (can (B a) D)
        (∧i injectioncan surjectioncan)

----------------------------------------------------------------------
-- Cocontinuity of polynomial endofunctors (Corollary 5.10) in a form
-- that is convenient for its use in
-- section 6 (FixedPointsAreQWITypes.agda)
----------------------------------------------------------------------
module CocontinuityOfPolynomialEndofunctors
  {l : Level}
  {I : Set l}
  (Σ : Slice.Sig{l} I)
  (ε : Slice.Syseq{l} I Σ)
  where
  open Slice I
  open Syseq ε

  theorem :
     Sz  Set l ,
     sz  SizeStructure Sz , (let open Colim Sz {{sz}} in
      ((D : I  Diag)(n : I)  isIso (canS {Σ = Σ} D n)))
  theorem with
    CocontinuityOfTakingPowers.theorem
     I ( I (Op (Σ  Γ))) (uncurry (Ar (Σ  Γ)))
  ... | ∃i Size (∃i ssz p) = ∃i Size (∃i ssz Scont)
    module _ where
    open Colim Size
    instance
      _ : SizeStructure Size
      _ = ssz

    Scont : (D : I  Diag)(n : I)  isIso (canS {Σ = Σ} D n)
    Scont D n = ∃i inv' (∧i linv' rinv')
      where
      φ :
        (a : Op Σ n)
        (i : Size) 
        (f :  m  Ar Σ n a m  vtx (D m) i)
         ----------------------------------
        colim (S∘{Σ = Σ} D n)
      φ a i f = ν (S∘{Σ = Σ} D n) i (a , f)

      Coconeφ : (a : Op Σ n)  Cocone (Ar Σ n a ⟶ᴵ D) (φ a)
      Coconeφ a i j {{j<ᵇi}} f =
        let
          k : Size
          k = ↑ˢ i
          instance
            j<ᵇk : j <ᵇ k
            j<ᵇk = <ᵇ<ᵇ {{q = <ᵇ↑ˢ}} {{j<ᵇi}}
            i<ᵇk : i <ᵇ k
            i<ᵇk = <ᵇ↑ˢ
        in
        quot.eq ( (S∘{Σ = Σ} D n)) (mk≈ k
          (proof
             edg (S∘{Σ = Σ} D n) k j (a , f)
           =[ refl ]
            (a , λ m x  edg (D m) k j (f m x))
           =[ ap {B =  λ _  S{Σ}  m  vtx (D m) k) n}
               g  (a ,  m x  g m x)))
              (funext λ m  funext λ x  act (D m) k i j (f m x)) ]
             (a , λ m x  edg (D m) k i (edg (D m) i j (f m x)))
           =[ refl ]
             (a , λ m x  edg (D m) k i (edg (Ar Σ n a ⟶ᴵ D) i j f m x))
           =[ refl ]
             edg (S∘{Σ = Σ} D n) k i (a , edg (Ar Σ n a ⟶ᴵ D) i j f)
           qed))

      c : (a : Op Σ n)  colim (Ar Σ n a ⟶ᴵ D)  colim (S∘{Σ = Σ} D n)
      c a =  (Ar Σ n a ⟶ᴵ D) (φ a) (Coconeφ a)

      lemma : {a : Op Σ n}  canS{Σ = Σ} D n  c a == (a ,_)  can (Ar Σ n a) D
      lemma {a} = colimext (Ar Σ n a ⟶ᴵ D) λ _  refl

      inv' : S{Σ} (colim  D) n  colim (S∘{Σ = Σ} D n)
      inv' (a , f) = c a (((can (Ar Σ n a) D)⁻¹) f)
        where
        instance
          _ : isIso (can (Ar Σ n a) D)
          _ = p (n , ι₁ a) D

      linv' : (z : colim (S∘{Σ = Σ} D n))  inv' (canS{Σ = Σ} D n z) == z
      linv' = quot.ind ( (S∘ {Σ = Σ} D n)) _ λ{(i , a , f) 
        let instance _ = p (n , ι₁ a) D in
        ap (c a) (linv _ (ν (Ar Σ n a ⟶ᴵ D) i f))}

      rinv' : (s : S{Σ} (colim  D) n)  canS{Σ = Σ} D n (inv' s) == s
      rinv' (a , f) =
        let instance _ = p (n , ι₁ a) D in
        proof
          canS{Σ = Σ} D n (inv' (a , f))
        =[ refl ]
          canS{Σ = Σ} D n (c a (((can (Ar Σ n a) D)⁻¹) f))
        =[ ap (case ((can _ D ⁻¹) f)) lemma ]
          (a , can _ D (((can _ D)⁻¹) f))
        =[ ap (a ,_) (rinv _ f) ]
          (a , f)
        qed