summaryrefslogtreecommitdiff
path: root/src/Problem17.agda
diff options
context:
space:
mode:
authorChloe Brown <chloe.brown.00@outlook.com>2024-01-22 11:51:56 +0000
committerChloe Brown <chloe.brown.00@outlook.com>2024-01-22 11:51:56 +0000
commit4527250aee1d1d4655e84f0583d04410b7c53642 (patch)
treea87ce7f38a26b1d9fb11248f9428704816fc4fb4 /src/Problem17.agda
Advent of proof submissions.HEADmaster
Completed all problems save 12, where I had to postulate two lemma.
Diffstat (limited to 'src/Problem17.agda')
-rw-r--r--src/Problem17.agda116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/Problem17.agda b/src/Problem17.agda
new file mode 100644
index 0000000..d02502e
--- /dev/null
+++ b/src/Problem17.agda
@@ -0,0 +1,116 @@
+{-# OPTIONS --safe #-}
+
+module Problem17 (Act : Set) where
+
+open import Data.Empty
+open import Data.List
+open import Data.List.Membership.Propositional
+open import Data.List.Membership.Propositional.Properties
+open import Data.List.Relation.Unary.Any using (here; there)
+open import Data.Product hiding (map)
+open import Data.Sum using (inj₁; inj₂)
+open import Data.Unit
+open import Function.Base using (id)
+open import Relation.Binary.PropositionalEquality hiding ([_])
+
+data Process : Set where
+ ⟨_⟩ : Act → Process
+ skip : Process
+ abort : Process
+ -- not the normal semicolon, use \; and choose the correct option..
+ _;_ : Process → Process → Process
+ _+_ : Process → Process → Process
+ _∥_ : Process → Process → Process
+
+infixr 60 _;_
+infixr 70 _+_
+infixr 80 _∥_
+variable P P′ Q Q′ : Process
+variable a b c x : Act
+variable xs : List Act
+
+NoPar : Process → Set
+NoPar (P ; Q) = NoPar P × NoPar Q
+NoPar (P + Q) = NoPar P × NoPar Q
+NoPar (P ∥ Q) = ⊥
+NoPar ⟨ _ ⟩ = ⊤
+NoPar skip = ⊤
+NoPar abort = ⊤
+
+interleave : List Act → List Act → List (List Act)
+interleave [] ys = [ ys ]
+interleave xs [] = [ xs ]
+interleave (x ∷ xs) (y ∷ ys) = map (x ∷_) (interleave xs (y ∷ ys)) ++ map (y ∷_) (interleave (x ∷ xs) ys)
+
+⟦_⟧ : Process → List (List Act)
+⟦ ⟨ a ⟩ ⟧ = [ [ a ] ]
+⟦ skip ⟧ = [ [] ]
+⟦ abort ⟧ = []
+⟦ P + Q ⟧ = ⟦ P ⟧ ++ ⟦ Q ⟧
+⟦ P ; Q ⟧ = concatMap (λ p → map (p ++_) ⟦ Q ⟧) ⟦ P ⟧
+⟦ P ∥ Q ⟧ = concatMap (λ p → concatMap (interleave p) ⟦ Q ⟧) ⟦ P ⟧
+
+_≈_ : Process → Process → Set
+P ≈ Q = ∀ xs → (xs ∈ ⟦ P ⟧ → xs ∈ ⟦ Q ⟧) × (xs ∈ ⟦ Q ⟧ → xs ∈ ⟦ P ⟧)
+
+-- Helpers for dealing with sequential traces
+
+;-trace : ∀ (P Q : Process) {xs ys} → xs ∈ ⟦ P ⟧ → ys ∈ ⟦ Q ⟧ → xs ++ ys ∈ ⟦ P ; Q ⟧
+;-trace P Q {xs} xs∈⟦P⟧ ys∈⟦Q⟧ =
+ ∈-concat⁺′ (∈-map⁺ (xs ++_) ys∈⟦Q⟧) (∈-map⁺ (λ p → map (p ++_) ⟦ Q ⟧) xs∈⟦P⟧)
+
+;-trace⁻¹ :
+ ∀ (P Q : Process) {xs} →
+ xs ∈ ⟦ P ; Q ⟧ → ∃₂ λ ys zs → xs ≡ ys ++ zs × ys ∈ ⟦ P ⟧ × zs ∈ ⟦ Q ⟧
+;-trace⁻¹ P Q {xs} xs∈⟦P;Q⟧ with ∈-concat⁻′ (map (λ p → map (p ++_) ⟦ Q ⟧) ⟦ P ⟧) xs∈⟦P;Q⟧
+... | xss , xs∈xss , xss∈⟦P⟧++⟦Q⟧ with ∈-map⁻ (λ p → map (p ++_) ⟦ Q ⟧) xss∈⟦P⟧++⟦Q⟧
+... | ys , ys∈⟦P⟧ , refl with ∈-map⁻ (ys ++_) xs∈xss
+... | zs , zs∈⟦Q⟧ , refl = ys , zs , refl , ys∈⟦P⟧ , zs∈⟦Q⟧
+
+-- Idea
+-- Each trace has a canonical process---the list of actions. We can map a list
+-- of possible traces to a canonical process by taking the sum of all individual
+-- traces.
+--
+-- We show the canonical process for list of traces is correct (contains all
+-- traces) and unique (contains only the desired traces).
+
+canonical₁ : List Act → Process
+canonical₁ [] = skip
+canonical₁ (a ∷ as) = ⟨ a ⟩ ; canonical₁ as
+
+canonical : List (List Act) → Process
+canonical [] = abort
+canonical (as ∷ ass) = canonical₁ as + canonical ass
+
+canonical₁-correct : ∀ as → as ∈ ⟦ canonical₁ as ⟧
+canonical₁-correct [] = here refl
+canonical₁-correct (a ∷ as) = ;-trace ⟨ a ⟩ (canonical₁ as) (here refl) (canonical₁-correct as)
+
+canonical₁-unique : ∀ as {xs} → xs ∈ ⟦ canonical₁ as ⟧ → xs ≡ as
+canonical₁-unique [] (here prf) = prf
+canonical₁-unique (a ∷ as) prf with ;-trace⁻¹ ⟨ a ⟩ (canonical₁ as) prf
+... | .([ a ]) , xs , refl , here refl , prf = cong (a ∷_) (canonical₁-unique as prf)
+
+canonical₁-NoPar : ∀ as → NoPar (canonical₁ as)
+canonical₁-NoPar [] = _
+canonical₁-NoPar (a ∷ as) = _ , canonical₁-NoPar as
+
+canonical-correct : ∀ ass {as} → as ∈ ass → as ∈ ⟦ canonical ass ⟧
+canonical-correct (as ∷ ass) (here refl) = ∈-++⁺ˡ (canonical₁-correct as)
+canonical-correct (as ∷ ass) (there prf) = ∈-++⁺ʳ ⟦ canonical₁ as ⟧ (canonical-correct ass prf)
+
+canonical-unique : ∀ ass {as} → as ∈ ⟦ canonical ass ⟧ → as ∈ ass
+canonical-unique (as ∷ ass) prf with ∈-++⁻ ⟦ canonical₁ as ⟧ prf
+... | inj₁ prf with refl ← canonical₁-unique as prf = here refl
+... | inj₂ prf = there (canonical-unique ass prf)
+
+canonical-NoPar : ∀ ass → NoPar (canonical ass)
+canonical-NoPar [] = _
+canonical-NoPar (as ∷ ass) = canonical₁-NoPar as , canonical-NoPar ass
+
+goal : ∀ (P : Process) → ∃[ P′ ] (P′ ≈ P) × NoPar P′
+goal P =
+ canonical ⟦ P ⟧
+ , (λ as → canonical-unique ⟦ P ⟧ , canonical-correct ⟦ P ⟧)
+ , canonical-NoPar ⟦ P ⟧