module TotalRecognisers.LeftRecursion.ExpressiveStrength where
open import Algebra
open import Codata.Musical.Notation
open import Data.Bool as Bool hiding (_∧_)
open import Data.Empty
open import Data.List
import Data.List.Properties as ListProp
open import Data.List.Reverse
open import Data.Nat as Nat
open import Data.Nat.InfinitelyOften as Inf
import Data.Nat.Properties as NatProp
open import Data.Product
open import Data.Sum
open import Function
open import Relation.Binary
open import Relation.Binary.PropositionalEquality hiding ([_])
open import Relation.Nullary
open import Relation.Nullary.Decidable
open import Relation.Nullary.Negation
private
module ListMonoid {A : Set} = Monoid (ListProp.++-monoid A)
module NatOrder = DecTotalOrder NatProp.≤-decTotalOrder
import TotalRecognisers.LeftRecursion
open TotalRecognisers.LeftRecursion Bool using (_∧_; left-zero)
private
open module LR {Tok : Set} = TotalRecognisers.LeftRecursion Tok
hiding (P; ∞⟨_⟩P; _∧_; left-zero; _∷_)
P : Set → Bool → Set
P Tok = LR.P {Tok}
∞⟨_⟩P : Bool → Set → Bool → Set
∞⟨ b ⟩P Tok n = LR.∞⟨_⟩P {Tok} b n
open import TotalRecognisers.LeftRecursion.Lib Bool hiding (_∷_)
private
lemma : (f : List Bool → Bool) →
(false ∧ f [ true ] ∨ false ∧ f [ false ]) ∨ f [] ≡ f []
lemma f = cong₂ (λ b₁ b₂ → (b₁ ∨ b₂) ∨ f [])
(left-zero (f [ true ]))
(left-zero (f [ false ]))
grammar⇒pred : ∀ {Tok n} (p : P Tok n) →
∃ λ (f : List Tok → Bool) → ∀ {s} → s ∈ p ⇔ T (f s)
grammar⇒pred p =
((λ s → ⌊ s ∈? p ⌋) , λ {_} → mk⇔ fromWitness toWitness)
pred⇒grammar : (f : List Bool → Bool) →
∃ λ (p : P Bool (f [])) → ∀ {s} → s ∈ p ⇔ T (f s)
pred⇒grammar f =
(p f , λ {s} → mk⇔ (p-sound f) (p-complete f s))
where
p : (f : List Bool → Bool) → P Bool (f [])
p f = cast (lemma f)
( ♯? (sat id ) · ♯ p (f ∘ _∷_ true )
∣ ♯? (sat not) · ♯ p (f ∘ _∷_ false)
∣ accept-if-true (f [])
)
p-sound : ∀ f {s} → s ∈ p f → T (f s)
p-sound f (cast (∣-right s∈)) with AcceptIfTrue.sound (f []) s∈
... | (refl , ok) = ok
p-sound f (cast (∣-left (∣-left (t∈ · s∈)))) with drop-♭♯ (f [ true ]) t∈
... | sat {t = true} _ = p-sound (f ∘ _∷_ true ) s∈
... | sat {t = false} ()
p-sound f (cast (∣-left (∣-right (t∈ · s∈)))) with drop-♭♯ (f [ false ]) t∈
... | sat {t = false} _ = p-sound (f ∘ _∷_ false) s∈
... | sat {t = true} ()
p-complete : ∀ f s → T (f s) → s ∈ p f
p-complete f [] ok =
cast (∣-right {n₁ = false ∧ f [ true ] ∨ false ∧ f [ false ]} $
AcceptIfTrue.complete ok)
p-complete f (true ∷ bs) ok =
cast (∣-left $ ∣-left $
add-♭♯ (f [ true ]) (sat _) ·
p-complete (f ∘ _∷_ true ) bs ok)
p-complete f (false ∷ bs) ok =
cast (∣-left $ ∣-right {n₁ = false ∧ f [ true ]} $
add-♭♯ (f [ false ]) (sat _) ·
p-complete (f ∘ _∷_ false) bs ok)
pred⇒grammar′ : (f : List Bool → Bool) →
∃ λ (p : P Bool (f [])) → ∀ {s} → s ∈ p ⇔ T (f s)
pred⇒grammar′ f =
(p f , λ {s} → mk⇔ (p-sound f) (p-complete f s))
where
extend : {A B : Set} → (List A → B) → A → (List A → B)
extend f x = λ xs → f (xs ∷ʳ x)
p : (f : List Bool → Bool) → P Bool (f [])
p f = ♯ p (extend f true ) · ♯? (sat id )
∣ ♯ p (extend f false) · ♯? (sat not)
∣ accept-if-true (f [])
p-sound : ∀ f {s} → s ∈ p f → T (f s)
p-sound f (∣-right s∈) with AcceptIfTrue.sound (f []) s∈
... | (refl , ok) = ok
p-sound f (∣-left (∣-left (s∈ · t∈))) with drop-♭♯ (f [ true ]) t∈
... | sat {t = true} _ = p-sound (extend f true ) s∈
... | sat {t = false} ()
p-sound f (∣-left (∣-right (s∈ · t∈))) with drop-♭♯ (f [ false ]) t∈
... | sat {t = false} _ = p-sound (extend f false) s∈
... | sat {t = true} ()
p-complete′ : ∀ f {s} → Reverse s → T (f s) → s ∈ p f
p-complete′ f [] ok =
∣-right {n₁ = false} $ AcceptIfTrue.complete ok
p-complete′ f (bs ∶ rs ∶ʳ true ) ok =
∣-left {n₁ = false} $ ∣-left {n₁ = false} $
p-complete′ (extend f true ) rs ok ·
add-♭♯ (f [ true ]) (sat _)
p-complete′ f (bs ∶ rs ∶ʳ false) ok =
∣-left {n₁ = false} $ ∣-right {n₁ = false} $
p-complete′ (extend f false) rs ok ·
add-♭♯ (f [ false ]) (sat _)
p-complete : ∀ f s → T (f s) → s ∈ p f
p-complete f s = p-complete′ f (reverseView s)
module NotExpressible where
pair : ℕ → List ℕ
pair n = n ∷ n ∷ []
OnlyPairs : ∀ {n} → P ℕ n → Set
OnlyPairs p = ∀ {n s} → n ∷ s ∈ p → s ≡ [ n ]
ManyPairs : ∀ {n} → P ℕ n → Set
ManyPairs p = Inf (λ n → pair n ∈ p)
AcceptsNonEmptyString : ∀ {Tok n} → P Tok n → Set
AcceptsNonEmptyString p = ∃₂ λ t s → t ∷ s ∈ p
nullable-or-fail : ∀ {Tok n} {p : P Tok n} →
¬ AcceptsNonEmptyString p →
[] ∈ p ⊎ (∀ s → ¬ s ∈ p)
nullable-or-fail {p = p} ¬a with [] ∈? p
... | yes []∈p = inj₁ []∈p
... | no []∉p = inj₂ helper
where
helper : ∀ s → ¬ s ∈ p
helper [] = []∉p
helper (t ∷ s) = ¬a ∘ _,_ t ∘ _,_ s
at-most-one : ∀ {n₁ n₂} {p₁ : ∞⟨ n₂ ⟩P ℕ n₁} {p₂ : ∞⟨ n₁ ⟩P ℕ n₂} →
OnlyPairs (p₁ · p₂) →
ManyPairs (p₁ · p₂) →
AcceptsNonEmptyString (♭? p₁) →
AcceptsNonEmptyString (♭? p₂) → ⊥
at-most-one op mp (n₁ , s₁ , n₁s₁∈p₁) (n₂ , s₂ , n₂s₂∈p₂)
with op (n₁s₁∈p₁ · n₂s₂∈p₂)
at-most-one _ _ (_ , _ ∷ [] , _) (_ , _ , _) | ()
at-most-one _ _ (_ , _ ∷ _ ∷ _ , _) (_ , _ , _) | ()
at-most-one {p₁ = p₁} {p₂} op mp
(n , [] , n∈p₁) (.n , .[] , n∈p₂) | refl =
twoDifferentWitnesses mp helper
where
¬pair : ∀ {i s} → s ∈ p₁ · p₂ → n ≢ i → s ≢ pair i
¬pair (_·_ {s₁ = []} _ ii∈p₂) n≢i refl with op (n∈p₁ · ii∈p₂)
... | ()
¬pair (_·_ {s₁ = i ∷ []} i∈p₁ _) n≢i refl with op (i∈p₁ · n∈p₂)
¬pair (_·_ {s₁ = .n ∷ []} n∈p₁ _) n≢n refl | refl = n≢n refl
¬pair (_·_ {s₁ = i ∷ .i ∷ []} ii∈p₁ _) n≢i refl with op (ii∈p₁ · n∈p₂)
... | ()
¬pair (_·_ {s₁ = _ ∷ _ ∷ _ ∷ _} _ _) _ ()
helper : ¬ ∃₂ λ i j → i ≢ j × pair i ∈ p₁ · p₂ × pair j ∈ p₁ · p₂
helper (i , j , i≢j , ii∈ , jj∈) with Nat._≟_ n i
helper (.n , j , n≢j , nn∈ , jj∈) | yes refl = ¬pair jj∈ n≢j refl
helper (i , j , i≢j , ii∈ , jj∈) | no n≢i = ¬pair ii∈ n≢i refl
¬pairs : ∀ {n} (p : P ℕ n) → OnlyPairs p → ManyPairs p → ⊥
¬pairs fail op mp = witness mp (helper ∘ proj₂)
where
helper : ∀ {t} → ¬ pair t ∈ fail
helper ()
¬pairs empty op mp = witness mp (helper ∘ proj₂)
where
helper : ∀ {t} → ¬ pair t ∈ empty
helper ()
¬pairs (sat f) op mp = witness mp (helper ∘ proj₂)
where
helper : ∀ {t} → ¬ pair t ∈ sat f
helper ()
¬pairs (nonempty p) op mp =
¬pairs p (op ∘ nonempty) (Inf.map helper mp)
where
helper : ∀ {n} → pair n ∈ nonempty p → pair n ∈ p
helper (nonempty pr) = pr
¬pairs (cast eq p) op mp = ¬pairs p (op ∘ cast) (Inf.map helper mp)
where
helper : ∀ {n} → pair n ∈ cast eq p → pair n ∈ p
helper (cast pr) = pr
¬pairs (p₁ ∣ p₂) op mp = commutes-with-∪ (Inf.map split mp) helper
where
helper : ¬ (ManyPairs p₁ ⊎ ManyPairs p₂)
helper (inj₁ mp₁) = ¬pairs p₁ (op ∘ ∣-left) mp₁
helper (inj₂ mp₂) = ¬pairs p₂ (op ∘ ∣-right {p₁ = p₁}) mp₂
split : ∀ {s} → s ∈ p₁ ∣ p₂ → s ∈ p₁ ⊎ s ∈ p₂
split (∣-left s∈p₁) = inj₁ s∈p₁
split (∣-right s∈p₂) = inj₂ s∈p₂
¬pairs (p₁ · p₂) op mp =
¬¬-excluded-middle λ a₁? →
¬¬-excluded-middle λ a₂? →
helper a₁? a₂?
where
continue : {n n′ : Bool} (p : ∞⟨ n′ ⟩P ℕ n) → n′ ≡ true →
OnlyPairs (♭? p) → ManyPairs (♭? p) → ⊥
continue p eq with forced? p
continue p refl | true = ¬pairs p
continue p () | false
helper : Dec (AcceptsNonEmptyString (♭? p₁)) →
Dec (AcceptsNonEmptyString (♭? p₂)) → ⊥
helper (yes a₁) (yes a₂) = at-most-one op mp a₁ a₂
helper (no ¬a₁) _ with nullable-or-fail ¬a₁
... | inj₁ []∈p₁ =
continue p₂ (⇒ []∈p₁) (op ∘ _·_ []∈p₁) (Inf.map right mp)
where
right : ∀ {s} → s ∈ p₁ · p₂ → s ∈ ♭? p₂
right (_·_ {s₁ = []} _ ∈p₂) = ∈p₂
right (_·_ {s₁ = _ ∷ _} ∈p₁ _) = ⊥-elim (¬a₁ (-, -, ∈p₁))
... | inj₂ is-fail = witness mp (∉ ∘ proj₂)
where
∉ : ∀ {s} → ¬ s ∈ p₁ · p₂
∉ (∈p₁ · _) = is-fail _ ∈p₁
helper _ (no ¬a₂) with nullable-or-fail ¬a₂
... | inj₁ []∈p₂ =
continue p₁ (⇒ []∈p₂)
(op ∘ (λ ∈p₁ → cast∈ (proj₂ ListMonoid.identity _) refl
(∈p₁ · []∈p₂)))
(Inf.map left mp)
where
left : ∀ {s} → s ∈ p₁ · p₂ → s ∈ ♭? p₁
left (_·_ {s₂ = _ ∷ _} _ ∈p₂) = ⊥-elim (¬a₂ (-, -, ∈p₂))
left (_·_ {s₁ = s₁} {s₂ = []} ∈p₁ _) =
cast∈ (sym $ proj₂ ListMonoid.identity s₁) refl ∈p₁
... | inj₂ is-fail = witness mp (∉ ∘ proj₂)
where
∉ : ∀ {s} → ¬ s ∈ p₁ · p₂
∉ (_ · ∈p₂) = is-fail _ ∈p₂
pair? : List ℕ → Bool
pair? (m ∷ n ∷ []) = ⌊ Nat._≟_ m n ⌋
pair? _ = false
not-realisable :
¬ ∃₂ (λ n (p : P ℕ n) → ∀ {s} → s ∈ p ⇔ T (pair? s))
not-realisable (_ , p , hyp) = ¬pairs p op mp
where
op : OnlyPairs p
op {n} {[]} s∈p = ⊥-elim (Equivalence.to hyp s∈p)
op {n} { m ∷ []} s∈p with toWitness (Equivalence.to hyp s∈p)
op {n} {.n ∷ []} s∈p | refl = refl
op {n} {_ ∷ _ ∷ _} s∈p = ⊥-elim (Equivalence.to hyp s∈p)
mp : ManyPairs p
mp (i , ¬pair) =
¬pair i NatOrder.refl $ Equivalence.from hyp $ fromWitness refl
not-expressible :
∃₂ λ (Tok : Set) (f : List Tok → Bool) →
¬ ∃₂ (λ n (p : P Tok n) → ∀ {s} → s ∈ p ⇔ T (f s))
not-expressible = (ℕ , pair? , not-realisable)
where open NotExpressible