module lps.Tactics where
open import Bag-equivalence
open import Equality.Propositional
import Relation.Nullary as RN
import Relation.Binary.PropositionalEquality as RBEq
open import lib.Maybe
open import lib.Context
open Context
module BT = BelongsTo
module Il = Interleaving
module MyFin where
open import Data.Nat hiding (_≟_)
open import Data.Fin as Fin
open import lib.Nullary
open import Function
suc-inj : {n : ℕ} {k l : Fin n} (eq : Fin.suc k RBEq.≡ suc l) → k RBEq.≡ l
suc-inj RBEq.refl = RBEq.refl
_≟_ : {n : ℕ} (k l : Fin n) → RN.Dec (k RBEq.≡ l)
zero ≟ zero = RN.yes RBEq.refl
zero ≟ suc l = RN.no (λ ())
suc k ≟ zero = RN.no (λ ())
suc k ≟ suc l = dec (k ≟ l) (RN.yes ∘ RBEq.cong suc) (λ p → RN.no $ p ∘ suc-inj)
module TacticsBasics (Pr : Set) where
open import Prelude
open import lps.IMLL Pr
open Type
open Pointwise
toContext : List Pr → Con ty
toContext = foldr (λ p Γ → Γ ∙ `κ p) ε
toGoal : Pr → List Pr → ty
toGoal p [] = `κ p
toGoal p (q ∷ qs) = `κ p `⊗ toGoal q qs
data isAtom : (σ : ty) → Set where
`κ : (p : Pr) → isAtom $ `κ p
data isProduct : (σ : ty) → Set where
`κ : (p : Pr) → isProduct $ `κ p
_`⊗_ : {σ τ : ty} (S : isProduct σ) (T : isProduct τ) → isProduct $ σ `⊗ τ
isProductToGoal : (x : Pr) (xs : List Pr) → isProduct $ toGoal x xs
isProductToGoal x [] = `κ x
isProductToGoal x (y ∷ xs) = `κ x `⊗ isProductToGoal y xs
fromProduct : {σ : ty} (S : isProduct σ) → List Pr
fromProduct (`κ p) = p ∷ []
fromProduct (S `⊗ T) = fromProduct S ++ fromProduct T
isAtoms : (Γ : Con ty) → Set
isAtoms = PCon isAtom
isAtomsToContext : (xs : List Pr) → isAtoms $ toContext xs
isAtomsToContext [] = ε
isAtomsToContext (x ∷ xs) = isAtomsToContext xs ∙ `κ x
fromAtoms : {γ : Con ty} (Γ : isAtoms γ) → List Pr
fromAtoms ε = []
fromAtoms (Γ ∙ `κ p) = p ∷ fromAtoms Γ
noWith : {γ : Con ty} {σ τ : ty} (Γ : isAtoms γ) (var : σ `& τ BT.∈ γ) → ⊥ {lzero}
noWith (Γ ∙ ()) BT.zro
noWith (Γ ∙ _) (BT.suc var) = noWith Γ var
noTensor : {γ : Con ty} {σ τ : ty} (Γ : isAtoms γ) (var : σ `⊗ τ BT.∈ γ) → ⊥ {lzero}
noTensor (Γ ∙ ()) BT.zro
noTensor (Γ ∙ _) (BT.suc var) = noTensor Γ var
isAtoms-merge⁻¹ : {γ δ e : Con ty} (Γ : isAtoms γ) (mg : γ Interleaving.≡ δ ⋈ e) →
isAtoms δ × isAtoms e
isAtoms-merge⁻¹ ε Il.ε = ε , ε
isAtoms-merge⁻¹ (Γ ∙ S) (mg Il.∙ʳ σ) = Σ-map id (λ E → E ∙ S) $ isAtoms-merge⁻¹ Γ mg
isAtoms-merge⁻¹ (Γ ∙ S) (mg Il.∙ˡ σ) = Σ-map (λ Δ → Δ ∙ S) id $ isAtoms-merge⁻¹ Γ mg
fromToContext : (xs : List Pr) → xs RBEq.≡ fromAtoms (isAtomsToContext xs)
fromToContext [] = RBEq.refl
fromToContext (x ∷ xs) = RBEq.cong₂ _∷_ RBEq.refl $ fromToContext xs
fromToGoal : (x : Pr) (xs : List Pr) → x ∷ xs RBEq.≡ fromProduct (isProductToGoal x xs)
fromToGoal x [] = RBEq.refl
fromToGoal x (y ∷ ys) = RBEq.cong₂ _∷_ RBEq.refl $ fromToGoal y ys
open import Algebra
open CommutativeMonoid
open import Level
import Data.Product as Prod
import Data.Empty as Zero
module TacticsAbMon
(Mon : CommutativeMonoid zero zero)
(_≟_ : (x y : Carrier Mon) → RN.Dec (x RBEq.≡ y))
where
open import Algebra.Structures
module M = CommutativeMonoid Mon
open import Data.Nat as Nat hiding (_≟_)
open import Prelude hiding (ℕ; Fin)
open import Data.Fin
open import Data.Vec as Vec
infixr 6 _`∙_
data Term (n : ℕ) : Set where
`v : (k : Fin n) → Term n
`c : (el : Carrier Mon) → Term n
_`∙_ : (t u : Term n) → Term n
⟦_⟧ : {n : ℕ} (t : Term n) (ρ : Vec M.Carrier n) → M.Carrier
⟦ `v k ⟧ ρ = Vec.lookup k ρ
⟦ `c el ⟧ ρ = el
⟦ t `∙ u ⟧ ρ = ⟦ t ⟧ ρ M.∙ ⟦ u ⟧ ρ
_∙∙_ : {n : ℕ} → M.Carrier × List (Fin n) → M.Carrier × List (Fin n) → M.Carrier × List (Fin n)
(e , ks) ∙∙ (f , ls) = e M.∙ f , ks Prelude.++ ls
norm : {n : ℕ} (t : Term n) → M.Carrier × List (Fin n)
norm (`v k) = M.ε , k ∷ []
norm (`c el) = el , []
norm (t `∙ u) = norm t ∙∙ norm u
⟦_⟧s : {n : ℕ} (ks : List $ Fin n) (ρ : Vec M.Carrier n) → M.Carrier
⟦ ks ⟧s ρ = Prelude.foldr M._∙_ M.ε $ Prelude.map (flip Vec.lookup ρ) ks
open import Relation.Binary.EqReasoning M.setoid
⟦_`++_⟧s : {n : ℕ} (ks ls : List $ Fin n) (ρ : Vec M.Carrier n) →
⟦ ks Prelude.++ ls ⟧s ρ M.≈ ⟦ ks ⟧s ρ M.∙ ⟦ ls ⟧s ρ
⟦ [] `++ ls ⟧s ρ = M.sym $ M.identityˡ _
⟦ k ∷ ks `++ ls ⟧s ρ =
begin
⟦ k ∷ ks Prelude.++ ls ⟧s ρ ≈⟨ M.∙-cong M.refl $ ⟦ ks `++ ls ⟧s ρ ⟩
Vec.lookup k ρ M.∙ (⟦ ks ⟧s ρ M.∙ ⟦ ls ⟧s ρ) ≈⟨ M.sym $ M.assoc (Vec.lookup k ρ) (⟦ ks ⟧s ρ) (⟦ ls ⟧s ρ) ⟩
⟦ k ∷ ks ⟧s ρ M.∙ ⟦ ls ⟧s ρ
∎
⟦_⟧′ : {n : ℕ} (t : M.Carrier × List (Fin n)) (ρ : Vec M.Carrier n) → M.Carrier
⟦ el , ks ⟧′ ρ = el M.∙ ⟦ ks ⟧s ρ
flip23 : (e f g h : M.Carrier) → (e M.∙ f) M.∙ (g M.∙ h) M.≈ (e M.∙ g) M.∙ (f M.∙ h)
flip23 e f g h =
begin
(e M.∙ f) M.∙ (g M.∙ h) ≈⟨ M.assoc e f (g M.∙ h) ⟩
e M.∙ (f M.∙ (g M.∙ h)) ≈⟨ M.∙-cong M.refl (M.sym $ M.assoc f g h) ⟩
e M.∙ (f M.∙ g M.∙ h) ≈⟨ M.∙-cong M.refl (M.∙-cong (M.comm f g) M.refl) ⟩
e M.∙ (g M.∙ f M.∙ h) ≈⟨ M.∙-cong M.refl (M.assoc g f h) ⟩
e M.∙ (g M.∙ (f M.∙ h)) ≈⟨ M.sym $ M.assoc e g (f M.∙ h) ⟩
(e M.∙ g) M.∙ (f M.∙ h)
∎
∙∙-sound : {n : ℕ} (t u : M.Carrier × List (Fin n)) (ρ : Vec M.Carrier n) →
⟦ t ⟧′ ρ M.∙ ⟦ u ⟧′ ρ M.≈ ⟦ t ∙∙ u ⟧′ ρ
∙∙-sound (e , ks) (f , ls) ρ =
let F ks = ⟦ ks ⟧s ρ in
begin
(e M.∙ F ks) M.∙ (f M.∙ F ls) ≈⟨ flip23 e (F ks) f (F ls) ⟩
(e M.∙ f) M.∙ (F ks M.∙ F ls) ≈⟨ M.∙-cong M.refl (M.sym $ ⟦ ks `++ ls ⟧s ρ) ⟩
(e M.∙ f) M.∙ (F $ ks Prelude.++ ls)
∎
norm-sound : {n : ℕ} (t : Term n) (ρ : Vec M.Carrier n) → ⟦ t ⟧ ρ M.≈ ⟦ norm t ⟧′ ρ
norm-sound (`v k) ρ =
begin
Vec.lookup k ρ ≈⟨ M.sym $ Prod.proj₂ M.identity _ ⟩
Vec.lookup k ρ M.∙ M.ε ≈⟨ M.sym $ Prod.proj₁ M.identity _ ⟩
M.ε M.∙ (Vec.lookup k ρ M.∙ M.ε)
∎
norm-sound (`c el) ρ = M.sym $ Prod.proj₂ M.identity _
norm-sound (t `∙ u) ρ =
begin
⟦ t ⟧ ρ M.∙ ⟦ u ⟧ ρ ≈⟨ M.∙-cong (norm-sound t ρ) (norm-sound u ρ) ⟩
⟦ norm t ⟧′ ρ M.∙ ⟦ norm u ⟧′ ρ ≈⟨ ∙∙-sound (norm t) (norm u) ρ ⟩
⟦ norm t ∙∙ norm u ⟧′ ρ
∎
module FixedVars (n : ℕ) (ρ : Vec M.Carrier n) where
open import lps.IMLL (Fin n)
open Type
open Pointwise
open TacticsBasics (Fin n)
sound⋈ : {γ δ e : Con ty} (Γ : isAtoms γ) (Δ : isAtoms δ) (E : isAtoms e)
(mg : γ Interleaving.≡ δ ⋈ e) → ⟦ fromAtoms Γ ⟧s ρ M.≈ ⟦ fromAtoms Δ ⟧s ρ M.∙ ⟦ fromAtoms E ⟧s ρ
sound⋈ ε ε ε Il.ε = M.sym $ M.identityˡ M.ε
sound⋈ (Γ ∙ `κ p) Δ (E ∙ `κ .p) (mg Il.∙ʳ .(`κ p)) =
begin
⟦ p ∷ fromAtoms Γ ⟧s ρ ≈⟨ M.∙-cong M.refl $ sound⋈ Γ Δ E mg ⟩
Vec.lookup p ρ M.∙ (⟦ fromAtoms Δ ⟧s ρ M.∙ ⟦ fromAtoms E ⟧s ρ) ≈⟨ M.sym $ M.assoc _ _ _ ⟩
⟦ p ∷ fromAtoms Δ ⟧s ρ M.∙ ⟦ fromAtoms E ⟧s ρ ≈⟨ M.∙-cong (M.comm _ _) M.refl ⟩
⟦ fromAtoms Δ ⟧s ρ M.∙ Vec.lookup p ρ M.∙ ⟦ fromAtoms E ⟧s ρ ≈⟨ M.assoc _ _ _ ⟩
⟦ fromAtoms Δ ⟧s ρ M.∙ ⟦ p ∷ fromAtoms E ⟧s ρ
∎
sound⋈ (Γ ∙ `κ p) (Δ ∙ `κ .p) E (mg Il.∙ˡ .(`κ p)) =
begin
⟦ p ∷ fromAtoms Γ ⟧s ρ ≈⟨ M.∙-cong M.refl $ sound⋈ Γ Δ E mg ⟩
Vec.lookup p ρ M.∙ (⟦ fromAtoms Δ ⟧s ρ M.∙ ⟦ fromAtoms E ⟧s ρ) ≈⟨ M.sym $ M.assoc _ _ _ ⟩
⟦ p ∷ fromAtoms Δ ⟧s ρ M.∙ ⟦ fromAtoms E ⟧s ρ
∎
sound : {γ : Con ty} {σ : ty} (Γ : isAtoms γ) (S : isProduct σ) →
γ ⊢ σ → ⟦ fromAtoms Γ ⟧s ρ M.≈ ⟦ fromProduct S ⟧s ρ
sound (ε ∙ `κ p) (`κ .p) `v = M.refl
sound Γ (S `⊗ T) (s `⊗ʳ t by mg) =
let (Δ , E) = isAtoms-merge⁻¹ Γ mg
ih₁ = sound Δ S s
ih₂ = sound E T t
in begin
⟦ fromAtoms Γ ⟧s ρ ≈⟨ sound⋈ Γ Δ E mg ⟩
⟦ fromAtoms Δ ⟧s ρ M.∙ ⟦ fromAtoms E ⟧s ρ ≈⟨ M.∙-cong ih₁ ih₂ ⟩
⟦ fromProduct S ⟧s ρ M.∙ ⟦ fromProduct T ⟧s ρ ≈⟨ M.sym $ ⟦ fromProduct S `++ fromProduct T ⟧s ρ ⟩
⟦ fromProduct $ S `⊗ T ⟧s ρ
∎
sound Γ _ (var `⊗ˡ _) = ⊥-elim $ noTensor Γ var
sound Γ _ (var `&ˡ₁ _) = ⊥-elim $ noWith Γ var
sound Γ _ (var `&ˡ₂ _) = ⊥-elim $ noWith Γ var
open import lps.ProofSearch
open import lib.Nullary as LN
open Maybe
import Data.Empty as Zero
import lps.Equivalence as Equivalence
eq-const : ∀ {n e f} (eq : e RBEq.≡ f) (ρ : Vec M.Carrier n) → ⟦ e , [] ⟧′ ρ M.≈ ⟦ f , [] ⟧′ ρ
eq-const RBEq.refl ρ = M.refl
proveM : {n : ℕ} (t u : Term n) (ρ : Vec M.Carrier n) → Maybe $ ⟦ t ⟧ ρ M.≈ ⟦ u ⟧ ρ
proveM {n} t u ρ with norm t | norm u | norm-sound t ρ | norm-sound u ρ
... | (e , k ∷ ks) | (f , []) | sndt | sndu = none
... | (e , []) | (f , []) | sndt | sndu = dec (e ≟ f) (some ∘ p₁) (const none)
where
p₁ : (ef : e RBEq.≡ f) → ⟦ t ⟧ ρ M.≈ ⟦ u ⟧ ρ
p₁ ef =
begin
⟦ t ⟧ ρ ≈⟨ sndt ⟩
⟦ e , [] ⟧′ ρ ≈⟨ eq-const ef ρ ⟩
⟦ f , [] ⟧′ ρ ≈⟨ M.sym sndu ⟩
⟦ u ⟧ ρ
∎
... | (e , ks) | (f , l ∷ ls) | sndt | sndu =
flip (dec (e ≟ f)) (const none) $ λ eq →
let open FixedVars n ρ
open TacticsBasics (Fin n)
open Prove (Fin n) (MyFin._≟_ {n})
open Equivalence (Fin n) (MyFin._≟_ {n})
okContext = isAtomsToContext ks
okGoal = isProductToGoal l ls
result = dec (⊢-dec (toContext ks) (toGoal l ls)) some (const none)
mon-eq = sound okContext okGoal <$> result
fromTo l = fromProduct ∘ isProductToGoal l
rew-eqks = RBEq.subst (λ e → ⟦ e ⟧s ρ M.≈ _) (RBEq.sym $ fromToContext ks)
rew-eqls = RBEq.subst (λ e → ⟦ e ⟧s ρ M.≈ ⟦ l ∷ ls ⟧s ρ) (fromToGoal l ls)
in (λ pr →
begin
⟦ t ⟧ ρ ≈⟨ sndt ⟩
⟦ e , ks ⟧′ ρ ≈⟨ M.∙-cong (RBEq.subst (M._≈_ e) eq M.refl) (rew-eqks pr) ⟩
f M.∙ ⟦ fromTo l ls ⟧s ρ ≈⟨ M.∙-cong M.refl (rew-eqls M.refl) ⟩
⟦ f , l ∷ ls ⟧′ ρ ≈⟨ M.sym sndu ⟩
⟦ u ⟧ ρ
∎) <$> mon-eq
proveMonEq : {n : ℕ} (t u : Term n) (ρ : Vec M.Carrier n) {_ : maybe (const ⊤) ⊥ $ proveM t u ρ} →
⟦ t ⟧ ρ M.≈ ⟦ u ⟧ ρ
proveMonEq t u ρ {pr} = Maybe.induction P ⊥-elim const (proveM t u ρ) pr
where P = λ a → ∀ (pr : maybe (const ⊤) ⊥ a) → ⟦ t ⟧ ρ M.≈ ⟦ u ⟧ ρ
module BagEq (Pr : Set) (_≟_ : (x y : Pr) → RN.Dec (x RBEq.≡ y)) where
open import Algebra.Structures
open import Prelude
open import Function-universe equality-with-J as FU
import Bijection equality-with-J as Bij
isSg : IsSemigroup _≈-bag_ _++_
isSg = record { isEquivalence = record { refl = λ _ → Bij.id
; sym = Prelude._∘_ FU.inverse
; trans = λ f g z → g z Bij.∘ f z }
; assoc = ++-assoc
; ∙-cong = ++-cong }
where
++-assoc : (xs ys zs : List Pr) → (xs ++ ys) ++ zs ≈-bag xs ++ ys ++ zs
++-assoc [] ys zs = λ z → Bij.id
++-assoc (x ∷ xs) ys zs = _≡_.refl ∷-cong ++-assoc xs ys zs
Mon : CommutativeMonoid lzero lzero
Mon = record
{ Carrier = List Pr
; _≈_ = _≈-bag_
; _∙_ = _++_
; ε = []
; isCommutativeMonoid = record { isSemigroup = isSg
; identityˡ = λ _ _ → Bij.id
; comm = ++-comm } }
∷-inj : {x y : Pr} {xs ys : List Pr} (eq : RBEq._≡_ {_} {List Pr} (x ∷ xs) (y ∷ ys)) →
x RBEq.≡ y × xs RBEq.≡ ys
∷-inj RBEq.refl = RBEq.refl , RBEq.refl
_≟s_ : (xs ys : List Pr) → RN.Dec (xs RBEq.≡ ys)
[] ≟s [] = RN.yes RBEq.refl
[] ≟s (x ∷ ys) = RN.no (λ ())
(x ∷ xs) ≟s [] = RN.no (λ ())
(x ∷ xs) ≟s (y ∷ ys) with x ≟ y | xs ≟s ys
... | RN.yes p | RN.yes ps = RN.yes $ RBEq.cong₂ _∷_ p ps
... | _ | RN.no ¬ps = RN.no (¬ps Prelude.∘ proj₂ Prelude.∘ ∷-inj)
... | RN.no ¬p | _ = RN.no (¬p Prelude.∘ proj₁ Prelude.∘ ∷-inj)
open TacticsAbMon Mon _≟s_ public