Artifact 29c2261ad3027258bfb627bd4eee67c5a1e3e5e007ff99e0678825b82a842dab:
- File
r30/less3
— part of check-in
[eb17ceb7f6]
at
2020-04-21 19:40:01
on branch master
— Add Reduce 3.0 to the historical section of the archive, and some more
files relating to version sof PSL from the early 1980s. Thanks are due to
Paul McJones and Nelson Beebe for these, as well as to all the original
authors.git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/historical@5328 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 13042) [annotate] [blame] [check-ins using] [more...]
COMMENT REDUCE INTERACTIVE LESSON NUMBER 3 David R. Stoutemyer University of Hawaii COMMENT This is lesson 3 of 7 REDUCE lessons. Please refrain from using variables beginning with the letters F through H during the lesson. Mathematics is replete with many named elementary and not-so- elementary functions besides the set built into REDUCE such as SIN, COS, and LOG, and it is often convenient to utilize expressions containing a functional form such as f(x) to denote an unknown function or a class of functions. Functions are called operators in REDUCE, and by merely declaring their names as such, we are free to use them for functional forms. For example; OPERATOR F; G1 := F(F(COT(F)), F()); COMMENT Note that 1. We can use the same name for both a variable and an operator. (However, this practice often leads to confusion.) 2. We can use the same operator for any number of arguments -- including zero arguments such as for F(). 3. We can assign values to specific instances of functional forms; PAUSE; COMMENT COT is one of the functions already defined in REDUCE together with a few of its properties. However, the user can augment or even override these definitions depending on the needs of a given problem. For example, if one wished to write COT(F) in terms of TAN, one could say; COT(F) := 1/TAN(F); G1 := G1 + COT(H+1); PAUSE; COMMENT Naturally, our assignment for COT(F) did not affect COT(H+1) in our example above. However, we can use a LET rule to make all cotangents automatically be replaced by the reciprocal of the corresponding tangents:; FOR ALL F LET COT(F) = 1/TAN(F); G1; COMMENT Any variable designated "FOR ALL" is a dummy variable which is distinct from any other previously or subsequently introduced indeterminate, variable, or dummy variable having the same name outside the rule. To clear a LET rule having dummy variables, the CLEAR command must employ the same dummy variables; FOR ALL F CLEAR COT(F); COT(G+5); PAUSE; COMMENT The arguments of a functional form on the left-hand side of a LET rule can be more complicated than mere indeterminates. For example, we may wish to inform REDUCE how to differentiate expressions involving SEC, which is not defined in the basic system; OPERATOR SEC; FOR ALL G1 LET DF(SEC(G1),G1) = SEC(G1)*TAN(G1); DF(3*SEC(F*G), G); COMMENT Also, REDUCE obviously knows the chain rule because otherwise we would have had to type FOR ALL Y,X LET DF(SEC(Y),X)=SEC(Y)*TAN(Y)*DF(Y,X); PAUSE; COMMENT As another example, suppose that we wish to employ the angle-sum identities for SIN and COS; FOR ALL X, Y LET SIN(X+Y) = SIN(X)*COS(Y) + SIN(Y)*COS(X), COS(X+Y) = COS(X)*COS(Y) - SIN(X)*SIN(Y); COS(5+F-G); COMMENT Note that: 1. LET can have any number of replacement rules separated by commas. 2. There was no need for rules with 3 or more addends, because the above rules were automatically employed recursively, with two of the three addends 5, F, and -G grouped together as one of the dummy variables the first time through. 3. Despite the subexpression F-G in our example, there was no need to make rules for the difference of two angles, because subexpressions of the form X-Y are treated as X+(-Y). 4. Built-in rules were employed to convert expressions of the form SIN(-X) or COS(-X) to -SIN(X) or COS(X) respectively. As an exercise, try to implement rules which transform the logarithms of products and quotients respectively to sums and differences of logarithms, while converting the logarithm of a power of a quantity to the power times the logarithm of the quantity; PAUSE; COMMENT Actually, the left-hand side of a LET rule also can be somewhat more general than a functional form. The left-hand side can be a power of an indeterminate or of a functional form, or the left- hand side can be a product of such powers and/or indeterminates or functional forms. For example, we can have the rule "FOR ALL X LET SIN(X)**2=1-COS(X)**2", or we can have the rule; FOR ALL X LET COS(X)**2 = 1 - SIN(X)**2; G1 := COS(F)**3 + COS(G); PAUSE; COMMENT Note that a replacement takes place wherever a left-hand side of a rule divides a term. With a rule replacing SIN(X)**2 and a rule replacing COS(X)**2 simultaneously in effect, an expression which uses either one will lead to an infinite recursion that eventually exhausts the available storage. (Try it if you wish -- after the lesson). We are also permitted to employ a more symmetric rule using a top level "+" provided that no free variables appear in the rule. However, a rule such as "FOR ALL X LET SIN(X)**2+COS(X)**2=1" is not permitted. We can get around the restriction against a top-level "+" on the left side though, at the minor nuisance of having to employ an operator whenever we want the rule applied to an expression:; FOR ALL X CLEAR COS(X)**2; OPERATOR TRIGSIMP; FOR ALL A, C, X LET TRIGSIMP(X) = X, TRIGSIMP(A*SIN(X)**2 + A*COS(X)**2 + C) = A + TRIGSIMP(C), TRIGSIMP(A*SIN(X)**2 + A*COS(X)**2) = A, TRIGSIMP(SIN(X)**2 + COS(X)**2 + C) = 1 + TRIGSIMP(C), TRIGSIMP(SIN(X)**2 + COS(X)**2) = 1; G1 := F*COS(G)**2 + F*SIN(G)**2 + G*SIN(G)**2 + G*COS(G)**2 + 5; G1 := TRIGSIMP(G1); PAUSE; COMMENT Why doesn't our rule TRIGSIMP(X)=X defeat the other more specific ones? The reason is that rules are applied in a last-in-first-applied order, with the whole process immediately restarted whenever any rule succeeds. Thus the rule TRIGSIMP(X)=X, intended to make the operator TRIGSIMP eventually evaporate, is tried only after all of the genuine simplification rules have done all that they can. For such reasons we usually write rules for an operator in an order which proceeds from the most general to the most specific cases. Experimentation will reveal that TRIGSIMP will not simplify higher powers of sine and cosine, such as COS(X)**4 + 2*COS(X)**2*SIN(X)**2 + SIN(X)**4, and that TRIGSIMP will not necessarily work when there are more than 6 terms. This latter restriction is not fundamental but is a practical one imposed to keep the combinatorial searching associated with the current algorithm under reasonable control. As an exercise, see if you can generalize the rules sufficiently so that 5*COS(H)**2+6*SIN(H)**2 simplifies to 5 + SIN(H)**2 or to 6-COS(H)**2; PAUSE; COMMENT LET rules do not need to have a "FOR ALL" prefix. For example, we could introduce the simplification rule "LET E**(I*PI)=-1". As another example, we might wish to replace all subsequent instances of M*C**2 by ENERGY; CLEAR M, C, ENERGY; LET M*C**2 = ENERGY; G1 := 3*M**2*C**2 + M*C**3 + C**2 + M + M*C + M1*C1**2; PAUSE; COMMENT Suppose that instead we wish to replace M by ENERGY/C**2:; CLEAR M*C**2; LET M = ENERGY/C**2; G1; COMMENT Without the CLEAR M*C**2, the subsequent statements would have produced an infinite recursion. You may wonder how a LET rule of the trivial form "LET indeterminate = ..." differs from the corresponding assignment "indeterminate := ...". The difference is 1. The LET rule does not replace any contained bound variables with their values until the rule is actually used for a replacement. 2. The LET rule performs the evaluation of any contained bound variables every time the rule is used. Thus, the rule "LET X = X + 1" would cause infinite recursion at the first subsequent occurrence of X, as would the pair of rules "LET X=Y" and "LET Y=X". (Try it! -- after the lesson.) To illustrate point 1 above, compare the following sequence with the analogous earlier one in lesson 2 using assignments throughout; CLEAR E1, F; E2:= F; LET F1 = E1 + E2; F1; E2 := G; F1; PAUSE; COMMENT For a subsequent example, we need to replace E**(I*X) by COS(X)**2 + I*SIN(X)**2 for all X. See if you can successfully introduce this rule; PAUSE; E**I; COMMENT REDUCE does not match I as an instance of the pattern I*X with X=1, so if you neglected to include a rule for this degenerate case, do so now; PAUSE; CLEAR X, N, NMINUS1; ZERO := E**(N*I*X) - E**(NMINUS1*I*X)*E**(I*X); REALZERO := SUB(I=0, ZERO); IMAGZERO := SUB(I=0, -I*ZERO); COMMENT Regarding the last two assignments as equations, we can solve them to get recurrence relations defining SIN(N*X) and COS(N*X) in terms of angles having lower multiplicity. Can you figure out why I didn't use N-1 rather than NMINUS1 above? Can you devise a similar technique to derive the angle-sum identities that we previously implemented?; PAUSE; COMMENT To implement a set of trigonometric multiple-angle expansion rules, we need to match the patterns SIN(N*X) and COS(N*X) only when N is an integer exceeding 1. We can implement one of the necessary rules as follows; FOR ALL N,X SUCH THAT NUMBERP N AND N>1 LET COS(N*X) = COS(X)*COS((N-1)*X) - SIN(X)*SIN((N-1)*X); COMMENT Note: 1. In a conditional LET statement, any dummy variables should appear in the preceding FOR ALL clause. 2. NUMBERP, standing for NUMBER Predicate, is a built-in function which yields true if and only if its argument is an integer or a floating-point number. In lesson 6 we will learn how to write such a function exclusively for integers, so until then our multiple-angle rules should not be used under the influence of ON FLOAT. 3. Arbitrarily-complicated true-false conditions can be composed using the relational operators =, NEQ, <, >, <=, >=, together with the logical operators "AND", "OR", "NOT". 4. Operators < and > work only when both sides are integers or floating-point numbers. Moreover, = together with NEQ check only whether or not the two sides appear identical under the influence of whatever rules and computational flags are in effect. For example, (X-1)/(X+1)=(X**2-2*X+1)/(X**2-1) will yield false under the influence of OFF GCD. Operator <= works only in circumstances where < or = would work, and similarly for >=. Consequently, it is usually advisable to compare the difference in two expressions with 0, which forces a certain amount of algebraic simplification. 5. The relational operators have higher precedence than "NOT", which has higher precedence than "AND", which has higher precedence than "OR". 6. In a sequence of items joined by "AND" operators, testing is done left to right, and testing is discontinued after the first item which is false. 7. In a sequence of items joined by "OR" operators, testing is done left to right, and testing is discontinued after the first item which is true. 8. We didn't actually need the "AND N>1" part in the above rule Can you guess why? Your mission is to complete the set of multiple-angle rules and to test them on the example COS(4*X) + COS(X/3) + COS(F*X); PAUSE; COMMENT Now suppose that we wish to write a set of rules for doing symbolic integration, such that expressions of the form INTEGRATE(X**P,X) are replaced by X**(P+1)/(P+1) for arbitrary X and P, provided P is independent of X. This will of course be less complete that the analytic integration package available with REDUCE, but for specific classes of integrals it is often a reasonable way to do such integration. Noting that DF(P,X) is 0 if P is independent of X, we can accomplish this as follows; OPERATOR INTEGRATE; FOR ALL P,X SUCH THAT DF(P,X)=0 LET INTEGRATE(X**P,X) = X**(P+1)/(P+1); INTEGRATE(F**5,F); INTEGRATE(G**G, G); INTEGRATE(F**G,F); G1 := INTEGRATE(G*F**5,F) + INTEGRATE(F**5+F**G,F); COMMENT The last example indicates that we must incorporate rules which distribute integrals over sums and extract factors which are independent of the second argument of INTEGRATE. Can you think of LET rules which accomplish this? It is a good exercise, but this particular pair of properties of INTEGRATE is so prevalent in mathematics that operators with these properties are called linear, and a corresponding declaration is built into REDUCE; LINEAR INTEGRATE; G1; G1:= INTEGRATE(F+1,F) + INTEGRATE(1/F**5,F); PAUSE; COMMENT We overcame one difficulty and uncovered 3 others. Clearly REDUCE does not regard F to match the pattern F**P as F**1, or 1 to match the pattern as F**0, or 1/F**5 to match the pattern as F**(-1), so we can add additional rules for such cases; FOR ALL P,X SUCH THAT DF(P,X)=0 LET INTEGRATE(1/X**P,X) = X**(1-P)/(1-P); FOR ALL X LET INTEGRATE(X,X) = X**2/2, INTEGRATE(1,X) = X; G1; COMMENT A remaining problem is that INTEGRATE(X**-1,X) will lead to X**0/(-1+1), which simplifies to 1/0, which will cause a zero-divide error message. Consequently, we should also include the correct rule for this special case; FOR ALL X LET INTEGRATE(X**-1,X) = LOG(X); INTEGRATE(1/X,X); COMMENT This is the end of lesson 3. We leave it as an intriguing exercise to extend this integrator. ;END;