module Tactic.Nat.Auto.Lemmas where open import Prelude open import Tactic.Nat.NF open import Tactic.Nat.Exp open import Data.Bag open import Data.Nat.Properties.Core map++ : ∀ {a b} {A : Set a} {B : Set b} (f : A → B) (xs ys : List A) → map f (xs ++ ys) ≡ map f xs ++ map f ys map++ f [] ys = refl map++ f (x ∷ xs) ys rewrite map++ f xs ys = refl prod++ : ∀ xs ys → product (xs ++ ys) ≡ product xs * product ys prod++ [] ys = refl prod++ (x ∷ xs) ys rewrite prod++ xs ys = mul-assoc x _ _ private shuffle₁ : ∀ a b c d → a + ((b + c) + d) ≡ b + c + (a + d) shuffle₁ a b c d rewrite add-assoc a (b + c) d | add-commute a (b + c) | add-assoc (b + c) a d = refl shuffle₂ : ∀ a b c d → a + b + (c + d) ≡ a + c + (b + d) shuffle₂ a b c d rewrite add-assoc (a + b) c d | sym (add-assoc a b c) | add-commute b c | add-assoc a c b | add-assoc (a + c) b d = refl shuffle₃ : ∀ a b c d → (a * b) * (c * d) ≡ (a * c) * (b * d) shuffle₃ a b c d rewrite mul-assoc (a * b) c d | sym (mul-assoc a b c) | mul-commute b c | mul-assoc a c b | mul-assoc (a * c) b d = refl shuffle₄ : ∀ a b c d → a * (b * c * d) ≡ b * c * (a * d) shuffle₄ a b c d rewrite mul-assoc a (b * c) d | mul-commute a (b * c) | mul-assoc (b * c) a d = refl module _ {Atom : Set} {{_ : Ord Atom}} where ⟨+⟩-sound : ∀ v₁ v₂ (ρ : Env Atom) → ⟦ v₁ +nf v₂ ⟧n ρ ≡ ⟦ v₁ ⟧n ρ + ⟦ v₂ ⟧n ρ ⟨+⟩-sound [] [] ρ = refl ⟨+⟩-sound [] (_ ∷ _) ρ = refl ⟨+⟩-sound (t ∷ v₁) [] ρ = sym (add-0-r _) ⟨+⟩-sound ((i , t₁) ∷ v₁) ((j , t₂) ∷ v₂) ρ with compare t₁ t₂ ... | less _ rewrite ⟨+⟩-sound v₁ ((j , t₂) ∷ v₂) ρ = add-assoc (i * product (map ρ t₁)) _ _ ... | equal eq rewrite eq | ⟨+⟩-sound v₁ v₂ ρ | mul-distr-r i j (product (map ρ t₂)) = shuffle₂ (⟦ i , t₂ ⟧t ρ) (⟦ j , t₂ ⟧t ρ) _ _ ... | greater _ rewrite ⟨+⟩-sound ((i , t₁) ∷ v₁) v₂ ρ = shuffle₁ (⟦ j , t₂ ⟧t ρ) (⟦ i , t₁ ⟧t ρ) _ _ map-merge : ∀ x y (ρ : Env Atom) → product (map ρ (merge x y)) ≡ product (map ρ x) * product (map ρ y) map-merge [] [] ρ = refl map-merge [] (x ∷ xs) ρ = refl map-merge (x ∷ xs) [] ρ = sym (mul-1-r _) map-merge (x ∷ xs) (y ∷ ys) ρ with x <? y ... | true rewrite map-merge xs (y ∷ ys) ρ = mul-assoc (ρ x) _ _ ... | false rewrite map-merge (x ∷ xs) ys ρ = shuffle₄ (ρ y) (ρ x) _ _ mulTm-sound : ∀ t t′ (ρ : Env Atom) → ⟦ mulTm t t′ ⟧t ρ ≡ ⟦ t ⟧t ρ * ⟦ t′ ⟧t ρ mulTm-sound (a , x) (b , y) ρ rewrite map-merge x y ρ = shuffle₃ a b _ _ mulTmDistr : ∀ t v (ρ : Env Atom) → ⟦ map (mulTm t) v ⟧n ρ ≡ ⟦ t ⟧t ρ * ⟦ v ⟧n ρ mulTmDistr t [] ρ = sym (mul-0-r (⟦ t ⟧t ρ)) mulTmDistr t (t′ ∷ v) ρ = ⟦ mulTm t t′ ⟧t ρ + ⟦ map (mulTm t) v ⟧n ρ ≡⟨ cong₂ _+_ (mulTm-sound t t′ ρ) (mulTmDistr t v ρ) ⟩ ⟦ t ⟧t ρ * ⟦ t′ ⟧t ρ + ⟦ t ⟧t ρ * ⟦ v ⟧n ρ ≡⟨ mul-distr-l (⟦ t ⟧t ρ) _ _ ⟩ʳ ⟦ t ⟧t ρ * ⟦ t′ ∷ v ⟧n ρ ∎ sort-sound : ∀ xs ρ → ⟦ sort xs ⟧n ρ ≡ ⟦ xs ⟧n ρ sort-sound [] ρ = refl sort-sound (x ∷ xs) ρ rewrite ⟨+⟩-sound [ x ] (sort xs) ρ | sort-sound xs ρ | add-0-r (⟦ x ⟧t ρ) = refl ⟨*⟩-sound : ∀ v₁ v₂ (ρ : Env Atom) → ⟦ v₁ *nf v₂ ⟧n ρ ≡ ⟦ v₁ ⟧n ρ * ⟦ v₂ ⟧n ρ ⟨*⟩-sound [] v₂ ρ = refl ⟨*⟩-sound (t ∷ v₁) v₂ ρ = ⟦ sort (map (mulTm t) v₂) +nf (v₁ *nf v₂) ⟧n ρ ≡⟨ ⟨+⟩-sound (sort (map (mulTm t) v₂)) (v₁ *nf v₂) ρ ⟩ ⟦ sort (map (mulTm t) v₂) ⟧n ρ + ⟦ v₁ *nf v₂ ⟧n ρ ≡⟨ cong (flip _+_ (⟦ v₁ *nf v₂ ⟧n ρ)) (sort-sound (map (mulTm t) v₂) ρ) ⟩ ⟦ map (mulTm t) v₂ ⟧n ρ + ⟦ v₁ *nf v₂ ⟧n ρ ≡⟨ cong (_+_ (⟦ map (mulTm t) v₂ ⟧n ρ)) (⟨*⟩-sound v₁ v₂ ρ) ⟩ ⟦ map (mulTm t) v₂ ⟧n ρ + ⟦ v₁ ⟧n ρ * ⟦ v₂ ⟧n ρ ≡⟨ cong (flip _+_ (⟦ v₁ ⟧n ρ * ⟦ v₂ ⟧n ρ)) (mulTmDistr t v₂ ρ) ⟩ ⟦ t ⟧t ρ * ⟦ v₂ ⟧n ρ + ⟦ v₁ ⟧n ρ * ⟦ v₂ ⟧n ρ ≡⟨ mul-distr-r (⟦ t ⟧t ρ) _ _ ⟩ʳ ⟦ t ∷ v₁ ⟧n ρ * ⟦ v₂ ⟧n ρ ∎ sound : ∀ e (ρ : Env Atom) → ⟦ e ⟧e ρ ≡ ⟦ norm e ⟧n ρ sound (var x) ρ = ρ x ≡⟨ mul-1-r (ρ x) ⟩ʳ ρ x * 1 ≡⟨ add-0-r (ρ x * 1) ⟩ʳ (ρ x * 1) + 0 ∎ sound (lit 0) ρ = refl sound (lit (suc n)) ρ rewrite mul-1-r n | add-commute n 1 = sym (add-0-r _) sound (e ⟨+⟩ e₁) ρ = ⟦ e ⟧e ρ + ⟦ e₁ ⟧e ρ ≡⟨ cong₂ _+_ (sound e ρ) (sound e₁ ρ) ⟩ ⟦ norm e ⟧n ρ + ⟦ norm e₁ ⟧n ρ ≡⟨ ⟨+⟩-sound (norm e) (norm e₁) ρ ⟩ʳ ⟦ norm e +nf norm e₁ ⟧n ρ ∎ sound (e ⟨*⟩ e₁) ρ = ⟦ e ⟧e ρ * ⟦ e₁ ⟧e ρ ≡⟨ cong₂ _*_ (sound e ρ) (sound e₁ ρ) ⟩ ⟦ norm e ⟧n ρ * ⟦ norm e₁ ⟧n ρ ≡⟨ ⟨*⟩-sound (norm e) (norm e₁) ρ ⟩ʳ ⟦ norm e *nf norm e₁ ⟧n ρ ∎ module _ (ρ₁ ρ₂ : Env Atom) (eq : ∀ x → ρ₁ x ≡ ρ₂ x) where private lem-eval-env-a : ∀ a → product (map ρ₁ a) ≡ product (map ρ₂ a) lem-eval-env-a [] = refl lem-eval-env-a (x ∷ xs) = _*_ $≡ eq x *≡ lem-eval-env-a xs lem-eval-env-t : ∀ t → ⟦ t ⟧t ρ₁ ≡ ⟦ t ⟧t ρ₂ lem-eval-env-t (k , a) = _*_ k $≡ lem-eval-env-a a lem-eval-env : ∀ n → ⟦ n ⟧n ρ₁ ≡ ⟦ n ⟧n ρ₂ lem-eval-env [] = refl lem-eval-env (x ∷ n) = _+_ $≡ lem-eval-env-t x *≡ lem-eval-env n