\import Algebra.Monoid \import Algebra.Pointed \import Arith.Fin \import Data.List \import Function.Meta \import Meta \import Order.Lattice \import Order.PartialOrder \import Paths \import Paths.Meta \import Set \hiding (#) \open FinLinearOrder \data MonoidTerm (V : \Type) | var V | :ide | \infixl 7 :* (t s : MonoidTerm V) \func normalize {V : \Type} (t : MonoidTerm V) => aux t nil \where \func aux {V : \Type} (t : MonoidTerm V) (acc : List V) : List V \elim t | var v => v :: acc | :ide => acc | :* t s => aux t (aux s acc) \class Data \noclassifying {M : Monoid} (vars : Array M) { \meta V => Fin vars.len \func interpret (t : MonoidTerm V) : M \elim t | var x => vars x | :ide => ide | :* t s => interpret t * interpret s \func interpretNF (l : List V) : M \elim l | nil => ide | :: x nil => vars x | :: x l => vars x * interpretNF l \where \lemma cons (x : V) (l : List V) : interpretNF (x :: l) = vars x * interpretNF l \elim l | nil => inv ide-right | :: a l => idp \lemma normalize-consistent (t : MonoidTerm V) : interpret t = interpretNF (normalize t) => inv ide-right *> aux t nil \where \lemma aux (t : MonoidTerm V) (acc : List V) : interpret t * interpretNF acc = interpretNF (normalize.aux t acc) \elim t | var x => inv (interpretNF.cons x acc) | :ide => ide-left | :* t s => *-assoc *> pmap (interpret t *) (aux s acc) *> aux t (normalize.aux s acc) \lemma terms-equality (t s : MonoidTerm V) (p : interpretNF (normalize t) = interpretNF (normalize s)) : interpret t = interpret s => normalize-consistent t *> p *> inv (normalize-consistent s) \lemma terms-equality-conv (t s : MonoidTerm V) (p : interpret t = interpret s) : interpretNF (normalize t) = interpretNF (normalize s) => inv (normalize-consistent t) *> p *> normalize-consistent s \lemma interpretNF_++ (l1 l2 : List V) : interpretNF (l1 ++ l2) = interpretNF l1 * interpretNF l2 \elim l1 | nil => inv ide-left | :: a l1 => repeat {2} (rewrite interpretNF.cons) $ rewrite interpretNF_++ (inv *-assoc) \lemma replace-consistent (l : List V) (i s : Nat) (r : List V) (p : interpretNF (slice l i s) = interpretNF r) : interpretNF l = interpretNF (replace l i s r) => run { rewriteI {1} (slice.appendLem l i s), repeat {4} (rewrite interpretNF_++), rewriteI p, idp } } \class CData \extends Data { \override M : CMonoid \lemma sort-consistent (l : List V) : interpretNF l = interpretNF (sort {FinLinearOrderInst} l) => rewrite sort=insert (perm-consistent (Insertion.sort-perm l)) \lemma perm-consistent {l l' : List V} (p : Perm l l') : interpretNF l = interpretNF l' \elim l, l', p | nil, nil, perm-nil => idp | :: a1 l1, :: a2 l2, perm-:: idp p => repeat {2} (rewrite interpretNF.cons) (pmap (vars a1 *) (perm-consistent p)) | :: a1 (:: a1' l1), :: a2 (:: a2' l2), perm-swap idp idp idp => repeat {2} (rewrite interpretNF.cons) (inv *-assoc *> pmap (`* interpretNF l1) *-comm *> *-assoc) | l1, l2, perm-trans p1 p2 => perm-consistent p1 *> perm-consistent p2 \lemma normalize-consistent (t : MonoidTerm V) : interpret t = interpretNF (sort (normalize t)) => Data.normalize-consistent t *> sort-consistent (normalize t) \lemma terms-equality (t s : MonoidTerm V) (p : interpretNF (sort (normalize t)) = interpretNF (sort (normalize s))) : interpret t = interpret s => normalize-consistent t *> p *> inv (normalize-consistent s) \lemma terms-equality-conv (t s : MonoidTerm V) (p : interpret t = interpret s) : interpretNF (sort (normalize t)) = interpretNF (sort (normalize s)) => inv (normalize-consistent t) *> p *> normalize-consistent s \lemma replace-consistent (l : List V) (is : List Nat) (r : List V) (p : interpretNF (indices is l) = interpretNF r) : interpretNF l = interpretNF (r ++ removeIndices is l) => replace-consistent-lem is l *> interpretNF_++ _ _ *> pmap (`* interpretNF (removeIndices is l)) p *> inv (interpretNF_++ _ _) \lemma replace-consistent-lem (is : List Nat) (l : List V) : interpretNF l = interpretNF (indices is l ++ removeIndices is l) | nil, l => idp | :: 0 is, nil => idp | :: (suc _) is, nil => idp | :: 0 is, :: a l => repeat {2} (rewrite interpretNF.cons) (pmap (vars a *) (replace-consistent-lem is l)) | :: (suc n) is, :: a l => interpretNF.cons a l *> pmap (vars a *) (replace-consistent-lem (n :: is) l) *> inv (interpretNF.cons a _) *> perm-consistent Perm.perm-head } \where { \open Data \open Sort \open Sort.RedBlack \func indices {A : \Type} (is : List Nat) (l : List A) : List A \elim is, l | nil, _ => nil | :: _ _, nil => nil | :: 0 is, :: a l => a :: indices is l | :: (suc n) is, :: _ l => indices (n :: is) l \func removeIndices {A : \Type} (is : List Nat) (l : List A) : List A \elim is, l | nil, l => l | :: _ _, nil => nil | :: 0 is, :: a l => removeIndices is l | :: (suc n) is, :: a l => a :: removeIndices (n :: is) l } \class LData {L : Bounded.MeetSemilattice} \extends CData { | M => L \func removeDuplicates (l : List V) : List V \elim l | nil => nil | :: a nil => a :: nil | :: a (:: a' _ \as l) => \case decideEq a a' \with { | yes _ => removeDuplicates l | no _ => a :: removeDuplicates l } \lemma removeDuplicates-consistent (l : List V) : interpretNF l = interpretNF (removeDuplicates l) | nil => idp | :: a nil => idp | :: a (:: a1 l) => mcases \with { | yes p => rewrite (p, inv (removeDuplicates-consistent (a1 :: l)), interpretNF.cons) $ inv M.*-assoc *> pmap (`∧ interpretNF l) (<=-antisymmetric meet-left (meet-univ <=-refl <=-refl)) | no _ => rewrite {2} interpretNF.cons $ pmap (vars a ∧) (removeDuplicates-consistent (a1 :: l)) } \lemma normalize-consistent (t : MonoidTerm V) : interpret t = interpretNF (removeDuplicates (RedBlack.sort (normalize t))) => CData.normalize-consistent t *> removeDuplicates-consistent _ \lemma terms-equality (t s : MonoidTerm V) (p : interpretNF (removeDuplicates (RedBlack.sort (normalize t))) = interpretNF (removeDuplicates (RedBlack.sort (normalize s)))) : interpret t = interpret s => normalize-consistent t *> p *> inv (normalize-consistent s) \lemma terms-equality-conv (t s : MonoidTerm V) (p : interpret t = interpret s) : interpretNF (removeDuplicates (RedBlack.sort (normalize t))) = interpretNF (removeDuplicates (RedBlack.sort (normalize s))) => inv (normalize-consistent t) *> p *> normalize-consistent s } \where { \open Data \open Sort }