### The Maxima on-line user's manual

Algebra Calculator

#### Tellsimpafter

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  sqrt(2)  sqrt(3)
(%o3)              [-, -------, -------, 1, 0]
2     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);
Error: bb was declared mode boolean, has value: %e
-- an error.  Quitting.  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```

```(%o1)                                true
(%i2) ```