Origin for each line in Lesson_3.red from check-in 5f892713c3:

5f892713c3 2021-03-03    1: COMMENT
5f892713c3 2021-03-03    2: 
5f892713c3 2021-03-03    3:                   REDUCE INTERACTIVE LESSON NUMBER 3
5f892713c3 2021-03-03    4: 
5f892713c3 2021-03-03    5:                          David R. Stoutemyer
5f892713c3 2021-03-03    6:                          University of Hawaii
5f892713c3 2021-03-03    7: 
5f892713c3 2021-03-03    8:                         Update for REDUCE 3.4
5f892713c3 2021-03-03    9:                             Herbert Melenk
5f892713c3 2021-03-03   10:                       Konrad-Zuse-Zentrum Berlin
5f892713c3 2021-03-03   11:                                    
5f892713c3 2021-03-03   12: 
5f892713c3 2021-03-03   13: COMMENT This is lesson 3 of 7 REDUCE lessons.  Please refrain from
5f892713c3 2021-03-03   14: using variables beginning with the letters F through H during the
5f892713c3 2021-03-03   15: lesson.
5f892713c3 2021-03-03   16: 
5f892713c3 2021-03-03   17: Mathematics is replete with many named elementary and not-so-
5f892713c3 2021-03-03   18: elementary functions besides the set built into REDUCE such as SIN,
5f892713c3 2021-03-03   19: COS, and LOG, and it is often convenient to utilize expressions
5f892713c3 2021-03-03   20: containing a functional form such as F(X) to denote an unknown
5f892713c3 2021-03-03   21: function or a class of functions.  Functions are called operators in
5f892713c3 2021-03-03   22: REDUCE, and by merely declaring their names as such, we are free to
5f892713c3 2021-03-03   23: use them for functional forms.  For example:;
5f892713c3 2021-03-03   24: 
5f892713c3 2021-03-03   25: operator f;
5f892713c3 2021-03-03   26: g1 := f(f(cot(f)), f());
5f892713c3 2021-03-03   27: 
5f892713c3 2021-03-03   28: COMMENT Note that
5f892713c3 2021-03-03   29: 
5f892713c3 2021-03-03   30:    1.  We can use the same name for both a variable and an operator.
5f892713c3 2021-03-03   31:        (However, this practice often leads to confusion.)
5f892713c3 2021-03-03   32:    2.  We can use the same operator for any number of arguments --
5f892713c3 2021-03-03   33:        including zero arguments such as for F().
5f892713c3 2021-03-03   34:    3.  We can assign values to specific instances of functional
5f892713c3 2021-03-03   35:        forms.;
5f892713c3 2021-03-03   36: 
5f892713c3 2021-03-03   37: pause;
5f892713c3 2021-03-03   38: 
5f892713c3 2021-03-03   39: COMMENT COT is one of the functions already defined in REDUCE together
5f892713c3 2021-03-03   40: with a few of its properties.  However, you can augment or even
5f892713c3 2021-03-03   41: override these definitions depending on the needs of a given problem.
5f892713c3 2021-03-03   42: For example, if you wished to write COT(F) in terms of TAN, you could
5f892713c3 2021-03-03   43: say:;
5f892713c3 2021-03-03   44: 
5f892713c3 2021-03-03   45: cot(f) := 1/tan(f);
5f892713c3 2021-03-03   46: g1 := g1 + cot(h+1);
5f892713c3 2021-03-03   47: 
5f892713c3 2021-03-03   48: pause;
5f892713c3 2021-03-03   49: 
5f892713c3 2021-03-03   50: COMMENT Naturally, our assignment for COT(F) did not affect COT(H+1)
5f892713c3 2021-03-03   51: in our example above.  However, we can use a LET rule to make all
5f892713c3 2021-03-03   52: cotangents automatically be replaced by the reciprocal of the
5f892713c3 2021-03-03   53: corresponding tangents:;
5f892713c3 2021-03-03   54: 
5f892713c3 2021-03-03   55: let cot(~f) => 1/tan(f);
5f892713c3 2021-03-03   56: g1;
5f892713c3 2021-03-03   57: 
5f892713c3 2021-03-03   58: COMMENT Any variable preceded by a tilde is a dummy variable which is
5f892713c3 2021-03-03   59: distinct from any other previously or subsequently introduced
5f892713c3 2021-03-03   60: indeterminate, variable, or dummy variable having the same name
5f892713c3 2021-03-03   61: outside the rule.  The leftmost occurrence of a dummy variable in a
5f892713c3 2021-03-03   62: rule must be marked with a tilde.
5f892713c3 2021-03-03   63: 
5f892713c3 2021-03-03   64: The arguments to LET are either single rules or lists (explicitly
5f892713c3 2021-03-03   65: enclosed in {..} or as variables with list values).  All elements of a
5f892713c3 2021-03-03   66: list have to be rules (i.e., expressions written in terms of the
5f892713c3 2021-03-03   67: operator "=>") or names of other rule lists.  So we could have written
5f892713c3 2021-03-03   68: the above command either as
5f892713c3 2021-03-03   69: 
5f892713c3 2021-03-03   70:       LET COT(~F) => 1/TAN(F)
5f892713c3 2021-03-03   71: 
5f892713c3 2021-03-03   72: or as the command sequence
5f892713c3 2021-03-03   73: 
5f892713c3 2021-03-03   74:       RS := {COT(~F) => 1/TAN(F)}
5f892713c3 2021-03-03   75:       LET RS
5f892713c3 2021-03-03   76: 
5f892713c3 2021-03-03   77: The CLEARRULES command clears one or more rules.  They have to be
5f892713c3 2021-03-03   78: entered in the same form as for LET -- otherwise REDUCE is unable to
5f892713c3 2021-03-03   79: identify them.;
5f892713c3 2021-03-03   80: 
5f892713c3 2021-03-03   81: clearrules cot(~f) => 1/tan(f);
5f892713c3 2021-03-03   82: cot(g+5);
5f892713c3 2021-03-03   83: 
5f892713c3 2021-03-03   84: COMMENT Alternative forms would have been
5f892713c3 2021-03-03   85: 
5f892713c3 2021-03-03   86:      CLEARRULES {COT(~F) => 1/TAN(F)}
5f892713c3 2021-03-03   87: 
5f892713c3 2021-03-03   88:    or with the above value of RS
5f892713c3 2021-03-03   89: 
5f892713c3 2021-03-03   90:      CLEARRULES RS
5f892713c3 2021-03-03   91: 
5f892713c3 2021-03-03   92: Note that CLEAR RS would not remove the rule(s) from the system -- it
5f892713c3 2021-03-03   93: would only remove the list value from the variable RS.;
5f892713c3 2021-03-03   94: 
5f892713c3 2021-03-03   95: pause;
5f892713c3 2021-03-03   96: 
5f892713c3 2021-03-03   97: COMMENT The arguments of a functional form on the left-hand side of a
5f892713c3 2021-03-03   98: rule can be more complicated than mere indeterminates.  For example,
5f892713c3 2021-03-03   99: we may wish to inform REDUCE how to differentiate expressions
5f892713c3 2021-03-03  100: involving a symbolic function P, whose derivative is expressed in
5f892713c3 2021-03-03  101: terms of another function Q.;
5f892713c3 2021-03-03  102: 
5f892713c3 2021-03-03  103: operator p, q;
5f892713c3 2021-03-03  104: let df(p(~x), x) => q(x)^2;
5f892713c3 2021-03-03  105: 
5f892713c3 2021-03-03  106: df(3*p(f*g), g);
5f892713c3 2021-03-03  107: 
5f892713c3 2021-03-03  108: COMMENT Also, REDUCE obviously knows the chain rule.;
5f892713c3 2021-03-03  109: 
5f892713c3 2021-03-03  110: pause;
5f892713c3 2021-03-03  111: 
5f892713c3 2021-03-03  112: COMMENT As another example, suppose that we wish to employ the
5f892713c3 2021-03-03  113: angle-sum identities for SIN and COS:;
5f892713c3 2021-03-03  114: 
5f892713c3 2021-03-03  115: let {sin(~x+~y) => sin(x)*cos(y) + sin(y)*cos(x),
5f892713c3 2021-03-03  116:      cos(~x+~y) => cos(x)*cos(y) - sin(x)*sin(y)};
5f892713c3 2021-03-03  117: cos(5 + f - g);
5f892713c3 2021-03-03  118: 
5f892713c3 2021-03-03  119: COMMENT Note that:
5f892713c3 2021-03-03  120: 
5f892713c3 2021-03-03  121:    1.  LET can have any number of replacement rules written as a list.
5f892713c3 2021-03-03  122:    2.  There was no need for rules with 3 or more addends, because the
5f892713c3 2021-03-03  123:        above rules were automatically employed recursively, with two
5f892713c3 2021-03-03  124:        of the three addends 5, F, and -G grouped together as one of
5f892713c3 2021-03-03  125:        the dummy variables the first time through.
5f892713c3 2021-03-03  126:    3.  Despite the sub-expression F-G in our example, there was no
5f892713c3 2021-03-03  127:        need to make rules for the difference of two angles, because
5f892713c3 2021-03-03  128:        sub-expressions of the form X-Y are treated as X+(-Y).
5f892713c3 2021-03-03  129:    4.  Built-in rules were employed to convert expressions of the form
5f892713c3 2021-03-03  130:        SIN(-X) or COS(-X) to -SIN(X) or COS(X) respectively.
5f892713c3 2021-03-03  131: 
5f892713c3 2021-03-03  132: As an exercise, try to implement rules which transform the logarithms
5f892713c3 2021-03-03  133: of products and quotients respectively to sums and differences of
5f892713c3 2021-03-03  134: logarithms, while converting the logarithm of a power of a quantity to
5f892713c3 2021-03-03  135: the power times the logarithm of the quantity.;
5f892713c3 2021-03-03  136: 
5f892713c3 2021-03-03  137: pause;
5f892713c3 2021-03-03  138: 
5f892713c3 2021-03-03  139: COMMENT Actually, the left-hand side of a rule also can be somewhat
5f892713c3 2021-03-03  140: more general than a functional form.  The left-hand side can be a
5f892713c3 2021-03-03  141: power of an indeterminate or of a functional form, or a product of
5f892713c3 2021-03-03  142: such powers and/or indeterminates or functional forms.  For example,
5f892713c3 2021-03-03  143: we can have the rule
5f892713c3 2021-03-03  144: 
5f892713c3 2021-03-03  145:        SIN(~X)^2 => 1 - COS(~X)^2
5f892713c3 2021-03-03  146: 
5f892713c3 2021-03-03  147: or we can have the rule:;
5f892713c3 2021-03-03  148: 
5f892713c3 2021-03-03  149: let cos(~x)^2 => 1 - sin(~x)^2;
5f892713c3 2021-03-03  150: g1 := cos(f)^3 + cos(g);
5f892713c3 2021-03-03  151: pause;
5f892713c3 2021-03-03  152: 
5f892713c3 2021-03-03  153: COMMENT Note that a replacement takes place wherever the left-hand
5f892713c3 2021-03-03  154: side of a rule divides a term.  With a rule replacing SIN(X)^2 and a
5f892713c3 2021-03-03  155: rule replacing COS(X)^2 simultaneously in effect, an expression which
5f892713c3 2021-03-03  156: uses either one will lead to an infinite recursion that eventually
5f892713c3 2021-03-03  157: exhausts the available storage.  (Try it if you wish -- after the
5f892713c3 2021-03-03  158: lesson).  We are also permitted to employ a more symmetric rule using
5f892713c3 2021-03-03  159: a top level "+" provided that no free variables appear in the rule.
5f892713c3 2021-03-03  160: However, a rule such as "SIN(~X)^2 + COS(X)^2 => 1" is not permitted.
5f892713c3 2021-03-03  161: We can get around the restriction against a top-level "+" on the
5f892713c3 2021-03-03  162: left-hand side though, at the minor nuisance of having to employ an
5f892713c3 2021-03-03  163: operator whenever we want the rule applied to an expression:;
5f892713c3 2021-03-03  164: 
5f892713c3 2021-03-03  165: clearrules cos(~x)^2 => 1 - sin(~x)^2;
5f892713c3 2021-03-03  166: operator trigsimp;
5f892713c3 2021-03-03  167: trigsimp_rules := {
5f892713c3 2021-03-03  168:    trigsimp(~a*sin(~x)^2 + a*cos(x)^2 + ~c) => a + trigsimp(c),
5f892713c3 2021-03-03  169:    trigsimp(~a*sin(~x)^2 + a*cos(x)^2) => a,
5f892713c3 2021-03-03  170:    trigsimp(sin(~x)^2 + cos(x)^2 + ~c) => 1 + trigsimp(c),
5f892713c3 2021-03-03  171:    trigsimp(sin(~x)^2 + cos(x)^2) => 1,
5f892713c3 2021-03-03  172:    trigsimp(~x) => x }$
5f892713c3 2021-03-03  173: g1 := f*cos(g)^2 + f*sin(g)^2 + g*sin(g)^2 + g*cos(g)^2 + 5;
5f892713c3 2021-03-03  174: g1 := trigsimp(g1) where trigsimp_rules;
5f892713c3 2021-03-03  175: pause;
5f892713c3 2021-03-03  176: 
5f892713c3 2021-03-03  177: COMMENT Here we use another syntactical paradigm: the rule list is
5f892713c3 2021-03-03  178: assigned to a name (here TRIGSIMP_RULES) and it is activated only
5f892713c3 2021-03-03  179: locally for one evaluation, using the WHERE clause.
5f892713c3 2021-03-03  180: 
5f892713c3 2021-03-03  181: Why doesn't our rule TRIGSIMP(~X) => X defeat the other more specific
5f892713c3 2021-03-03  182: ones?  The reason is that rules inside a list are applied in the order
5f892713c3 2021-03-03  183: they are written, with the whole process immediately restarted
5f892713c3 2021-03-03  184: whenever any rule succeeds.  Thus the rule TRIGSIMP(X) = X, intended
5f892713c3 2021-03-03  185: to make the operator TRIGSIMP eventually evaporate, is tried only
5f892713c3 2021-03-03  186: after all of the genuine simplification rules have done all they can.
5f892713c3 2021-03-03  187: For such reasons we usually write rules for an operator in an order
5f892713c3 2021-03-03  188: which proceeds from the most specific to the most general cases.
5f892713c3 2021-03-03  189: Experimentation will reveal that TRIGSIMP will not simplify higher
5f892713c3 2021-03-03  190: powers of sine and cosine, such as COS(X)^4 + 2*COS(X)^2*SIN(X)^2 +
5f892713c3 2021-03-03  191: SIN(X)^4, and that TRIGSIMP will not necessarily work when there are
5f892713c3 2021-03-03  192: more than 6 terms.  This latter restriction is not fundamental but is
5f892713c3 2021-03-03  193: a practical one imposed to keep the combinatorial searching associated
5f892713c3 2021-03-03  194: with the current algorithm under reasonable control.  As an exercise,
5f892713c3 2021-03-03  195: see if you can generalize the rules sufficiently so that 5*COS(H)^2 +
5f892713c3 2021-03-03  196: 6*SIN(H)^2 simplifies to 5 + SIN(H)^2 or to 6 - COS(H)^2.;
5f892713c3 2021-03-03  197: 
5f892713c3 2021-03-03  198: pause;
5f892713c3 2021-03-03  199: 
5f892713c3 2021-03-03  200: COMMENT Rules do not need to have free variables.  For example, we
5f892713c3 2021-03-03  201: could introduce the simplification rule to replace all subsequent
5f892713c3 2021-03-03  202: instances of M*C^2 by ENERGY:;
5f892713c3 2021-03-03  203: 
5f892713c3 2021-03-03  204: clear m, c, energy;
5f892713c3 2021-03-03  205: g1 := (3*m^2*c^2 + m*c^3 + c^2 + m + m*c + m1*c1^2)
5f892713c3 2021-03-03  206:               where m*c^2 => energy;
5f892713c3 2021-03-03  207: pause;
5f892713c3 2021-03-03  208: 
5f892713c3 2021-03-03  209: COMMENT Suppose that instead we wish to replace M by ENERGY/C^2:;
5f892713c3 2021-03-03  210: 
5f892713c3 2021-03-03  211: g1 where m => energy/c^2;
5f892713c3 2021-03-03  212: 
5f892713c3 2021-03-03  213: COMMENT You may wonder how a rule of the trivial form 
5f892713c3 2021-03-03  214: "indeterminate => ..." differs from the corresponding assignment 
5f892713c3 2021-03-03  215: "indeterminate := ...".  The difference is this:
5f892713c3 2021-03-03  216: 
5f892713c3 2021-03-03  217:    1.  The LET rule does not replace any contained bound
5f892713c3 2021-03-03  218:        variables with their values until the rule is actually used for
5f892713c3 2021-03-03  219:        a replacement.
5f892713c3 2021-03-03  220:    2.  The LET rule performs the evaluation of any contained bound
5f892713c3 2021-03-03  221:        variables every time the rule is used.
5f892713c3 2021-03-03  222: 
5f892713c3 2021-03-03  223: Thus, the rule "X => X + 1" would cause infinite recursion at the
5f892713c3 2021-03-03  224: first subsequent occurrence of X, as would the pair of rules "{X => Y,
5f892713c3 2021-03-03  225: Y => X}".  (Try it! -- After the lesson.)  To illustrate point 1
5f892713c3 2021-03-03  226: above, compare the following command sequence with the analogous
5f892713c3 2021-03-03  227: earlier one in lesson 2, which used assignments throughout:;
5f892713c3 2021-03-03  228: 
5f892713c3 2021-03-03  229: clear e1, f;
5f892713c3 2021-03-03  230: e2 := f;
5f892713c3 2021-03-03  231: let f1 => e1 + e2;
5f892713c3 2021-03-03  232: f1;
5f892713c3 2021-03-03  233: e2 := g;
5f892713c3 2021-03-03  234: f1;
5f892713c3 2021-03-03  235: pause;
5f892713c3 2021-03-03  236: 
5f892713c3 2021-03-03  237: COMMENT For a subsequent example, we need to replace E^(I*X) by
5f892713c3 2021-03-03  238: COS(X)^2 + I*SIN(X)^2 for all X.  See if you can successfully
5f892713c3 2021-03-03  239: introduce this rule.  (Without it, the following code will not work
5f892713c3 2021-03-03  240: correctly!);
5f892713c3 2021-03-03  241: 
5f892713c3 2021-03-03  242: pause;
5f892713c3 2021-03-03  243: e^i;
5f892713c3 2021-03-03  244: 
5f892713c3 2021-03-03  245: COMMENT REDUCE does not match I as an instance of the pattern I*X with
5f892713c3 2021-03-03  246: X = 1, so if you neglected to include a rule for this degenerate case,
5f892713c3 2021-03-03  247: do so now.;
5f892713c3 2021-03-03  248: 
5f892713c3 2021-03-03  249: pause;
5f892713c3 2021-03-03  250: clear x, n, nminusone;
5f892713c3 2021-03-03  251: zero := e^(n*i*x) - e^(nminusone*i*x)*e^(i*x);
5f892713c3 2021-03-03  252: realzero := sub(i=0, zero);
5f892713c3 2021-03-03  253: imagzero := sub(i=0, -i*zero);
5f892713c3 2021-03-03  254: 
5f892713c3 2021-03-03  255: COMMENT Regarding the last two assignments as equations, we can solve
5f892713c3 2021-03-03  256: them to get recurrence relations defining SIN(N*X) and COS(N*X) in
5f892713c3 2021-03-03  257: terms of angles having lower multiplicity.
5f892713c3 2021-03-03  258: 
5f892713c3 2021-03-03  259: Can you figure out why I didn't use N-1 rather than NMINUSONE above?
5f892713c3 2021-03-03  260: 
5f892713c3 2021-03-03  261: Can you devise a similar technique to derive the angle-sum identities
5f892713c3 2021-03-03  262: that we previously implemented?;
5f892713c3 2021-03-03  263: 
5f892713c3 2021-03-03  264: pause;
5f892713c3 2021-03-03  265: 
5f892713c3 2021-03-03  266: COMMENT To implement a set of trigonometric multiple-angle expansion
5f892713c3 2021-03-03  267: rules, we need to match the patterns SIN(N*X) and COS(N*X) only when N
5f892713c3 2021-03-03  268: is an integer exceeding 1.  We can implement one of the necessary
5f892713c3 2021-03-03  269: rules as follows:;
5f892713c3 2021-03-03  270: 
5f892713c3 2021-03-03  271:    cos(~n*~x) => cos(x)*cos((n-1)*x) - sin(x)*sin((n-1)*x)
5f892713c3 2021-03-03  272:              when fixp n and n>1;
5f892713c3 2021-03-03  273: 
5f892713c3 2021-03-03  274: COMMENT Note:
5f892713c3 2021-03-03  275: 
5f892713c3 2021-03-03  276:    1.  In a conditional rule, any dummy variables should appear in the
5f892713c3 2021-03-03  277:        left-hand side of the replacement with a tilde.
5f892713c3 2021-03-03  278:    2.  FIXP, standing for FIX Predicate, is a built-in function which
5f892713c3 2021-03-03  279:        yields true if and only if its argument is an integer.  Other
5f892713c3 2021-03-03  280:        useful predicates are NUMBERP, which is true if its argument
5f892713c3 2021-03-03  281:        represents a numeric value, that is an integer, a rational
5f892713c3 2021-03-03  282:        number or a rounded (floating point) number, and EVENP, which
5f892713c3 2021-03-03  283:        is true if its argument is an integer multiple of 2.
5f892713c3 2021-03-03  284:    3.  Arbitrarily-complicated true-false conditions can be composed
5f892713c3 2021-03-03  285:        using the relational operators =, NEQ, <, >, <=, >=, together
5f892713c3 2021-03-03  286:        with the logical operators "AND", "OR", "NOT".
5f892713c3 2021-03-03  287:    4.  The operators < , >, <=, and >= work only when both sides are
5f892713c3 2021-03-03  288:        numbers.
5f892713c3 2021-03-03  289:    5.  The relational operators have higher precedence than "NOT",
5f892713c3 2021-03-03  290:        which has higher precedence than "AND", which has higher
5f892713c3 2021-03-03  291:        precedence than "OR".
5f892713c3 2021-03-03  292:    6.  In a sequence of expressions joined by "AND" operators, testing
5f892713c3 2021-03-03  293:        is done left to right, and testing is discontinued after the
5f892713c3 2021-03-03  294:        first item which is false.
5f892713c3 2021-03-03  295:    7.  In a sequence of expressions joined by "OR" operators, testing
5f892713c3 2021-03-03  296:        is done left to right, and testing is discontinued after the
5f892713c3 2021-03-03  297:        first item which is true.
5f892713c3 2021-03-03  298:    8.  We didn't actually need the "AND N>1" part in the above rule.
5f892713c3 2021-03-03  299:        Can you guess why?
5f892713c3 2021-03-03  300: 
5f892713c3 2021-03-03  301: Your mission is to complete the set of multiple-angle rules and to
5f892713c3 2021-03-03  302: test them on the example COS(4*X) + COS(X/3) + COS(F*X).;
5f892713c3 2021-03-03  303: 
5f892713c3 2021-03-03  304: pause;
5f892713c3 2021-03-03  305: 
5f892713c3 2021-03-03  306: COMMENT Now suppose that we wish to write a set of rules for doing
5f892713c3 2021-03-03  307: symbolic integration, such that expressions of the form
5f892713c3 2021-03-03  308: INTEGRATE(X^P, X) are replaced by X^(P+1)/(P+1) for arbitrary X and P,
5f892713c3 2021-03-03  309: provided P is independent of X.  This will of course be less complete
5f892713c3 2021-03-03  310: that the analytic integration package available with REDUCE, but for
5f892713c3 2021-03-03  311: specific classes of integrals it is often a reasonable way to do such
5f892713c3 2021-03-03  312: integration.  Noting that DF(P,X) is 0 if P is independent of X, we
5f892713c3 2021-03-03  313: can accomplish this as follows:;
5f892713c3 2021-03-03  314: 
5f892713c3 2021-03-03  315: operator integrate;
5f892713c3 2021-03-03  316: let integrate(~x^~p, x) => x^(p+1)/(p+1) when df(p, x) = 0;
5f892713c3 2021-03-03  317: integrate(f^5, f);
5f892713c3 2021-03-03  318: integrate(g^g, g);
5f892713c3 2021-03-03  319: integrate(f^g, f);
5f892713c3 2021-03-03  320: pause;
5f892713c3 2021-03-03  321: 
5f892713c3 2021-03-03  322: g1 := integrate(g*f^5, f) + integrate(f^5+f^g, f);
5f892713c3 2021-03-03  323: 
5f892713c3 2021-03-03  324: COMMENT The last example indicates that we must incorporate rules
5f892713c3 2021-03-03  325: which distribute integrals over sums and extract factors which are
5f892713c3 2021-03-03  326: independent of the second argument of INTEGRATE.  Can you think of
5f892713c3 2021-03-03  327: rules which accomplish this?  It is a good exercise, but this
5f892713c3 2021-03-03  328: particular pair of properties of INTEGRATE is so prevalent in
5f892713c3 2021-03-03  329: mathematics that operators with these properties are called linear,
5f892713c3 2021-03-03  330: and a corresponding declaration is built into REDUCE:;
5f892713c3 2021-03-03  331: 
5f892713c3 2021-03-03  332: linear integrate;
5f892713c3 2021-03-03  333: g1;
5f892713c3 2021-03-03  334: g1 := integrate(f+1, f) + integrate(1/f^5, f);
5f892713c3 2021-03-03  335: pause;
5f892713c3 2021-03-03  336: 
5f892713c3 2021-03-03  337: COMMENT We overcame one difficulty and uncovered 3 others.  Clearly
5f892713c3 2021-03-03  338: REDUCE does not consider F to match the pattern F^P as F^1, or 1 to
5f892713c3 2021-03-03  339: match the pattern as F^0, or 1/F^5 to match the pattern as F^(-1), but
5f892713c3 2021-03-03  340: we can add additional rules for such cases:;
5f892713c3 2021-03-03  341: 
5f892713c3 2021-03-03  342: let {
5f892713c3 2021-03-03  343:    integrate(1/~x^~p, x) => x^(1-p)/(1-p) when df(p, x) = 0,
5f892713c3 2021-03-03  344:    integrate(~x, x) => x^2/2,
5f892713c3 2021-03-03  345:    integrate(1, ~x) => x }$
5f892713c3 2021-03-03  346: g1;
5f892713c3 2021-03-03  347: 
5f892713c3 2021-03-03  348: COMMENT A remaining problem is that INTEGRATE(X^-1, X) will lead to
5f892713c3 2021-03-03  349: X^0/(-1+1), which simplifies to 1/0, which will cause a zero-divide
5f892713c3 2021-03-03  350: error message.  Consequently, we should also include the correct rule
5f892713c3 2021-03-03  351: for this special case:;
5f892713c3 2021-03-03  352: 
5f892713c3 2021-03-03  353: let integrate(~x^-1, x) => log(x);
5f892713c3 2021-03-03  354: integrate(1/x, x);
5f892713c3 2021-03-03  355: pause;
5f892713c3 2021-03-03  356:  
5f892713c3 2021-03-03  357: COMMENT We now collect the integration rules so far into one list
5f892713c3 2021-03-03  358: according to the law that within a rule set a more specific rule
5f892713c3 2021-03-03  359: should precede the more general one:;
5f892713c3 2021-03-03  360:  
5f892713c3 2021-03-03  361: integrate_rules := {
5f892713c3 2021-03-03  362:   integrate(1, ~x) => x,
5f892713c3 2021-03-03  363:   integrate(~x, x) => x^2/2,
5f892713c3 2021-03-03  364:   integrate(~x^-1, x) => log(x),
5f892713c3 2021-03-03  365:   integrate(1/~x^~p, x) => x^(1-p)/(1-p) when df(p, x) = 0,
5f892713c3 2021-03-03  366:   integrate(~x^~p, x) => x^(p+1)/(p+1) when df(p, x) = 0 }$
5f892713c3 2021-03-03  367: 
5f892713c3 2021-03-03  368: COMMENT Note that there are more elegant ways to match special cases
5f892713c3 2021-03-03  369: in which variables have the values 0 or 1 by using "double tilde
5f892713c3 2021-03-03  370: variables" -- see "Advanced use of rule lists" in section 11.3 of the
5f892713c3 2021-03-03  371: REDUCE User's Manual.
5f892713c3 2021-03-03  372: 
5f892713c3 2021-03-03  373: This is the end of lesson 3.  We leave it as an intriguing exercise to
5f892713c3 2021-03-03  374: extend this integrator.
5f892713c3 2021-03-03  375: 
5f892713c3 2021-03-03  376: ;end;

iCAS Bundled REDUCE Scripts
Homepage | GitHub Mirror | SourceHut Mirror | NotABug Mirror | Chisel Mirror | Chisel RSS ]