\import Algebra.Meta \import Algebra.Monoid \import Algebra.Monoid.GCD \import Data.Array \import Function.Meta \import Logic \import Meta \import Paths \import Paths.Meta \import Relation.Equivalence \import Set.Fin \class Semiring \extends AbMonoid, Monoid { | ldistr {x y z : E} : x * (y + z) = x * y + x * z | rdistr {x y z : E} : (x + y) * z = x * z + y * z | zro_*-left {x : E} : zro * x = zro | zro_*-right {x : E} : x * zro = zro | natCoef : Nat -> E \default natCoef \as natCoefImpl n \with { | 0 => zro | suc n => natCoefImpl n + ide } | natCoefZero : natCoef 0 = zro \default natCoefZero \as natCoefZeroImpl : natCoefImpl 0 = zro => idp | natCoefSuc (n : Nat) : natCoef (suc n) = natCoef n + ide \default natCoefSuc \as natCoefSucImpl n : natCoefImpl (suc n) = natCoefImpl n + ide => idp \lemma zero-div {x : E} : LDiv x 0 0 \cowith | inv-right => zro_*-right \lemma ldiv=0 {x y : E} (l : LDiv x y) (p : x = 0) : y = 0 => Paths.inv l.inv-right *> pmap (`* _) p *> zro_*-left \lemma ldiv/=0 {x y : E} (y/=0 : y /= 0) (x|y : LDiv x y) : x /= 0 => \lam x=0 => y/=0 (ldiv=0 x|y x=0) \func LDiv_+ {a b c : E} (a|b : LDiv a b) (a|c : LDiv a c) : LDiv a (b + c) \cowith | inv => a|b.inv + a|c.inv | inv-right => ldistr *> pmap2 (+) a|b.inv-right a|c.inv-right \func LDiv_BigSum {a : E} {l : Array E} (p : \Pi (j : Fin l.len) -> LDiv a (l j)) : LDiv a (BigSum l) \cowith | inv => BigSum (\lam j => LDiv.inv {p j}) | inv-right => BigSum-ldistr *> pmap BigSum (later $ exts \lam j => LDiv.inv-right {p j}) \lemma natCoef_+ (n m : Nat) : natCoef (n Nat.+ m) = natCoef n + natCoef m \elim m | 0 => inv (pmap (_ +) natCoefZero *> zro-right) | suc m => natCoefSuc _ *> pmap (`+ 1) (natCoef_+ n m) *> +-assoc *> inv (pmap (_ +) (natCoefSuc m)) \lemma BigSum-ldistr {x : E} {l : Array E} : x * BigSum l = BigSum (map (x *) l) \elim l | nil => zro_*-right | :: a l => ldistr *> pmap (x * a +) BigSum-ldistr \lemma FinSum-ldistr {A : FinSet} {x : E} {y : A -> E} : x * FinSum y = FinSum (x * y __) => \case FinSum_char y \with { | inP p => pmap (x *) p.2 *> BigSum-ldistr *> inv (FinSum_char2 _ p.1) } \lemma BigSum-rdistr {l : Array E} {z : E} : BigSum l * z = BigSum (\lam i => l i * z) \elim l | nil => zro_*-left | :: a arr => rdistr *> pmap (_ +) BigSum-rdistr \lemma FinSum-rdistr {A : FinSet} {x : E} {y : A -> E} : FinSum y * x = FinSum (y __ * x) => \case FinSum_char y \with { | inP p => pmap (`* x) p.2 *> BigSum-rdistr *> inv (FinSum_char2 _ p.1) } \lemma FinSum-distr {A B : FinSet} {x : A -> E} {y : B -> E} : FinSum x * FinSum y = FinSum (\lam (s : \Sigma A B) => x s.1 * y s.2) => FinSum-rdistr *> path (\lam i => FinSum (\lam a => FinSum-ldistr {_} {_} {x a} i)) *> FinSum-double \lemma BigSum_replicate {x : E} {n : Nat} : BigSum (replicate n x) = natCoef n * x \elim n | 0 => rewrite natCoefZero (inv zro_*-left) | suc n => rewrite natCoefSuc $ pmap (x +) BigSum_replicate *> equation \lemma BigSum_replicate1 {n : Nat} : BigSum (replicate n ide) = natCoef n => BigSum_replicate *> ide-right \lemma FinSum_replicate {A : FinSet} {x : E} : FinSum {_} {A} (\lam _ => x) = natCoef A.finCard * x => FinSum-const *> BigSum_replicate \lemma BigProd_zro {l : Array E} (j : Fin l.len) (p : l j = 0) : BigProd l = 0 \elim l, j | a :: l, 0 => pmap (`* _) p *> zro_*-left | a :: l, suc j => pmap (_ *) (BigProd_zro j p) *> zro_*-right \lemma trivial (p : 0 = {E} 1) {x y : E} : x = y => inv ide-right *> inv (pmap (x *) p) *> zro_*-right *> inv zro_*-right *> pmap (y *) p *> ide-right \lemma associates0 {a b : E} (c : associates a b) (p : a = 0) : b = 0 => (associates-sym c).2 *> pmap (_ *) p *> zro_*-right \func op : Semiring \cowith | AbMonoid => \this | Monoid => Monoid.op | ldistr => rdistr | rdistr => ldistr | zro_*-left => zro_*-right | zro_*-right => zro_*-left } \where { \open Monoid(LDiv) } \class NonZeroSemiring \extends Semiring { | zro/=ide : zro /= ide \lemma inv-nonZero {a : E} (i : Monoid.Inv a) : a /= zro => \lam a=0 => zro/=ide (inv zro_*-right *> pmap (_ *) (inv a=0) *> i.inv-left) } \class CSemiring \extends Semiring, CMonoid { \default ldistr => *-comm *> rdistr *> pmap2 (+) *-comm *-comm \default rdistr => *-comm *> ldistr *> pmap2 (+) *-comm *-comm \default zro_*-left => *-comm *> zro_*-right \default zro_*-right => *-comm *> zro_*-left \lemma divQuotient_un0 {a : E} (p : in~ a = {DivQuotient \this} in~ 0) : a = 0 => \case (DivQuotient.make~ p).1 \with { | inP d => inv (Monoid.LDiv.inv-right {d}) *> zro_*-left } }