{-# OPTIONS --no-termination-check  #-}

open import Prelude hiding (P; A)

module CCS.Homomorphism.CtoP where

open import CCS.Alg
open import CCS.SemiModel
import CCS.Proc as β„™
open import Algebra

open β„™ using (Proc; procAlg; procMod; cong-proc)

open import Data.Set renaming (⟦_⟧ to π’¦βŸ¦_⟧)

private
  A : Type
  A = β„•


open import Hyper.Base
open import CCS.Hyp.Definition A (Proc A)

open CCSAlg ⦃ ... ⦄
open CCSSemiModel ⦃ ... ⦄

instance
  _ : CCSAlg (Proc A)
  _ = procAlg

instance
  _ : CCSSemiModel (Proc A)
  _ = procMod

open import CCS.Hyp.Properties {R = Proc A} procMod hiding (βŠ•βŒŠ)

instance
  _ : CCSAlg Communicator
  _ = hypAlg

instance
  _ : CCSSemiModel Communicator
  _ = hypMod


open import CCS.Hyp.Interp {R = Proc A} procAlg ⦃ it ⦄

open import CCS.Fresh.Hyp
import CCS.Fresh.Proc as β„™
open import CCS.Fresh
open import Swaps {A = A}


⌊-hom↓    : (n : List A) (p q : P A) β†’ ⟦ Ξ½β‚› n - ⟦ p ⌊ q ⟧ βŸ§β†“ ≑ Ξ½β‚› n - ⟦ p ⌊ q ⟧
βˆ₯-hom↓    : (n : List A) (p q : P A) β†’ ⟦ Ξ½β‚› n - ⟦ p βˆ₯ q ⟧ βŸ§β†“ ≑ Ξ½β‚› n - ⟦ p βˆ₯ q ⟧
sync-hom↓ : (n : List A) (a : Act A) (p q : P A) β†’ ⟦ Ξ½β‚› n - syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q ⟧ βŸ§β†“ ≑ Ξ½β‚› n - β„™.syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q ⟧
step-hom↓ : (n : List A) (a : Act A) (p q : P A) β†’ ⟦ Ξ½β‚› n - ⟦ a Β· (p βˆ₯ q) ⟧ βŸ§β†“ ≑ Ξ½β‚› n - β„™.stepβ‚— ⟦ a Β· p ⟧ ⟦ q ⟧

𝟘-hom↓ : βˆ€ (n : List A) (p : Communicator) (q : Proc A)
       β†’ p ≑ 𝟘
       β†’ q ≑ 𝟘
       β†’ ⟦ Ξ½β‚› n - p βŸ§β†“ ≑ Ξ½β‚› n - q

𝟘-hom↓ n p q c0 p0 =
  ⟦ Ξ½β‚› n - p βŸ§β†“  β‰‘βŸ¨ cong (⟦_βŸ§β†“ ∘ (Ξ½β‚› n -_)) c0 ⟩
  ⟦ Ξ½β‚› n - 𝟘 βŸ§β†“      β‰‘βŸ¨ cong ⟦_βŸ§β†“ (Ξ½β‚›-𝟘 n) ⟩
  ⟦ 𝟘 βŸ§β†“             β‰‘βŸ¨βŸ©
  𝟘                  β‰‘Λ˜βŸ¨ Ξ½β‚›-𝟘 n ⟩
  Ξ½β‚› n - 𝟘           β‰‘Λ˜βŸ¨ cong (Ξ½β‚› n -_) p0 ⟩
  Ξ½β‚› n - q ∎

βˆ₯-hom↓ n p q =
  ⟦ Ξ½β‚› n - ⟦ p βˆ₯ q ⟧ βŸ§β†“ β‰‘βŸ¨ cong ⟦_βŸ§β†“ (Ξ½β‚›-βŠ• n _ _) ⟩
  ⟦ Ξ½β‚› n - ⟦ p ⌊ q ⟧ βŸ§β†“ βŠ• ⟦ Ξ½β‚› n - ⟦ q ⌊ p ⟧ βŸ§β†“ β‰‘βŸ¨ congβ‚‚ _βŠ•_ (⌊-hom↓ n p q) (⌊-hom↓ n q p) ⟩
  Ξ½β‚› n - ⟦ p ⌊ q ⟧ βŠ• Ξ½β‚› n - ⟦ q ⌊ p ⟧ β‰‘Λ˜βŸ¨ cong (Ξ½β‚› n -_) (cong-proc refl) β¨Ύ Ξ½β‚›-βŠ• n _ _  ⟩
  Ξ½β‚› n - ⟦ p βˆ₯ q ⟧ ∎

step-hom↓ n a p q with n β‚›βˆˆβ‚? a
... | yes n∈a =
  ⟦ Ξ½β‚› n - ⟦ a Β· (p βˆ₯ q) ⟧ βŸ§β†“ β‰‘βŸ¨ cong ⟦_βŸ§β†“ (Ξ½β‚›-∈-Β· n a ⟦ p βˆ₯ q ⟧ n∈a) ⟩
  ⟦ 𝟘 βŸ§β†“ β‰‘Λ˜βŸ¨ Ξ½β‚›-∈-Β· n a ⟦ p βˆ₯ q ⟧ n∈a ⟩
  Ξ½β‚› n - a Β· ⟦ p βˆ₯ q ⟧ β‰‘βŸ¨ cong (Ξ½β‚› n -_) (cong-proc refl) ⟩
  Ξ½β‚› n - β„™.stepβ‚— ⟦ a Β· p ⟧ ⟦ q ⟧ ∎
... | no  nβˆ‰a =
  ⟦ Ξ½β‚› n - ⟦ a Β· (p βˆ₯ q) ⟧ βŸ§β†“ β‰‘βŸ¨ cong ⟦_βŸ§β†“ (Ξ½β‚›-βˆ‰-Β· n a ⟦ p βˆ₯ q ⟧ nβˆ‰a) ⟩
  ⟦ a Β· Ξ½β‚› n - ⟦ p βˆ₯ q ⟧ βŸ§β†“ β‰‘βŸ¨βŸ©
  a Β· ⟦ Ξ½β‚› n - ⟦ p βˆ₯ q ⟧ βŸ§β†“ β‰‘βŸ¨ cong (a Β·_) (βˆ₯-hom↓ n p q) ⟩
  a Β· Ξ½β‚› n - ⟦ p βˆ₯ q ⟧ β‰‘Λ˜βŸ¨ Ξ½β‚›-βˆ‰-Β· n a ⟦ p βˆ₯ q ⟧ nβˆ‰a ⟩
  Ξ½β‚› n - a Β· ⟦ p βˆ₯ q ⟧ β‰‘βŸ¨ cong (Ξ½β‚› n -_) (cong-proc refl) ⟩
  Ξ½β‚› n - β„™.stepβ‚— ⟦ a Β· p ⟧ ⟦ q ⟧ ∎

sync-hom↓ n (inp a) p `𝟘 =
  𝟘-hom↓ n _ _ (sync𝟘ʳ (inp a) p) (cong-proc refl)

sync-hom↓ n a p (q₁ `βŠ• qβ‚‚) =
  ⟦ Ξ½β‚› n - syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ βŠ• qβ‚‚ ⟧ βŸ§β†“ β‰‘βŸ¨ cong (⟦_βŸ§β†“ ∘ Ξ½β‚› n -_) (syncα΅’β‚’-βŠ•Κ³ _ _ _ _) ⟩
  ⟦ Ξ½β‚› n - (syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ ⟧ βŠ• syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ qβ‚‚ ⟧) βŸ§β†“ β‰‘βŸ¨ cong ⟦_βŸ§β†“ (Ξ½β‚›-βŠ• n _ _) ⟩
  ⟦ (Ξ½β‚› n - syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ ⟧) βŠ• (Ξ½β‚› n - syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ qβ‚‚ ⟧) βŸ§β†“ β‰‘βŸ¨βŸ©
  ⟦ Ξ½β‚› n - syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ ⟧ βŸ§β†“ βŠ• ⟦ Ξ½β‚› n - syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ qβ‚‚ ⟧ βŸ§β†“ β‰‘βŸ¨ congβ‚‚ _βŠ•_ (sync-hom↓ n a p q₁) (sync-hom↓ n a p qβ‚‚) ⟩
  (Ξ½β‚› n - β„™.syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ ⟧) βŠ• (Ξ½β‚› n - β„™.syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ qβ‚‚ ⟧) β‰‘Λ˜βŸ¨ Ξ½β‚›-βŠ• n _ _ ⟩
  Ξ½β‚› n - (β„™.syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ ⟧ βŠ• β„™.syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ qβ‚‚ ⟧) β‰‘Λ˜βŸ¨ cong (Ξ½β‚› n -_) (β„™.syncα΅’β‚’-βŠ•Κ³ _ _ _) ⟩
  Ξ½β‚› n - β„™.syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ βŠ• qβ‚‚ ⟧ ∎

