-- -- -- Mathematics Expressions -- -- inductive pattern MathExpr := | div MathExpr MathExpr | (/) MathExpr MathExpr | plus [MathExpr] | poly [MathExpr] | term Integer [(MathExpr, Integer)] | mult Integer MathExpr | (+) MathExpr MathExpr | (*) MathExpr MathExpr | (^) MathExpr Integer | symbol String [IndexExpr] | apply1 (MathExpr -> MathExpr) MathExpr | apply2 (MathExpr -> MathExpr -> MathExpr) MathExpr MathExpr | apply3 (MathExpr -> MathExpr -> MathExpr -> MathExpr) MathExpr MathExpr MathExpr | apply4 (MathExpr -> MathExpr -> MathExpr -> MathExpr -> MathExpr) MathExpr MathExpr MathExpr MathExpr | quote MathExpr | func MathExpr [MathExpr] inductive pattern IndexExpr := | sub MathExpr | sup MathExpr | user MathExpr def indexExpr : Matcher IndexExpr := matcher | sub $ as (mathExpr) with | Sub $e -> [e] | _ -> [] | sup $ as (mathExpr) with | Sup $e -> [e] | _ -> [] | user $ as (mathExpr) with | User $e -> [e] | _ -> [] | #$val as () with | $tgt -> if val = tgt then [()] else [] | $ as something with | $tgt -> [tgt] def mathExpr : Matcher MathExpr := matcher | div $ $ as (mathExpr, mathExpr) with | Div $p1 $p2 -> [(p1, p2)] | _ -> [] | $ / $ as (mathExpr, mathExpr) with | Div $p1 $p2 -> [(p1, p2)] | _ -> [] | poly $ as (multiset mathExpr) with | Div (Plus $ts) (Plus [Term 1 []]) -> [ts] | _ -> [] | plus $ as (multiset mathExpr) with | Div (Plus $ts) (Plus [Term 1 []]) -> [ts] | _ -> [] | $ + $ as (mathExpr, mathExpr) with | Div (Plus $ts) (Plus [Term 1 []]) -> matchAll ts as multiset something with | $t :: $tss -> (t, sum' tss) | _ -> [] | term $ $ as (integer, assocMultiset mathExpr) with | Div (Plus [Term $n $xs]) (Plus [Term 1 []]) -> [(n, xs)] | _ -> [] | mult $ $ as (integer, multExpr) with | Div (Plus [Term $n $xs]) (Plus [Term 1 []]) -> [(n, product' (map (\(x, n) -> x ^' n) xs))] | _ -> [] | $ * $ as (integer, multExpr) with | Div (Plus [Term $n $xs]) (Plus [Term 1 []]) -> [(n, product' (map (\(x, n) -> x ^' n) xs))] | _ -> [] | symbol $ $ as (something, list indexExpr) with | Div (Plus [Term 1 [(Symbol $v $js, 1)]]) (Plus [Term 1 []]) -> [(v, js)] | _ -> [] | apply1 $ $ as (something, mathExpr) with | Div (Plus [Term 1 [(Apply1 $v $a1, 1)]]) (Plus [Term 1 []]) -> [(v, a1)] | _ -> [] | apply2 $ $ $ as (something, mathExpr, mathExpr) with | Div (Plus [Term 1 [(Apply2 $v $a1 $a2, 1)]]) (Plus [Term 1 []]) -> [(v, a1, a2)] | _ -> [] | apply3 $ $ $ $ as (something, mathExpr, mathExpr, mathExpr) with | Div (Plus [Term 1 [(Apply3 $v $a1 $a2 $a3, 1)]]) (Plus [Term 1 []]) -> [(v, a1, a2, a3)] | _ -> [] | apply4 $ $ $ $ $ as (something, mathExpr, mathExpr, mathExpr, mathExpr) with | Div (Plus [Term 1 [(Apply4 $v $a1 $a2 $a3 $a4, 1)]]) (Plus [Term 1 []]) -> [(v, a1, a2, a3, a4)] | _ -> [] | quote $ as (mathExpr) with | Div (Plus [Term 1 [(Quote $mexpr, 1)]]) (Plus [Term 1 []]) -> [mexpr] | _ -> [] | func $ $ as (mathExpr, list mathExpr) with | Div (Plus [Term 1 [(Function $name $args, 1)]]) (Plus [Term 1 []]) -> [(name, args)] | _ -> [] | #$val as () with | $tgt -> if val = tgt then [()] else [] | $ as something with | $tgt -> [tgt] def multExpr : Matcher MathExpr := matcher | ($ ^ $) * $ as (mathExpr, integer, multExpr) with | $tgt -> matchAll tgt as mathExpr with | term _ (($x, $n) :: $rs) -> (x, n, product' (map (\(x, n) -> x ^' n) rs)) | $ ^ $ as (mathExpr, integer) with | $tgt -> match tgt as mathExpr with | term _ (($x, $n) :: []) -> [(x, n)] | _ -> [] | $ * $ as (mathExpr, multExpr) with | $tgt -> matchAll tgt as mathExpr with | term _ (($x, $n) :: $rs) -> (x ^' n, product' (map (\(x, n) -> x ^' n) rs)) | #$val as () with | $tgt -> if val = tgt then [()] else [] | $ as something with | $tgt -> [tgt] def termExpr : Matcher MathExpr := mathExpr def isSymbol (mexpr: MathExpr) : Bool := match mexpr as mathExpr with | symbol _ _ -> True | _ -> False def isApply (mexpr: MathExpr) : Bool := match mexpr as mathExpr with | apply1 _ _ -> True | apply2 _ _ _ -> True | apply3 _ _ _ _ -> True | apply4 _ _ _ _ _ -> True | _ -> False def isSimpleTerm (mexpr: MathExpr) : Bool := isSymbol mexpr || isApply mexpr def isTerm (mexpr: MathExpr) : Bool := match mexpr as mathExpr with | term _ _ -> True | #0 -> True | _ -> False def isPolynomial (mexpr: MathExpr) : Bool := match mexpr as mathExpr with | poly _ -> True | #0 -> True | _ -> False def isMonomial (mexpr: MathExpr) : Bool := match mexpr as mathExpr with | poly [term _ _] / poly [term _ _] -> True | #0 -> True | _ -> False -- -- Accessor -- def fromMonomial (mexpr: MathExpr) : (MathExpr, MathExpr) := match mexpr as mathExpr with | term $a $xs / term $b $ys -> (a / b, foldl (*') 1 (map (uncurry (^')) xs) / foldl (*') 1 (map (uncurry (^')) ys)) -- -- Map -- def mapPolys (fn: MathExpr -> MathExpr) (mexpr: MathExpr) : MathExpr := match mexpr as mathExpr with | $p1 / $p2 -> fn p1 /' fn p2 def fromPoly (mexpr: MathExpr) : [MathExpr] := match mexpr as mathExpr with | poly $ts1 / $q -> map (\t1 -> t1 /' q) ts1 def mapPoly (fn: MathExpr -> MathExpr) (mexpr: MathExpr) : MathExpr := match mexpr as mathExpr with | poly $ts1 / $q -> foldl (+') 0 (map (\t1 -> fn (t1 /' q)) ts1) def mapTerms (fn: MathExpr -> MathExpr) (mexpr: MathExpr) : MathExpr := match mexpr as mathExpr with | poly $ts1 / poly $ts2 -> foldl (+') 0 (map fn ts1) /' foldl (+') 0 (map fn ts2) def mapSymbols (fn: MathExpr -> MathExpr) (mexpr: MathExpr) : MathExpr := mapTerms (\match as mathExpr with | term $a $xs -> a *' foldl (*') 1 (map (\(x, n) -> match x as mathExpr with | symbol _ _ -> fn x ^' n | apply1 $g $a1 -> let a1' := mapSymbols fn a1 in if a1 = a1' then x ^' n else fn (g a1') ^' n | apply2 $g $a1 $a2 -> let a1' := mapSymbols fn a1 a2' := mapSymbols fn a2 in if a1 = a1' && a2 = a2' then x ^' n else fn (g a1' a2') ^' n | apply3 $g $a1 $a2 $a3 -> let a1' := mapSymbols fn a1 a2' := mapSymbols fn a2 a3' := mapSymbols fn a3 in if a1 = a1' && a2 = a2' && a3 = a3' then x ^' n else fn (g a1' a2' a3') ^' n | apply4 $g $a1 $a2 $a3 $a4 -> let a1' := mapSymbols fn a1 a2' := mapSymbols fn a2 a3' := mapSymbols fn a3 a4' := mapSymbols fn a4 in if a1 = a1' && a2 = a2' && a3 = a3' && a4 = a4' then x ^' n else fn (g a1' a2' a3' a4') ^' n | func _ $args -> let args' := map (mapSymbols fn) args in if args = args' then x ^' n else fn (updateFunctionArgs x args') ^' n) xs)) mexpr def scanAllTerms (mexpr: MathExpr) (f: MathExpr -> Bool) : Bool := match mexpr as mathExpr with | poly $ts1 / poly $ts2 -> any f (ts1 ++ ts2) | _ -> not ((debug2 "scanAllTerms" mexpr) = mexpr) -- TODO: if tensorMap is inserted correctly, we canremove this def containSymbol (x: MathExpr) (mexpr: MathExpr) : Bool := scanAllTerms mexpr (\t -> match t as mathExpr with | term _ $xs -> any (\(y, _) -> match y as mathExpr with | #x -> True | apply1 _ $a1 -> containSymbol x a1 | apply2 _ $a1 $a2 -> containSymbol x a1 || containSymbol x a2 | apply3 _ $a1 $a2 $a3 -> containSymbol x a1 || containSymbol x a2 || containSymbol x a3 | apply4 _ $a1 $a2 $a3 $a4 -> containSymbol x a1 || containSymbol x a2 || containSymbol x a3 || containSymbol x a4 | _ -> False) xs) def containFunction1 (f : MathExpr -> MathExpr) (mexpr: MathExpr) : Bool := scanAllTerms mexpr (\t -> match t as mathExpr with | term _ $xs -> any (\(y, _) -> match y as mathExpr with | apply1 #f _ -> True | apply1 _ $a1 -> containFunction1 f a1 | apply2 _ $a1 $a2 -> containFunction1 f a1 || containFunction1 f a2 | apply3 _ $a1 $a2 $a3 -> containFunction1 f a1 || containFunction1 f a2 || containFunction1 f a3 | apply4 _ $a1 $a2 $a3 $a4 -> containFunction1 f a1 || containFunction1 f a2 || containFunction1 f a3 || containFunction1 f a4 | _ -> False) xs) def containFunction2 (f : MathExpr -> MathExpr -> MathExpr) (mexpr: MathExpr) : Bool := scanAllTerms mexpr (\t -> match t as mathExpr with | term _ $xs -> any (\(y, _) -> match y as mathExpr with | apply2 #f _ _ -> True | apply1 _ $a1 -> containFunction2 f a1 | apply2 _ $a1 $a2 -> containFunction2 f a1 || containFunction2 f a2 | apply3 _ $a1 $a2 $a3 -> containFunction2 f a1 || containFunction2 f a2 || containFunction2 f a3 | apply4 _ $a1 $a2 $a3 $a4 -> containFunction2 f a1 || containFunction2 f a2 || containFunction2 f a3 || containFunction2 f a4 | _ -> False) xs) def containFunction3 (f : MathExpr -> MathExpr -> MathExpr -> MathExpr) (mexpr: MathExpr) : Bool := scanAllTerms mexpr (\t -> match t as mathExpr with | term _ $xs -> any (\(y, _) -> match y as mathExpr with | apply3 #f _ _ _ -> True | apply1 _ $a1 -> containFunction3 f a1 | apply2 _ $a1 $a2 -> containFunction3 f a1 || containFunction3 f a2 | apply3 _ $a1 $a2 $a3 -> containFunction3 f a1 || containFunction3 f a2 || containFunction3 f a3 | apply4 _ $a1 $a2 $a3 $a4 -> containFunction3 f a1 || containFunction3 f a2 || containFunction3 f a3 || containFunction3 f a4 | _ -> False) xs) def containFunction4 (f : MathExpr -> MathExpr -> MathExpr -> MathExpr -> MathExpr) (mexpr: MathExpr) : Bool := scanAllTerms mexpr (\t -> match t as mathExpr with | term _ $xs -> any (\(y, _) -> match y as mathExpr with | apply4 #f _ _ _ _ -> True | apply1 _ $a1 -> containFunction4 f a1 | apply2 _ $a1 $a2 -> containFunction4 f a1 || containFunction4 f a2 | apply3 _ $a1 $a2 $a3 -> containFunction4 f a1 || containFunction4 f a2 || containFunction4 f a3 | apply4 _ $a1 $a2 $a3 $a4 -> containFunction4 f a1 || containFunction4 f a2 || containFunction4 f a3 || containFunction4 f a4 | _ -> False) xs) -- -- Substitute -- def substitute (ls: [(MathExpr, MathExpr)]) (mexpr: MathExpr) : MathExpr := match ls as list (mathExpr, mathExpr) with | [] -> mathNormalize mexpr | ($x, $a) :: $rs -> substitute rs (substitute' x a mexpr) def substitute' (x: MathExpr) (a: MathExpr) (mexpr: MathExpr) : MathExpr := mapSymbols (rewriteSymbol x a) mexpr def rewriteSymbol (x: MathExpr) (a: MathExpr) (sexpr: MathExpr) : MathExpr := match sexpr as mathExpr with | #x -> a | _ -> sexpr def V.substitute (xs: Vector MathExpr) (ys: Vector MathExpr) (mexpr: MathExpr) : MathExpr := substitute (zip (tensorToList xs) (tensorToList ys)) mexpr def expandAll (mexpr: MathExpr) : MathExpr := match mexpr as mathExpr with | ?isInteger -> mexpr | ?isSymbol -> mexpr -- function application | apply1 $g $a1 -> `(g (expandAll a1)) | apply2 $g $a1 $a2 -> `(g (expandAll a1) (expandAll a2)) | apply3 $g $a1 $a2 $a3 -> `(g (expandAll a1) (expandAll a2) (expandAll a3)) | apply4 $g $a1 $a2 $a3 $a4 -> `(g (expandAll a1) (expandAll a2) (expandAll a3) (expandAll a4)) -- quote | quote $g -> g -- term (multiplication) | term $a $ps -> a * product (map (\(x, n) -> expandAll x ^ n) ps) -- polynomial | poly $ts -> sum (map expandAll ts) -- quotient | $p1 / $p2 -> expandAll p1 / expandAll p2 def expandAll' (mexpr: MathExpr) : MathExpr := match mexpr as mathExpr with | ?isInteger -> mexpr | ?isSymbol -> mexpr -- function application | apply1 $g $a1 -> `(g (expandAll' a1)) | apply2 $g $a1 $a2 -> `(g (expandAll' a1) (expandAll' a2)) | apply3 $g $a1 $a2 $a3 -> `(g (expandAll' a1) (expandAll' a2) (expandAll' a3)) | apply4 $g $a1 $a2 $a3 $a4 -> `(g (expandAll' a1) (expandAll' a2) (expandAll' a3) (expandAll' a4)) -- quote | quote $g -> g -- term (multiplication) | term $a $ps -> a *' product' (map (\(x, n) -> expandAll' x ^' n) ps) -- polynomial | poly $ts -> sum' (map expandAll' ts) -- quotient | $p1 / $p2 -> expandAll' p1 / expandAll' p2 -- -- Coefficient -- def coefficients (f: MathExpr) (x: MathExpr) : [MathExpr] := let m := maximum (0 :: (matchAll f as mathExpr with | poly (term $a ((#x, $k) :: $ts) :: _) / _ -> k)) in map (coefficient f x) (between 0 m) def coefficient (f: MathExpr) (x: MathExpr) (m: Integer) : MathExpr := if m = 0 then sum (matchAll f as mathExpr with | poly (term $a (!((#x, _) :: _) & $ts) :: _) / _ -> foldl (*') a (map (uncurry (^')) ts)) / denominator f else coefficient' f x m def coefficient' (f: MathExpr) (x: MathExpr) (m: Integer) : MathExpr := sum (matchAll f as mathExpr with | poly (term $a ((#x, #m) :: (!((#x, _) :: _) & $ts)) :: _) /_ -> foldl (*') a (map (uncurry (^')) ts)) /' denominator f def L./ (xs: [MathExpr]) (ys: [MathExpr]) : ([MathExpr], [MathExpr]) := if length xs < length ys then ([], xs) else match (ys, xs) as (list mathExpr, list mathExpr) with | ($y :: $yrs, $x :: $xrs) -> let (zs, rs) := L./ (map2 (-) (take (length yrs) xrs) (map (* (x / y)) yrs) ++ drop (length yrs) xrs) ys in (x / y :: zs, rs)