(maxima.info)Functions and Variables for Rules and Patterns
34.2 Functions and Variables for Rules and Patterns
===================================================
-- Function: apply1 (<expr>, <rule_1>, ..., <rule_n>)
Repeatedly applies <rule_1> to <expr> until it fails, then
repeatedly applies the same rule to all subexpressions of <expr>,
left to right, until <rule_1> has failed on all subexpressions.
Call the result of transforming <expr> in this manner <expr_2>.
Then <rule_2> is applied in the same fashion starting at the top of
<expr_2>. When <rule_n> fails on the final subexpression, the
result is returned.
'maxapplydepth' is the depth of the deepest subexpressions
processed by 'apply1' and 'apply2'.
See also 'applyb1', 'apply2' and 'let'.
-- Function: apply2 (<expr>, <rule_1>, ..., <rule_n>)
If <rule_1> fails on a given subexpression, then <rule_2> is
repeatedly applied, etc. Only if all rules fail on a given
subexpression is the whole set of rules repeatedly applied to the
next subexpression. If one of the rules succeeds, then the same
subexpression is reprocessed, starting with the first rule.
'maxapplydepth' is the depth of the deepest subexpressions
processed by 'apply1' and 'apply2'.
See also 'apply1' and 'let'.
-- Function: applyb1 (<expr>, <rule_1>, ..., <rule_n>)
Repeatedly applies <rule_1> to the deepest subexpression of <expr>
until it fails, then repeatedly applies the same rule one level
higher (i.e., larger subexpressions), until <rule_1> has failed on
the top-level expression. Then <rule_2> is applied in the same
fashion to the result of <rule_1>. After <rule_n> has been applied
to the top-level expression, the result is returned.
'applyb1' is similar to 'apply1' but works from the bottom up
instead of from the top down.
'maxapplyheight' is the maximum height which 'applyb1' reaches
before giving up.
See also 'apply1', 'apply2' and 'let'.
-- Option variable: current_let_rule_package
Default value: 'default_let_rule_package'
'current_let_rule_package' is the name of the rule package that is
used by functions in the 'let' package ('letsimp', etc.) if no
other rule package is specified. This variable may be assigned the
name of any rule package defined via the 'let' command.
If a call such as 'letsimp (expr, rule_pkg_name)' is made, the rule
package 'rule_pkg_name' is used for that function call only, and
the value of 'current_let_rule_package' is not changed.
-- Option variable: default_let_rule_package
Default value: 'default_let_rule_package'
'default_let_rule_package' is the name of the rule package used
when one is not explicitly set by the user with 'let' or by
changing the value of 'current_let_rule_package'.
-- Function: defmatch
defmatch (<progname>, <pattern>, <x_1>, ..., <x_n>)
defmatch (<progname>, <pattern>)
Defines a function '<progname>(<expr>, <x_1>, ..., <x_n>)' which
tests <expr> to see if it matches <pattern>.
<pattern> is an expression containing the pattern arguments <x_1>,
..., <x_n> (if any) and some pattern variables (if any). The
pattern arguments are given explicitly as arguments to 'defmatch'
while the pattern variables are declared by the 'matchdeclare'
function. Any variable not declared as a pattern variable in
'matchdeclare' or as a pattern argument in 'defmatch' matches only
itself.
The first argument to the created function <progname> is an
expression to be matched against the pattern and the other
arguments are the actual arguments which correspond to the dummy
variables <x_1>, ..., <x_n> in the pattern.
If the match is successful, <progname> returns a list of equations
whose left sides are the pattern arguments and pattern variables,
and whose right sides are the subexpressions which the pattern
arguments and variables matched. The pattern variables, but not
the pattern arguments, are assigned the subexpressions they match.
If the match fails, <progname> returns 'false'.
A literal pattern (that is, a pattern which contains neither
pattern arguments nor pattern variables) returns 'true' if the
match succeeds.
See also 'matchdeclare', 'defrule', 'tellsimp' and 'tellsimpafter'.
Examples:
Define a function 'linearp(expr, x)' which tests 'expr' to see if
it is of the form 'a*x + b' such that 'a' and 'b' do not contain
'x' and 'a' is nonzero. This match function matches expressions
which are linear in any variable, because the pattern argument 'x'
is given to 'defmatch'.
(%i1) matchdeclare (a, lambda ([e], e#0 and freeof(x, e)), b,
freeof(x));
(%o1) done
(%i2) defmatch (linearp, a*x + b, x);
(%o2) linearp
(%i3) linearp (3*z + (y + 1)*z + y^2, z);
2
(%o3) [b = y , a = y + 4, x = z]
(%i4) a;
(%o4) y + 4
(%i5) b;
2
(%o5) y
(%i6) x;
(%o6) x
Define a function 'linearp(expr)' which tests 'expr' to see if it
is of the form 'a*x + b' such that 'a' and 'b' do not contain 'x'
and 'a' is nonzero. This match function only matches expressions
linear in 'x', not any other variable, because no pattern argument
is given to 'defmatch'.
(%i1) matchdeclare (a, lambda ([e], e#0 and freeof(x, e)), b,
freeof(x));
(%o1) done
(%i2) defmatch (linearp, a*x + b);
(%o2) linearp
(%i3) linearp (3*z + (y + 1)*z + y^2);
(%o3) false
(%i4) linearp (3*x + (y + 1)*x + y^2);
2
(%o4) [b = y , a = y + 4]
Define a function 'checklimits(expr)' which tests 'expr' to see if
it is a definite integral.
(%i1) matchdeclare ([a, f], true);
(%o1) done
(%i2) constinterval (l, h) := constantp (h - l);
(%o2) constinterval(l, h) := constantp(h - l)
(%i3) matchdeclare (b, constinterval (a));
(%o3) done
(%i4) matchdeclare (x, atom);
(%o4) done
(%i5) simp : false;
(%o5) false
(%i6) defmatch (checklimits, 'integrate (f, x, a, b));
(%o6) checklimits
(%i7) simp : true;
(%o7) true
(%i8) 'integrate (sin(t), t, %pi + x, 2*%pi + x);
x + 2 %pi
/
[
(%o8) I sin(t) dt
]
/
x + %pi
(%i9) checklimits (%);
(%o9) [b = x + 2 %pi, a = x + %pi, x = t, f = sin(t)]
-- Function: defrule (<rulename>, <pattern>, <replacement>)
Defines and names a replacement rule for the given pattern. If the
rule named <rulename> is applied to an expression (by 'apply1',
'applyb1', or 'apply2'), every subexpression matching the pattern
will be replaced by the replacement. All variables in the
replacement which have been assigned values by the pattern match
are assigned those values in the replacement which is then
simplified.
The rules themselves can be treated as functions which transform an
expression by one operation of the pattern match and replacement.
If the match fails, the rule function returns 'false'.
-- Function: disprule
disprule (<rulename_1>, ..., <rulename_2>)
disprule (all)
Display rules with the names <rulename_1>, ..., <rulename_n>, as
returned by 'defrule', 'tellsimp', or 'tellsimpafter', or a pattern
defined by 'defmatch'. Each rule is displayed with an intermediate
expression label ('%t').
'disprule (all)' displays all rules.
'disprule' quotes its arguments. 'disprule' returns the list of
intermediate expression labels corresponding to the displayed
rules.
See also 'letrules', which displays rules defined by 'let'.
Examples:
(%i1) tellsimpafter (foo (x, y), bar (x) + baz (y));
(%o1) [foorule1, false]
(%i2) tellsimpafter (x + y, special_add (x, y));
(%o2) [+rule1, simplus]
(%i3) defmatch (quux, mumble (x));
(%o3) quux
(%i4) disprule (foorule1, ?\+rule1, quux);
(%t4) foorule1 : foo(x, y) -> baz(y) + bar(x)
(%t5) +rule1 : y + x -> special_add(x, y)
(%t6) quux : mumble(x) -> []
(%o6) [%t4, %t5, %t6]
(%i7) ev(%);
(%o7) [foorule1 : foo(x, y) -> baz(y) + bar(x),
+rule1 : y + x -> special_add(x, y), quux : mumble(x) -> []]
-- Function: let
let (<prod>, <repl>, <predname>, <arg_1>, ..., <arg_n>)
let ([<prod>, <repl>, <predname>, <arg_1>, ..., <arg_n>],
<package_name>)
Defines a substitution rule for 'letsimp' such that <prod> is
replaced by <repl>. <prod> is a product of positive or negative
powers of the following terms:
* Atoms which 'letsimp' will search for literally unless
previous to calling 'letsimp' the 'matchdeclare' function is
used to associate a predicate with the atom. In this case
'letsimp' will match the atom to any term of a product
satisfying the predicate.
* Kernels such as 'sin(x)', 'n!', 'f(x,y)', etc. As with atoms
above 'letsimp' will look for a literal match unless
'matchdeclare' is used to associate a predicate with the
argument of the kernel.
A term to a positive power will only match a term having at least
that power. A term to a negative power on the other hand will only
match a term with a power at least as negative. In the case of
negative powers in <prod> the switch 'letrat' must be set to
'true'. See also 'letrat'.
If a predicate is included in the 'let' function followed by a list
of arguments, a tentative match (i.e. one that would be accepted
if the predicate were omitted) is accepted only if 'predname
(arg_1', ..., arg_n')' evaluates to 'true' where <arg_i'> is the
value matched to <arg_i>. The <arg_i> may be the name of any atom
or the argument of any kernel appearing in <prod>. <repl> may be
any rational expression. If any of the atoms or arguments from
<prod> appear in <repl> the appropriate substitutions are made.
The global flag 'letrat' controls the simplification of quotients
by 'letsimp'. When 'letrat' is 'false', 'letsimp' simplifies the
numerator and denominator of <expr> separately, and does not
simplify the quotient. Substitutions such as 'n!/n' goes to
'(n-1)!' then fail. When 'letrat' is 'true', then the numerator,
denominator, and the quotient are simplified in that order.
These substitution functions allow you to work with several rule
packages at once. Each rule package can contain any number of
'let' rules and is referenced by a user-defined name. The command
'let ([<prod>, <repl>, <predname>, <arg_1>, ..., <arg_n>],
<package_name>)' adds the rule <predname> to the rule package
<package_name>. The command 'letsimp (<expr>, <package_name>)'
applies the rules in <package_name>. 'letsimp (<expr>,
<package_name1>, <package_name2>, ...)' is equivalent to 'letsimp
(<expr>, <package_name1>)' followed by 'letsimp (%,
<package_name2>)', ...
'current_let_rule_package' is the name of the rule package that is
presently being used. This variable may be assigned the name of
any rule package defined via the 'let' command. Whenever any of
the functions comprising the 'let' package are called with no
package name, the package named by 'current_let_rule_package' is
used. If a call such as 'letsimp (<expr>, <rule_pkg_name>)' is
made, the rule package <rule_pkg_name> is used for that 'letsimp'
command only, and 'current_let_rule_package' is not changed. If
not otherwise specified, 'current_let_rule_package' defaults to
'default_let_rule_package'.
(%i1) matchdeclare ([a, a1, a2], true)$
(%i2) oneless (x, y) := is (x = y-1)$
(%i3) let (a1*a2!, a1!, oneless, a2, a1);
(%o3) a1 a2! --> a1! where oneless(a2, a1)
(%i4) letrat: true$
(%i5) let (a1!/a1, (a1-1)!);
a1!
(%o5) --- --> (a1 - 1)!
a1
(%i6) letsimp (n*m!*(n-1)!/m);
(%o6) (m - 1)! n!
(%i7) let (sin(a)^2, 1 - cos(a)^2);
2 2
(%o7) sin (a) --> 1 - cos (a)
(%i8) letsimp (sin(x)^4);
4 2
(%o8) cos (x) - 2 cos (x) + 1
-- Option variable: letrat
Default value: 'false'
When 'letrat' is 'false', 'letsimp' simplifies the numerator and
denominator of a ratio separately, and does not simplify the
quotient.
When 'letrat' is 'true', the numerator, denominator, and their
quotient are simplified in that order.
(%i1) matchdeclare (n, true)$
(%i2) let (n!/n, (n-1)!);
n!
(%o2) -- --> (n - 1)!
n
(%i3) letrat: false$
(%i4) letsimp (a!/a);
a!
(%o4) --
a
(%i5) letrat: true$
(%i6) letsimp (a!/a);
(%o6) (a - 1)!
-- Function: letrules
letrules ()
letrules (<package_name>)
Displays the rules in a rule package. 'letrules ()' displays the
rules in the current rule package. 'letrules (<package_name>)'
displays the rules in <package_name>.
The current rule package is named by 'current_let_rule_package'.
If not otherwise specified, 'current_let_rule_package' defaults to
'default_let_rule_package'.
See also 'disprule', which displays rules defined by 'tellsimp' and
'tellsimpafter'.
-- Function: letsimp
letsimp (<expr>)
letsimp (<expr>, <package_name>)
letsimp (<expr>, <package_name_1>, ..., <package_name_n>)
Repeatedly applies the substitution rules defined by 'let' until no
further change is made to <expr>.
'letsimp (<expr>)' uses the rules from 'current_let_rule_package'.
'letsimp (<expr>, <package_name>)' uses the rules from
<package_name> without changing 'current_let_rule_package'.
'letsimp (<expr>, <package_name_1>, ..., <package_name_n>)' is
equivalent to 'letsimp (<expr>, <package_name_1>)', followed by
'letsimp (%, <package_name_2>)', and so on.
See also 'let'. For other ways to do substitutions see also
'subst', 'psubst', 'at' and 'ratsubst'.
(%i1) e0:e(k)=-(9*y(k))/(5*z)-u(k-1)/(5*z)+(4*y(k))/(5*z^2)+(3*u(k-1))/(5*z^2)+y(k)-(2*u(k-1))/5;
9 y(k) u(k - 1) 4 y(k) 3 u(k - 1)
(%o1) e(k) = (- ------) - -------- + ------ + ---------- + y(k)
5 z 5 z 2 2
5 z 5 z
2 u(k - 1)
- ----------
5
(%i2) matchdeclare(h,any)$
(%i3) let(u(h)/z,u(h-1));
u(h)
(%o3) ---- --> u(h - 1)
z
(%i4) let(y(h)/z, y(h-1));
y(h)
(%o4) ---- --> y(h - 1)
z
(%i5) e1:letsimp(e0);
2 u(k - 1) 3 u(k - 3) 4 y(k - 2)
(%o5) e(k) = (- ----------) + y(k) + ---------- + ----------
5 5 5
u(k - 2) 9 y(k - 1)
+ (- --------) + (- ----------)
5 5
-- Option variable: let_rule_packages
Default value: '[default_let_rule_package]'
'let_rule_packages' is a list of all user-defined let rule packages
plus the default package 'default_let_rule_package'.
-- Function: matchdeclare (<a_1>, <pred_1>, ..., <a_n>, <pred_n>)
Associates a predicate <pred_k> with a variable or list of
variables <a_k> so that <a_k> matches expressions for which the
predicate returns anything other than 'false'.
A predicate is the name of a function, or a lambda expression, or a
function call or lambda call missing the last argument, or 'true'
or 'all'. Any expression matches 'true' or 'all'. If the
predicate is specified as a function call or lambda call, the
expression to be tested is appended to the list of arguments; the
arguments are evaluated at the time the match is evaluated.
Otherwise, the predicate is specified as a function name or lambda
expression, and the expression to be tested is the sole argument.
A predicate function need not be defined when 'matchdeclare' is
called; the predicate is not evaluated until a match is attempted.
A predicate may return a Boolean expression as well as 'true' or
'false'. Boolean expressions are evaluated by 'is' within the
constructed rule function, so it is not necessary to call 'is'
within the predicate.
If an expression satisfies a match predicate, the match variable is
assigned the expression, except for match variables which are
operands of addition '+' or multiplication '*'. Only addition and
multiplication are handled specially; other n-ary operators (both
built-in and user-defined) are treated like ordinary functions.
In the case of addition and multiplication, the match variable may
be assigned a single expression which satisfies the match
predicate, or a sum or product (respectively) of such expressions.
Such multiple-term matching is greedy: predicates are evaluated in
the order in which their associated variables appear in the match
pattern, and a term which satisfies more than one predicate is
taken by the first predicate which it satisfies. Each predicate is
tested against all operands of the sum or product before the next
predicate is evaluated. In addition, if 0 or 1 (respectively)
satisfies a match predicate, and there are no other terms which
satisfy the predicate, 0 or 1 is assigned to the match variable
associated with the predicate.
The algorithm for processing addition and multiplication patterns
makes some match results (for example, a pattern in which a "match
anything" variable appears) dependent on the ordering of terms in
the match pattern and in the expression to be matched. However, if
all match predicates are mutually exclusive, the match result is
insensitive to ordering, as one match predicate cannot accept terms
matched by another.
Calling 'matchdeclare' with a variable <a> as an argument changes
the 'matchdeclare' property for <a>, if one was already declared;
only the most recent 'matchdeclare' is in effect when a rule is
defined. Later changes to the 'matchdeclare' property (via
'matchdeclare' or 'remove') do not affect existing rules.
'propvars (matchdeclare)' returns the list of all variables for
which there is a 'matchdeclare' property. 'printprops (<a>,
matchdeclare)' returns the predicate for variable 'a'. 'printprops
(all, matchdeclare)' returns the list of predicates for all
'matchdeclare' variables. 'remove (<a>, matchdeclare)' removes the
'matchdeclare' property from <a>.
The functions 'defmatch', 'defrule', 'tellsimp', 'tellsimpafter',
and 'let' construct rules which test expressions against patterns.
'matchdeclare' quotes its arguments. 'matchdeclare' always returns
'done'.
Examples:
A predicate is the name of a function, or a lambda expression, or a
function call or lambda call missing the last argument, or 'true'
or 'all'.
(%i1) matchdeclare (aa, integerp);
(%o1) done
(%i2) matchdeclare (bb, lambda ([x], x > 0));
(%o2) done
(%i3) matchdeclare (cc, freeof (%e, %pi, %i));
(%o3) done
(%i4) matchdeclare (dd, lambda ([x, y], gcd (x, y) = 1) (1728));
(%o4) done
(%i5) matchdeclare (ee, true);
(%o5) done
(%i6) matchdeclare (ff, all);
(%o6) done
If an expression satisfies a match predicate, the match variable is
assigned the expression.
(%i1) matchdeclare (aa, integerp, bb, atom);
(%o1) done
(%i2) defrule (r1, bb^aa, ["integer" = aa, "atom" = bb]);
aa
(%o2) r1 : bb -> [integer = aa, atom = bb]
(%i3) r1 (%pi^8);
(%o3) [integer = 8, atom = %pi]
In the case of addition and multiplication, the match variable may
be assigned a single expression which satisfies the match
predicate, or a sum or product (respectively) of such expressions.
(%i1) matchdeclare (aa, atom, bb, lambda ([x], not atom(x)));
(%o1) done
(%i2) defrule (r1, aa + bb, ["all atoms" = aa, "all nonatoms" =
bb]);
(%o2) r1 : bb + aa -> [all atoms = aa, all nonatoms = bb]
(%i3) r1 (8 + a*b + sin(x));
(%o3) [all atoms = 8, all nonatoms = sin(x) + a b]
(%i4) defrule (r2, aa * bb, ["all atoms" = aa, "all nonatoms" =
bb]);
(%o4) r2 : aa bb -> [all atoms = aa, all nonatoms = bb]
(%i5) r2 (8 * (a + b) * sin(x));
(%o5) [all atoms = 8, all nonatoms = (b + a) sin(x)]
When matching arguments of '+' and '*', if all match predicates are
mutually exclusive, the match result is insensitive to ordering, as
one match predicate cannot accept terms matched by another.
(%i1) matchdeclare (aa, atom, bb, lambda ([x], not atom(x)));
(%o1) done
(%i2) defrule (r1, aa + bb, ["all atoms" = aa, "all nonatoms" =
bb]);
(%o2) r1 : bb + aa -> [all atoms = aa, all nonatoms = bb]
(%i3) r1 (8 + a*b + %pi + sin(x) - c + 2^n);
n
(%o3) [all atoms = %pi + 8, all nonatoms = sin(x) + 2 - c + a b]
(%i4) defrule (r2, aa * bb, ["all atoms" = aa, "all nonatoms" =
bb]);
(%o4) r2 : aa bb -> [all atoms = aa, all nonatoms = bb]
(%i5) r2 (8 * (a + b) * %pi * sin(x) / c * 2^n);
n + 3
(b + a) 2 sin(x)
(%o5) [all atoms = %pi, all nonatoms = ---------------------]
c
The functions 'propvars' and 'printprops' return information about
match variables.
(%i1) matchdeclare ([aa, bb, cc], atom, [dd, ee], integerp);
(%o1) done
(%i2) matchdeclare (ff, floatnump, gg, lambda ([x], x > 100));
(%o2) done
(%i3) propvars (matchdeclare);
(%o3) [aa, bb, cc, dd, ee, ff, gg]
(%i4) printprops (ee, matchdeclare);
(%o4) [integerp(ee)]
(%i5) printprops (gg, matchdeclare);
(%o5) [lambda([x], x > 100, gg)]
(%i6) printprops (all, matchdeclare);
(%o6) [lambda([x], x > 100, gg), floatnump(ff), integerp(ee),
integerp(dd), atom(cc), atom(bb), atom(aa)]
-- Option variable: maxapplydepth
Default value: 10000
'maxapplydepth' is the maximum depth to which 'apply1' and 'apply2'
will delve.
-- Option variable: maxapplyheight
Default value: 10000
'maxapplyheight' is the maximum height to which 'applyb1' will
reach before giving up.
-- Function: remlet
remlet (<prod>, <name>)
remlet ()
remlet (all)
remlet (all, <name>)
Deletes the substitution rule, <prod> -> repl, most recently
defined by the 'let' function. If name is supplied the rule is
deleted from the rule package name.
'remlet()' and 'remlet(all)' delete all substitution rules from the
current rule package. If the name of a rule package is supplied,
e.g. 'remlet (all, <name>)', the rule package <name> is also
deleted.
If a substitution is to be changed using the same product, 'remlet'
need not be called, just redefine the substitution using the same
product (literally) with the 'let' function and the new replacement
and/or predicate name. Should 'remlet (<prod>)' now be called the
original substitution rule is revived.
See also 'remrule', which removes a rule defined by 'tellsimp' or
'tellsimpafter'.
-- Function: remrule
remrule (<op>, <rulename>)
remrule (<op>, all)
Removes rules defined by 'tellsimp' or 'tellsimpafter'.
'remrule (<op>, <rulename>)' removes the rule with the name
<rulename> from the operator <op>. When <op> is a built-in or
user-defined operator (as defined by 'infix', 'prefix', etc.), <op>
and <rulename> must be enclosed in double quote marks.
'remrule (<op>, all)' removes all rules for the operator <op>.
See also 'remlet', which removes a rule defined by 'let'.
Examples:
(%i1) tellsimp (foo (aa, bb), bb - aa);
(%o1) [foorule1, false]
(%i2) tellsimpafter (aa + bb, special_add (aa, bb));
(%o2) [+rule1, simplus]
(%i3) infix ("@@");
(%o3) @@
(%i4) tellsimp (aa @@ bb, bb/aa);
(%o4) [@@rule1, false]
(%i5) tellsimpafter (quux (%pi, %e), %pi - %e);
(%o5) [quuxrule1, false]
(%i6) tellsimpafter (quux (%e, %pi), %pi + %e);
(%o6) [quuxrule2, quuxrule1, false]
(%i7) [foo (aa, bb), aa + bb, aa @@ bb, quux (%pi, %e),
quux (%e, %pi)];
bb
(%o7) [bb - aa, special_add(aa, bb), --, %pi - %e, %pi + %e]
aa
(%i8) remrule (foo, foorule1);
(%o8) foo
(%i9) remrule ("+", ?\+rule1);
(%o9) +
(%i10) remrule ("@@", ?\@\@rule1);
(%o10) @@
(%i11) remrule (quux, all);
(%o11) quux
(%i12) [foo (aa, bb), aa + bb, aa @@ bb, quux (%pi, %e),
quux (%e, %pi)];
(%o12) [foo(aa, bb), bb + aa, aa @@ bb, quux(%pi, %e),
quux(%e, %pi)]
-- Function: tellsimp (<pattern>, <replacement>)
is similar to 'tellsimpafter' but places new information before old
so that it is applied before the built-in simplification rules.
'tellsimp' is used when it is important to modify the expression
before the simplifier works on it, for instance if the simplifier
"knows" something about the expression, but what it returns is not
to your liking. If the simplifier "knows" something about the main
operator of the expression, but is simply not doing enough for you,
you probably want to use 'tellsimpafter'.
The pattern may not be a sum, product, single variable, or number.
The system variable 'rules' is the list of rules defined by
'defrule', 'defmatch', 'tellsimp', and 'tellsimpafter'.
Examples:
(%i1) matchdeclare (x, freeof (%i));
(%o1) done
(%i2) %iargs: false$
(%i3) tellsimp (sin(%i*x), %i*sinh(x));
(%o3) [sinrule1, simp-%sin]
(%i4) trigexpand (sin (%i*y + x));
(%o4) sin(x) cos(%i y) + %i cos(x) sinh(y)
(%i5) %iargs:true$
(%i6) errcatch(0^0);
0
0 has been generated
(%o6) []
(%i7) ev (tellsimp (0^0, 1), simp: false);
(%o7) [^rule1, simpexpt]
(%i8) 0^0;
(%o8) 1
(%i9) remrule ("^", %th(2)[1]);
(%o9) ^
(%i10) tellsimp (sin(x)^2, 1 - cos(x)^2);
(%o10) [^rule2, simpexpt]
(%i11) (1 + sin(x))^2;
2
(%o11) (sin(x) + 1)
(%i12) expand (%);
2
(%o12) 2 sin(x) - cos (x) + 2
(%i13) sin(x)^2;
2
(%o13) 1 - cos (x)
(%i14) kill (rules);
(%o14) done
(%i15) matchdeclare (a, true);
(%o15) done
(%i16) tellsimp (sin(a)^2, 1 - cos(a)^2);
(%o16) [^rule3, simpexpt]
(%i17) sin(y)^2;
2
(%o17) 1 - cos (y)
-- Function: tellsimpafter (<pattern>, <replacement>)
Defines a simplification rule which the Maxima simplifier applies
after built-in simplification rules. <pattern> is an expression,
comprising pattern variables (declared by 'matchdeclare') and other
atoms and operators, considered literals for the purpose of pattern
matching. <replacement> is substituted for an actual expression
which matches <pattern>; pattern variables in <replacement> are
assigned the values matched in the actual expression.
<pattern> may be any nonatomic expression in which the main
operator is not a pattern variable; the simplification rule is
associated with the main operator. The names of functions (with
one exception, described below), lists, and arrays may appear in
<pattern> as the main operator only as literals (not pattern
variables); this rules out expressions such as 'aa(x)' and 'bb[y]'
as patterns, if 'aa' and 'bb' are pattern variables. Names of
functions, lists, and arrays which are pattern variables may appear
as operators other than the main operator in <pattern>.
There is one exception to the above rule concerning names of
functions. The name of a subscripted function in an expression
such as 'aa[x](y)' may be a pattern variable, because the main
operator is not 'aa' but rather the Lisp atom 'mqapply'. This is a
consequence of the representation of expressions involving
subscripted functions.
Simplification rules are applied after evaluation (if not
suppressed through quotation or the flag 'noeval'). Rules
established by 'tellsimpafter' are applied in the order they were
defined, and after any built-in rules. Rules are applied
bottom-up, that is, applied first to subexpressions before
application to the whole expression. It may be necessary to
repeatedly simplify a result (for example, via the quote-quote
operator '''' or the flag 'infeval') to ensure that all rules are
applied.
Pattern variables are treated as local variables in simplification
rules. Once a rule is defined, the value of a pattern variable
does not affect the rule, and is not affected by the rule. An
assignment to a pattern variable which results from a successful
rule match does not affect the current assignment (or lack of it)
of the pattern variable. However, as with all atoms in Maxima, the
properties of pattern variables (as declared by 'put' and related
functions) are global.
The rule constructed by 'tellsimpafter' is named after the main
operator of <pattern>. Rules for built-in operators, and
user-defined operators defined by 'infix', 'prefix', 'postfix',
'matchfix', and 'nofix', have names which are Lisp identifiers.
Rules for other functions have names which are Maxima identifiers.
The treatment of noun and verb forms is slightly confused. If a
rule is defined for a noun (or verb) form and a rule for the
corresponding verb (or noun) form already exists, the newly-defined
rule applies to both forms (noun and verb). If a rule for the
corresponding verb (or noun) form does not exist, the newly-defined
rule applies only to the noun (or verb) form.
The rule constructed by 'tellsimpafter' is an ordinary Lisp
function. If the name of the rule is '$foorule1', the construct
':lisp (trace $foorule1)' traces the function, and ':lisp
(symbol-function '$foorule1)' displays its definition.
'tellsimpafter' quotes its arguments. 'tellsimpafter' returns the
list of rules for the main operator of <pattern>, including the
newly established rule.
See also 'matchdeclare', 'defmatch', 'defrule', 'tellsimp', 'let',
'kill', 'remrule' and 'clear_rules'.
Examples:
<pattern> may be any nonatomic expression in which the main
operator is not a pattern variable.
(%i1) matchdeclare (aa, atom, [ll, mm], listp, xx, true)$
(%i2) tellsimpafter (sin (ll), map (sin, ll));
(%o2) [sinrule1, simp-%sin]
(%i3) sin ([1/6, 1/4, 1/3, 1/2, 1]*%pi);
1 1 sqrt(3)
(%o3) [-, -------, -------, 1, 0]
2 sqrt(2) 2
(%i4) tellsimpafter (ll^mm, map ("^", ll, mm));
(%o4) [^rule1, simpexpt]
(%i5) [a, b, c]^[1, 2, 3];
2 3
(%o5) [a, b , c ]
(%i6) tellsimpafter (foo (aa (xx)), aa (foo (xx)));
(%o6) [foorule1, false]
(%i7) foo (bar (u - v));
(%o7) bar(foo(u - v))
Rules are applied in the order they were defined. If two rules can
match an expression, the rule which was defined first is applied.
(%i1) matchdeclare (aa, integerp);
(%o1) done
(%i2) tellsimpafter (foo (aa), bar_1 (aa));
(%o2) [foorule1, false]
(%i3) tellsimpafter (foo (aa), bar_2 (aa));
(%o3) [foorule2, foorule1, false]
(%i4) foo (42);
(%o4) bar_1(42)
Pattern variables are treated as local variables in simplification
rules. (Compare to 'defmatch', which treats pattern variables as
global variables.)
(%i1) matchdeclare (aa, integerp, bb, atom);
(%o1) done
(%i2) tellsimpafter (foo(aa, bb), bar('aa=aa, 'bb=bb));
(%o2) [foorule1, false]
(%i3) bb: 12345;
(%o3) 12345
(%i4) foo (42, %e);
(%o4) bar(aa = 42, bb = %e)
(%i5) bb;
(%o5) 12345
As with all atoms, properties of pattern variables are global even
though values are local. In this example, an assignment property
is declared via 'define_variable'. This is a property of the atom
'bb' throughout Maxima.
(%i1) matchdeclare (aa, integerp, bb, atom);
(%o1) done
(%i2) tellsimpafter (foo(aa, bb), bar('aa=aa, 'bb=bb));
(%o2) [foorule1, false]
(%i3) foo (42, %e);
(%o3) bar(aa = 42, bb = %e)
(%i4) define_variable (bb, true, boolean);
(%o4) true
(%i5) foo (42, %e);
translator: bb was declared with mode boolean, but it has value:
%e
-- an error. To debug this try: debugmode(true);
Rules are named after main operators. Names of rules for built-in
and user-defined operators are Lisp identifiers, while names for
other functions are Maxima identifiers.
(%i1) tellsimpafter (foo (%pi + %e), 3*%pi);
(%o1) [foorule1, false]
(%i2) tellsimpafter (foo (%pi * %e), 17*%e);
(%o2) [foorule2, foorule1, false]
(%i3) tellsimpafter (foo (%i ^ %e), -42*%i);
(%o3) [foorule3, foorule2, foorule1, false]
(%i4) tellsimpafter (foo (9) + foo (13), quux (22));
(%o4) [+rule1, simplus]
(%i5) tellsimpafter (foo (9) * foo (13), blurf (22));
(%o5) [*rule1, simptimes]
(%i6) tellsimpafter (foo (9) ^ foo (13), mumble (22));
(%o6) [^rule1, simpexpt]
(%i7) rules;
(%o7) [foorule1, foorule2, foorule3, +rule1, *rule1, ^rule1]
(%i8) foorule_name: first (%o1);
(%o8) foorule1
(%i9) plusrule_name: first (%o4);
(%o9) +rule1
(%i10) remrule (foo, foorule1);
(%o10) foo
(%i11) remrule ("^", ?\^rule1);
(%o11) ^
(%i12) rules;
(%o12) [foorule2, foorule3, +rule1, *rule1]
A worked example: anticommutative multiplication.
(%i1) gt (i, j) := integerp(j) and i < j;
(%o1) gt(i, j) := integerp(j) and (i < j)
(%i2) matchdeclare (i, integerp, j, gt(i));
(%o2) done
(%i3) tellsimpafter (s[i]^^2, 1);
(%o3) [^^rule1, simpncexpt]
(%i4) tellsimpafter (s[i] . s[j], -s[j] . s[i]);
(%o4) [.rule1, simpnct]
(%i5) s[1] . (s[1] + s[2]);
(%o5) s . (s + s )
1 2 1
(%i6) expand (%);
(%o6) 1 - s . s
2 1
(%i7) factor (expand (sum (s[i], i, 0, 9)^^5));
(%o7) 100 (s + s + s + s + s + s + s + s + s + s )
9 8 7 6 5 4 3 2 1 0
-- Function: clear_rules ()
Executes 'kill (rules)' and then resets the next rule number to 1
for addition '+', multiplication '*', and exponentiation '^'.
automatically generated by info2www version 1.2.2.9