{-# OPTIONS --safe #-} module Multiset.ListQuotient.ListFinality where open import Multiset.Prelude open import Multiset.Util.Path using (substIso) open import Multiset.Functor using (NatTrans ; NatEquiv) open import Multiset.Util.Vec as VecExt using () open import Multiset.Util.BundledVec as BVec using ( ΣVec ; #_ ; ΣVecPathP ; ΣVecIsoΣ ; ΣVecUnit*-ℕ-Iso ) open import Multiset.Limit.Chain as Chain using ( lim ; Limit ; Chain ; isSet→LimitPathExt ; isLimit ; isOfHLevelLimit ) open import Multiset.Coalgebra using ( CoalgebraMorphism ; isCoalgebraMorphism ; isTerminal ; isSet→isPropIsCoalgebraMorphism ) open import Multiset.Limit.TerminalChain as TerminalChain using ( Functor ; Lim ; ShLim ; _^_ ; _map-!^_ ; isShLim ; isLim ; isLimitPreserving ; ShLim→Lim ) open import Cubical.Foundations.Equiv open import Cubical.Foundations.Function using (_∘_ ; ∘-assoc ; flip) open import Cubical.Foundations.Isomorphism open import Cubical.Foundations.Transport using (substEquiv) open import Cubical.Foundations.Univalence using (ua) open import Cubical.Functions.FunExtEquiv using (funExtDep) open import Cubical.Data.Sigma as Sigma using ( ΣPathP ; Σ≡Prop ; Σ-cong-iso-fst ; Σ-cong-iso-snd ) open import Cubical.Data.Nat.Base as Nat using (ℕ ; suc ; zero ; _+_) open import Cubical.Data.FinData as Fin using (FinVec) open import Cubical.Data.Unit.Base using (Unit* ; tt*) open import Cubical.Data.Unit.Properties as Unit using (isOfHLevelUnit*) open import Cubical.Data.Vec.Base as Vec using (Vec) open import Cubical.Data.Vec.Properties as Vec using (FinVecIsoVec) open ΣVec instance FunctorVec : ∀ {n} → Functor {ℓ-zero} (λ A → Vec A n) FunctorVec .Functor.map = Vec.map FunctorVec .Functor.map-id = VecExt.vec-map-id FunctorVec .Functor.map-comp = λ g f as → VecExt.vec-map-comp g f as FunctorΣVec : Functor {ℓ-zero} ΣVec FunctorΣVec .Functor.map = BVec.map FunctorΣVec .Functor.map-id = BVec.map-id FunctorΣVec .Functor.map-comp = BVec.map-comp module _ where open import Cubical.Data.List as List using (List) private instance FunctorList : Functor {ℓ-zero} List FunctorList .Functor.map = List.map FunctorList .Functor.map-id {X = X} = go where go : (xs : List X) → _ go List.[] = refl go (x List.∷ xs) = cong (x List.∷_) (go xs) FunctorList .Functor.map-comp {X} {Y} {Z} g f = go where go : (xs : List X) → _ go List.[] = refl go (x List.∷ xs) = cong (g (f x) List.∷_) (go xs) ΣVec→List : {A : Type} → ΣVec A → List A ΣVec→List (# Vec.[]) = List.[] ΣVec→List (# (a Vec.∷ as)) = a List.∷ ΣVec→List (# as) List→ΣVec : {A : Type} → List A → ΣVec A List→ΣVec List.[] = BVec.[] List→ΣVec (a List.∷ as) = a BVec.#∷ List→ΣVec as ΣVec⇒List : NatTrans {ℓ = ℓ-zero} ΣVec List ΣVec⇒List .NatTrans.mor = ΣVec→List ΣVec⇒List .NatTrans.is-nat {X = X} f = funExt is-nat where is-nat : (xs : ΣVec X) → ΣVec→List (BVec.map f xs) ≡ List.map f (ΣVec→List xs) is-nat (# Vec.[]) = refl {x = List.[]} is-nat (# (x Vec.∷ xs)) = cong (f x List.∷_) (is-nat (# xs)) ΣVec-List-EquivNat : NatEquiv ΣVec List ΣVec-List-EquivNat .fst = ΣVec⇒List ΣVec-List-EquivNat .snd {X} = isoToIsEquiv nat-iso where nat-iso : Iso (ΣVec X) (List X) nat-iso .Iso.fun = ΣVec→List nat-iso .Iso.inv = List→ΣVec nat-iso .Iso.rightInv = right-inv where right-inv : (xs : List _) → _ ≡ xs right-inv List.[] = refl right-inv (x List.∷ xs) = cong (x List.∷_) (right-inv xs) nat-iso .Iso.leftInv = left-inv where left-inv : (xs : ΣVec _) → _ ≡ xs left-inv (# Vec.[]) = refl left-inv (# (x Vec.∷ xs)) = cong (x BVec.#∷_) (left-inv (# xs)) open Functor ⦃...⦄ isSetΣVec^ : ∀ n → isSet (ΣVec ^ n) isSetΣVec^ zero = isOfHLevelUnit* 2 isSetΣVec^ (suc n) = BVec.isSetΣVec (isSetΣVec^ n) !^ : (n : ℕ) → ΣVec ^ (suc n) → ΣVec ^ n !^ = ΣVec map-!^_ Tree : Type Tree = Lim ΣVec isTree : ((n : ℕ) → ΣVec ^ n) → Type isTree = isLim ΣVec pres⁺ : ΣVec (Lim ΣVec) → ShLim ΣVec pres⁺ = TerminalChain.pres ΣVec cut : (n : ℕ) → Lim ΣVec → ΣVec ^ n cut = TerminalChain.cut ΣVec width : ShLim ΣVec → (d : ℕ) → ℕ width tree d = length $ tree .Limit.elements d vecs : (tree : ShLim ΣVec) → (d : ℕ) → Vec (ΣVec ^ d) (width tree d) vecs tree d = tree .Limit.elements d .vec widthConstSuc : ∀ (tree : ShLim ΣVec) n → width tree n ≡ width tree (suc n) widthConstSuc (lim tree is-lim) n = cong length (sym $ is-lim n) open Iso open Limit module ConstLength (len₀ : ℕ) (xs : (d : ℕ) → Vec (ΣVec ^ d) len₀) where constLengthApprox : (d : ℕ) → ΣVec ^ (suc d) constLengthApprox d .length = len₀ constLengthApprox d .vec = xs d module _ (islim : isShLim ΣVec constLengthApprox) where constLengthLim : ShLim ΣVec constLengthLim .elements = constLengthApprox constLengthLim .is-lim = islim inh' : FinVec (Lim ΣVec) len₀ inh' k .elements = Vec.lookup k ∘ xs inh' k .is-lim d = (!^ d) (Vec.lookup k $ xs (suc d)) ≡⟨ sym (VecExt.lookup-map (!^ d) (xs (suc d)) k) ⟩ (Vec.lookup k $ Vec.map (!^ d) (xs (suc d))) ≡⟨ cong (Vec.lookup k) (BVec.mk-vec-inj (islim d)) ⟩∎ (Vec.lookup k $ xs d) ∎ inh : ΣVec (Lim ΣVec) inh .length = len₀ inh .vec = Vec.FinVec→Vec inh' abstract inh∈fiber : pres⁺ inh ≡ constLengthLim inh∈fiber = TerminalChain.isSet→ShLimPath ΣVec (isSetΣVec^ ∘ suc) ptwise where ptwise : ∀ n → pres⁺ inh .elements n ≡ constLengthApprox n ptwise n = cong #_ $ Vec.map (cut n) (Vec.FinVec→Vec inh') ≡⟨ VecExt.lookup⁻¹-map (cut n) inh' ⟩ Vec.FinVec→Vec (cut n ∘ inh') ≡⟨ Vec.Vec→FinVec→Vec (xs n) ⟩∎ xs n ∎ inhFibers : fiber pres⁺ constLengthLim inhFibers = inh , inh∈fiber inhFibers : (base : ShLim ΣVec) → fiber pres⁺ base inhFibers base = subst (fiber pres⁺) shlim≡ (ConstLength.inhFibers length₀ approx approx-is-shlim) where length₀ : ℕ length₀ = base .elements 0 .length constLength : ∀ d → base .elements d .length ≡ length₀ constLength zero = refl constLength (suc d) = cong length (base .is-lim d) ∙ constLength d approx : (d : ℕ) → Vec (ΣVec ^ d) length₀ approx d = subst (Vec (ΣVec ^ d)) (constLength d) (base .elements d .vec) approx≡ : ∀ d → base .elements d ≡ # (approx d) approx≡ d = ΣVecPathP (constLength d) $ subst-filler (Vec (ΣVec ^ d)) (constLength d) (base .elements d .vec) approx-is-shlim : isShLim ΣVec (ConstLength.constLengthApprox length₀ approx) approx-is-shlim = subst (isShLim ΣVec) (funExt approx≡) (base .is-lim) shlim≡ : ConstLength.constLengthLim length₀ approx approx-is-shlim ≡ base shlim≡ = TerminalChain.isSet→ShLimPath ΣVec (isSetΣVec^ ∘ suc) (sym ∘ approx≡) module Direct where pres⁻ : ShLim ΣVec → ΣVec (Lim ΣVec) pres⁻ = fst ∘ inhFibers pres-section : section pres⁺ pres⁻ pres-section = snd ∘ inhFibers private open import Multiset.Util.Trace as Trace using (Trace ; constTrace ; TraceIso) OverTrace : Trace ℕ → Type OverTrace as = Σ[ vs ∈ ((n : ℕ) → Vec (ΣVec ^ n) (as .Trace.step n)) ] ∀ (n : ℕ) → PathP (λ i → Vec (ΣVec ^ n) (as .Trace.connect n i)) (vs n) (Vec.map (!^ n) (vs (suc n))) pres-Iso : Iso (ShLim ΣVec) (ΣVec (Lim ΣVec)) pres-Iso = let snd-iso : ∀ n → Iso (OverTrace (constTrace n)) (Vec (Lim ΣVec) n) snd-iso n = OverTrace (constTrace n) Iso⟨ toVecLimit n ⟩ Limit (vecChain n) Iso⟨ toFinVecOfLimits n ⟩ FinVec (Lim ΣVec) n Iso⟨ Vec.FinVecIsoVec n ⟩ Vec (Lim ΣVec) n ∎Iso in ShLim ΣVec Iso⟨ toTraceFirstIso ⟩ Σ (Trace ℕ) OverTrace Iso⟨ invIso (Σ-cong-iso-fst (invIso TraceIso)) ⟩ Σ ℕ (OverTrace ∘ constTrace) Iso⟨ Σ-cong-iso-snd snd-iso ⟩ Σ ℕ (Vec (Lim ΣVec)) Iso⟨ invIso ΣVecIsoΣ ⟩ ΣVec (Lim ΣVec) ∎Iso where TraceFirst : Type TraceFirst = Σ (Trace ℕ) OverTrace toTraceFirstIso : Iso (ShLim ΣVec) TraceFirst toTraceFirstIso .fun tree = trace , vecs tree , vecs-coh where trace : Trace ℕ trace = width tree , widthConstSuc tree vecs-coh : ∀ n → PathP (λ i → Vec (ΣVec ^ n) (widthConstSuc tree n i)) (vecs tree n) (Vec.map (!^ n) (vecs tree (suc n))) vecs-coh n = cong vec (sym (tree .Limit.is-lim n)) toTraceFirstIso .inv (trace , vecs , vecs-coh) .elements n = #_ {length = trace .fst n} $ vecs n toTraceFirstIso .inv (trace , vecs , vecs-coh) .is-lim n = sym $ ΣVecPathP (trace .snd n) (vecs-coh n) toTraceFirstIso .rightInv _ = refl toTraceFirstIso .leftInv _ = refl module _ (sz : ℕ) where open Limit open VecExt using (lookup-map ; lookup⁻¹ ; lookup-right-inv ; lookup-left-inv) vecChain : Chain _ vecChain .Chain.Ob n = Vec (ΣVec ^ n) sz vecChain .Chain.π n = Vec.map (!^ n) toVecLimit : Iso (OverTrace (constTrace sz)) (Limit vecChain) toVecLimit .fun (vecs , vecs-coh) = lim vecs (sym ∘ vecs-coh) toVecLimit .inv (lim elements is-lim) = elements , sym ∘ is-lim toVecLimit .rightInv _ = refl toVecLimit .leftInv _ = refl toFinVecOfLimits : Iso (Limit vecChain) (FinVec (Lim ΣVec) sz) toFinVecOfLimits = go where module _ (vec : Limit vecChain) where f-elements : FinVec (∀ n → ΣVec ^ n) sz f-elements k = Vec.lookup k ∘ (vec .elements) f-is-lim : ∀ k → isTree (f-elements k) f-is-lim k n = (!^ n) (Vec.lookup k $ vec .elements (suc n)) ≡⟨ sym (VecExt.lookup-map (!^ n) (vec .elements (suc n)) k) ⟩ (Vec.lookup k $ Vec.map (!^ n) (vec .elements (suc n))) ≡⟨ cong (Vec.lookup k) (vec .is-lim n) ⟩∎ (Vec.lookup k $ vec .elements n) ∎ f : FinVec (Lim ΣVec) sz f k .elements = f-elements k f k .is-lim = f-is-lim k module _ (vec : FinVec (Lim ΣVec) sz) where f⁻¹-elements : ∀ n → Vec (ΣVec ^ n) sz f⁻¹-elements n = Vec.map (cut n) (lookup⁻¹ vec) f⁻¹-is-lim : isLimit vecChain f⁻¹-elements f⁻¹-is-lim n = map (!^ n) (map (cut (suc n)) (lookup⁻¹ vec)) ≡⟨ sym (map-comp (!^ n) (cut (suc n)) _) ⟩ map (!^ n ∘ (cut (suc n))) (lookup⁻¹ vec) ≡⟨ cong (λ f → map f (lookup⁻¹ vec)) (TerminalChain.cut-is-lim ΣVec n) ⟩ map (cut n) (lookup⁻¹ vec) ∎ f⁻¹ : Limit vecChain f⁻¹ .elements = f⁻¹-elements f⁻¹ .is-lim = f⁻¹-is-lim go : Iso _ _ go .fun = f go .inv = f⁻¹ go .rightInv vec-of-lim = funExt λ { k → isSet→LimitPathExt _ isSetΣVec^ (right-inv k) } where abstract right-inv : ∀ k n → f-elements (f⁻¹ vec-of-lim) k n ≡ vec-of-lim k .elements n right-inv k n = Vec.lookup k (Vec.map (cut n) (lookup⁻¹ vec-of-lim)) ≡⟨ VecExt.lookup-map (cut n) (lookup⁻¹ vec-of-lim) k ⟩ (cut n $ Vec.lookup k (lookup⁻¹ vec-of-lim)) ≡⟨ cong (cut n) (funExt⁻ (lookup-right-inv vec-of-lim) k) ⟩ (cut n $ vec-of-lim k) ∎ go .leftInv lim-of-vec = isSet→LimitPathExt vecChain (λ k → VecExt.isSetVec (isSetΣVec^ k)) left-inv where abstract left-inv : ∀ n → f⁻¹ (f lim-of-vec) .elements n ≡ lim-of-vec .elements n left-inv n = Vec.map (cut n) (lookup⁻¹ (f lim-of-vec)) ≡⟨ VecExt.lookup⁻¹-map (cut n) _ ⟩ lookup⁻¹ (cut n ∘ f lim-of-vec) ≡⟨⟩ lookup⁻¹ (λ k → f-elements lim-of-vec k n) ≡⟨⟩ lookup⁻¹ (λ k → (Vec.lookup k $ lim-of-vec .elements n)) ≡⟨ lookup-left-inv _ ⟩ lim-of-vec .elements n ∎ pres′⁺ : ΣVec (Lim ΣVec) → ShLim ΣVec pres′⁺ = pres-Iso .inv pres′⁺≡pres : pres′⁺ ≡ pres⁺ pres′⁺≡pres = funExt $ TerminalChain.isSet→ShLimPath ΣVec (isSetΣVec^ ∘ suc) ∘ goal where open Limit goal : ∀ (xs : ΣVec (Lim ΣVec)) n → pres-Iso .inv xs .elements n ≡ pres⁺ xs .elements n goal xs n = ΣVecPathP refl $ cong (Vec.map (cut n)) (VecExt.lookup-left-inv (xs .vec)) abstract isLimitPreservingΣVec : isLimitPreserving ΣVec isLimitPreservingΣVec = subst isEquiv pres′⁺≡pres (isoToIsEquiv (invIso pres-Iso)) pres : ΣVec (Lim ΣVec) ≃ ShLim ΣVec pres = pres⁺ , isLimitPreservingΣVec pres′ : ΣVec (Lim ΣVec) ≃ ShLim ΣVec pres′ = pres′⁺ , isoToIsEquiv (invIso pres-Iso) pres′≡pres : pres′ ≡ pres pres′≡pres = equivEq pres′⁺≡pres open TerminalChain.Fixpoint isLimitPreservingΣVec using (fix ; fix⁺ ; fix⁻ ; fix⁻-step-ext ; pres⁻) public ΣVecLimitEquiv : ΣVec (Lim ΣVec) ≃ Lim ΣVec ΣVecLimitEquiv = fix ΣVecLimitPath : ΣVec (Lim ΣVec) ≡ Lim ΣVec ΣVecLimitPath = ua ΣVecLimitEquiv isSetLimΣVec : isSet (Lim ΣVec) isSetLimΣVec = isOfHLevelLimit _ 2 isSetΣVec^ isSetTree = isSetLimΣVec open Limit TreePath : ∀ {l₁ l₂ : Lim ΣVec} → (∀ n → l₁ .elements n ≡ l₂ .elements n) → l₁ ≡ l₂ TreePath = isSet→LimitPathExt _ isSetΣVec^ module _ {C : Type} (γ : C → ΣVec C) where step : (n : ℕ) → C → ΣVec ^ n step zero _ = tt* step (suc n) c = map (step n) (γ c) is-lim-step : ∀ c → isLimit (TerminalChain.ch ΣVec) (flip step c) is-lim-step c zero = refl is-lim-step c (suc n) = goal where abstract goal : map (!^ n) (step (suc $ suc n) c) ≡ step (suc n) c goal = (map (!^ n) $ map (step (suc n)) $ γ c) ≡⟨ sym (map-comp (!^ n) _ (γ c)) ⟩ (map (!^ n ∘ step (suc n)) $ γ c) ≡⟨ cong (λ f → map f (γ c)) (funExt λ c' → is-lim-step c' n) ⟩ (map (step n) $ γ c) ∎ unfold : C → Lim ΣVec unfold c .elements = flip step c unfold c .is-lim = is-lim-step c abstract step-unfold : ∀ c n → step n c ≡ fix⁺ (map unfold (γ c)) .elements n step-unfold c zero = refl {x = tt*} step-unfold c (suc n) = map (step n) (γ c) ≡⟨⟩ map (cut n ∘ unfold) (γ c) ≡⟨ map-comp (cut n) unfold _ ⟩ map (cut n) (map unfold (γ c)) ≡⟨ cong-map-ext {{FunctorΣVec}} (sym $ TerminalChain.cut-is-lim _ n) _ ⟩ map (!^ n ∘ cut (suc n)) (map unfold (γ c)) ≡⟨ map-comp (!^ n) (cut (suc n)) _ ⟩ map (!^ n) (map (cut (suc n)) $ map unfold (γ c)) ≡⟨⟩ !^ (suc n) (pres⁺ (map unfold (γ c)) .elements (suc n)) ≡⟨⟩ ShLim→Lim _ (pres⁺ (map unfold (γ c))) .elements (suc n) ≡⟨⟩ fix⁺ (map unfold (γ c)) .elements (suc n) ∎ unfold-fix⁺ : ∀ c → unfold c ≡ fix⁺ (map unfold (γ c)) unfold-fix⁺ c = isSet→LimitPathExt _ isSetΣVec^ (step-unfold c) isCoalgebraMorphismUnfold : isCoalgebraMorphism ΣVec γ fix⁻ unfold isCoalgebraMorphismUnfold = funExt goal where abstract goal : ∀ c → fix⁻ (unfold c) ≡ BVec.map unfold (γ c) goal c = fix⁻ (unfold c) ≡⟨ cong fix⁻ (unfold-fix⁺ c) ⟩ fix⁻ (fix⁺ (BVec.map unfold (γ c))) ≡⟨ retEq ΣVecLimitEquiv (BVec.map unfold (γ c)) ⟩ map unfold (γ c) ∎ tree-width : Tree → ℕ tree-width = length ∘ fix⁻ isTerminalFix⁻ : isTerminal ΣVec fix⁻ isTerminalFix⁻ {B = B} β = ana , anaEq where open TerminalChain.Fixpoint isLimitPreservingΣVec using (fix⁺-step-ext) ana : CoalgebraMorphism ΣVec β fix⁻ ana = unfold β , isCoalgebraMorphismUnfold β anaEq : ∀ f → ana ≡ f anaEq (f , f-is-mor) = Σ≡Prop isPropIsCoalgebraMorphism' eq where abstract isPropIsCoalgebraMorphism' : (u : B → Lim ΣVec) → isProp (isCoalgebraMorphism ΣVec β fix⁻ u) isPropIsCoalgebraMorphism' u = isSet→isPropIsCoalgebraMorphism ΣVec β fix⁻ u (BVec.isSetΣVec isSetLimΣVec) eq : unfold β ≡ f eq = funExt $ TreePath ∘ λ b n → funExt⁻ (goal n) b where goal : ∀ n → step β n ≡ cut n ∘ f goal zero = refl goal (suc n) = map (step β n) ∘ β ≡⟨ cong (λ g → map g ∘ β) (goal n) ⟩ map (cut n ∘ f) ∘ β ≡⟨ cong (_∘ β) (map-comp-ext (cut n) f) ⟩ (map (cut n) ∘ map f) ∘ β ≡⟨ ∘-assoc (map (cut n)) (map f) β ⟩ map (cut n) ∘ (map f ∘ β) ≡⟨ cong (map (cut n) ∘_) (sym f-is-mor) ⟩ map (cut n) ∘ (fix⁻ ∘ f) ≡⟨ sym (∘-assoc (map (cut n)) fix⁻ f) ⟩ (map (cut n) ∘ fix⁻) ∘ f ≡⟨ cong (_∘ f) (fix⁻-step-ext n) ⟩ cut (suc n) ∘ f ∎