\import Algebra.Pointed \import Arith.Nat \import Data.Array \import Function.Meta \import Logic \import Meta \import Order.LinearOrder \import Order.PartialOrder \import Paths \import Paths.Meta \import Relation.Equivalence \func QPoly (R : AddPointed) => Quotient {Array R} (__ = __ ++ 0 :: nil) \where { \data \infix 5 ~ {R : AddPointed} (l l' : Array R) | eq-left (n : Nat) (l ++ replicate n zro = l') | eq-right (n : Nat) (l' ++ replicate (suc n) zro = l) \where { \lemma lists-lem1 {R : AddPointed} {l l' : Array R} (n m : Nat) (p : l ++ replicate n zro = l') (q : l ++ replicate m zro = l') : n = m => NatSemiring.cancel-left _ (inv len_++ *> pmap (DArray.len {__}) (p *> inv q) *> len_++) \lemma lists-lem2 {R : AddPointed} {l l' : Array R} {n m : Nat} (p : l ++ replicate n zro = l') (q : l' ++ replicate (suc m) zro = l) : Empty => \have t => ++-cancel-left $ inv ++-assoc *> pmap (`++ _) p *> q *> inv ++_nil \in \case \elim n, \elim t \with { | 0, t => \case pmap (DArray.len {__}) t } \use \level levelProp {R : AddPointed} {l l' : Array R} (x y : l ~ l') : x = y \elim x, y | eq-left n p, eq-left m q => path (\lam i => eq-left (lists-lem1 n m p q i) (prop-dpi _ _ _ i)) | eq-left n p, eq-right m q => absurd (lists-lem2 p q) | eq-right n p, eq-left m q => absurd (lists-lem2 q p) | eq-right n p, eq-right m q => path (\lam i => eq-right (pmap pred (lists-lem1 (suc n) (suc m) p q) @ i) (prop-dpi _ _ _ i)) } \func ~-isEquiv {R : AddPointed} : Equivalence (Array R) \cowith | ~ => ~ | ~-reflexive => eq-left 0 ++_nil | ~-symmetric => symm | ~-transitive => \case __, __ \with { | eq-left n p, eq-left m q => eq-left (n Nat.+ m) (pmap (_ ++) replicate_+ *> inv ++-assoc *> pmap (`++ _) p *> q) | eq-left n p, eq-right m q => \case totality (suc m) n \with { | byLeft s => lists-lem1 n (suc m) (p *> inv q) s | byRight s => symm (lists-lem1 (suc m) n (q *> inv p) s) } | eq-right n p, eq-left m q => \case totality (suc n) m \with { | byLeft s => lists-lem2 (suc n) m p q s | byRight s => symm (lists-lem2 m (suc n) q p s) } | eq-right n p, eq-right m q => eq-right (suc m Nat.+ n) (pmap (_ ++) (replicate_+ {_} {suc m} {suc n}) *> inv ++-assoc *> pmap (`++ zro :: _) q *> p) } \where { \lemma symm {R : AddPointed} {x y : Array R} (p : x ~ y) : y ~ x \elim p | eq-left 0 p => eq-left 0 (++_nil *> inv p *> ++_nil) | eq-left (suc n) p => eq-right n p | eq-right n p => eq-left (suc n) p \lemma lists-lem1 {R : AddPointed} {x z : Array R} (n m : Nat) (p : x ++ replicate n zro = z ++ replicate m zro) (q : m <= n) : x ~ z => eq-left (n -' m) $ ++-cancel-right $ rewrite (inv (<=_exists q), NatSemiring.+-comm, replicate_+, inv ++-assoc) in p \lemma lists-lem2 {R : AddPointed} {x y z : Array R} (n m : Nat) (p : y ++ replicate n zro = x) (q : y ++ replicate m zro = z) (s : n <= m) : x ~ z => eq-left (m -' n) $ rewrite (inv (<=_exists s), replicate_+, inv ++-assoc, p) in q } \lemma from=to~ {R : AddPointed} {l l' : Array R} (p : in~ l = {QPoly R} in~ l') : l ~ l' => Quotient.equalityClosure ~-isEquiv (\lam q => eq-right 0 (inv q)) p \lemma from~to= {R : AddPointed} {l l' : Array R} (p : l ~ l') : in~ l = {QPoly R} in~ l' \elim p | eq-left 0 p => pmap in~ (inv ++_nil *> p) | eq-left (suc n) p => from~to= (eq-left n idp) *> inv (path $ ~-equiv _ _ $ inv $ ++-assoc *> (rewrite (replicate_+ {_} {n} {1}) in p)) | eq-right 0 p => path (~-equiv l l' (inv p)) | eq-right (suc n) p => path (~-equiv _ _ $ inv $ ++-assoc {_} {l'} {replicate (suc n) zro} *> (rewrite (replicate_+ {_} {suc n} {1}) in p)) *> from~to= (eq-right n idp) -- | `qadd p e` is equivalent to `p * X + e` \func qadd {R : AddPointed} (p : QPoly R) (e : R) : QPoly R \elim p | in~ l => in~ (e :: l) | ~-equiv x y r => path (~-equiv _ _ (pmap (e ::) r)) \lemma nil_cons {R : AddPointed} {e : R} {l : Array R} (s : in~ nil = {QPoly R} in~ (e :: l)) : \Sigma (zro = e) (in~ nil = {QPoly R} in~ l) => \case from=to~ s \with { | eq-left 0 p => \case pmap (DArray.len {__}) p | eq-left (suc n) p => (unhead p, from~to= $ ~-isEquiv.lists-lem2 {_} {_} {nil} 0 n idp (untail p) zero<=_) | eq-right n () } \lemma qadd_nil {R : AddPointed} {p : QPoly R} {e : R} (s : qadd p e = in~ nil) : \Sigma (p = in~ nil) (e = 0) \elim p | in~ l => \case from=to~ s \with { | eq-left n () | eq-right n p => (inv $ from~to= $ ~-isEquiv.lists-lem2 {_} {_} {nil} 0 n idp (untail p) zero<=_, inv $ unhead p) } \lemma qadd_cons {R : AddPointed} {e a : R} {p : QPoly R} {l' : Array R} (s : qadd p e = in~ (a :: l')) : \Sigma (e = a) (p = in~ l') \elim p | in~ l => \case from=to~ s \with { | eq-left n p => (unhead p, from~to= $ eq-left n $ untail p) | eq-right n p => (inv $ unhead p, from~to= $ eq-right n $ untail p) } }