0 | module Algebra.Solver.Semiring.Sum
2 | import Algebra.Solver.Semiring.Expr
3 | import Algebra.Solver.Semiring.Prod
4 | import Algebra.Solver.Semiring.SolvableSemiring
5 | import Algebra.Solver.Semiring.Util
15 | record Term (a : Type) (as : List a) where
22 | eterm : Semiring a => {as : List a} -> Term a as -> a
23 | eterm (T f p) = f * eprod p
28 | data Sum : (a : Type) -> (as : List a) -> Type where
29 | Nil : {0 as : List a} -> Sum a as
30 | (::) : {0 as : List a} -> Term a as -> Sum a as -> Sum a as
34 | esum : Semiring a => {as : List a} -> Sum a as -> a
36 | esum (x :: xs) = eterm x + esum xs
48 | add : SolvableSemiring a => Sum a as -> Sum a as -> Sum a as
51 | add (T m x :: xs) (T n y :: ys) = case compProd x y of
52 | LT => T m x :: add xs (T n y :: ys)
53 | GT => T n y :: add (T m x :: xs) ys
54 | EQ => T (m + n) y :: add xs ys
59 | normSum : SolvableSemiring a => Sum a as -> Sum a as
61 | normSum (T f p :: y) = case isZero f of
62 | Just refl => normSum y
63 | Nothing => T f p :: normSum y
67 | mult1 : SolvableSemiring a => Term a as -> Sum a as -> Sum a as
68 | mult1 (T f p) (T g q :: xs) = T (f * g) (mult p q) :: mult1 (T f p) xs
73 | mult : SolvableSemiring a => Sum a as -> Sum a as -> Sum a as
75 | mult (x :: xs) ys = add (mult1 x ys) (mult xs ys)
79 | norm : SolvableSemiring a => {as : List a} -> Expr a as -> Sum a as
80 | norm (Lit n) = [T n one]
81 | norm (Var x y) = [T 1 $
fromVar y]
82 | norm (Plus x y) = add (norm x) (norm y)
83 | norm (Mult x y) = mult (norm x) (norm y)
87 | normalize : SolvableSemiring a => {as : List a} -> Expr a as -> Sum a as
88 | normalize e = normSum (norm e)
97 | {auto _ : SolvableSemiring a}
99 | -> esum x + esum y === esum (add x y)
100 | padd [] xs = plusZeroLeftNeutral
101 | padd (x :: xs) [] = plusZeroRightNeutral
102 | padd (T m x :: xs) (T n y :: ys) with (compProd x y) proof eq
104 | |~ (m * eprod x + esum xs) + (n * eprod y + esum ys)
105 | ~~ m * eprod x + (esum xs + (n * eprod y + esum ys))
106 | ..< plusAssociative
107 | ~~ m * eprod x + esum (add xs (T n y :: ys))
108 | ... cong (m * eprod x +) (padd xs (T n y :: ys))
111 | |~ (m * eprod x + esum xs) + (n * eprod y + esum ys)
112 | ~~ n * eprod y + ((m * eprod x + esum xs) + esum ys)
114 | ~~ n * eprod y + esum (add (T m x :: xs) ys)
115 | ... cong (n * eprod y +) (assert_total $
padd (T m x :: xs) ys)
117 | _ | EQ = case pcompProd x y eq of
119 | |~ (m * eprod x + esum xs) + (n * eprod x + esum ys)
120 | ~~ (m * eprod x + n * eprod x) + (esum xs + esum ys)
122 | ~~ (m + n) * eprod x + (esum xs + esum ys)
123 | ..< cong (+ (esum xs + esum ys)) rightDistributive
124 | ~~ (m + n) * eprod x + esum (add xs ys)
125 | ... cong ((m + n) * eprod x +) (padd xs ys)
129 | {auto _ : SolvableSemiring a}
136 | ~~ 0 + y ..< plusZeroLeftNeutral
137 | ~~ 0 * z + y ..< cong (+ y) multZeroLeftAbsorbs
141 | {auto _ : SolvableSemiring a}
145 | -> esum (mult1 (T m p) s) === (m * eprod p) * esum s
146 | pmult1 m p [] = sym multZeroRightAbsorbs
147 | pmult1 m p (T n q :: xs) = Calc $
148 | |~ (m * n) * (eprod (mult p q)) + esum (mult1 (T m p) xs)
149 | ~~ (m * n) * (eprod p * eprod q) + esum (mult1 (T m p) xs)
150 | ... cong (\x => (m*n) * x + esum (mult1 (T m p) xs)) (pmult p q)
151 | ~~ (m * eprod p) * (n * eprod q) + esum (mult1 (T m p) xs)
152 | ..< cong (+ esum (mult1 (T m p) xs)) m1324
153 | ~~ (m * eprod p) * (n * eprod q) + (m * eprod p) * esum xs
154 | ... cong ((m * eprod p) * (n * eprod q) +) (pmult1 m p xs)
155 | ~~ (m * eprod p) * (n * eprod q + esum xs)
156 | ..< leftDistributive
160 | {auto _ : SolvableSemiring a}
161 | -> (x,y : Sum a as)
162 | -> esum x * esum y === esum (mult x y)
163 | pmult [] y = multZeroLeftAbsorbs
164 | pmult (T n x :: xs) y = Calc $
165 | |~ (n * eprod x + esum xs) * esum y
166 | ~~ (n * eprod x) * esum y + esum xs * esum y
167 | ... rightDistributive
168 | ~~ (n * eprod x) * esum y + esum (mult xs y)
169 | ... cong ((n * eprod x) * esum y +) (pmult xs y)
170 | ~~ esum (mult1 (T n x) y) + esum (mult xs y)
171 | ..< cong (+ esum (mult xs y)) (pmult1 n x y)
172 | ~~ esum (add (mult1 (T n x) y) (mult xs y))
173 | ... padd (mult1 (T n x) y) (mult xs y)
178 | {auto _ : SolvableSemiring a}
180 | -> esum (normSum s) === esum s
182 | pnormSum (T f p :: y) with (isZero f)
183 | _ | Nothing = Calc $
184 | |~ f * eprod p + esum (normSum y)
185 | ~~ f * eprod p + esum y ... cong ((f * eprod p) +) (pnormSum y)
187 | _ | Just refl = Calc $
188 | |~ esum (normSum y)
189 | ~~ esum y ... pnormSum y
190 | ~~ 0 + esum y ..< plusZeroLeftNeutral
191 | ~~ 0 * eprod p + esum y ..< cong (+ esum y) multZeroLeftAbsorbs
192 | ~~ f * eprod p + esum y ..< cong (\x => x * eprod p + esum y) refl
197 | {auto _ : SolvableSemiring a}
199 | -> eval e === esum (norm e)
200 | pnorm (Lit n) = Calc $
202 | ~~ n * 1 ..< multOneRightNeutral
203 | ~~ n * eprod (one {as}) ..< cong (n *) (pone as)
204 | ~~ n * eprod (one {as}) + 0 ..< plusZeroRightNeutral
206 | pnorm (Var x y) = Calc $
208 | ~~ eprod (fromVar y) ..< pvar as y
209 | ~~ 1 * eprod (fromVar y) ..< multOneLeftNeutral
210 | ~~ 1 * eprod (fromVar y) + 0 ..< plusZeroRightNeutral
212 | pnorm (Plus x y) = Calc $
214 | ~~ esum (norm x) + eval y
215 | ... cong (+ eval y) (pnorm x)
216 | ~~ esum (norm x) + esum (norm y)
217 | ... cong (esum (norm x) +) (pnorm y)
218 | ~~ esum (add (norm x) (norm y))
221 | pnorm (Mult x y) = Calc $
223 | ~~ esum (norm x) * eval y
224 | ... cong (* eval y) (pnorm x)
225 | ~~ esum (norm x) * esum (norm y)
226 | ... cong (esum (norm x) *) (pnorm y)
227 | ~~ esum (mult (norm x) (norm y))
233 | {auto _ : SolvableSemiring a}
235 | -> eval e === esum (normalize e)
236 | pnormalize e = Calc $
238 | ~~ esum (norm e) ... pnorm e
239 | ~~ esum (normSum (norm e)) ..< pnormSum (norm e)
263 | {auto _ : SolvableSemiring a}
265 | -> (e1,e2 : Expr a as)
266 | -> {auto prf : normalize e1 === normalize e2}
267 | -> eval e1 === eval e2
268 | solve _ e1 e2 = Calc $
270 | ~~ esum (normalize e1) ...(pnormalize e1)
271 | ~~ esum (normalize e2) ...(cong esum prf)
272 | ~~ eval e2 ..<(pnormalize e2)