{-# OPTIONS --safe #-}
module Cubical.Tactics.MonoidSolver.CommSolver where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Structure
open import Cubical.Data.FinData
open import Cubical.Data.Nat using (ℕ; _+_; iter)
open import Cubical.Data.Vec
open import Cubical.Algebra.CommMonoid
open import Cubical.Tactics.MonoidSolver.MonoidExpression
private
variable
ℓ : Level
module Eval (M : CommMonoid ℓ) where
open CommMonoidStr (snd M)
open CommMonoidTheory M
Env : ℕ → Type ℓ
Env n = Vec ⟨ M ⟩ n
⟦_⟧ : ∀{n} → Expr ⟨ M ⟩ n → Env n → ⟨ M ⟩
⟦ ε⊗ ⟧ v = ε
⟦ ∣ i ⟧ v = lookup i v
⟦ e₁ ⊗ e₂ ⟧ v = ⟦ e₁ ⟧ v · ⟦ e₂ ⟧ v
NormalForm : ℕ → Type _
NormalForm n = Vec ℕ n
_⊞_ : {n : ℕ} → NormalForm n → NormalForm n → NormalForm n
x ⊞ y = zipWith _+_ x y
emptyForm : {n : ℕ} → NormalForm n
emptyForm = replicate 0
e[_] : {n : ℕ} → Fin n → NormalForm n
e[ Fin.zero ] = 1 ∷ emptyForm
e[ (Fin.suc j) ] = 0 ∷ e[ j ]
normalize : {n : ℕ} → Expr ⟨ M ⟩ n → NormalForm n
normalize (∣ i) = e[ i ]
normalize ε⊗ = emptyForm
normalize (e₁ ⊗ e₂) = (normalize e₁) ⊞ (normalize e₂)
eval : {n : ℕ} → NormalForm n → Env n → ⟨ M ⟩
eval [] v = ε
eval (x ∷ xs) (v ∷ vs) = iter x (λ w → v · w) (eval xs vs)
emptyFormEvaluatesToε : {n : ℕ} (v : Env n) → eval emptyForm v ≡ ε
emptyFormEvaluatesToε [] = refl
emptyFormEvaluatesToε (v ∷ vs) = emptyFormEvaluatesToε vs
UnitVecEvaluatesToVar : ∀{n} (i : Fin n) (v : Env n) → eval e[ i ] v ≡ lookup i v
UnitVecEvaluatesToVar zero (v ∷ vs) =
v · eval emptyForm vs ≡⟨ cong₂ _·_ refl (emptyFormEvaluatesToε vs) ⟩
v · ε ≡⟨ ·IdR _ ⟩
v ∎
UnitVecEvaluatesToVar (suc i) (v ∷ vs) = UnitVecEvaluatesToVar i vs
evalIsHom : ∀ {n} (x y : NormalForm n) (v : Env n)
→ eval (x ⊞ y) v ≡ (eval x v) · (eval y v)
evalIsHom [] [] v = sym (·IdL _)
evalIsHom (x ∷ xs) (y ∷ ys) (v ∷ vs) =
lemma x y (evalIsHom xs ys vs)
where
lemma : ∀ x y {a b c}(p : a ≡ b · c)
→ iter (x + y) (v ·_) a ≡ iter x (v ·_) b · iter y (v ·_) c
lemma 0 0 p = p
lemma 0 (ℕ.suc y) p = (cong₂ _·_ refl (lemma 0 y p)) ∙ commAssocl _ _ _
lemma (ℕ.suc x) y p = (cong₂ _·_ refl (lemma x y p)) ∙ ·Assoc _ _ _
module EqualityToNormalform (M : CommMonoid ℓ) where
open Eval M
open CommMonoidStr (snd M)
isEqualToNormalform : {n : ℕ}
→ (e : Expr ⟨ M ⟩ n)
→ (v : Env n)
→ eval (normalize e) v ≡ ⟦ e ⟧ v
isEqualToNormalform ε⊗ v = emptyFormEvaluatesToε v
isEqualToNormalform (∣ i) v = UnitVecEvaluatesToVar i v
isEqualToNormalform (e₁ ⊗ e₂) v =
eval ((normalize e₁) ⊞ (normalize e₂)) v ≡⟨ evalIsHom (normalize e₁) (normalize e₂) v ⟩
(eval (normalize e₁) v) · (eval (normalize e₂) v) ≡⟨ cong₂ _·_ (isEqualToNormalform e₁ v) (isEqualToNormalform e₂ v) ⟩
⟦ e₁ ⟧ v · ⟦ e₂ ⟧ v ∎
solve : {n : ℕ}
→ (e₁ e₂ : Expr ⟨ M ⟩ n)
→ (v : Env n)
→ (p : eval (normalize e₁) v ≡ eval (normalize e₂) v)
→ ⟦ e₁ ⟧ v ≡ ⟦ e₂ ⟧ v
solve e₁ e₂ v p =
⟦ e₁ ⟧ v ≡⟨ sym (isEqualToNormalform e₁ v) ⟩
eval (normalize e₁) v ≡⟨ p ⟩
eval (normalize e₂) v ≡⟨ isEqualToNormalform e₂ v ⟩
⟦ e₂ ⟧ v ∎
solve : (M : CommMonoid ℓ)
{n : ℕ} (e₁ e₂ : Expr ⟨ M ⟩ n) (v : Eval.Env M n)
(p : Eval.eval M (Eval.normalize M e₁) v ≡ Eval.eval M (Eval.normalize M e₂) v)
→ _
solve M = EqualityToNormalform.solve M