open import Relation.Binary
open import Relation.Binary.PropositionalEquality
open import Data.Product renaming (map to map∑)
open import Data.Maybe hiding (_>>=_)
open import Data.Sum
open import Data.String
open import Data.Nat hiding (_≟_)
open import Data.Unit hiding (_≟_ ; _≤_ ; _≤?_)
open import Function
open import Relation.Nullary
open import Relation.Unary using (Pred) renaming (Decidable to Decidableₚ)
open import Data.List.Relation.Unary.Any renaming (Any to Anyₗ)
open import Data.List.Relation.Unary.All
open import Data.List hiding (_++_ ; all) renaming (map to mapₗ)
open import Data.Nat.Show renaming (show to showℕ)
open import Helper
open import Codata.Musical.Costring
open import IO.Primitive hiding (return ; _>>=_)
open import Data.Maybe.Categorical
open import Category.Monad
open import Agda.Primitive
open import Data.Maybe.Relation.Unary.Any
open import Relation.Nullary.Negation
open import Data.Empty
module Petrinet where
open import ListAssoc String _≟_
record Petrinet : Set where
constructor [ₘ_-_ₜ][_] ; field
marking : Map {B = ℕ}
transitions : Map {B = Map {B = ℕ × ℕ}}
.conformity : ∀ {t t∈trans p} →
p ∈ₗ (get t from transitions if t∈trans) → p ∈ₗ marking
open Petrinet
newPet : Petrinet
newPet = [ₘ newMap - newMap ₜ][ (λ { {_} {()}}) ]
+Place : String → ℕ → Petrinet → Maybe Petrinet
+Place s _ [ₘ m - _ ₜ][ _ ] with dec∈ₗ s m
+Place _ _ _ | yes _ = nothing
+Place s n [ₘ m - t ₜ][ c ] | no ¬p =
just [ₘ put s , n into m when ¬p - t ₜ][ put∈ ∘ c ]
+Trans : String → Petrinet → Maybe Petrinet
+Trans s [ₘ _ - t ₜ][ _ ] with dec∈ₗ s t
+Trans _ _ | yes _ = nothing
+Trans s [ₘ m - t ₜ][ c ] | no ¬p =
just [ₘ m - put s , newMap into t when ¬p ₜ][
(λ { {_} {there _} → c}) ]
putpres : ∀ {m₁ : Map {B = ℕ × ℕ}} {m₂ : Map {B = ℕ}} {k v}
{¬k∈m₁ : ¬ k ∈ₗ m₁} (k∈m₂ : k ∈ₗ m₂) →
(∀ {x} → x ∈ₗ m₁ → x ∈ₗ m₂) →
(∀ {x} → x ∈ₗ (put k , v into m₁ when ¬k∈m₁) → x ∈ₗ m₂)
putpres k∈m₂ _ (here refl) = k∈m₂
putpres _ m₁⊑m₂ (there x∈put) = m₁⊑m₂ x∈put
prop₀ : ∀ {m₁ : Map {B = Map {B = ℕ × ℕ}}}
{m₂ : Map {B = ℕ × ℕ}} {k x} {k∈m₁ x∈assm₁} →
get x from (assign k , m₂ inside m₁ if k∈m₁) if x∈assm₁ ≡
get x from m₁ if ∈assign x∈assm₁ ⊎
get x from (assign k , m₂ inside m₁ if k∈m₁) if x∈assm₁ ≡ m₂
prop₀ {k∈m₁ = here _} {here _} = inj₂ refl
prop₀ {k∈m₁ = here _} {there _} = inj₁ refl
prop₀ {k∈m₁ = there _} {here _} = inj₁ refl
prop₀ {m₁} {k∈m₁ = there k∈m₁} {there x∈assm₁} =
prop₀ {m₁ = trim m₁ λ ()} {k∈m₁ = k∈m₁} {x∈assm₁}
prop₂ : ∀ {m₁ : Map {B = Map {B = ℕ × ℕ}}}
{m₂ : Map {B = ℕ}} {m₃ : Map {B = ℕ × ℕ}} {k} {k∈m₁} →
(∀ {x} → x ∈ₗ m₃ → x ∈ₗ m₂) →
(∀ {x x∈m₁ p} → p ∈ₗ (get x from m₁ if x∈m₁) → p ∈ₗ m₂) →
∀ {x x∈assm₁ p} →
p ∈ₗ (get x from assign k , m₃ inside m₁ if k∈m₁ if x∈assm₁) →
p ∈ₗ m₂
prop₂ {m₁} {m₂} {m₃} {k} {k∈m₁} p q {x} {x∈assm₁} {r}
with prop₀ {m₁} {m₃} {k} {x} {k∈m₁} {x∈assm₁}
prop₂ _ q | inj₁ x₁ rewrite x₁ = q
prop₂ p _ | inj₂ y rewrite y = p
+Arc : String → String → ℕ → ℕ → Petrinet → Maybe Petrinet
+Arc st _ _ _ [ₘ _ - t ₜ][ _ ] with dec∈ₗ st t
+Arc _ _ _ _ _ | no _ = nothing
+Arc _ sp _ _ [ₘ m - _ ₜ][ _ ] | yes _ with dec∈ₗ sp m
+Arc _ _ _ _ _ | yes _ | no _ = nothing
+Arc st sp _ _ [ₘ _ - t ₜ][ _ ] | yes p | yes _
with dec∈ₗ sp (get st from t if p)
+Arc _ _ _ _ _ | yes _ | yes _ | yes _ = nothing
+Arc st sp -n +n [ₘ m - t ₜ][ c ] | yes p | yes q | no ¬p =
just [ₘ m - assign st ,
(put sp , -n , +n into get st from t if p when ¬p) inside t if p ₜ][
prop₂ {t} {m} (putpres {get st from t if p} {m} {¬k∈m₁ = ¬p} q c) c ]
showₗ : ∀ {a} {A B : Set a} f g → Fun₂ String → List (A × B) → String
showₗ f g h = foldr ((uncurry h ∘ (map∑ f g)) -⟦ _++_ ⟧- ("\n" ++_)) ""
showₚ : List (String × ℕ) → String
showₚ = showₗ id showℕ (λ s₀ s₁ → "pl " ++ s₀ ++ " (" ++ s₁ ++ ")")
Mshowₚ : Map → String
Mshowₚ = showₚ ∘ Map.content
aggregate : List (String × ℕ) → String
aggregate = foldr ((λ {(_ , zero) → "" ; (s , suc zero) → s ++ " " ;
(s , suc (suc n)) → s ++ "*"
++ showℕ (suc (suc n)) ++ " "}) -⟦ _++_ ⟧- id) ""
splito : List (String × (ℕ × ℕ)) → String
splito l = aggregate (mapₗ (λ {(a , b , _) → a , b}) l) ++ " -> " ++
aggregate (mapₗ (λ {(a , _ , c) → a , c}) l)
splitoₘ : Map → String
splitoₘ = splito ∘ Map.content
showₜ : List (String × Map) → String
showₜ = showₗ id splitoₘ (λ s₀ s₁ → "tr " ++ s₀ ++ " " ++ s₁)
Mshowₜ : Map → String
Mshowₜ = showₜ ∘ Map.content
MPshow : Petrinet → String
MPshow p = Mshowₚ (marking p) ++ "\n" ++ Mshowₜ (transitions p)
MPshowₘ : Maybe Petrinet → String
MPshowₘ (just x) = MPshow x
MPshowₘ nothing = "Unsound net!"
printₚ : Maybe Petrinet → IO ⊤
printₚ = putStrLn ∘ toCostring ∘ MPshowₘ
outₚ : String → Maybe Petrinet → IO ⊤
outₚ name = (writeFile name) ∘ toCostring ∘ MPshowₘ
open RawMonad {lzero} monad
seasons : Maybe Petrinet
seasons = return newPet
>>= +Place "spring" 1
>>= +Place "summer" 0
>>= +Place "winter" 0
>>= +Place "autumn" 0
>>= +Trans "s2a"
>>= +Trans "a2w"
>>= +Trans "w2s"
>>= +Trans "s2s"
>>= +Arc "s2a" "summer" 0 1
>>= +Arc "s2a" "autumn" 1 0
>>= +Arc "a2w" "autumn" 0 1
>>= +Arc "a2w" "winter" 1 0
>>= +Arc "w2s" "winter" 0 1
>>= +Arc "w2s" "spring" 1 0
>>= +Arc "s2s" "spring" 0 1
>>= +Arc "s2s" "summer" 1 0
deadlock : Maybe Petrinet
deadlock = return newPet
>>= +Place "waitA" 0
>>= +Place "waitB" 0
>>= +Place "A" 1
>>= +Place "B" 1
>>= +Place "idle" 2
>>= +Trans "UseA"
>>= +Trans "UseB"
>>= +Trans "UseAB"
>>= +Trans "UseBA"
>>= +Arc "UseBA" "A" 1 1
>>= +Arc "UseBA" "idle" 0 1
>>= +Arc "UseBA" "B" 0 1
>>= +Arc "UseBA" "waitA" 1 0
>>= +Arc "UseB" "waitA" 0 1
>>= +Arc "UseB" "idle" 1 0
>>= +Arc "UseB" "B" 1 0
>>= +Arc "UseAB" "B" 1 1
>>= +Arc "UseAB" "idle" 0 1
>>= +Arc "UseAB" "A" 0 1
>>= +Arc "UseAB" "waitB" 1 0
>>= +Arc "UseA" "waitB" 0 1
>>= +Arc "UseA" "idle" 1 0
>>= +Arc "UseA" "A" 1 0
CanFireArcs : REL Map (List (String × ℕ × ℕ)) _
CanFireArcs m =
All (_⟨ (λ {(a , -n , _) → Any (-n ≤_) ∘ (get a)}) ⟩ m)
CanFireTrans : REL String Petrinet _
CanFireTrans s [ₘ marking - transitions ₜ][ _ ] =
Any (CanFireArcs marking ∘ Map.content) (get s transitions)
private
_≤₀_ : REL ℕ (Maybe ℕ) _
_≤₀_ x = Any (x ≤_)
CanFireArc₀ : REL (String × ℕ × ℕ) Map _
CanFireArc₀ (a , -n , _) = (-n ≤₀_) ∘ (get a)
CanFireArcs₀ : REL Map (List (String × ℕ × ℕ)) _
CanFireArcs₀ m = All ( _⟨ CanFireArc₀ ⟩ m)
CanFireTrans₀ : REL String Petrinet _
CanFireTrans₀ s [ₘ marking - transitions ₜ][ _ ] =
Any (CanFireArcs₀ marking ∘ Map.content) (get s transitions)
live : Pred Petrinet _
live pet = ∃ (_⟨ CanFireTrans ⟩ pet)
decFire : Decidable CanFireTrans
decFire _ [ₘ _ - _ ₜ][ _ ] =
dec ((all λ {_ → dec (_≤?_ _) _}) ∘ Map.content) _
dec≤₀ : Decidable _≤₀_
dec≤₀ x = dec (x ≤?_)
deccfa₀ : Decidable CanFireArc₀
deccfa₀ (a , -n , _) = (dec≤₀ -n) ∘ (get a)
deccfas₀ : Decidable CanFireArcs₀
deccfas₀ m = all λ x → deccfa₀ x m
deccft₀ : Decidable CanFireTrans₀
deccft₀ s [ₘ marking - transitions ₜ][ _ ] =
dec ((deccfas₀ marking) ∘ Map.content) (get s transitions)
decLive : Decidableₚ live
decLive pet = let t = transitions pet in
fromSample (keys t) (flip decFire pet)
(_∘ (prop← {m = t}) ∘ getp {m = t})
fireArcs : ∀ (m : Map {B = ℕ}) {l} → CanFireArcs m l
→ ∃ λ (m' : Map {B = ℕ}) → ∀ {x} → x ∈ₗ m → x ∈ₗ m'
fireArcs m [] = m , id
fireArcs m {l = (a , _ , _) ∷ _} (_ ∷ _) with dec∈ₗ a m
fireArcs m (just _ ∷ p) | yes _ with fireArcs m p
fireArcs m {(a , _ , +n) ∷ _} (just -n≤x ∷ p) | yes q | m' , p' =
(assign a , (sub -n≤x) + +n inside m' if p' q) , assign∈ ∘ p'
fire_inside_when_ : ∀ s pet → CanFireTrans s pet → Petrinet
fire s inside pet when _ with dec∈ₗ s (transitions pet)
(fire s inside [ₘ m - _ ₜ][ _ ] when just p) | yes _ with fireArcs m p
(fire s inside [ₘ m - t ₜ][ conf ] when just p) | yes _ | m' , q =
[ₘ m' - t ₜ][ q ∘ conf ]
fire : String → Petrinet → Maybe Petrinet
fire s pet with decFire s pet
fire s pet | yes p = just (fire s inside pet when p)
fire _ _ | no _ = nothing
fireLive : Petrinet → Maybe Petrinet
fireLive pet with decLive pet
fireLive pet | yes (s , p) = just (fire s inside pet when p)
fireLive _ | no _ = nothing
liveness-state : Maybe Petrinet → String
liveness-state nothing = "nothing"
liveness-state (just x) with decLive x
liveness-state (just _) | yes (s , _) = "I can at least fire " ++ s
liveness-state (just _) | no _ = "deadlock"
l-s-d : String
l-s-d = liveness-state deadlock
deadlock₁ : Maybe Petrinet
deadlock₁ = deadlock >>= (fire "UseB")
l-s-d₁ : String
l-s-d₁ = liveness-state deadlock₁
deadlock₂ : Maybe Petrinet
deadlock₂ = deadlock₁ >>= (fire "UseA")
l-s-d₂ : String
l-s-d₂ = liveness-state deadlock₂
deadlock₃ : Maybe Petrinet
deadlock₃ = deadlock₂ >>= (fire "UseAB")
l-s-d₃ : String
l-s-d₃ = liveness-state deadlock₃