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