0 | module Algebra.Solver.Ring
2 | import public Data.List.Elem
3 | import public Algebra.Group
4 | import public Algebra.Ring
5 | import public Algebra.Solver.Ops
6 | import public Algebra.Solver.Product
7 | import public Algebra.Solver.Sum
8 | import Algebra.Solver.Semiring as SR
9 | import Syntax.PreorderReasoning
16 | data Expr : (a : Type) -> (as : List a) -> Type where
19 | Lit : (v : a) -> Expr a as
24 | Var : (x : a) -> Elem x as -> Expr a as
27 | (+) : (x,y : Expr a as) -> Expr a as
30 | (*) : (x,y : Expr a as) -> Expr a as
32 | (-) : Expr a as -> Expr a as -> Expr a as
39 | fromInteger : Num a => Integer -> Expr a as
40 | fromInteger = Lit . fromInteger
45 | var : {0 as : List a} -> (x : a) -> Elem x as => Expr a as
46 | var x = Var x %search
54 | -> {auto _ : Elem x as}
55 | -> {auto _ : Elem y as}
57 | (.+.) x y =var x + var y
66 | -> {auto _ : Elem y as}
68 | (+.) x y = x + var y
77 | -> {auto _ : Elem x as}
79 | (.+) x y = var x + y
87 | -> {auto _ : Elem x as}
88 | -> {auto _ : Elem y as}
90 | (.-.) x y =var x - var y
99 | -> {auto _ : Elem y as}
101 | (-.) x y = x - var y
110 | -> {auto _ : Elem x as}
112 | (.-) x y = var x - y
120 | -> {auto _ : Elem x as}
121 | -> {auto _ : Elem y as}
123 | (.*.) x y = var x * var y
132 | -> {auto _ : Elem y as}
134 | (*.) x y = x * var y
143 | -> {auto _ : Elem x as}
145 | (.*) x y = var x * y
152 | parameters {0 a : Type}
155 | {p,m,sub : a -> a -> a}
156 | (0 r : Ring a z o p m sub)
157 | (isZ : (v : a) -> Maybe (v === z))
159 | public export %inline
163 | public export %inline
167 | public export %inline
175 | eval : Expr a as -> a
178 | eval (x + y) = eval x + eval y
179 | eval (x * y) = eval x * eval y
180 | eval (x - y) = eval x - eval y
187 | negate : Sum a as -> Sum a as
189 | negate (T f x :: xs) = T (z - f) x :: negate xs
193 | norm : Expr a as -> Sum a as
194 | norm (Lit n) = [T n one]
195 | norm (Var x y) = [T o $
fromVar y]
196 | norm (x + y) = add r.rig isZ (norm x) (norm y)
197 | norm (x * y) = mult r.rig isZ (norm x) (norm y)
198 | norm (x - y) = add r.rig isZ (norm x) (negate $
norm y)
202 | normalize : Expr a as -> Sum a as
203 | normalize e = normSum r.rig isZ (norm e)
205 | 0 pneg : (s : Sum a as) -> esum r.rig isZ (negate s) === z - esum r.rig isZ s
206 | pneg [] = sym r.minusSelf
207 | pneg (T f x :: xs) = Calc $
208 | |~ (z - f) * eprod m o x + esum (r .rig) isZ (negate xs)
209 | ~~ (z - f) * eprod m o x + (z - esum (r .rig) isZ xs)
210 | ... cong ((z - f) * eprod m o x +) (pneg xs)
211 | ~~ (z - f * eprod m o x) + (z - esum (r .rig) isZ xs)
212 | ... cong (+ (z - esum (r .rig) isZ xs)) r.multNegLeft
213 | ~~ z - (esum (r .rig) isZ xs + f * eprod m o x)
214 | ..< invertProduct r.plus.grp
215 | ~~ z - (f * eprod m o x + esum r.rig isZ xs)
216 | ... cong (z `sub`) r.plus.commutative
220 | 0 pnorm : (e : Expr a as) -> eval e === esum r.rig isZ (norm e)
221 | pnorm (Lit n) = Calc $
223 | ~~ n * o ..< r.mult.rightNeutral
224 | ~~ n * eprod m o (one {as}) ..< cong (n *) (pone r.mult as)
225 | ~~ n * eprod m o (one {as}) + z ..< r.plus.rightNeutral
227 | pnorm (Var x y) = Calc $
229 | ~~ eprod m o (fromVar y) ..< pvar r.mult as y
230 | ~~ o * eprod m o (fromVar y) ..< r.mult.leftNeutral
231 | ~~ o * eprod m o (fromVar y) + z ..< r.plus.rightNeutral
233 | pnorm (x + y) = Calc $
235 | ~~ esum r.rig isZ (norm x) + eval y
236 | ... cong (+ eval y) (pnorm x)
237 | ~~ esum r.rig isZ (norm x) + esum r.rig isZ (norm y)
238 | ... cong (esum r.rig isZ (norm x) +) (pnorm y)
239 | ~~ esum r.rig isZ (add r.rig isZ (norm x) (norm y))
240 | ... padd r.rig isZ _ _
242 | pnorm (x * y) = Calc $
244 | ~~ esum r.rig isZ (norm x) * eval y
245 | ... cong (* eval y) (pnorm x)
246 | ~~ esum r.rig isZ (norm x) * esum r.rig isZ (norm y)
247 | ... cong (esum r.rig isZ (norm x) *) (pnorm y)
248 | ~~ esum r.rig isZ (mult r.rig isZ (norm x) (norm y))
249 | ... pmult r.rig isZ _ _
251 | pnorm (x - y) = Calc $
253 | ~~ esum r.rig isZ (norm x) - eval y
254 | ... cong (\v => v - eval y) (pnorm x)
255 | ~~ esum r.rig isZ (norm x) - esum r.rig isZ (norm y)
256 | ... cong (esum r.rig isZ (norm x) -) (pnorm y)
257 | ~~ (esum r.rig isZ (norm x) + z) - esum r.rig isZ (norm y)
258 | ..< cong (\v => v - esum r.rig isZ (norm y)) r.plus.rightNeutral
259 | ~~ esum r.rig isZ (norm x) + (z - esum r.rig isZ (norm y))
260 | ..< r.minusAssociative
261 | ~~ esum r.rig isZ (norm x) + (esum r.rig isZ (negate $
norm y))
262 | ..< cong (esum r.rig isZ (norm x) +) (pneg $
norm y)
263 | ~~ esum r.rig isZ (add r.rig isZ (norm x) (negate (norm y)))
264 | ... padd r.rig isZ _ _
268 | 0 pnormalize : (e : Expr a as) -> eval e === esum r.rig isZ (normalize e)
269 | pnormalize e = Calc $
271 | ~~ esum r.rig isZ (norm e) ... pnorm e
272 | ~~ esum r.rig isZ (normSum r.rig isZ (norm e)) ..< pnormSum r.rig isZ (norm e)
296 | (e1,e2 : Expr a as)
297 | -> {auto prf : normalize e1 === normalize e2}
298 | -> eval e1 === eval e2
299 | solve e1 e2 @{prf} = Calc $
301 | ~~ esum r.rig isZ (normalize e1) ...(pnormalize e1)
302 | ~~ esum r.rig isZ (normalize e2) ...(cong (esum r.rig isZ) prf)
303 | ~~ eval e2 ..<(pnormalize e2)