{-# OPTIONS --safe #-}

module CCS.SemiModel where

open import Prelude hiding (P)
open import CCS.Alg
open import Algebra

record CCSSemiModel (C : Type c) : Type (β„“suc c) where
  field ⦃ ccsAlg ⦄ : CCSAlg C
  open CCSAlg ccsAlg

  open CCSAlg ccsAlg public
    using ()
    renaming (Name to MName)

  field
    πŸ˜βŠ• : βˆ€ p β†’ 𝟘 βŠ• p ≑ p
    βŠ•-assoc : βˆ€ x y z β†’ (x βŠ• y) βŠ• z ≑ x βŠ• (y βŠ• z)
    βŠ•-comm : βˆ€ x y β†’ x βŠ• y ≑ y βŠ• x
    βŠ•-idem : βˆ€ x β†’ x βŠ• x ≑ x

    ⌊-βˆ₯ : βˆ€ p q β†’ p βˆ₯ q ≑ (p ⌊ q) βŠ• (q ⌊ p)
    ⌊-assoc : βˆ€ x y z β†’ (x ⌊ y) ⌊ z ≑ x ⌊ (y βˆ₯ z)

    𝟘⌊ : βˆ€ p β†’ 𝟘 ⌊ p ≑ 𝟘
    ⌊𝟘 : βˆ€ p β†’ p ⌊ 𝟘 ≑ p
    βŠ•βŒŠ : βˆ€ p q r β†’ (p βŠ• q) ⌊ r ≑ (p ⌊ r) βŠ• (q ⌊ r)

    ν𝟘 : βˆ€ x β†’ Ξ½ x - 𝟘 ≑ 𝟘
    Ξ½-comm : βˆ€ x y p β†’ Ξ½ x - Ξ½ y - p ≑ Ξ½ y - Ξ½ x - p
    Ξ½-βŠ• : βˆ€ x p q β†’ Ξ½ x - (p βŠ• q) ≑ Ξ½ x - p βŠ• Ξ½ x - q

    !-⌊ : βˆ€ p β†’ ! p ≑ p ⌊ ! p
    !-βˆ₯ : βˆ€ p β†’ ! p ≑ p βˆ₯ ! p

    Ξ½-∈-Β· : βˆ€ n a p β†’ n βˆˆβ‚ a β†’ Ξ½ n - a Β· p ≑ 𝟘
    Ξ½-βˆ‰-Β· : βˆ€ n a p β†’ n βˆ‰β‚ a β†’ Ξ½ n - a Β· p ≑ a Β· Ξ½ n - p

  βŠ•πŸ˜ : βˆ€ p β†’ p βŠ• 𝟘 ≑ p
  βŠ•πŸ˜ p = βŠ•-comm p 𝟘 β¨Ύ πŸ˜βŠ• p

  βŠ•-semilattice : Semilattice C
  βŠ•-semilattice = record
    { commutativeMonoid = record
      { monoid = record
        { _βˆ™_ = _βŠ•_
        ; Ρ = 𝟘
        ; Ξ΅βˆ™ = πŸ˜βŠ•
        ; βˆ™Ξ΅ = βŠ•πŸ˜
        ; assoc = βŠ•-assoc
        }
      ; comm = βŠ•-comm
      }
    ; idem = βŠ•-idem
    }

  𝟘βˆ₯ : βˆ€ p β†’ 𝟘 βˆ₯ p ≑ p
  𝟘βˆ₯ p = ⌊-βˆ₯ 𝟘 p β¨Ύ congβ‚‚ _βŠ•_ (𝟘⌊ p) (⌊𝟘 p) β¨Ύ πŸ˜βŠ• p

  βˆ₯-comm : βˆ€ p q β†’ p βˆ₯ q ≑ q βˆ₯ p
  βˆ₯-comm p q = ⌊-βˆ₯ p q β¨Ύ βŠ•-comm _ _ β¨Ύ sym (⌊-βˆ₯ q p)

  βˆ₯𝟘 : βˆ€ p β†’ p βˆ₯ 𝟘 ≑ p
  βˆ₯𝟘 p = βˆ₯-comm p 𝟘 β¨Ύ 𝟘βˆ₯ p

  ⌊-comm : βˆ€ x y z β†’ x ⌊ y ⌊ z ≑ x ⌊ z ⌊ y
  ⌊-comm x y z =
    x ⌊ y ⌊ z β‰‘βŸ¨ ⌊-assoc x y z ⟩
    x ⌊ (y βˆ₯ z) β‰‘βŸ¨ cong (x ⌊_) (βˆ₯-comm y z) ⟩
    x ⌊ (z βˆ₯ y) β‰‘Λ˜βŸ¨ ⌊-assoc x z y ⟩
    x ⌊ z ⌊ y ∎

  βˆ₯-assoc : βˆ€ x y z β†’ (x βˆ₯ y) βˆ₯ z ≑ x βˆ₯ (y βˆ₯ z)
  βˆ₯-assoc x y z =
    (x βˆ₯ y) βˆ₯ z                             β‰‘βŸ¨ ⌊-βˆ₯ (x βˆ₯ y) z ⟩
    (x βˆ₯ y)         ⌊ z       βŠ• z ⌊ (x βˆ₯ y) β‰‘βŸ¨ cong (Ξ» e β†’ e ⌊ z βŠ• z ⌊ (x βˆ₯ y)) (⌊-βˆ₯ x y) ⟩
    (x ⌊ y βŠ• y ⌊ x) ⌊ z       βŠ• z ⌊ (x βˆ₯ y) β‰‘βŸ¨ cong (_βŠ• z ⌊ (x βˆ₯ y)) (βŠ•βŒŠ (x ⌊ y) (y ⌊ x) z) ⟩
    (x ⌊  y ⌊ z  βŠ• y ⌊ x ⌊ z) βŠ• z ⌊ (x βˆ₯ y) β‰‘βŸ¨ congβ‚‚ _βŠ•_ (congβ‚‚ _βŠ•_ (⌊-assoc x y z) (⌊-comm y x z)) (cong (z ⌊_) (βˆ₯-comm x y) β¨Ύ sym (⌊-assoc z y x)) ⟩
    (x ⌊ (y βˆ₯ z) βŠ• y ⌊ z ⌊ x) βŠ• z ⌊  y ⌊ x   β‰‘βŸ¨ βŠ•-assoc (x ⌊ (y βˆ₯ z)) (y ⌊ z ⌊ x) (z ⌊ y ⌊ x) ⟩
     x ⌊ (y βˆ₯ z) βŠ• (y ⌊ z ⌊ x βŠ• z ⌊  y ⌊ x)  β‰‘Λ˜βŸ¨ cong (x ⌊ (y βˆ₯ z) βŠ•_) (βŠ•βŒŠ (y ⌊ z) (z ⌊ y) x) ⟩
     x ⌊ (y βˆ₯ z) βŠ• (y ⌊ z βŠ• z ⌊ y) ⌊ x      β‰‘Λ˜βŸ¨ cong (Ξ» e β†’ x ⌊ (y βˆ₯ z) βŠ• e ⌊ x) (⌊-βˆ₯ y z) ⟩
     x ⌊ (y βˆ₯ z) βŠ• (y βˆ₯ z)         ⌊ x      β‰‘Λ˜βŸ¨ ⌊-βˆ₯ x (y βˆ₯ z) ⟩
     x βˆ₯ (y βˆ₯ z) ∎

  open import Data.List.Properties

  Ξ½β‚›-comm-∷ : βˆ€ x xs p β†’ Ξ½ x - Ξ½β‚› xs - p ≑ Ξ½β‚› xs - Ξ½ x - p
  Ξ½β‚›-comm-∷ x xs p = foldl-fusion (Ξ½ x -_) p (flip (Ξ½-comm x)) xs

  Ξ½β‚›-comm : βˆ€ xs ys p β†’ Ξ½β‚› xs - Ξ½β‚› ys - p ≑ Ξ½β‚› ys - Ξ½β‚› xs - p
  Ξ½β‚›-comm xs ys p = sym (foldl-fusion (Ξ½β‚› ys -_) p (Ξ» p y β†’ sym (Ξ½β‚›-comm-∷ y ys p)) xs)

  Ξ½β‚›-βŠ• : βˆ€ x p q β†’ Ξ½β‚› x - (p βŠ• q) ≑ Ξ½β‚› x - p βŠ• Ξ½β‚› x - q
  Ξ½β‚›-βŠ• []       p q = refl
  Ξ½β‚›-βŠ• (x ∷ xs) p q = cong (Ξ½β‚› xs -_) (Ξ½-βŠ• x p q) β¨Ύ Ξ½β‚›-βŠ• xs (Ξ½ x - p) (Ξ½ x - q)

  Ξ½β‚›-lr : βˆ€ ns p β†’ Ξ½β‚› ns - p ≑ Ξ½β‚›α΅£ ns - p
  Ξ½β‚›-lr [] p = refl
  Ξ½β‚›-lr (n ∷ ns) p =
    Ξ½β‚› n ∷ ns - p β‰‘βŸ¨βŸ©
    Ξ½β‚› ns - Ξ½ n - p β‰‘Λ˜βŸ¨ Ξ½β‚›-comm-∷ n ns p ⟩
    Ξ½ n - Ξ½β‚› ns - p β‰‘βŸ¨ cong (Ξ½ n -_) (Ξ½β‚›-lr ns p) ⟩
    Ξ½ n - Ξ½β‚›α΅£ ns - p β‰‘βŸ¨βŸ©
    Ξ½β‚›α΅£ n ∷ ns - p ∎

  Ξ½β‚›-𝟘 : βˆ€ ns β†’ Ξ½β‚› ns - 𝟘 ≑ 𝟘
  Ξ½β‚›-𝟘 [] = refl
  Ξ½β‚›-𝟘 (n ∷ ns) = cong (Ξ½β‚› ns -_) (ν𝟘 n) β¨Ύ Ξ½β‚›-𝟘 ns

  open import Data.Fin

  module _ ⦃ _ : IsDiscrete Name ⦄ where

    Ξ½β‚›-∈-Β· : βˆ€ ns a p β†’ ns β‚›βˆˆβ‚ a β†’ Ξ½β‚› ns - a Β· p ≑ 𝟘
    Ξ½β‚›-∈-Β· (n ∷ ns) a p (fz   , n∈a) = cong (Ξ½β‚› ns -_) (Ξ½-∈-Β· n a p n∈a) β¨Ύ Ξ½β‚›-𝟘 ns
    Ξ½β‚›-∈-Β· (n ∷ ns) a p (fs i , ns∈a) with n βˆˆβ‚? a
    ... | yes n∈a = cong (Ξ½β‚› ns -_) (Ξ½-∈-Β· n a p n∈a) β¨Ύ Ξ½β‚›-𝟘 ns
    ... | no  nβˆ‰a = cong (Ξ½β‚› ns -_) (Ξ½-βˆ‰-Β· n a p nβˆ‰a) β¨Ύ Ξ½β‚›-∈-Β· ns a (Ξ½ n - p) (i , ns∈a)

  Ξ½β‚›-βˆ‰-Β· : βˆ€ ns a p β†’ ns β‚›βˆ‰β‚ a β†’ Ξ½β‚› ns - a Β· p ≑ a Β· Ξ½β‚› ns - p
  Ξ½β‚›-βˆ‰-Β· []       a p nsβˆ‰a = refl
  Ξ½β‚›-βˆ‰-Β· (n ∷ ns) a p nsβˆ‰a = cong (Ξ½β‚› ns -_) (Ξ½-βˆ‰-Β· n a p (nsβˆ‰a ∘ (fz ,_))) β¨Ύ Ξ½β‚›-βˆ‰-Β· ns a (Ξ½ n - p) (nsβˆ‰a ∘ there {P = _βˆˆβ‚ a} n)

  ν⌊-βŠ• : βˆ€ p q ns r β†’ Ξ½β‚› ns - ((p βŠ• q) ⌊ r) ≑ Ξ½β‚› ns - (p ⌊ r) βŠ• Ξ½β‚› ns - (q ⌊ r)
  ν⌊-βŠ• p q ns r =
    Ξ½β‚› ns - ((p βŠ• q) ⌊ r) β‰‘βŸ¨ cong (Ξ½β‚› ns -_) (βŠ•βŒŠ _ _ _) ⟩
    Ξ½β‚› ns - (p ⌊ r βŠ• q ⌊ r) β‰‘βŸ¨ Ξ½β‚›-βŠ• ns (p ⌊ r) (q ⌊ r) ⟩
    Ξ½β‚› ns - (p ⌊ r) βŠ• Ξ½β‚› ns - (q ⌊ r) ∎

  ν⌊-𝟘 : βˆ€ ns r β†’ Ξ½β‚› ns - (𝟘 ⌊ r) ≑ 𝟘
  ν⌊-𝟘 ns r = cong (Ξ½β‚› ns -_) (𝟘⌊ r) β¨Ύ Ξ½β‚›-𝟘 ns