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