-- -- -- Mathematics Expressions -- -- mathExpr := matcher | #$val as () with | $tgt -> if val = tgt then [()] else [] | $ as (mathExpr') with | $tgt -> [fromMathExpr tgt] mathExpr' := matcher | div $ $ as (mathExpr, mathExpr) with | Div $p1 $p2 -> [(toMathExpr' p1, toMathExpr' p2)] | _ -> [] | poly $ as (multiset mathExpr) with | Div (Plus $ts) (Plus [Term 1 []]) -> [map toMathExpr' ts] | _ -> [] | plus $ as (plusExpr) with | Div (Plus $ts) (Plus [Term 1 []]) -> [toMathExpr' (Div (Plus ts) (Plus [Term 1 []]))] | _ -> [] | term $ $ as (integer, assocMultiset mathExpr) with | Div (Plus [Term $n $xs]) (Plus [Term 1 []]) -> [(n, map 2#(toMathExpr' %1, %2) xs)] | _ -> [] | mult $ $ as (integer, multExpr) with | Div (Plus [Term $n $xs]) (Plus [Term 1 []]) -> [(n, product' (map 2#(toMathExpr' %1 ^' %2) xs))] | _ -> [] | symbol $ $ as (eq, list indexExpr) with | Div (Plus [Term 1 [(Symbol $v $js, 1)]]) (Plus [Term 1 []]) -> [(v, js)] | _ -> [] | apply $ $ as (eq, list mathExpr) with | Div (Plus [Term 1 [(Apply $v $mexprs, 1)]]) (Plus [Term 1 []]) -> [(v, map toMathExpr' mexprs)] | _ -> [] | quote $ as (mathExpr) with | Div (Plus [Term 1 [(Quote $mexpr, 1)]]) (Plus [Term 1 []]) -> [toMathExpr' mexpr] | _ -> [] | func $ $ $ $ as (mathExpr, list mathExpr, list mathExpr, list indexExpr ) with | Div (Plus [Term 1 [(Function $name $argnames $args $js, 1)]]) (Plus [Term 1 []]) -> [(name, argnames, args, js)] | _ -> [] | $ as (something) with | $tgt -> [toMathExpr' tgt] indexExpr := algebraicDataMatcher | sub mathExpr | sup mathExpr | user mathExpr polyExpr := mathExpr termExpr := mathExpr symbolExpr := mathExpr plusExpr := matcher | [] as () with | $tgt -> if tgt = 0 then [()] else [] | $ :: $ as (mathExpr, plusExpr) with | $tgt -> matchAll tgt as mathExpr with | poly ($t :: $ts) -> (t, sum' ts) | $ as (mathExpr) with | $tgt -> [tgt] multExpr := matcher | [] as () with | $tgt -> match tgt as mathExpr with | #0 -> [()] | _ -> [] | $ :: $ as (mathExpr, multExpr) with | $tgt -> match tgt as mathExpr with | term _ $xs -> matchAll xs as assocMultiset mathExpr with | $x :: $rs -> (x, product' (map (^') rs)) | _ -> [] | ncons $ #$k $ as (mathExpr, multExpr) with | $tgt -> match tgt as mathExpr with | term _ $xs -> matchAll xs as list (mathExpr, integer) with | $hs ++ ($x, ?(>= k) & $n) :: $ts -> (x, product' (map (^') (hs ++ (x, n - k) :: ts))) | _ -> [] | ncons $ $ $ as (mathExpr, integer, multExpr) with | $tgt -> match tgt as mathExpr with | term _ $xs -> matchAll xs as list (mathExpr, integer) with | $hs ++ ($x, $n) :: $ts -> (x, n, product' (map (^') (hs ++ ts))) | _ -> [] | $ as (mathExpr) with | $tgt -> [tgt] isSymbol %mexpr := match mexpr as mathExpr with | symbol _ _ -> True | _ -> False isApply %mexpr := match mexpr as mathExpr with | apply _ _ -> True | _ -> False isSimpleTerm := 1#(isSymbol %1 || isApply %1) isTerm %mexpr := match mexpr as mathExpr with | term _ _ -> True | #0 -> True | _ -> False isPolynomial %mexpr := match mexpr as mathExpr with | poly _ -> True | #0 -> True | _ -> False isMonomial %mexpr := match mexpr as mathExpr with | poly [term _ _] / poly [term _ _] -> True | #0 -> True | _ -> False -- -- Accessor -- symbolIndices $mexpr := match mexpr as mathExpr with | symbol _ $js -> js | _ -> undefined fromMonomial $mexpr := match mexpr as mathExpr with | (term $a $xs) / (term $b $ys) -> (a / b, foldl (*') 1 (map (^') xs) / foldl (*') 1 (map (^') ys)) -- -- Map -- mapPolys $fn $mexpr := match mexpr as mathExpr with | $p1 / $p2 -> fn p1 /' fn p2 fromPoly $mexpr := match mexpr as mathExpr with | poly $ts1 / $q -> map (\t1 -> t1 /' q) ts1 mapPoly $fn $mexpr := match mexpr as mathExpr with | poly $ts1 / $q -> foldl (+') 0 (map (\t1 -> fn (t1 /' q)) ts1) mapTerms $fn $mexpr := match mexpr as mathExpr with | poly $ts1 / poly $ts2 -> foldl (+') 0 (map fn ts1) /' foldl (+') 0 (map fn ts2) mapSymbols $fn $mexpr := mapTerms (\term -> match term as termExpr with | term $a $xs -> a *' foldl (*') 1 (map 2#(match %1 as symbolExpr with | symbol _ _ -> fn %1 ^' %2 | apply $g $args -> let args' := map 1#(mapSymbols fn %1) args in if args = args' then %1 ^' %2 else fn (capply g args') ^' %2) xs)) mexpr containSymbol $x $mexpr := any id (match mexpr as mathExpr with | poly $ts1 / poly $ts2 -> map (\term -> match term as termExpr with | term _ $xs -> any id (map 2#(match %1 as symbolExpr with | #x -> True | apply _ $args -> any id (map 1#(containSymbol x %1) args) | _ -> False) xs)) (ts1 ++ ts2)) containFunction $f $mexpr := any id (match mexpr as mathExpr with | poly $ts1 / poly $ts2 -> map (\term -> match term as termExpr with | term _ $xs -> any id (map 2#(match %1 as symbolExpr with | apply $g $args -> if f = g then True else any id (map 1#(containFunction f %1) args) | _ -> False) xs)) (ts1 ++ ts2)) containFunctionWithOrder $f $n $mexpr := any id (match mexpr as mathExpr with | poly $ts1 / poly $ts2 -> map (\term -> match term as termExpr with | term _ $xs -> any id (map 2#(match %1 as symbolExpr with | apply $g $args -> if f = g && %2 >= n then True else any id (map 1#(containFunctionWithOrder f n %1) args) | _ -> False) xs)) (ts1 ++ ts2)) containFunctionWithIndex $mexpr := any id (match mexpr as mathExpr with | poly $ts1 / poly $ts2 -> map (\term -> match term as termExpr with | term _ $xs -> any id (map 2#(match %1 as symbolExpr with | apply (?isScalar & $f) $args -> match f as mathExpr with | symbol _ ![] -> True | _ -> any id (map 1#(containFunctionWithIndex %1) args) | apply _ $args -> any id (map 1#(containFunctionWithIndex %1) args) | _ -> False) xs)) (ts1 ++ ts2)) findSymbolsFromPoly $poly := matchAll poly as mathExpr with | poly (term _ ((symbol _ _ & $s) :: _) :: _) -> s -- -- Substitute -- substitute %ls $mexpr := match ls as list (symbolExpr, mathExpr) with | [] -> mexpr | ($x, $a) :: $rs -> substitute rs (substitute' x a mexpr) substitute' $x %a $mexpr := mapSymbols 1#(rewriteSymbol x a %1) mexpr rewriteSymbol $x $a $sexpr := match sexpr as symbolExpr with | #x -> a | _ -> sexpr V.substitute %xs %ys $mexpr := substitute (zip (tensorToList xs) (tensorToList ys)) mexpr expandAll $mexpr := match mexpr as mathExpr with | ?isSymbol -> mexpr -- function application | apply $g $args -> capply g (map expandAll args) -- quote | quote $g -> g -- term (multiplication) | term $a $ps -> a * product (map 2#(expandAll %1 ^ expandAll %2) ps) -- polynomial | poly $ts -> sum (map expandAll ts) -- quotient | $p1 / $p2 -> let p1' := expandAll p1 p2' := expandAll p2 in p1' / p2' expandAll' $mexpr := match mexpr as mathExpr with | ?isSymbol -> mexpr -- function application | apply $g $args -> capply g (map expandAll' args) -- quote | quote $g -> g -- term (multiplication) | term $a $ps -> a *' product' (map 2#(expandAll' %1 ^' expandAll' %2) ps) -- polynomial | poly $ts -> sum' (map expandAll' ts) -- quotient | $p1 / $p2 -> let p1' := expandAll' p1 p2' := expandAll' p2 in p1' /' p2' -- -- Coefficient -- coefficients $f $x := let m := maximum (0 :: (matchAll f as mathExpr with | poly (term $a (ncons #x $k $ts) :: _) / _ -> k)) in map 1#(coefficient f x %1) (between 0 m) coefficient $f $x $m := if m = 0 then sum (matchAll f as mathExpr with | poly (term $a (!(#x :: _) & $ts) :: _) / _ -> foldl (*') a (map (^') ts)) / denominator f else coefficient' f x m coefficient' $f $x $m := sum (matchAll f as mathExpr with | poly (term $a (ncons #x $k $ts) :: _) / _ -> if m = k then foldl (*') a (map (^') ts) else 0) / denominator f coefficient2 $f $x $y := sum (matchAll f as mathExpr with | poly (term $a (#x :: #y :: $ts) :: _) / _ -> foldl (*') a (map (^') ts)) / denominator f