sync-hom↓ n a p (q₁ `βˆ₯ qβ‚‚) =
  ⟦ Ξ½β‚› n - syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ βˆ₯ qβ‚‚ ⟧ βŸ§β†“ β‰‘βŸ¨βŸ©
  ⟦ Ξ½β‚› n - syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ ⌊ qβ‚‚ βŠ• qβ‚‚ ⌊ q₁ ⟧ βŸ§β†“ β‰‘βŸ¨ sync-hom↓ n a p (q₁ ⌊ qβ‚‚ βŠ• qβ‚‚ ⌊ q₁) ⟩
  Ξ½β‚› n - β„™.syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ ⌊ qβ‚‚ βŠ• qβ‚‚ ⌊ q₁ ⟧ β‰‘βŸ¨ cong (Ξ½β‚› n -_) (cong (β„™.syncα΅’β‚’ ⟦ a Β· p ⟧) (cong-proc refl)) ⟩
  Ξ½β‚› n - β„™.syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ βˆ₯ qβ‚‚ ⟧ ∎

sync-hom↓ n (out a) p q =
  𝟘-hom↓ n _ _ (sync-out a ⟦ p ⟧ q) (cong-proc refl)

sync-hom↓ n Ο„ p q = 𝟘-hom↓ n _ _ (sync-Ο„ ⟦ p ⟧ q) (cong-proc refl)

sync-hom↓ n a p (q₁ `⌊ qβ‚‚) =
  ⟦ Ξ½β‚› n - syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ ⌊ qβ‚‚ ⟧ βŸ§β†“ β‰‘βŸ¨ cong (⟦_βŸ§β†“ ∘ Ξ½β‚› n -_) (syncα΅’β‚’-assoc a ⟦ p ⟧ _ _) ⟩
  ⟦ Ξ½β‚› n - syncα΅’β‚’ ⟦ a Β· (p βˆ₯ qβ‚‚) ⟧ ⟦ q₁ ⟧ βŸ§β†“ β‰‘βŸ¨ sync-hom↓ n a (p βˆ₯ qβ‚‚) q₁ ⟩
  Ξ½β‚› n - β„™.syncα΅’β‚’ ⟦ a Β· (p βˆ₯ qβ‚‚) ⟧ ⟦ q₁ ⟧ β‰‘βŸ¨ cong (Ξ½β‚› n -_) (β„™.syncα΅’β‚’-assoc a ⟦ p ⟧ ⟦ qβ‚‚ ⟧ ⟦ q₁ ⟧) ⟩
  Ξ½β‚› n - β„™.syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ q₁ ⌊ qβ‚‚ ⟧ ∎

