module Tactic.Nat.Subtract.Exp where open import Prelude open import Tactic.Nat.Exp open import Tactic.Nat.NF open import Data.Bag open import Data.TreeRep infixl 6 _⟨+⟩_ _⟨-⟩_ infixl 7 _⟨*⟩_ data SubExp : Set where var : (x : Var) → SubExp lit : (n : Nat) → SubExp _⟨+⟩_ _⟨-⟩_ _⟨*⟩_ : (a b : SubExp) → SubExp infix 4 _:≡_ _:<_ data Eqn : Set where _:≡_ : (a b : SubExp) → Eqn _:<_ : (a b : SubExp) → Eqn ⟦_⟧se : SubExp → Env Var → Nat ⟦ var x ⟧se ρ = ρ x ⟦ lit n ⟧se ρ = n ⟦ e₁ ⟨+⟩ e₂ ⟧se ρ = ⟦ e₁ ⟧se ρ + ⟦ e₂ ⟧se ρ ⟦ e₁ ⟨-⟩ e₂ ⟧se ρ = ⟦ e₁ ⟧se ρ - ⟦ e₂ ⟧se ρ ⟦ e₁ ⟨*⟩ e₂ ⟧se ρ = ⟦ e₁ ⟧se ρ * ⟦ e₂ ⟧se ρ ⟦_⟧eqn : Eqn → Env Var → Set ⟦ e₁ :≡ e₂ ⟧eqn ρ = ⟦ e₁ ⟧se ρ ≡ ⟦ e₂ ⟧se ρ ⟦ e₁ :< e₂ ⟧eqn ρ = ⟦ e₁ ⟧se ρ < ⟦ e₂ ⟧se ρ data SubAtom : Set SubNF : Set SubNF = NF SubAtom data SubAtom where var : Var → SubAtom _⟨-⟩_ : (a b : SubNF) → SubAtom ⟦_⟧sn : SubNF → Env Var → Nat ⟦_⟧st : Tm SubAtom → Env Var → Nat ⟦_⟧sa : SubAtom → Env Var → Nat ⟦ var x ⟧sa ρ = ρ x ⟦ a ⟨-⟩ b ⟧sa ρ = ⟦ a ⟧sn ρ - ⟦ b ⟧sn ρ ⟦ [] ⟧st ρ = 1 ⟦ t ∷ ts ⟧st ρ = ⟦ t ⟧sa ρ * ⟦ ts ⟧st ρ ⟦ [] ⟧sn ρ = 0 ⟦ (k , ts) ∷ n ⟧sn ρ = k * ⟦ ts ⟧st ρ + ⟦ n ⟧sn ρ ⟦_⟧sns : SubNF → Env Var → Nat ⟦_⟧sts : Tm SubAtom → Env Var → Nat ⟦_⟧sas : SubAtom → Env Var → Nat ⟦ var x ⟧sas ρ = ρ x ⟦ a ⟨-⟩ b ⟧sas ρ = ⟦ a ⟧sns ρ - ⟦ b ⟧sns ρ ⟦ [] ⟧sts ρ = 1 ⟦ t ∷ [] ⟧sts ρ = ⟦ t ⟧sas ρ ⟦ t ∷ ts ⟧sts ρ = ⟦ t ⟧sas ρ * ⟦ ts ⟧sts ρ ⟦ [] ⟧sns ρ = 0 ⟦ (k , ts) ∷ [] ⟧sns ρ = k * ⟦ ts ⟧sts ρ ⟦ (k , ts) ∷ n ⟧sns ρ = k * ⟦ ts ⟧sts ρ + ⟦ n ⟧sns ρ atomEnv : Env Var → Env SubAtom atomEnv ρ x = ⟦ x ⟧sa ρ atomEnvS : Env Var → Env SubAtom atomEnvS ρ x = ⟦ x ⟧sas ρ instance EncodeSubAtom : TreeEncoding SubAtom EncodeSubAtom = treeEncoding enc dec emb where enc : SubAtom → TreeRep encNF : SubNF → TreeRep encNFs : SubNF → List TreeRep encTm : Tm SubAtom → List TreeRep enc (var x) = node x [] enc (a ⟨-⟩ b) = node 0 (encNF a ∷ encNF b ∷ []) encNF n = node 0 (encNFs n) encNFs [] = [] encNFs ((n , t) ∷ ns) = node n (encTm t) ∷ encNFs ns encTm [] = [] encTm (x ∷ xs) = enc x ∷ encTm xs dec : TreeRep → Maybe SubAtom decNF : TreeRep → Maybe SubNF decNFs : List TreeRep → Maybe SubNF decTm : List TreeRep → Maybe (Tm SubAtom) dec (node x []) = just (var x) dec (node _ (t ∷ t₁ ∷ [])) = _⟨-⟩_ <$> decNF t <*> decNF t₁ dec _ = nothing decNF (leaf _) = nothing decNF (node _ ts) = decNFs ts decNFs (node n ts ∷ ts₁) = _∷_ <$> (_,_ n <$> decTm ts) <*> decNFs ts₁ decNFs _ = just [] decTm [] = just [] decTm (x ∷ ts) = _∷_ <$> dec x <*> decTm ts emb : ∀ a → dec (enc a) ≡ just a embNFs : ∀ n → decNFs (encNFs n) ≡ just n embTm : ∀ t → decTm (encTm t) ≡ just t emb (var x) = refl emb (a ⟨-⟩ b) = _⟨-⟩_ =$= embNFs a =*= embNFs b embNFs [] = refl embNFs ((n , t) ∷ ns) = _∷_ =$= (_,_ n =$= embTm t) =*= embNFs ns embTm [] = refl embTm (x ∷ xs) = _∷_ =$= emb x =*= embTm xs EqSubAtom : Eq SubAtom EqSubAtom = EqByTreeEncoding OrdSubAtom : Ord SubAtom OrdSubAtom = OrdByTreeEncoding _-nf′_ : SubNF → SubNF → SubNF a -nf′ b = case cancel a b of λ { (x , []) → x ; ([] , _) → [] ; (a′ , b′) → [ 1 , [ a′ ⟨-⟩ b′ ] ] } data IsSubtraction : SubNF → Set where _⟨-⟩_ : ∀ a b → IsSubtraction [ 1 , [ a ⟨-⟩ b ] ] no : ∀ {a} → IsSubtraction a is-subtraction : ∀ a → IsSubtraction a is-subtraction [ 1 , [ a ⟨-⟩ b ] ] = a ⟨-⟩ b is-subtraction a = no infixl 6 _-nf_ infixl 7 _*nf₁_ _*tm_ _*ktm_ _*ktm′_ _-nf_ : SubNF → SubNF → SubNF a -nf b with is-subtraction a ._ -nf c | a ⟨-⟩ b = a -nf′ (b +nf c) a -nf b | no = a -nf′ b data IsSubtractionTm : Nat × Tm SubAtom → Set where _⟨-⟩_ : ∀ a b → IsSubtractionTm (1 , [ a ⟨-⟩ b ]) no : ∀ {a} → IsSubtractionTm a is-subtraction-tm : ∀ a → IsSubtractionTm a is-subtraction-tm (1 , [ a ⟨-⟩ b ]) = a ⟨-⟩ b is-subtraction-tm a = no _*nf₁_ : SubNF → SubNF → SubNF _*ktm′_ : Nat × Tm SubAtom → SubNF → SubNF _*tm_ : Nat × Tm SubAtom → Nat × Tm SubAtom → SubNF s *tm t with is-subtraction-tm t s *tm ._ | b ⟨-⟩ c = s *ktm′ b -nf s *ktm′ c (a , x) *tm (b , y) | no = [ a * b , merge x y ] t *ktm′ [] = [] t *ktm′ (x ∷ a) = t *tm x +nf t *ktm′ a _*ktm_ : Nat × Tm SubAtom → SubNF → SubNF t *ktm a with is-subtraction-tm t ._ *ktm c | a ⟨-⟩ b = a *nf₁ c -nf b *nf₁ c t *ktm a | no = t *ktm′ a [] *nf₁ b = [] (t ∷ a) *nf₁ b = t *ktm b +nf (a *nf₁ b) normSub : SubExp → SubNF normSub (var x) = [ 1 , [ var x ] ] normSub (lit 0) = [] normSub (lit n) = [ n , [] ] normSub (e ⟨+⟩ e₁) = normSub e +nf normSub e₁ normSub (e ⟨-⟩ e₁) = normSub e -nf normSub e₁ normSub (e ⟨*⟩ e₁) = normSub e *nf₁ normSub e₁