``Learning Macsyma'' shows you how to type commands into the macsyma interactive algebraic manipulation system. You will learn a number of the basic commands, how to correct simple errors, and enough details for you to understand the kinds of operations which can be done by an algebraic manipulation ystem. macsyma (pronounced ``maxima'') is a large computer program designed for the manipulation of algebraic expressions involving indeterminates, constants, and functions. macsyma can differentiate, integrate, take limits, solve equations, factor polynomials, expand functions in power series, and perform many other operations. You can use a programming language to extend macsyma's capabilities to new domains. ``Learning Macsyma'' is divided into twelve short sections. A complete outline of the material they cover follows. In chapter 1 you will learn O How to type expressions into macsyma O Some simple commands: expand, diff, ev, substitute O Defining functions O Fill this in 1.1 Typing Expressions The section Getting started explained what to do to get to the first command prompt on your computer. We assume you are now faced with a display something like this: % macsyma (this is what you typed) Ésome textÉ (c1) Suppose you wanted to work with the expression (x+1)3. You could type it in by using Fortran-style syntax as follows: (c1) (x+1)**3; The ``;'' and the (invisible) ``carriage return'' terminates your command, and prompts macsyma to evaluate your expression and display the result. Your command can be several lines long, in which case you can format it any way you wish with extra spaces, tabs, or returns before the ``;''. In this case of command c1 above, and every other command you type in, your expression is simplified and then evaluated. As it happens here, tthese processes the expression unchanged, and macsyma responds with the display below 3 (d1) (x + 1) (c2) Note that expressions are normally printed in a two-dimensional format with raised superscripts. This usually makes the expression easier to understand than a linear format, although as you will see in later displays, it sometimes requires some effort. The result is assigned a label d1 which may be used in subsequent commands. You can also use a ``$'' to end a command, in which case the result will be computed but not displayed. An important observation: the system is assigning values to the names c1, d1, etc. You should avoid using these same names for other purposes in your computations. ÑÑÑÑÑÑÑÑÑÑÑÑÑÑNoteÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ If you choose to leave macsyma at this point, or any time a c-line prompt appears, type quit();. If you wish to stop in the midst of a computation and quit in a less orderly fashion, type -z (that's one character), to get back to the UNIX shell, and then type kill % . ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ After the display, macsyma prompts you with the next line label, c2. Çset name=Your Next CommandÈÇset section=2ÈÇinclude chapter-headÈ One of the many commands available in macsyma is expand, which converts an expression to a mathematically equivalent one, but with certain changes in the form. Most macsyma commands have the form of a ``function'' being applied to some arguments. In this case, the expression labelled d1 above is the single argument to expand. (c2) expand(d1); 3 2 (d2) x + 3 x + 3 x + 1 1.2 Typing Errors Before getting too involved, you should realize that if you make a mistake in typing, you can delete erroneous characters by using your standard UNIX erase, kill, word-kill, etc. characters. (Typically these are backspace, control-U, control-W, respectively). Some workstations provide various on-screen editing facilities, and these may also be used. macsyma provides one extra facility: If you wish to delete all lines of a multi-line command, type ?? to get a freshly re-displayed line label. If you make a mistake but type the semi-colon and return key before you notice, the system will print a message: (c2) expand((d1); expand (( d1) ***$*** syntax error please rephrase or edit. (c2) You should probably just retype the expression, if it is short. To use the editor, you would type the escape key and you would then enter the vi editor. This is described in further detail in ``Using Macsyma.'' Since only a small selection of commands will be covered in ``Learning Macsyma,'' you should be aware that additional information is available on almost any command in macsyma on-line. To see a blurb on, for example, the command expand, type describe(expand);(return) to the system. For some commands, an example is also available, and can be viewed by typing, for instance, example(expand); The on-line documentation may include local commands and other information that has not yet been incorporated into printed material. More Commands Let us consider a few additional commands and facilities. To compute the derivative of an expression, you use the diff command. Diff(expr,var) differentiates an expression with respect to the variable var. (c3) sin(x)*cos(x); (d3) cos(x) sin(x) (c4) diff(%,x); 2 2 (d4) cos (x) - sin (x) In line c4 we used the special symbol %. This symbol is a shorthand for the previous expression computed, which in this case is labelled d3. To differentiate an expression twice, use diff(expr,var,2). (c5) diff(d3,x,2); (d5) - 4 cos(x) sin(x) The concept of differentiation in macsyma is actually a good deal more general than is illustrated by this example. Application of the chain rule is generally supported, and a large repertoire of built-in functions and operations are provided. 1.3 Substitution and Evaluation There are a number of ways of producing a new expression from an old one. One technique is to evaluate an expression with (temporary) asssociation of values with some of the indeterminates or variables in it. For example, to substitute x2 for every occurrence of z in the expression z exp(z) you could type (c6) z*exp(z); z (d6) z %e (c7) ev(d6,z=x**2); 2 2 x (d7) x %e In macsyma, the base of the natural logarithms is written %e, to distinguish it from a simple variable named e. Ö-1 is written as %i and p is written %pi. An alternative syntax for exactly the same command as the explicit command ev (for evaluation in a context where z = x 2 ) on line c7 is to implicitly invoke the command. (c8) d6,z=x**2; 2 2 x (d8) x %e The ev command has more elaborate options and uses. Ev ``evaluates'' the first expression (leftmost argument) in an environment specified by the additional expressions which are either equations as shown above, or built-in ``switches'' which control macsyma. An equivalent command in this particular case, is substitute. You can abbreviate the command as subst: (c9) subst(x**2,z,d6); 2 2 x (d9) x %e Observe that if you substitute a for b in c you write subst(a,b,c);. Note that the commands ev and subst do not change the value of z itself. The next section explains how you can assign values to variables. 1.5 Assignment Although some very sophisticated linguistic facilities are available in macsyma, we will describe only the most basic features here. Assignment is very familiar to programmers, and it is used to associate a ``value'' with a name. macsyma implicitly assigns values to the d-labels we have been using. You can, however, make up your own labels for using single-letter or multiple-letter names. To assign a value to a variable a, used a colon (:) as follows: (c10) a:%; 2 2 x (d10) x %e (c11) a+1; 2 2 x (d11) x %e + 1 Sometimes users unintentionally re-use a variable such as a above as a symbols or an ``indeterminate'': as though they had no value. Differentiating with respect to x is not very meaningful when x is (say) a number. If you are surprised when such values appear and wish to reuse the same name again, you can refer to the symbol a regardless of any value associated with it, you can use the expression 'a. This is pronounced ``quote a''. To permanently ``unassign'' a value from a, say: (c12) a:'a; (d12) a Now if you ask for the value of a, you get: (c13) a; (d13) a Another command which is sometimes used for the same purpose is kill(a); It also removes other possible information you might have about a, too. 1.6 Defining Functions Function definition in macsyma is a way of storing computational routines to be used repeatedly. Functions in macsyma always return values and can therefore be used in expressions. Sometimes it is convenient to think of functions in macsyma or other programming languages as similar to mathematical functions. Although we can also ask macsyma to compute a number approximating sin(0.5), that is not where it ends. When you use macsyma there is a real possibility that you might really mean a mathematical function rather than merely the ``computing rule associating a number with some input.'' For example, in macsyma you can find solutions to equations involving the sine function (named sin), or you might expect sin in the answer to a differentiation problem, etc. Nevertheless, we will abuse the term function to describe these computational routines. In the jargon of programming language descriptions, these function definiitions associate a name with some number of ``formal parameters'' and a computational rule or expression or ``body''. The value which is produced by ``applying'' the function is basically the result of substituting ``actual parameters'' or values for the formal parameters in the``body''. For example to define a function f (z) which will be, essentially, a short-hand for sin2z + 1 you use the following command. Note the use of ``:=''. (c14) f(z) := sin(z)**2+1; 2 (d14) f(z) := sin (z) + 1 (c15) f(x+1); 2 (d15) sin (x + 1) + 1 It is possible to define functions which use any of the built-in macsyma commands, or use other user-defined functions which may be defined with other function definition commands. macsyma allows you to define self-referential or recursive functions, and allows you to use ``undefined'' functions as well. An undefined function merely returns ``itself'' as its value. macsyma has many more commands than we have illustrated here. Even so, it is unlikely that everything you might want to do has been anticipated, and therefore macsyma provides you with a complete programming language. This may not be a comfort to you if you are totally unfamiliar with programming, but if you want to use macsyma for elaborate processing of mathematical equations or data, you may have to learn some of this. If you have some familiarity with some conventional programming languages, you may be pleasantly surprised by the additional generality afforded by ``symbolic'' computation. Further on in ``Learning Macsyma'' we give some lessons in this language. 1.7 Equations, Part, and Solve Sometimes it is convenient to compute with equations in macsyma . An equation is not the same as an assignment, a function definition, or a test for equality. Some programming languages overuse the symbol ``='' for some of these, but macsyma does not. In macsyma, an equation is just an expression containing two subexpressions separated by an ``=''. Certain simplification and evaluation operations are defined to work in (usually) conventional ways on equations, as illustrated below. Line c16 shows how to type in an equation. (c16) x**2+2*x=y**2; 2 2 (d16) x + 2 x = y (c17) d16+1; 2 2 (d17) x + 2 x + 1 = y + 1 The left-hand-side of an equation can be selected with the lhs command, or by the more general part command which can be used to pick apart expressions such as sums, products, etc. (c18) lhs(%); 2 (d18) x + 2 x + 1 (c19) part(d17,2); 2 (d19) y + 1 (c20) part(%,1); 2 (d20) y To save typing, the same result as d20 could have been obtained from part(part (d17,2),1) or even more simply, part(d17,2,1). Equations are used by some commands, such as solve. Solve returns a list of equations, that is, a sequence separated by commas and enclosed in square brackets: (c21) x**2-1; 2 (d21) x - 1 (c22) solve(%,x); (d22) [x = - 1, x = 1] Notice the way the list of the two solutions is displayed. We can substitute the first of the two answers in d21, and evaluate: (c23) d21,part(%,1); (d23) 0 1.8 Sums, Programs, Ev Revisited You can compute the sum of the first five positive integers, squaredby: (c24) sum(i**2,i,1,5); (d24) 55 Another way of providing a similar result by writing a small program, is to use a for statement. (c25) for i:1 step 1 thru 5 do s:s+i**2 ; (d25) done The result is stored as the value of the variable s. If s had been 0 previously, the current value of s would be 55. Actually, (c26) s; (d26) s + 55 This reflects the fact that the value of s initially was just s. You can, of course, substitute 0 for the original value: (c27) subst(0,'s,%); (d27) 55 Note that this substitution does not affect the value of s. It just sets d27 to 55. A more mysterious case occurs if you type (c28) ev(s+55); (d28) s + 165 explanation: if we had typed merely s+55, it would evaluate to (s+55)+55, or s+110. But ev evaluates ``once more'' to get (s+55)+110. Ev is sometimes a puzzle if you do not separate those symbols that you use for programming purposes and therefore have values, and those symbols you use only for indeterminates. In spite of the previous example, summations are not really the same as the programming languages' ``for loops''. Sometimes summations are merely placeholders for computations which for one reason or another cannot be done. This is an example: (c29) 'sum(g(i),i,0,n); n ==== \ (d29) > g(i) / ==== i = 0 There are three reasons for this summation to be returned ``unsummed''. We have not provided a ``function definition'' for g; the variable n is not some fixed integer value; and finally the ``quote'' symbol or apostrophe (') to the left of the sum on line c29 inhibits evaluation. The effect of the quote is, in most circumstances the prevention of evaluation. Sometimes macsyma can deduce the value of a summation in closed form even though it cannot be evaluated, because of built-in simplification capabilities. Some summations can, for example, be solved by a fairly general procedure analogous to symbolic integration. In macsyma a distinction is sometimes drawn between ``noun'' and ``verb'' forms of commands. Most functions are ``verbs'' in that they will be evaluated ``away'' in an effort to eliminate them from expressions. To prevent such evaluation, the ``quote'' illustrated above can generally be used. Some functions are nouns or verbs depending upon context such as the nature of their arguments. The trigonometric functions are this way, being nouns if they are given integer arguments, but verbs if they are given floating-point arguments, or ev'd with the numer option set: (c30) sin(1); (d30) sin(1) (c31) sin(1),numer; (d31) 0.8414709848078965 Floating-point numbers are carried to double precision. There is also an implementation of higher (arbitrarily higher!) precision ``bigfloats'' available and described in ``Using Macsyma.'' More Expansion Let us return to our very first example of a command, and provide some more details and techniques for expansion, or application of the distributive law of multiplication. In some computations where an indeterminate represents a quantity of small magnitude, you might wish to automatically drop higher-degree terms from an expansion. In some cases you might wish to drop terms in several variables, e.g.all terms in q with exponent greater than 7, and terms in p with exponent greater than 4, or terms of pn and qm combined so that their ``weight'' 2n + m exceeds 7. This sequence of commands does that: (c32) ratwtlvl:7$ (c33) ratweight(q,1,p,2); (d33) [q, 1, p, 2] (c34) ratexpand((p+q+1)^8); 7 6 5 5 4 4 2 3 3 (d34) 8 q + 28 q + 168 p q + 56 q + 280 p q + 70 q + 560 p q + 280 p q 3 2 2 2 2 3 2 + 56 q + 420 p q + 168 p q + 28 q + 280 p q + 168 p q + 56 p q + 8 q 3 2 + 56 p + 28 p + 8 p + 1 The ``rats'' appearing in the command names here are an indication that the commands use something called ``canonical RATional expression form,'' or CRE form, an efficient data representation used for dealing with polynomials and ratios of polynomials. We have also used ``^'' instead of ``**'' (the two notations are interchangeable in macsyma.) We will return to representation issues shortly. 1.9 Integration One of macsyma 's flashiest features is its ability to compute symbolic indefinite integrals: (c35) x/(x^3+1); x (d35) ------ 3 x + 1 (c36) integrate(%,x); 2 x - 1 2 atan(-------) log(x - x + 1) sqrt(3) log(x + 1) (d36) --------------- + ------------- - ---------- 6 sqrt(3) 3 To check the solution, we can differentiate. (c37) diff(%,x); 2 2 x - 1 1 (d37) ------------------ + -------------- - --------- 2 2 3 (x + 1) (2 x - 1) 6 (x - x + 1) 3 (---------- + 1) 3 A more satisfactory form would result if the terms were expanded and the sum put over a common denominator. By converting this result to a CRE form (the same form used for the previous RAT commands) the expression is simplified. The ratsimp command does this: (c38) ratsimp(%); x (d38) ------ 3 x + 1 2 Representation and Simplification The acronym stands for Project MAC's SYmbolic MAnipulation System. MAC itself is an acronym, usually cited as meaning Man and Computer or Machine Aided Cognition. The Laboratory for Computer Science at the Massachusetts Institute of Technology was known as Project MAC during the initial development of macsyma . There are more readable (but slower) typesetting display facilities which requires more a elaborate computer terminal than the usual character-display type. 2 Representation and Simplification The multiplicity of representations illustrated by lines d38 and d37 constitute an important feature of macsyma . It is not always so clear which command will produce the most appealing form of an expression. Ratsimp, which did such a fine job above, would produce a huge expression if applied to (x + 5) sup 100 , since it multiplies through all those terms. The correct choice of representation is often the key to solving challenging problems. The factor command is another way of changing representation, illustrated below. (c39) factor(x^12+1); 4 8 4 (d39) (x + 1) (x - x + 1) Factor finds exact integral factors, not approximate zeros, and is thus qualitatively different from numerical root-finders. It is generally much slower than numerical routines, but gives a different type of answer, as illustrated above. Numerical zero-finding for polynomials or other functions can be found in an extensive library of routines from the Numerical Algorithms Group (NAG), which has been linked to macsyma in a package called NAGLINK. This is described in reference. (ref) If your system does not have NAGlink , but has another numerical library program for zero-finding, it can probably be connected to macsyma. Details on linking macsyma to such libraries is described in (ref: section ?). Factor and integrate are probably two of the more surprising commands in macsyma because most people who understand the problems involved are not familiar with general algorithms for solving them. There are general algorithms for these problems, although the algorithm for integration sometimes indicates that the answer does not exist in terms of elementary functions. When a general solution to a problem is not available, or even when it is known but inefficient, it is sometimes possible to simulate a good solution method by ``pattern recognition'': that is, by recognizing those cases that can be solved, and providing the answers, without dealing with the complete problem. Many user programs, and a few built-in macsyma facilities use this approach. Factor, and indeed many of the commands illustrated above, are used internally by macsyma for its own more complicated algorithms. For example, solve uses factor and other routines on polynomial problems. 2 Limitations You should realize that an algebraic manipulation system like macsyma cannot solve all symbolic problems. There are times when solve or integrate or other commands will determine that there are no closed-form solutions to the problem posed (in which case they will generally inform you of the situation). There are other instances in which the solution method may be known in principal, but because the calculations are so onerous, the computer seems unlikely to finish in a reasonable time. Algebraic computations are often subject to ``intermediate expression swell'' where (even though the final answer may be small -- perhaps 0), the route to the answer is difficult. Occasionally you may run out of memory space. A clever computer system administrator may change the program and operating system parameters to your benefit, but it is more likely that you should try to rearrange your computations. Just because it is possible to type a command in a syntactically satisfactory manner does not mean that the required computation is easy or even feasible. Once a computation has started, you may have second thoughts about allowing it to finish. Hence you might be concerned with the information in the next section: 2 Stopping You may, from time to time, get your system running on a fool's errand. How do you bring it to its senses? There are several related notions of running uncontrollably. If the output is streaming past you at too high a speed to read, (this is unlikely to happen on a slow printing terminal, but might happen on a display terminal) you can make the system pause by typing -S (that's done by holding the control key down and typing S. We usually write this as ^S), which is the default ``X-off'' character. Normally, no output gets lost, but transmission is temporarily halted. You can resume the display by typing -Q (or ``X-on''). Sometimes you want to halt computation, not just printing. You have an interrupt character, usually or ^C, which you have chosen as your standard in your UNIX operating system shell. If you wish to halt a computation, you can type this interrupt character one, two, or three times. The first character will cause an interrupt at the next available clean place in your computation. (Technically, this would be at the interface between some compiled and some interpreted code). If the interrupt does not happen promptly enough for you, you may type the interrupt character a second time. (Technically speaking, this will snap ``transfer links'' which are used when compiled code calls compiled code, and then cause an interrupt at the next such function-call.) It is possible to be caught in a very tight loop in which there are no function calls, in which case the third typing of the interrupt character will stop the computation cold. Even using this drastic interrupt, you will generally be able to avail yourself of any of several alternatives. When the system stops, it will type Interrupt (type h for help): You can then type one of several characters: q Just quit out of the interrupt and continue the computation (after displaying the time if showtime was set to true or all.); r Reset the computation to the top-level of macsyma , exit Exit from macsyma , l Enter a LISP break, (something a LISP expert might want to do: LISP, an acronym for LISt Processing Language, is the computer language in which macsyma is implemented.), m Enter a macsyma -break. This gives you a kind of macsyma -subprocess within your running program, which you can use to inquire about variables, resetting things, etc. You exit by typing exit; which returns you to your previous computation. h Type a menu of options. Basically what you see above. It is also possible to quit temporarily out of your job by typing ^Z. See your UNIX manual for details on job control, background jobs, and similar issues. Some people, in desperation, hang up their telephone. This might work, assuming you are connected to the computer that way. Turning the power off on a hard-wired terminal usually does not work. 2 Out of Core? In the 4BSD UNIX system, the message 'killed' or 'out of core' immediately after the starting of a vaxima means that there is currently insufficient free space on the swapping device to run macsyma . This can happen with any job, but is perhaps more likely to happen with macsyma because of its size. This situation is system-load dependent and swap-space dependent: when the load decreases, try again. 2 Quitting If you wish to exit from macsyma , in an orderly fashion, removing the quiescent job, returning control to the shell (or whatever invoked macsyma ), you can do this by typing the command exit(); 2 Storage Allocation and Timing If you run macsyma for long enough, and especially if you set up a long computation, you will see strange messages like the two below: [*list:634{22%}; fixnum:43{2%}; ut:0%] [*list:634{23%}; fixnum:43{2%}; ut:69%] This is caused by a phenomenon known as a ``garbage collection'' (really) which is part of the underlying LISP language system. This is an activity started up when the computation needs more free storage. The system then stops doing ``useful'' work, and identifies objects in memory which are no longer needed. This takes a few seconds of computer time (maybe 2), which under heavy load may take a half-minute of real time. A message occurs after each garbage collection. You cannot really stop the garbage collector, but you can stop the message from printing out by setting gcprint : false . You may think you don't want to see this information, but it is actually reassuring to know that your program is running sometimes, even though it is printing nothing but ``gc'' messages. Programs which may have run out of storage on other version of macsyma may run successfully on the VAX. However, the address space available to a user is in practice restricted by operating system constraints, some of which have been incorporated as parameters in the LISP system. An error message which declares ``Attempt to allocate beyond static structures'' indicates that you will have to have a reconfigured LISP system to grow larger. You should save your computation and ask your system administration or manager to make a larger LISP system and macsyma . This takes about 3 or 4 minutes of computation, but requires familiarity with the instructions for generating a system. Since the current allocation is really fairly large, you should also take this opportunity to see if you really want to continue with the computation. Large jobs in most time-sharing systems, tend to be more burdensome than small ones, even those running for longer periods of time. It is possible to fiddle with various allocations to attempt to decrease the number of garbage collections in a system which you suspect will require large amounts of a particular kind of space. The command alloc(,) allocates some number of pages. Spacetypes include list, bignum, fixnum, flonum, array and a few others. Most macsyma computations use list cells predominantly. See the Franz LISP manual for more details. The message ``[fasl hole filled up]'' which you may provoke by using the fasl or load program, is merely informative, and is not an indication of trouble. If the macsyma variable gcprint is set to a non-false value then after each garbage collection a summary of current memory allocation will be printed out in this form: [*list:634{87%}; fixnum:23{27%}; ut:87%]. The meaning of this is that after garbage collection and subsequent allocation of new data space, there are 634 (512 byte) pages of list data and 23 pages of fixnum data. 87% of the list space is used and 27% of the fixnum space is used. The * before list indicates that it was list space which ran out and caused the garbage collection. The ut indicates the percentage of time utilized in non-garbage collection mode. The first time the message is printed, this item will be 0% because various counters must be initialized. The allocation of storage is automatic; you will never be asked to make a decision about which data space to allocate, although a low utilization measure is an indication that automatic allocation is not working appropriately for your problem, and various parameters can be fiddled with via alloc. You can also get brief information about the time taken by each command by setting showtime : all. The ``garbage collection'' or ``gc'' time is indicated separately, because it happens asynchronously and it seems unfair to penalize a particular (perhaps millisecond) operation for the fact that it was the unlucky one to trigger a ``gc''. Intermission. Take a break. In the next two sections of the primer we introduce a number of facilities in macsyma useful in dealing with trigonometric functions. A section on rule-directed transformations follows, since our favorite examples are trigonometry simplifications. 2 Operations with Trigonometric Forms Consider the expression cos sup 2 x - sin sup 2 x . (c40) cos(x)^2-sin(x)^2; 2 2 (d40) cos (x) - sin (x) To evaluate the last expression at a point, say pi / 3 , you can use the ev command: (c41)ev(%,x=%pi/3) 1 (d41) - - 2 The value of 1 / 2 was obtained not by computing pi / 3 numerically and approximating the value of sin at that point, but by a routine which provides simplification of special values of trigonometric functions at points n pi / m , where m = 1,2,3,4,6 and n is an integer. To obtain a real approximation, we could use numer, as illustrated previously. Of course macsyma is able to differentiate expressions involving trigonometric functions, also as illustrated previously. (c42) diff(d40,x); (d42) - 4 cos(x) sin(x) and knows how to integrate them. (c43) integrate(d40,x); sin(2 x) sin(2 x) -------- + x x - -------- 2 2 (d43) ------------ - ------------ 2 2 This result is less than satisfactory. See what we can do: (c44) expand(%); sin(2 x) (d44) -------- 2 2 Trigonometric Re-representations and Identities There are a number of identity transformations specifically oriented to trigonometric forms. Whether these produce simpler or more complex expressions depends on the expressions they are used upon, and sometimes is a matter of opinion. macsyma can convert trigonometric functions with argument nx, n an integer, to trigonometric functions in x. You use trigexpand for this transformation: (c45) trigexpand(%); (d45) cos(x) sin(x) Another operation named trigreduce performs a related, almost ``inverse'' transformation, that of converting products of powers of trigonometric functions to functions with multiple angles. (c46) trigreduce(%); sin(2 x) (d46) -------- 2 Sometimes you wish to convert all trigonometric functions to exponentials with complex arguments. With the flag exponentialize set to true you can perform this transformation: (c47) exponentialize:true$ (c48) sin(x); %i x - %i x %i (%e - %e ) (d48) - ---------------------- 2 In order to convert back to trigonometric functions you can use realpart. First we must turn off the exponentialize flag. (c49) exponentialize:false$ (c50) realpart(d48); (d50) sin(x) Exponentials with complex arguments of the form n i pi / m , ~~~m = 1,2,3,4,6, n an integer, will be transformed to algebraic numbers if the flag %emode is set to true. (c51) %emode:true$ (c52) d50,x=%pi; (d52) 0 Before continuing, let's reset that flag. (c53) %emode:false$ A very powerful technique for approximation of analytic functions is the use of truncated Taylor series (more generally, Laurent series). macsyma provides a command for the computation of these approximations, as illustrated below: (c54) taylor(sin(x)/x,x,0,4); 2 4 x x (d54)/t/ 1 - -- + --- + . . . 6 120 This is a Taylor series in x about x=0 up to the 4th power. Observe that the display has some unusual features: the terms are ordered in reverse of the conventional (non-series) display, there is a /t/ mark near the label, and the ellipsis (. . .) is printed to the right to indicate truncation of other terms. Taylor series are a separate representation of expressions in macsyma . Recall that we have encountered the ``rational'' representation used internally by commands like ratsimp, factor, and sometimes in integrate. This form can also be directly provided in answers from some commands. All along we have been seeing a ``usual'' or ``general'' representation in our interactions. Thus we have already seen evidence of three representations. Many of macsyma 's most powerful commands for simplification are essentially switching between representations. There are a few more representations in the system directly accessible by the user such as ``Poisson'' series, used in celestial mechanics; there are a number of additional alternative representations used, but away from the user's sight. 2 Rules It is handy to have a facility for applying identities or side relations. The prototypical one is sin sup 2 x ~+~ cos sup 2 x ~ -> ~ 1 . There are a number of ways of achieving the effect of such a rule. The simplest is substitution. Let us recall expression d40. (c55) d40; 2 2 (d55) cos (x) - sin (x) (c56) %,sin(x)^2=1-cos(x)^2; 2 (d56) 2 cos (x) - 1 The same effect could have been achieved by using substitute(1-cos(x)^2,sin(x)^2,%). To continue with the same prototypical rule, often one wishes to recognize that sin sup 4 x can be transformed using the same rule. For this one needs the added power of ratsubst. (c57) ratsubst(1-cos(x)^2,sin(x)^2,sin(x)^4); 4 2 (d57) cos (x) - 2 cos (x) + 1 In general ratsubst will perform a ratsimp (and thus an expansion) as well as apply the substitution. When performing calculations repeatedly, you may wish to apply a substitution rule whenever possible. You can have an ``automatic'' facility, although not the full power of a ratsubst command by using a tellsimp rule. (c58) tellsimp(sin(x)^2,1-cos(x)^2)$ (c59) (sin(x)+1)^2; 2 (d59) (sin(x) + 1) (c60) expand(%); 2 (d60) 2 sin(x) - cos (x) + 2 (c61) sin(x)^2; 2 (c61) 1 - cos (x) You can ``tell the simplifier'' a more general rule which will convert sin sup 2 a to 1 - cos sup 2 a for any a using a declaration: (c62) matchdeclare(a,true)$ (c63) tellsimp(sin(a)^2,1-cos(a)^2)$ (c64) sin(y)^2; 2 (d64) 1 - cos (y) You should understand that the existence of such rules generally slows down the simplification of expressions with the same ``main operator'' as the tellsimp rules. In this case the main operator is ``^''. Another rule-defining mechanism, let has much of the power of a ratsubst, although it will be applied only when using letsimp. First let us remove the tellsimp rule. (c65) kill(rules)$ (c66) let(sin(a)^2,1-cos(a)^2); 2 2 (d66) (sin (a) --> 1 - cos (a)) Note that a is still declared true for matching purposes. To effect a transformation using the let rules, whatever their number, you use the letsimp command. (c67) sin(x)^4; 4 (d67) sin (x) (c68) letsimp(%); 4 2 (d68) cos (x) - 2 cos (x) + 1 We have not exhausted macsyma facilities for dealing with trigonometric functions, or for that matter, its facilities for defining and applying rules. Poisson series, mentioned earlier, deals with a special class of trigonometric expressions frequently used in celestial mechanics have a special representation. A program called trigsimp may provide appropriate simplifications in a goal-driven fashion (to make the smallest expression). Other ways of defining rules and ``advising'' the simplifier are described in the macsyma manual. Introduction to MACSYMA\'s Programming Language 2 2 Introduction 2 1 This second chapter of the primer on macsyma is intended for readers who are familiar with the basic ideas of algebraic manipulation from chapter 1, who know at least one programming language, and who wish to use macsyma for more ambitious tasks than can be handled in a few sequential commands. If you are familiar with Pascal or Algol 60, you will probably find this adequate as a programming background. Familiarity with Fortran or Basic is less useful. macsyma 's user-programming language\** \** The system-programming language used for implementing macsyma , namely LISP, is quite different. If you wish to see how macsyma was constructed, you need to know LISP to understand the source code. is designed to allow you to define program modules or ``functions'' for algebraic manipulation. Each module uses zero or more arguments, and returns an algebraic expression. Since numbers are special cases of algebraic expressions, macsyma 's user-language can be used as a numeric language too. Because the language is implemented as an interpreter it is usually more general than compiler-based languages, and also tends to be rather slow in tight inner loops of simple operations, by comparison. It has novel linguistic features, some of which are illustrated below. 2 Some Examples f1 and f2 defined below, are versions of the ``factorial'' function. Observe the punctuation carefully. Assignment is ``:'', function definition is ``:='', statements are separated from one another by ``,'' [not terminated by commas]. The label ``loop'' is set off by a comma as though it were a statement too. We have added indentation to make the programs conform to what you might expect, but extra spaces and tabs are optional. There is a conditional execution statement (the if) which has an optional else clause. (c1) f1(x):=if x<1 then 1 else x*f1(x-1)$ (c2) f1(5); (d2) 120 (c3) f2(x) := block ([temp], temp:1, while n > 1 do ( temp:n*temp, n:n-1), /*end while*/ temp)$ (c4) f2(5); (d4) 120 Observe the simplicity of using macsyma compared to, say, Pascal. There is no need to write a ``driver'' or main program with input or output commands. The input is provide through function application on an argument, and the output is the displayed value. Every command or function in macsyma has a value, and may, in addition, have some side-effects, such as the setting of variables, or the printing of messages. The block construction illustrated above is analogous to a procedure declaration. The first part of it is a list of local variables, and following that, expressions which are evaluated in order. Certain expressions or commands make sense only within a block, not at macsyma 's command level: these are labels, returns and gos. The semantics of each of these commands conforms to the usual intuitive meaning. If the last statement in a block does not cause a transfer of control, and ``execution falls through the bottom'', the value returned from the block is the value of the last expression evaluated. 2 Unconventional Conditionals The next example shows a function with a side-effect, but the major point is to illustrate some subtleties which you may not have thought about in conditional statements (if-then-else). If you were asked, ``Is A greater than B'', it would seem you could respond either ``yes'' or ``no''. In your conventional programming language, certainly, that would be a reasonable assumption. But really, wouldn't it be appropriate in some circumstances for you to answer, ``How should I know?''? That option is preserved in macsyma . If the flag prederror is set to true, the default, and if macsyma is unable to evaluate a predicate, it signals an error, and unless directed otherwise, returns control to the top-level macsyma command monitor. However, if the prederror flag is false, execution continues to the next statement, ignoring both then and else clauses! This is illustrated below: (c5) test(x,y):=block([], if x > y then print(x, '' is greater than '', y) else print(x, '' is not greater than'', y), return(alldone))$ (c6) test(4,3); 4 is greater than 3 (d6) alldone (c7) test(3,4); 3 is not greater than 4 (d7) alldone (c8) test(y^2+1,-y); 2 MACSYMA was unable to evaluate the predicate: y + 1 > - y (c9) prederror:false$ (c10) test(y^2+1,-y); (d10) alldone Note that no message was printed for line d10, but the return value, ``alldone'' was displayed. 2 Assumptions What do YOU think? Is y sup 2 + 1 ~>~ - y? For this question to make sense, both sides of the inequality must be in the same ordered domain. We do not know, offhand, whether y can assume values which are matrices, complex numbers, sets, or even programs! If y were known to be real, or more specifically, positive real, a program could try some deduction. macsyma has some features of this nature, as illustrated below. (c11) assume(y>0); (d11) [y > 0] (c12) test(y^2+1,-y); 2 y + 1 is greater than - y (d12) alldone If we wish macsyma to forget that assumption, (c13) forget(y>0); (d13) [y > 0] 2 Arbitrary Numbers of Parameters Ambitious packages of programs have been written by many macsyma users. Sometimes the requirement that a command has a fixed number of arguments causes discomfort.\** \** The language Pascal does not allow you to define a function f which can be used with a variable number of actual parameters, although the Pascal design includes built-in procedures with variable numbers of arguments (write for example). It is possible to write a macsyma program which counts the number of arguments it is given, sets default values for others, and does any number of clever things. A simple example is shown below. Note the way the ``left-hand-side'' of the ``:='' is set up. (c14) prog3([l]) := block( [], print (''l is bound to'', l, '' and l[1] is '',l[1]), return(length(l)))$ (c15) prog3(a,b,c,d); l is bound to [a, b, c, d] and l[1] is a (d15) 4 (c16) prog3(a,b); l is bound to [a, b] and l[1] is a (d16) 2 2 Arrays Arrays are a useful data structure, and are provided in most programming languages. macsyma provides arrays, but does not require that they be declared, or that they have numeric (integer) index-sets. Rather than writing a program to fill up an array and then iterating through all elements, sometimes it is easier to describe a program to generate elements as they are called for. Such array-associated functions are often quite convenient. The usual way you set them up is to provide specific values for certain index values, and then let others be assigned as needed. Note carefully the use of ``:='' and ``:''. (c17) a[4]:4*u; (d17) 4 u (c18) a[22/7]:%pi; (d18) %pi (c19) a[x]:mystery; (d19) mystery (c20) a[h]:=cos(h); (d20) a := cos(h) h (c21) a[3]; (d21) cos(3) (c22) a[x+1]; (d22) cos(x + 1) You might wonder what the value of a is, after all this. Most disappointing: (c23) a; (d23) a The information that you are after is available this way: (c24) arrayinfo(a); 22 (d24) [hashed, 1, [3], [--], [4], [x], [x + 1]] 7 The list of information supplied indicates several aspects of the array. It is ``hashed'': uses the data-structure of a hash-table for storage (this is a common encoding trick discussed in data structure texts). The number of subscripts is 1. The specific indexes for which it has recorded values are listed. The array-associated function defined on line c20 can be displayed by dispfun. 2 Iteration ``For'' loops provide the major iteration facility in macsyma . Three examples which illustrate variants of this are the factorial functions below: (c25) f3(n) := block([temp], temp:1, for i:1 thru n do temp : temp*i, return(temp))$ (c26) f4(n) := block([temp], temp:1, for i:n step -1 thru 1 do temp : temp*i, return(temp))$ (c27) f5(n) := block([temp], temp:1, for i:n unless i <= 1 do (temp : temp*i , i:i-2), return(temp))$ Decrementing i by 2 in the previous program was needed because the default step size of 1 is added to i each time through. F5 is certainly a perverse program. Incidentally, returns from within a for exit from the loop, and not from the enclosing block. It is important to note that one can group a collection of statement to be ``done'' together with parentheses, as illustrated in f5. 2 Serious Business Most serious users of macsyma find that they are repeatedly using the same programs, and need to save them for another day. Some users also find they rarely get the programs or the data quite right the first time, and would rather type these things in to a text editor, and have macsyma gobble the text up from a file rather than the keyboard. Publication quality programs require comments and other features you are unlikely to want to type into macsyma interactively. Some people perfect a function or get an algebraic expression correct by typing definitions and commands into a file, say, newstuff, using an editor such as ed, ex, vi, or emacs and then within macsyma type batch(newstuff);. If your file-name has funny characters like periods or slashes, you must use quotes. For example, batch("/usr/mac/demo.begin"). macsyma then reads the statements the file, assigning labels etc., and if there are syntax or other errors, prompts for help from the keyboard. If you want it to continue on to the next line after an error, type batcon(true); . Reading very large text files of programs and data can be slow using batch, and if you are not changing the text, you might prefer saving your environment in another way. You can use save(savedstuff,all); to save every named or labelled object in a macsyma system, on the file savedstuff in your working directory. (You had better have write-permission or you'll get an error message.) Another time you can start up from where you left off by typing loadfile(savedstuff); into a fresh macsyma . You can load several saved files into a single system. Naturally if the files contain items with identical names, there is a potential for conflict. These will be resolved in favor of the last item read in. If you want to save only some material you have produced, say only the functions defined and the values of variables x, y, and z, you can type save(savfunxyz,functions,x,y,z); A neat way to save a useful section of your environment is to (carefully) use kill to remove useless items first, and then save all that is left. Doing kill(labels,...) after first making sure that any useful result also has a name other than a c or d-label is sometimes a good start. You generally should not save every computation, since disk space is not infinite. 2 Hardcopy If you print out the files produced by save to show to your colleagues who are as yet unconvinced of the merits of macsyma , you will be disappointed. While such files are ``ASCII'' character text, they do not make easy reading for persons uninitiated in various arcane matters. What you might want to do, then, is store human-readable versions of your output on a file. This is especially useful if you have a display terminal, or a slow hardcopy printer. macsyma provides a way of opening a file for echoing both input and output of the system. The command writefile(fn); where fn is a filename, starts the echoing, and closefile(); stops the echoing. If you want the output to be human-readable after being run through a typesetting program (eqn + troff in UNIX), you can experiment with the output produced by setting typeset : true . (Suggestion: gcprint : false is a good idea.) 2 Return to Arrays and Functions macsyma provides a fascinating trick: arrays of functions. Imagine an array, each of whose elements is a function. For example, Legendre polynomials have an index, and an argument. Thus we can refer to P sub 4 ( z sup 2 ). Just as arrays can have an associated function, function-arrays can have such an associated function. Because we like to show off occasionally, and typesetting can be done by the VAX macsyma system, we illustrate this feature here. This was produced by saving output in a file and running it through ``troff'' ( T\dE\uX may be an alternative at some time). (c28) p[n](x):=ratsimp(1/(2^n*n!)*diff((x^2-1)^n,x,n)); I (d28) p sub n [ x ] ~:=~ "ratsimp" ( 1 over { 2 sup n \^ n ! } \^ { d sup n } over { d x sup n } ( x sup 2 ^-^ 1 ) sup n ) (c29) p[4]; I (d29) lambda ( [ x ] , { "35" \^ x sup 4 ^-^ "30" \^ x sup 2 ^+^ 3 } over 8 ) (c30) p[4](y+1); I (d30) { "35" \^ ( y ^+^ 1 ) sup 4 ^-^ "30" \^ ( y ^+^ 1 ) sup 2 ^+^ 3 } over 8 The ``lambda'' (lambda) notation for a raw function of one variable appears on line c29. This notation comes from the ``lambda-calculus'' used to describe the programming language LISP, and illustrates the fact that macsyma can talk about such structures. You can generally ignore this fact, however. 2 More Useful Examples As has been indicated earlier, procedures in macsyma can be used for almost any classical programming purposes (e.g. numerical techniques, combinatorial search). We have already indicated some differences from a purely numerical language, such as FORTRAN. We have seen that in macsyma there are no required type declarations, and floating-point numbers, while ``contagious'' in the sense that mixed-mode (floating-point + integer) is converted to floating-point, do not necessarily arise from certain calculations. For example, sin(3) normally results in sin(3) in macsyma , rather than its floating-point equivalent. sin(3.0) will, however, return a floating-point number. The numerical subroutine below, a Newton's method zero-finder sets the flag numer to true to force macsyma to convert most expressions free of indeterminates to numbers. This program uses Newton's method to find a zero of the expression exp which depends on the variable var. The iteration starts with var=x0 and terminates when the expression, evaluated at the trial-point, has absolute value less than eps. The derivative of exp is computed algebraically, and its value is computed at various points as the search is being conducted: 0 (c1) newton(exp,var,x0,eps):= /* 1 */ block([xn,s,numer], /* 2 */ numer:true, /* 3 */ s:diff(exp,var), /* 4 */ xn:x0, /* 5 */ while abs(subst(xn,var,exp))> eps do xn:xn-subst(xn,var,exp)/subst(xn,var,s), return(xn) ) /* 8 */$ This procedure for Newton's method uses an explicit expression for the first argument exp (e.g. sin(x)*erf(2*x)-%e^x ). It is not a function name, e.g. f as we used before. The use of such an expression is straightforward and probably the best way for a beginner. The resulting program is somewhat verbose, because, as illustrated in lines 6 and 7 above, it is necessary to substitute values for variables in the expression and its derivative, s, to get numbers. Note the setting of numer on line 3 to assure that the if statement on line 6 would get numerical values for its test. The rest of the procedure is the classical Newton iteration. The advantage of this procedure over a purely numerical one is that it takes advantage of the ability to compute the derivative of exp algebraically and automatically, once, before evaluating it at any point. Another item to observe here is the use of comments in the text of programs which are batched in to the system. /* This is a comment */ . There are often many different ways of expressing the same computation, and some of them may be substantially more convenient or efficient than others. While it may not make much of a difference in efficiency in this case, the following revision of the newton procedure illustrates some techniques you may find useful in macsyma . 0 (c2) newton(exp,var,x0,eps):= /* 1 */ block([ xn:x0, s:diff(exp,var), numer:true], /* 2 */ define(f(var), exp), /* 3 */ define(fprime(var),s), /* 4 */ loop, if abs(f(xn)) < eps then return(xn), /* 5 */ xn: xn - f(xn)/fprime(xn), /* 6 */ go (loop) ) /* 7 */ $ Observe the list of local names at the beginning of the block, which are initialized at the same time they are declared on line 2. Lines 3 and 4 are interesting because they define two new functions, f and fprime each to have as their bodies, the values of exp and s. The Newton iteration is more easily observed in functional rather than ``substitution'' notation. An even smaller version of newton could be defined by using a single function for exp/diff(exp,var). Let us try this last function: (c3) h:expand((x-1)*(x-3)*(x-5)); 3 2 (d3) x - 9 x + 23 x - 15 (c4) newton(h,x,3.5,1.0e-10); (d4) 2.999999999994027 You might wonder how many iterations that took. One way is to use the very convenient debugging feature provided by macsyma which allows you to watch the assignment of values to variables. You set the variable setcheck to a list of the variables you wish to watch. (or all to watch all the variables.) (c5) setcheck:[xn]$ (c6) newton(h,x,3.5,1.0e-10); xn set to 3.5 xn set to 2.923076923076923 xn set to 3.000228597554006 [*flonum:20{5%}; list:634{17%}; fixnum:43{2%}; ut:0%] xn set to 2.999999999994027 (d6) 2.999999999994027 (That message ``[*flonum: ...]'' is a message from the garbage collector, mentioned in the first section of the primer. ) That tells us that only three iterations were needed in this case. We claimed that two functions were defined in running this program. To display a function using the same syntax that you would use to type it in, you use the grind\** command. \** When computers were slow and programs were large, reformatting programs took a long time. The name of a program at MIT to ``grind out'' LISP function definitions was grindef. The name was carried over to macsyma . Now, most LISP systems call this reformatting ``prettyprinting''. (c7) grind(fprime); fprime(x):=3*x^2-18*x+23$ (d7) done 2 Part Hacking An important tool for applications programs in macsyma the ability to extract and test parts of expressions. These are used for the definition or extension of algorithms which do various conditional manipulation of formulas. For example, you can write a symbolic differentiation algorithm for expressions by applying the rules below: I (1) d over dx~ x ~=~ 1 ~~~~~~~d over dx~ y ~=~ 0 ~~(y != x) I (2) d over dx~ ( u + v) ~=~ d over dx~ u ~+~ d over dx~ v I (3) d over dx~ ( u cdot v) ~=~ v d over dx~ u ~+~ u d over dx~ v The technique we shall consider for implementing a version of the differentiation program is to take the expression apart using the part command, and use the rules above to guide the manipulation. First, we check to see if the expression is an atom (e.g. number, variable). Thus we begin our differentiation program as follows: 0 newdiff(expr,var):= if atom(expr)=true then (if expr=var then 1 else 0) This fragment implements both parts of rule 1. If the if statement falls through to the else clause, then we have a composite expression. We then check what its leading operator is by selecting its zeroth ``part'' via part(expr,0). Based on its value we apply the appropriate rule. else if part(expr,0)=''+'' then newdiff(part(expr,1),var) + newdiff(part(expr,2),var) else if part(expr,0)=''*'' then part(expr,2)*newdiff(part(expr,1),var) + part(expr,1)*newdiff(part(expr,2),var) else 'newdiff(expr,var)$ Note the last clause which returns a 'newdiff form, that is, quoted, as a result when the program doesn't know how to handle the leading operator. With some thought, you should now be able to extend newdiff to accommodate expressions including sin and cos as well as sums and products with more than two terms. (The macsyma language does not at the moment have a case statement, which would make this particular program look better.) 2 User Representation of Data There is no ``record'' or ``structure'' data-type ``constructor'' in macsyma , but there is a way of doing something similar. If you have used a language like Pascal which has such a feature, you may appreciate its usefulness. Modern dialects of LISP use such structures, but when macsyma was first designed and initially implemented (in 1967), this was not in widespread use. It also influenced the user-level programming language. It is natural to have to deal with collections of information in writing programs. For example, you might wish to provide as input or output data, a pair of expressions representing a lower and an upper bound on a formula. One way of handling this is by making up a new ``function'' name, say bounds and using it as though it were a record designator or constructor, but never associating it with an algorithm. Thus bounds(1,x) could be an expression representing the ordered pair <1,x>. Another example would be the use of integer_vector(1,3,5,7) to designate a sequence (presumably of arbitrary length, in general), of integers. There is a built-in form in macsyma , namely a ``list'', which can be used to deal with such collections. It is part of the LISP heritage indicated earlier that there was initially only one type of structure: lists of any length or element type in macsyma . A list, when printed, looks like square-brackets enclosing a sequence of items. Thus you could express the bounds above as [1,x]. However, if you used lists for all collections, you would not know, on the face of it, whether [1,2] was an instance of bounds or integer_vector. macsyma allows you to designate functions you intend to treat as lists, although you can use a different ``header'' like bounds with each different type. macsyma makes available certain built-in functions which can then be used on such list-like constructions such as integer_vector. These are declared by, for example, declare(integer_vector,list). The built-in operations include cons, append, member, endcons, map, rest. list2:cons(element,list1) returns a (new) list2 which has the given element inserted at the beginning of list1; List1 and list2 have a common ``shared'' tail. list3:append(list1,list2) returns a (new) list3 which is a combination of the two lists, sharing a common tail with list2. Member(element,list) returns true or false depending on a test for membership. Endcons(element,list) returns an (unshared) list where the given element has been attached to the end of given list Map(fn,list) returns a new list where each element has had the function fn applied to it in turn. Rest(list,n) returns the part of the list beginning n items from the front. These functions are parts of the fundamental repertoire of the programming language LISP. The use of list-like objects should be considered whenever you are dealing with a collection of elements: a set of coordinates, a series of coefficients, a system of equations, a set of solutions, etc. Independent of the ``whole list'' operations above, macsyma has some selection and alteration operations which are available on the same collections of data by the use of a numeric index. If you wish to use these indexing facilities, as we will illustrate for the notion of complex below, you declare(complex,list). Then, if you define a complex number by x:complex(3,4) meaning that x has real part 3, and imaginary part 4, the notation x[1]:10; is supported, and changes the value of x to complex(10,4). The declaration explains to the macsyma system that the data structure for complex will be implemented (in effect) as a list of items, and should be decomposable using the semantics of the macsyma list-handling commands. In fact, both selection and alteration is supported, and if you set the notation up by (real:1,imag:2)$ you can use the following command: x[imag]:-x[imag] to change x to its complex conjugate. An important caution must be observed. When macsyma deals with compound structures, they are usually not recopied, and if there are two names for the same object and the object is changed, then both names refer to the changed object. If x and y refer to the same complex number, then changes to x[real] are also made to the corresponding component of y. If these items are to be kept separate, x:copylist(y); will give x a different representation, but whose value is the same as y's. You can then change their components separately. macsyma 's built-in lists mentioned earlier, which use square-brackets, can be altered and selected by indexing. There are two other compound structures in macsyma which we mention here, which may be useful for collections of data: arrays and matrices. The matrix form is useful for two-dimensional rectangular tables of data. The matrix data format is supported by a number of special commands oriented toward the conventional interpretation of matrices in mathematics: inverses, determinants, etc. Matrices can be used for other kinds of data, but you should be cautious about using them in a manner that is too far distant from the conventional: arithmetic operations in macsyma , in particular, have already been defined. Arrays are unusual in their flexibility in macsyma . They are usually treated as global tables, although they can be declared to be local to a function; they cannot be passed around as parameters as is the case with matrices. The names of arrays may be passed from program to program, but the data itself is not recopied, nor is it convenient to even make a copy of the data into another array. ``Hashed'' arrays are particularly ingenious, and have been illustrated earlier. Functions can be associated with arrays to provide new values for entries as they are required. At this point you should be able to make use of the macsyma manual to learn more details for representation of new data types as you develop your application. 1 More learning The true programming buff may also be interested in the macro-expansion capabilities of macsyma and its extensible syntax. At this point we would discourage the use of these facilities by novices, but encourage their use by persons willing to experiment in providing the most versatile user-oriented packages within the macsyma framework. There is a ``compilation'' facility which allows users to translate macsyma code into potentially faster running code. Since most of the time in most programs is used by calls to LISP programs, this is usually ineffective. In general, this should be avoided by novices and most experienced users, since time spent on this is more wisely spent on mathematical restructuring of the solution method, or (in the case of primarily numerical computation), using a numerical library routine written in a suitable language. 1 Maxims for the MACSYMA User Some beginning users of algebraic manipulation systems find that their previous experiences with traditional programming systems do not translate easily into algebraic programming; others find macsyma descriptions inadequate because the emphasis is on the mixture of mathematical notations and algorithms, and not on ``efficient'' use of machine or human resources (no one likes to wait longer than necessary for an answer!). While we cannot provide a complete education in efficient and effective programming, we have collected a few ``maxims'' in an attempt to help you with some of these ``start-up'' problems. Algebraic manipulation is a new and different computational approach for which prior experience with computational methods may be misleading. You should attempt to learn the ways in which algebraic manipulation differs from other approaches. For example, consider the problem of inverting an n times n matrix. In numerical analysis we learn that the problem requires on the order of n sup 3 operations. Theoreticians will point out that for n sufficiently large, one can reduce the number of multiplications below n sup 3 to n sup 2.8. This analysis is unfortunately not relevant in dealing with matrices with symbolic entries. Consider the number of terms in the determinant of the general n times n matrix whose elements are the symbols a sub i,j . When the inverse is written out in a fully expanded form, just the determinant (a necessary part of representing the inverse) has n ! terms. It is impossible to compute this determinant in less than ``time proportional to n !'' In fact, for large n, it is just not feasible to compute this form explicitly on existing computers. The combinatorial or exponential character that some algebraic manipulation problems have when they are approached with an inefficient algorithm, makes for a vastly different game from, say, numerical computation, where the size of objects is generally known at the onset of the calculation, and does not increase. Needlessly generalizing a problem usually results in unnecessary expense. For example, if you wish to obtain determinants for a collection of matrices whose general pattern of entries is represented by parametric formulas, you might consider obtaining the determinant of the general matrix and substituting various values for the parameters into the result. This may work for matrices of low order, but is probably a poor plan for dealing with the exponential growth inherent in computing symbolic determinants. It would probably be better to substitute the parameters first, since this would drastically reduce the cost of the determinant calculation. Sometimes, when humans are dealing with formulas, it is preferable to use an indeterminate, say G in a formula which is really known to be, say, 3/5. On the other hand, it is likely (although not certain!) that the calculation using 3/5 will take less time than the calculation with G. Since the cost inherent in some computations is usually a function of the number of variables in the expression, it pays to reduce the number of variables in a problem as much as possible. You should be aware of the types of calculations which in the general case have exponential growth (e.g. many matrix calculations with symbolic entries, repeated differentiation of products or quotients, solution of systems of polynomial equations). Your should anticipate a certain amount of trial-and-error in calculations. Just as in other problem-solving activities, often the first technique that comes to mind is not the best. While it occasionally happens that brute force carries the day, cleverness in computing can be as important as cleverness in hand calculations. It is natural, during hand calculations, to apply critical simplificiations or substitutions in computations. These simplifications include collecting terms selectively or striking out terms which do not ultimately contribute to the final answer because of physical interpretations. Computer algorithms which do not incorporate these same tricks may bog down surprisingly soon. Thinking about these shortcuts may be important. In fact, it is one of the more rewarding aspects of computer algebra systems that they give the problem solver an opportunity to organize, encapsulate and distribute a particularly clever piece of mathematical manipulation. Try to reduce your problem so that it can be performed in a simpler domain. For example, if your problem appears to involve trigonometric functions, logs, exponentials, etc. see if you can reduce it to a rational function (ratio of polynomials) problem. If it appears to be a rational function, see if you can, by substitutions, make it into a polynomial problem, or a truncated power-series problem. If it appears to be a problem involving rational numbers, consider the use of floating-point numbers as an alternative, if the growth in the size of numbers presents difficulties. There are other special forms that are especially efficient. In a number of areas of investigation it pays to convert all expressions to the internal rational form (using rat) or into Poisson-series form (using intopois) to avoid the overhead the the general representation. The price you may pay here is thtat the structure of the formulas may be significantly different from those you began with: The canonical transformations used by these representations drastically re-order, expand, and modify the original expressions. Sometimes someone else has already started on your problem. You should look through the ``share'' directory programs available to see if there are contributed packages that might be of use either as subroutines or as models for programming. You should also consider writing programs that you develop in solving your problems in a form suitable for sharing with others. Pattern matching allows you to ``tune'' the system simplifier to your application, and develop rule-replacement programs. Learning to use the pattern-matching facilities effectively is a nontrivial task. Nevertheless if you have a fairly complex problem involvilng the recognition and application of identities, you should consider making an effort to use these facilities. In recent years, advocates of ``rule-based expert systems'' have claimed that this type of formalism can or should be used to incorporate varied types of knowledge. Algebraic manipulation programs have depended on pattern matching since at least 1961, for some of their power. Finally, we would like to point out that algebraic manipulation systems, in spite of their pitfalls, can be of major assistance in solving difficult problems. If you are willing to invest some time in learning, there may be enormous benefits in using such a system. We think it is unfortunate that some users reserve macsyma for difficult problems. Those of us who have grown up with macsyma near at hand find it of great use in routine computations as well. We have enjoyed constructing macsyma , and we hope that you will enjoy using it. We hope you will consider contributing to program libraries at your local installation and at other sites. Naturally, any comments or additions to this primer are welcome. Richard Fateman University of California, Berkeley (Last revision 12/85)