sync-hom↓ ns a p (`Ξ½ n - q) =
  let m = # ((a · p) ⌊ q)
  in

  ⟦ Ξ½β‚› ns - syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ Ξ½ n - q ⟧ βŸ§β†“

    β‰‘βŸ¨ cong ⟦_βŸ§β†“ ( Ξ½-sync-rewrite ns n a p q) ⟩

  ⟦ Ξ½β‚› (m ∷ ns) - syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ `ρ  (n /β†’ m) q ⟧ βŸ§β†“

    β‰‘βŸ¨ sync-hom↓ (m ∷ ns) a p (`ρ (n /β†’ m) q) ⟩

  Ξ½β‚› (m ∷ ns) - β„™.syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ `ρ (n /β†’ m) q ⟧

    β‰‘Λ˜βŸ¨ cong (Ξ½β‚› ns -_) (β„™.Ξ½-sync-rewrite n a p q) ⟩

  Ξ½β‚› ns - β„™.syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ Ξ½ n - q ⟧ ∎

sync-hom↓ n a p (`! q) =

  ⟦ Ξ½β‚› n - syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ ! q ⟧ βŸ§β†“

    β‰‘βŸ¨ cong (⟦_βŸ§β†“ ∘ Ξ½β‚› n -_) (cong (syncα΅’β‚’ ⟦ a Β· p ⟧) (!-⌊ ⟦ q ⟧) β¨Ύ syncα΅’β‚’-assoc a ⟦ p ⟧ _ _) ⟩

  ⟦ Ξ½β‚› n - syncα΅’β‚’ ⟦ a Β· (p βˆ₯ ! q) ⟧ ⟦ q ⟧ βŸ§β†“

    β‰‘βŸ¨ sync-hom↓ n a (p βˆ₯ ! q) q ⟩

  Ξ½β‚› n - β„™.syncα΅’β‚’ ⟦ a Β· (p βˆ₯ ! q) ⟧ ⟦ q ⟧

    β‰‘βŸ¨ cong (Ξ½β‚› n -_) (β„™.syncα΅’β‚’-assoc a ⟦ p ⟧ ⟦ ! q ⟧ ⟦ q ⟧ β¨Ύ cong (β„™.syncα΅’β‚’ ⟦ a Β· p ⟧) (sym (!-⌊ ⟦ q ⟧))) ⟩

  Ξ½β‚› n - β„™.syncα΅’β‚’ ⟦ a Β· p ⟧ ⟦ ! q ⟧ ∎

sync-hom↓ n (inp a) p (Ο„ `Β· q) =
  𝟘-hom↓ n _ _ (sync-nomatch (inp a) Ο„ ⟦ p ⟧ ⟦ q ⟧ Ξ» ()) (cong-proc refl)

sync-hom↓ n (inp a) p (inp b `Β· q) =
  𝟘-hom↓ n _ _ (sync-nomatch (inp a) (inp b) ⟦ p ⟧ ⟦ q ⟧ Ξ» ()) (cong-proc refl)

sync-hom↓ n (inp a) p (out b `Β· q) with a β‰Ÿ b
... | no a≒b =
  𝟘-hom↓ n _ _ (sync-nomatch (inp a) (out b) ⟦ p ⟧ ⟦ q ⟧ aβ‰’b) (β„™.syncα΅’β‚’-nomatch (inp a) (out b) ⟦ p ⟧ ⟦ q ⟧ aβ‰’b)
... | yes a≑b =
  ⟦ Ξ½β‚› n - syncα΅’β‚’ ⟦ inp a Β· p ⟧ ⟦ out b Β· q ⟧ βŸ§β†“ β‰‘βŸ¨ cong (⟦_βŸ§β†“ ∘ (Ξ½β‚› n -_)) (sync-match (inp a) (out b) p ⟦ q ⟧ a≑b) ⟩
  ⟦ Ξ½β‚› n - Ο„ Β· ⟦ p βˆ₯ q ⟧ βŸ§β†“ β‰‘βŸ¨ cong ⟦_βŸ§β†“ (Ξ½β‚›-βˆ‰-Β· n Ο„ ⟦ p βˆ₯ q ⟧ Ξ» ()) ⟩
  Ο„ Β· ⟦ Ξ½β‚› n - ⟦ p βˆ₯ q ⟧ βŸ§β†“ β‰‘βŸ¨ cong (Ο„ Β·_) (βˆ₯-hom↓ n p q) ⟩
  Ο„ Β· Ξ½β‚› n - ⟦ p βˆ₯ q ⟧ β‰‘Λ˜βŸ¨ Ξ½β‚›-βˆ‰-Β· n Ο„ ⟦ p βˆ₯ q ⟧ (Ξ» ()) ⟩
  Ξ½β‚› n - Ο„ Β· ⟦ p βˆ₯ q ⟧ β‰‘Λ˜βŸ¨ cong (Ξ½β‚› n -_) (cong-proc (cong (bool βˆ… _) (it-does (a β‰Ÿ b) a≑b) )) ⟩
  Ξ½β‚› n - β„™.syncα΅’β‚’ ⟦ inp a Β· p ⟧ ⟦ out b Β· q ⟧ ∎

⌊-hom↓ n `𝟘 q =
  ⟦ Ξ½β‚› n - ⟦ 𝟘 ⌊ q ⟧ βŸ§β†“ β‰‘βŸ¨ cong ⟦_βŸ§β†“ (ν⌊-𝟘 n ⟦ q ⟧) ⟩
  𝟘 β‰‘Λ˜βŸ¨ ν⌊-𝟘 n ⟦ q ⟧ ⟩
  Ξ½β‚› n - ⟦ 𝟘 ⌊ q ⟧ ∎
⌊-hom↓ n (p₁ `βŠ• pβ‚‚) q =
  ⟦ Ξ½β‚› n - ⟦ (p₁ βŠ• pβ‚‚) ⌊ q ⟧ βŸ§β†“                   β‰‘βŸ¨ cong ⟦_βŸ§β†“ (ν⌊-βŠ• ⟦ p₁ ⟧ ⟦ pβ‚‚ ⟧ n ⟦ q ⟧) ⟩
  ⟦ Ξ½β‚› n - ⟦ p₁ ⌊ q ⟧ βŸ§β†“ βŠ• ⟦ Ξ½β‚› n - ⟦ pβ‚‚ ⌊ q ⟧ βŸ§β†“ β‰‘βŸ¨ congβ‚‚ _βŠ•_ (⌊-hom↓ n p₁ q) (⌊-hom↓ n pβ‚‚ q) ⟩
  Ξ½β‚› n - ⟦ p₁ ⌊ q ⟧ βŠ• Ξ½β‚› n - ⟦ pβ‚‚ ⌊ q ⟧           β‰‘Λ˜βŸ¨ ν⌊-βŠ• ⟦ p₁ ⟧ ⟦ pβ‚‚ ⟧ n ⟦ q ⟧ ⟩
  Ξ½β‚› n - ⟦ (p₁ βŠ• pβ‚‚) ⌊ q ⟧ ∎
⌊-hom↓ n (p₁ `⌊ pβ‚‚) q =
  ⟦ Ξ½β‚› n - ⟦ (p₁ ⌊ pβ‚‚) ⌊ q ⟧ βŸ§β†“ β‰‘βŸ¨ cong (Ξ» e β†’ ⟦ Ξ½β‚› n - e βŸ§β†“) (⌊-assoc ⟦ p₁ ⟧ ⟦ pβ‚‚ ⟧ ⟦ q ⟧)  ⟩
  ⟦ Ξ½β‚› n - ⟦ p₁ ⌊ (pβ‚‚ βˆ₯ q) ⟧ βŸ§β†“ β‰‘βŸ¨ ⌊-hom↓ n p₁ (pβ‚‚ βˆ₯ q) ⟩
  Ξ½β‚› n - ⟦ p₁ ⌊ (pβ‚‚ βˆ₯ q) ⟧      β‰‘Λ˜βŸ¨ cong (Ξ½β‚› n -_) (⌊-assoc ⟦ p₁ ⟧ ⟦ pβ‚‚ ⟧ ⟦ q ⟧) ⟩
  Ξ½β‚› n - ⟦ (p₁ ⌊ pβ‚‚) ⌊ q ⟧ ∎
⌊-hom↓ n (p₁ `βˆ₯ pβ‚‚) q =
  ⟦ Ξ½β‚› n - ⟦ (p₁ βˆ₯ pβ‚‚) ⌊ q ⟧ βŸ§β†“                                 β‰‘βŸ¨ cong (Ξ» e β†’ ⟦ Ξ½β‚› n - (e ⌊ ⟦ q ⟧) βŸ§β†“) (⌊-βˆ₯ ⟦ p₁ ⟧ ⟦ pβ‚‚ ⟧)  ⟩
  ⟦ Ξ½β‚› n - ⟦ (p₁ ⌊ pβ‚‚ βŠ• pβ‚‚ ⌊ p₁) ⌊ q ⟧ βŸ§β†“                       β‰‘βŸ¨ cong ⟦_βŸ§β†“ (ν⌊-βŠ• ⟦ p₁ ⌊ pβ‚‚ ⟧ ⟦ pβ‚‚ ⌊ p₁ ⟧ n ⟦ q ⟧) ⟩
  ⟦ Ξ½β‚› n - ⟦ p₁ ⌊ pβ‚‚ ⌊ q ⟧ βŸ§β†“ βŠ• ⟦ Ξ½β‚› n - ⟦ pβ‚‚ ⌊ p₁ ⌊ q ⟧ βŸ§β†“     β‰‘βŸ¨ congβ‚‚ _βŠ•_ (cong (⟦_βŸ§β†“ ∘ Ξ½β‚› n -_) (⌊-assoc ⟦ p₁ ⟧ ⟦ pβ‚‚ ⟧ ⟦ q ⟧)) (cong (⟦_βŸ§β†“ ∘ Ξ½β‚› n -_) (⌊-assoc ⟦ pβ‚‚ ⟧ ⟦ p₁ ⟧ ⟦ q ⟧)) ⟩
  ⟦ Ξ½β‚› n - ⟦ p₁ ⌊ (pβ‚‚ βˆ₯ q) ⟧ βŸ§β†“ βŠ• ⟦ Ξ½β‚› n - ⟦ pβ‚‚ ⌊ (p₁ βˆ₯ q) ⟧ βŸ§β†“ β‰‘βŸ¨ congβ‚‚ _βŠ•_ (⌊-hom↓ n p₁ (pβ‚‚ βˆ₯ q)) (⌊-hom↓ n pβ‚‚ (p₁ βˆ₯ q)) ⟩
  Ξ½β‚› n - ⟦ p₁ ⌊ (pβ‚‚ βˆ₯ q) ⟧ βŠ• Ξ½β‚› n - ⟦ pβ‚‚ ⌊ (p₁ βˆ₯ q) ⟧           β‰‘Λ˜βŸ¨ congβ‚‚ _βŠ•_ (cong (Ξ½β‚› n -_) (⌊-assoc ⟦ p₁ ⟧ ⟦ pβ‚‚ ⟧ ⟦ q ⟧)) (cong (Ξ½β‚› n -_) (⌊-assoc ⟦ pβ‚‚ ⟧ ⟦ p₁ ⟧ ⟦ q ⟧)) ⟩
  Ξ½β‚› n - ⟦ p₁ ⌊ pβ‚‚ ⌊ q ⟧ βŠ• Ξ½β‚› n - ⟦ pβ‚‚ ⌊ p₁ ⌊ q ⟧               β‰‘Λ˜βŸ¨ ν⌊-βŠ• ⟦ p₁ ⌊ pβ‚‚ ⟧ ⟦ pβ‚‚ ⌊ p₁ ⟧ n ⟦ q ⟧ ⟩
  Ξ½β‚› n - ((⟦ p₁ ⟧ ⌊ ⟦ pβ‚‚ ⟧ βŠ• ⟦ pβ‚‚ ⟧ ⌊ ⟦ p₁ ⟧) ⌊ ⟦ q ⟧)          β‰‘Λ˜βŸ¨ cong (Ξ» e β†’ Ξ½β‚› n - (e ⌊ ⟦ q ⟧)) (⌊-βˆ₯ ⟦ p₁ ⟧ ⟦ pβ‚‚ ⟧) ⟩
  Ξ½β‚› n - (⟦ p₁ ⟧ βˆ₯ ⟦ pβ‚‚ ⟧ ⌊ ⟦ q ⟧) ∎
⌊-hom↓ n (`! p) q =
  ⟦ Ξ½β‚› n - ⟦ ! p ⌊ q ⟧ βŸ§β†“       β‰‘βŸ¨ cong (Ξ» e β†’ ⟦ Ξ½β‚› n - (e ⌊ ⟦ q ⟧) βŸ§β†“) (!-⌊ ⟦ p ⟧) ⟩
  ⟦ Ξ½β‚› n - ⟦ p ⌊ ! p ⌊ q ⟧ βŸ§β†“   β‰‘βŸ¨ cong (Ξ» e β†’ ⟦ Ξ½β‚› n - e βŸ§β†“) (⌊-assoc ⟦ p ⟧ ⟦ ! p ⟧ ⟦ q ⟧) ⟩
  ⟦ Ξ½β‚› n - ⟦ p ⌊ (! p βˆ₯ q) ⟧ βŸ§β†“ β‰‘βŸ¨ ⌊-hom↓ n p (! p βˆ₯ q) ⟩
  Ξ½β‚› n - ⟦ p ⌊ (! p βˆ₯ q) ⟧      β‰‘Λ˜βŸ¨ cong (Ξ½β‚› n -_) (⌊-assoc ⟦ p ⟧ ⟦ ! p ⟧ ⟦ q ⟧) ⟩
  Ξ½β‚› n - ⟦ p ⌊ ! p ⌊ q ⟧        β‰‘Λ˜βŸ¨ cong (Ξ» e β†’ Ξ½β‚› n - (e ⌊ ⟦ q ⟧)) (!-⌊ ⟦ p ⟧) ⟩
  Ξ½β‚› n - ⟦ ! p ⌊ q ⟧ ∎
⌊-hom↓ n (a `Β· p) q =
  ⟦ Ξ½β‚› n - ⟦ a Β· p ⌊ q ⟧ βŸ§β†“

    β‰‘βŸ¨ cong (⟦_βŸ§β†“ ∘ (Ξ½β‚› n -_)) (·⌊-decomp a ⟦ p ⟧ ⟦ q ⟧) ⟩

  ⟦ Ξ½β‚› n - (syncα΅’β‚’ (a Β· ⟦ p ⟧) ⟦ q ⟧ βŠ• stepβ‚— (a Β· ⟦ p ⟧) ⟦ q ⟧) βŸ§β†“

    β‰‘βŸ¨ cong ⟦_βŸ§β†“ (Ξ½β‚›-βŠ• n _ _) ⟩

  ⟦ Ξ½β‚› n - syncα΅’β‚’ (a Β· ⟦ p ⟧) ⟦ q ⟧ βŸ§β†“ βŠ• ⟦ Ξ½β‚› n - stepβ‚— (a Β· ⟦ p ⟧) ⟦ q ⟧ βŸ§β†“

    β‰‘βŸ¨ congβ‚‚ _βŠ•_ (sync-hom↓ n a p q) (cong (⟦_βŸ§β†“ ∘ Ξ½β‚› n -_) (step-Β· a ⟦ p ⟧ ⟦ q ⟧ β¨Ύ cong (a Β·_) (βˆ₯-comm ⟦ q ⟧ ⟦ p ⟧)) β¨Ύ step-hom↓ n a p q) ⟩

  (Ξ½β‚› n - β„™.syncα΅’β‚’ (a Β· ⟦ p ⟧) ⟦ q ⟧) βŠ• (Ξ½β‚› n - β„™.stepβ‚— (a Β· ⟦ p ⟧) ⟦ q ⟧)

    β‰‘Λ˜βŸ¨ Ξ½β‚›-βŠ• n _ _ ⟩

  Ξ½β‚› n - (β„™.syncα΅’β‚’ (a Β· ⟦ p ⟧) ⟦ q ⟧ βŠ• β„™.stepβ‚— (a Β· ⟦ p ⟧) ⟦ q ⟧)

    β‰‘βŸ¨ cong (Ξ½β‚› n -_) (cong-proc refl) ⟩

  Ξ½β‚› n - ⟦ a Β· p ⌊ q ⟧ ∎


⌊-hom↓ ns (`Ξ½ n - p) q =
  let m = # (p ⌊ q)
  in

  ⟦ Ξ½β‚› ns - ⟦ Ξ½ n - p ⌊ q ⟧ βŸ§β†“

    β‰‘βŸ¨ cong ⟦_βŸ§β†“ (Ξ½-⌊-rewrite ns n p q) ⟩

  ⟦ Ξ½β‚› (m ∷ ns) - ⟦ `ρ (n /β†’ m) p ⌊ q ⟧ βŸ§β†“

    β‰‘βŸ¨ ⌊-hom↓ (m ∷ ns) (`ρ (n /β†’ m) p) q ⟩

  Ξ½β‚› (m ∷ ns) - ⟦ `ρ (n /β†’ m) p ⌊ q ⟧

    β‰‘Λ˜βŸ¨ β„™.Ξ½-⌊-rewrite ns n p q ⟩

  Ξ½β‚› ns - ⟦ Ξ½ n - p ⌊ q ⟧ ∎

hom↓ : βˆ€ (p : P A) β†’ ⟦ ⟦ p ⟧ βŸ§β†“ ≑ ⟦ p ⟧
hom↓ p =
  ⟦ ⟦ p ⟧ βŸ§β†“ β‰‘Λ˜βŸ¨ cong ⟦_βŸ§β†“ (⌊𝟘 ⟦ p ⟧) ⟩
  ⟦ ⟦ p ⟧ ⌊ 𝟘 βŸ§β†“ β‰‘βŸ¨ ⌊-hom↓ [] p 𝟘 ⟩
  ⟦ p ⌊ 𝟘 ⟧ β‰‘βŸ¨ ⌊𝟘 ⟦ p ⟧ ⟩
  ⟦ p ⟧ ∎