0 | module Algebra.Solver.Semiring
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 Syntax.PreorderReasoning
54 | data Expr : (a : Type) -> (as : List a) -> Type where
57 | Lit : (v : a) -> Expr a as
62 | Var : (x : a) -> Elem x as -> Expr a as
65 | (+) : (x,y : Expr a as) -> Expr a as
68 | (*) : (x,y : Expr a as) -> Expr a as
75 | fromInteger : Num a => Integer -> Expr a as
76 | fromInteger = Lit . fromInteger
81 | var : {0 as : List a} -> (x : a) -> Elem x as => Expr a as
82 | var x = Var x %search
84 | export infixl 8 .+.
, .+
, +.
86 | export infixl 9 .*.
, .*
, *.
94 | -> {auto _ : Elem x as}
95 | -> {auto _ : Elem y as}
97 | (.+.) x y =var x + var y
106 | -> {auto _ : Elem y as}
108 | (+.) x y = x + var y
117 | -> {auto _ : Elem x as}
119 | (.+) x y = var x + y
127 | -> {auto _ : Elem x as}
128 | -> {auto _ : Elem y as}
130 | (.*.) x y = var x * var y
139 | -> {auto _ : Elem y as}
141 | (*.) x y = x * var y
150 | -> {auto _ : Elem x as}
152 | (.*) x y = var x * y
159 | parameters {0 a : Type}
162 | {p,m : a -> a -> a}
163 | (0 r : Rig a z o p m)
164 | (isZ : (v : a) -> Maybe (v === z))
166 | public export %inline
170 | public export %inline
178 | eval : Expr a as -> a
181 | eval (x + y) = eval x + eval y
182 | eval (x * y) = eval x * eval y
190 | norm : Expr a as -> Sum a as
191 | norm (Lit n) = [T n one]
192 | norm (Var x y) = [T o $
fromVar y]
193 | norm (x + y) = add r isZ (norm x) (norm y)
194 | norm (x * y) = mult r isZ (norm x) (norm y)
198 | normalize : Expr a as -> Sum a as
199 | normalize e = normSum r isZ (norm e)
203 | 0 pnorm : (e : Expr a as) -> eval e === esum r isZ (norm e)
204 | pnorm (Lit n) = Calc $
206 | ~~ n * o ..< r.mult.rightNeutral
207 | ~~ n * eprod m o (one {as}) ..< cong (n *) (pone r.mult as)
208 | ~~ n * eprod m o (one {as}) + z ..< r.plus.rightNeutral
210 | pnorm (Var x y) = Calc $
212 | ~~ eprod m o (fromVar y) ..< pvar r.mult as y
213 | ~~ o * eprod m o (fromVar y) ..< r.mult.leftNeutral
214 | ~~ o * eprod m o (fromVar y) + z ..< r.plus.rightNeutral
216 | pnorm (x + y) = Calc $
218 | ~~ esum r isZ (norm x) + eval y
219 | ... cong (+ eval y) (pnorm x)
220 | ~~ esum r isZ (norm x) + esum r isZ (norm y)
221 | ... cong (esum r isZ (norm x) +) (pnorm y)
222 | ~~ esum r isZ (add r isZ (norm x) (norm y))
225 | pnorm (x * y) = Calc $
227 | ~~ esum r isZ (norm x) * eval y
228 | ... cong (* eval y) (pnorm x)
229 | ~~ esum r isZ (norm x) * esum r isZ (norm y)
230 | ... cong (esum r isZ (norm x) *) (pnorm y)
231 | ~~ esum r isZ (mult r isZ (norm x) (norm y))
232 | ... pmult r isZ _ _
236 | 0 pnormalize : (e : Expr a as) -> eval e === esum r isZ (normalize e)
237 | pnormalize e = Calc $
239 | ~~ esum r isZ (norm e) ... pnorm e
240 | ~~ esum r isZ (normSum r isZ (norm e)) ..< pnormSum r isZ (norm e)
264 | (e1,e2 : Expr a as)
265 | -> {auto prf : normalize e1 === normalize e2}
266 | -> eval e1 === eval e2
267 | solve e1 e2 @{prf} = Calc $
269 | ~~ esum r isZ (normalize e1) ...(pnormalize e1)
270 | ~~ esum r isZ (normalize e2) ...(cong (esum r isZ) prf)
271 | ~~ eval e2 ..<(pnormalize e2)
274 | NatIsZero : (n : Nat) -> Maybe (n === 0)
275 | NatIsZero 0 = Just Refl
276 | NatIsZero _ = Nothing
281 | -> (e1,e2 : Expr Nat as)
282 | -> {auto prf : normalize NatRig NatIsZero e1 === normalize NatRig NatIsZero e2}
283 | -> eval NatRig NatIsZero e1 === eval NatRig NatIsZero e2
284 | solveNat _ = solve NatRig NatIsZero
290 | 0 ex1 : (m,n : Nat) -> m + n === n + m
291 | ex1 m n = solveNat [m,n] (m .+. n) (n .+. m)
293 | 0 ex2 : (m,n : Nat) -> m + n + 3 === 1 + n + m + 2
294 | ex2 m n = solveNat [m,n] (m .+. n + 3) (1 +. n +. m + 2)
297 | 0 ex3 : (k,m,n : Nat) -> (12 + k) * (m + n) === n * 12 + 3 * m + (n + m) * k + m * 9
300 | ((12 +. k) * (m .+. n))
301 | (n .* 12 + 3 *. m + (n .+. m) *. k + (m .* 9))