egison-4.1.0: lib/math/expression.egi
--
--
-- Mathematics Expressions
--
--
infixr pattern 6 +
infixr pattern 7 *
infix pattern 7 /
infix pattern 8 ^
def mathExpr :=
matcher
| #$val as () with
| $tgt -> if val = tgt then [()] else []
| $ as (mathExpr') with
| $tgt -> [fromMathExpr tgt]
def mathExpr' :=
matcher
| $ / $ 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 (multiset mathExpr) with
| Div (Plus $ts) (Plus [Term 1 []]) ->
map (\t -> toMathExpr' (Div (Plus [t]) (Plus [Term 1 []]))) ts
| _ -> []
| $ + $ as (mathExpr, mathExpr) with
| Div (Plus $ts) (Plus [Term 1 []]) ->
matchAll (map toMathExpr' 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, map (\(x, n) -> (toMathExpr' x, n)) xs)]
| _ -> []
| mult $ $ as (integer, multExpr) with
| Div (Plus [Term $n $xs]) (Plus [Term 1 []]) ->
[(n, product' (map (\(x, n) -> toMathExpr' x ^' n) xs))]
| _ -> []
| $ * $ as (integer, multExpr) with
| Div (Plus [Term $n $xs]) (Plus [Term 1 []]) ->
[(n, product' (map (\(x, n) -> toMathExpr' x ^' n) 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]
def indexExpr :=
algebraicDataMatcher
| sub mathExpr
| sup mathExpr
| user mathExpr
def polyExpr := mathExpr
def termExpr := mathExpr
def symbolExpr := mathExpr
def multExpr :=
matcher
| [] as () with
| $tgt ->
match tgt as mathExpr with
| #0 -> [()]
| _ -> []
| $ ^ #$k * $ as (mathExpr, multExpr) with
| $tgt ->
matchAll tgt as mathExpr with
| term _ (ncons $x #k $xs) -> (x, product' (map (uncurry (^')) xs))
| $ ^ $ * $ as (mathExpr, integer, multExpr) with
| $tgt ->
matchAll tgt as mathExpr with
| term _ (ncons $x $n $xs) -> (x, n, product' (map (uncurry (^')) xs))
| $ ^ $ as (mathExpr, integer) with
| $tgt ->
match tgt as mathExpr with
| term _ (ncons $x $n []) -> [(x, n)]
| _ -> []
| $ * $ as (mathExpr, multExpr) with
| $tgt ->
matchAll tgt as mathExpr with
| term _ ($x :: $rs) -> (x, product' (map (uncurry (^')) rs))
| $ as mathExpr with
| $tgt -> [tgt]
def isSymbol %mexpr :=
match mexpr as mathExpr with
| symbol _ _ -> True
| _ -> False
def isApply %mexpr :=
match mexpr as mathExpr with
| apply _ _ -> True
| _ -> False
def isSimpleTerm mexpr := isSymbol mexpr || isApply mexpr
def isTerm %mexpr :=
match mexpr as mathExpr with
| term _ _ -> True
| #0 -> True
| _ -> False
def isPolynomial %mexpr :=
match mexpr as mathExpr with
| poly _ -> True
| #0 -> True
| _ -> False
def isMonomial %mexpr :=
match mexpr as mathExpr with
| poly [term _ _] / poly [term _ _] -> True
| #0 -> True
| _ -> False
--
-- Accessor
--
def fromMonomial $mexpr :=
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 $mexpr :=
match mexpr as mathExpr with
| $p1 / $p2 -> fn p1 /' fn p2
def fromPoly $mexpr :=
match mexpr as mathExpr with
| poly $ts1 / $q -> map (\t1 -> t1 /' q) ts1
def mapPoly $fn $mexpr :=
match mexpr as mathExpr with
| poly $ts1 / $q -> foldl (+') 0 (map (\t1 -> fn (t1 /' q)) ts1)
def mapTerms $fn $mexpr :=
match mexpr as mathExpr with
| poly $ts1 / poly $ts2 ->
foldl (+') 0 (map fn ts1) /' foldl (+') 0 (map fn ts2)
def mapSymbols $fn $mexpr :=
mapTerms
(\match as termExpr with
| term $a $xs ->
a *' foldl
(*')
1
(map
(\(x, n) -> match x as symbolExpr with
| symbol _ _ -> fn x ^' n
| apply $g $args ->
let args' := map (mapSymbols fn) args
in if args = args'
then x ^' n
else fn (capply g args') ^' n)
xs))
mexpr
def scanAllTerms $mexpr $f :=
match mexpr as mathExpr with
| poly $ts1 / poly $ts2 -> any f (ts1 ++ ts2)
def containSymbol $x $mexpr :=
scanAllTerms mexpr
(\match as termExpr with
| term _ $xs ->
any
(\(y, _) -> match y as symbolExpr with
| #x -> True
| apply _ $args -> any (containSymbol x) args
| _ -> False)
xs)
def containFunction $f $mexpr :=
scanAllTerms mexpr
(\match as termExpr with
| term _ $xs ->
any
(\(y, _) -> match y as symbolExpr with
| apply #f _ -> True
| apply $g $args -> any (containFunction f) args
| _ -> False)
xs)
--
-- Substitute
--
def substitute %ls $mexpr :=
match ls as list (symbolExpr, mathExpr) with
| [] -> mathNormalize mexpr
| ($x, $a) :: $rs -> substitute rs (substitute' x a mexpr)
def substitute' $x %a $mexpr := mapSymbols (rewriteSymbol x a) mexpr
def rewriteSymbol $x $a $sexpr :=
match sexpr as symbolExpr with
| #x -> a
| _ -> sexpr
def V.substitute %xs %ys $mexpr :=
substitute (zip (tensorToList xs) (tensorToList ys)) mexpr
def 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 (\(x, n) -> expandAll x ^ expandAll n) ps)
-- polynomial
| poly $ts -> sum (map expandAll ts)
-- quotient
| $p1 / $p2 -> expandAll p1 / expandAll p2
def 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 (\(x, n) -> expandAll' x ^' expandAll' n) ps)
-- polynomial
| poly $ts -> sum' (map expandAll' ts)
-- quotient
| $p1 / $p2 -> expandAll' p1 / expandAll' p2
--
-- Coefficient
--
def coefficients $f $x :=
let m := maximum
(0 :: (matchAll f as mathExpr with
| poly (term $a (ncons #x $k $ts) :: _) / _ -> k))
in map (coefficient f x) (between 0 m)
def coefficient $f $x $m :=
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 $x $m :=
sum
(matchAll f as mathExpr with
| poly (term $a (ncons #x #m (!(#x :: _) & $ts)) :: _) / _ ->
foldl (*') a (map (uncurry (^')) ts)) / denominator f
def coefficient2 $f $x $y :=
sum
(matchAll f as mathExpr with
| poly (term $a (#x :: #y :: $ts) :: _) / _ ->
foldl (*') a (map (uncurry (^')) ts)) / denominator f