Artifact e231e5e15816393a21e8a55481f11a46c0568bdcd4613e038e29eba1db4752cf:
- Executable file
r37/doc/manual/symbolic.tex
— part of check-in
[f2fda60abd]
at
2011-09-02 18:13:33
on branch master
— Some historical releases purely for archival purposes
git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1375 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 22496) [annotate] [blame] [check-ins using] [more...]
\chapter{Symbolic Mode}\index{Symbolic mode} At the system level, {\REDUCE} is based on a version of the programming language Lisp\index{Lisp} known as {\em Standard Lisp\/} which is described in J. Marti, Hearn, A. C., Griss, M. L. and Griss, C., ``Standard LISP Report" SIGPLAN Notices, ACM, New York, 14, No 10 (1979) 48-68. We shall assume in this section that the reader is familiar with the material in that paper. This also assumes implicitly that the reader has a reasonable knowledge about Lisp in general, say at the level of the LISP 1.5 Programmer's Manual (McCarthy, J., Abrahams, P. W., Edwards, D. J., Hart, T. P. and Levin, M. I., ``LISP 1.5 Programmer's Manual'', M.I.T. Press, 1965) or any of the books mentioned at the end of this section. Persons unfamiliar with this material will have some difficulty understanding this section. Although {\REDUCE} is designed primarily for algebraic calculations, its source language is general enough to allow for a full range of Lisp-like symbolic calculations. To achieve this generality, however, it is necessary to provide the user with two modes of evaluation, namely an algebraic mode\index{Algebraic mode} and a symbolic mode.\index{Symbolic mode} To enter symbolic mode, the user types {\tt symbolic;} \ttindex{SYMBOLIC} (or {\tt lisp;})\ttindex{LISP} and to return to algebraic mode one types {\tt algebraic;}.\ttindex{ALGEBRAIC} Evaluations proceed differently in each mode so the user is advised to check what mode he is in if a puzzling error arises. He can find his mode by typing\ttindex{EVAL\_MODE} \begin{verbatim} eval_mode; \end{verbatim} The current mode will then be printed as {\tt ALGEBRAIC} or {\tt SYMBOLIC}. Expression evaluation may proceed in either mode at any level of a calculation, provided the results are passed from mode to mode in a compatible manner. One simply prefixes the relevant expression by the appropriate mode. If the mode name prefixes an expression at the top level, it will then be handled as if the global system mode had been changed for the scope of that particular calculation. For example, if the current mode is {\tt ALGEBRAIC}, then the commands \extendedmanual{\newpage} \begin{verbatim} symbolic car '(a); x+y; \end{verbatim} will cause the first expression to be evaluated and printed in symbolic mode and the second in algebraic mode. Only the second evaluation will thus affect the expression workspace. On the other hand, the statement \begin{verbatim} x + symbolic car '(12); \end{verbatim} will result in the algebraic value {\tt X+12}. The use of {\tt SYMBOLIC} (and equivalently {\tt ALGEBRAIC}) in this manner is the same as any operator. That means that parentheses could be omitted in the above examples since the meaning is obvious. In other cases, parentheses must be used, as in \begin{verbatim} symbolic(x := 'a); \end{verbatim} Omitting the parentheses, as in \begin{verbatim} symbolic x := a; \end{verbatim} would be wrong, since it would parse as \begin{verbatim} symbolic(x) := a; \end{verbatim} For convenience, it is assumed that any operator whose {\em first\/} argument is quoted is being evaluated in symbolic mode, regardless of the mode in effect at that time. Thus, the first example above could be equally well written: \begin{verbatim} car '(a); \end{verbatim} Except where explicit limitations have been made, most {\REDUCE} algebraic constructions carry over into symbolic mode.\index{Symbolic mode} However, there are some differences. First, expression evaluation now becomes Lisp evaluation. Secondly, assignment statements are handled differently, as we shall discuss shortly. Thirdly, local variables and array elements are initialized to {\tt NIL} rather than {\tt 0}. (In fact, any variables not explicitly declared {\tt INTEGER} are also initialized to {\tt NIL} in algebraic mode, but the algebraic evaluator recognizes {\tt NIL} as {\tt 0}.) Finally, function definitions follow the conventions of Standard Lisp. To begin with, we mention a few extensions to our basic syntax which are designed primarily if not exclusively for symbolic mode. \section{Symbolic Infix Operators} There are three binary infix operators in {\REDUCE} intended for use in symbolic mode, namely . {\tt (CONS), EQ and MEMQ}. The precedence of these operators was given in another section. \section{Symbolic Expressions} These consist of scalar variables and operators and follow the normal rules of the Lisp meta language. {\it Examples:} \begin{verbatim} x car u . reverse v simp (u+v^2) \end{verbatim} \section{Quoted Expressions}\ttindex{QUOTE} Because symbolic evaluation requires that each variable or expression has a value, it is necessary to add to {\REDUCE} the concept of a quoted expression by analogy with the Lisp {\tt QUOTE} function. This is provided by the single quote mark {\tt '}. For example, \begin{quote} \begin{tabbing} {\tt '(a b c)} \= represents the Lisp S-expression \= {\tt (quote (a b c))}\kill {\tt 'a} \> represents the Lisp S-expression \> {\tt (quote a)} \\ {\tt '(a b c)} \> represents the Lisp S-expression \> {\tt (quote (a b c))} \end{tabbing} \end{quote} Note, however, that strings are constants and therefore evaluate to themselves in symbolic mode. Thus, to print the string {\tt "A String"}, one would write \begin{verbatim} prin2 "A String"; \end{verbatim} Within a quoted expression, identifier syntax rules are those of {\REDUCE}. Thus {\tt (A~!.~~B)} is the list consisting of the three elements {\tt A}, {\tt .}, and {\tt B}, whereas {\tt (A . B)} is the dotted pair of {\tt A} and {\tt B}. \section{Lambda Expressions}\ttindex{LAMBDA} \label{sec-lambda} {\tt LAMBDA} expressions provide the means for constructing Lisp {\tt LAMBDA} expressions in symbolic mode. They may not be used in algebraic mode. Syntax: \begin{verbatim} <LAMBDA expression> ::= LAMBDA <varlist><terminator><statement> \end{verbatim} where \begin{verbatim} <varlist> ::= (<variable>,...,<variable>) \end{verbatim} e.g., \begin{verbatim} lambda (x,y); car x . cdr y; \end{verbatim} is equivalent to the Lisp {\tt LAMBDA} expression \begin{verbatim} (lambda (x y) (cons (car x) (cdr y))) \end{verbatim} The parentheses may be omitted in specifying the variable list if desired. {\tt LAMBDA} expressions may be used in symbolic mode in place of prefix operators, or as an argument of the reserved word {\tt FUNCTION}. In those cases where a {\tt LAMBDA} expression is used to introduce local variables to avoid recomputation, a {\tt WHERE} statement can also be used. For example, the expression \begin{verbatim} (lambda (x,y); list(car x,cdr x,car y,cdr y)) (reverse u,reverse v) \end{verbatim} can also be written \begin{verbatim} {car x,cdr x,car y,cdr y} where x=reverse u,y=reverse v \end{verbatim} Where possible, {\tt WHERE} syntax is preferred to {\tt LAMBDA} syntax, since it is more natural. \section{Symbolic Assignment Statements}\index{Assignment} In symbolic mode, if the left side of an assignment statement is a variable, a {\tt SETQ} of the right-hand side to that variable occurs. If the left-hand side is an expression, it must be of the form of an array element, otherwise an error will result. For example, {\tt x:=y} translates into {\tt (SETQ X Y)} whereas {\tt a(3) := 3} will be valid if {\tt A} has been previously declared a single dimensioned array of at least four elements. \section{FOR EACH Statement}\ttindex{FOR EACH} The {\tt FOR EACH} form of the {\tt FOR} statement, designed for iteration down a list, is more general in symbolic mode. Its syntax is: \begin{verbatim} FOR EACH ID:identifier {IN|ON} LST:list {DO|COLLECT|JOIN|PRODUCT|SUM} EXPRN:S-expr \end{verbatim} As in algebraic mode, if the keyword {\tt IN} is used, iteration is on each element of the list. With {\tt ON}, iteration is on the whole list remaining at each point in the iteration. As a result, we have the following equivalence between each form of {\tt FOR EACH} and the various mapping functions in Lisp: \begin{center} {\tt \begin{tabular}{|l|lr r|} \hline & DO & COLLECT & JOIN \\ \hline IN & MAPC & MAPCAR & MAPCAN \\ ON & MAP & MAPLIST & MAPCON \\ \hline \end{tabular}} \end{center} {\it Example:} To list each element of the list {\tt (a b c)}: \begin{verbatim} for each x in '(a b c) collect list x; \end{verbatim} \section{Symbolic Procedures}\index{Symbolic procedure} All the functions described in the Standard Lisp Report are available to users in symbolic mode. Additional functions may also be defined as symbolic procedures. For example, to define the Lisp function {\tt ASSOC}, the following could be used: \begin{verbatim} symbolic procedure assoc(u,v); if null v then nil else if u = caar v then car v else assoc(u, cdr v); \end{verbatim} If the default mode were symbolic, then {\tt SYMBOLIC} could be omitted in the above definition. {\tt MACRO}s\ttindex{MACRO} may be defined by prefixing the keyword {\tt PROCEDURE} by the word {\tt MACRO}. (In fact, ordinary functions may be defined with the keyword {\tt EXPR} \ttindex{EXPR} prefixing {\tt PROCEDURE} as was used in the Standard Lisp Report.) For example, we could define a {\tt MACRO CONSCONS} by \begin{verbatim} symbolic macro procedure conscons l; expand(cdr l,'cons); \end{verbatim} Another form of macro, the {\tt SMACRO}\ttindex{SMACRO} is also available. These are described in the Standard Lisp Report. The Report also defines a function type {\tt FEXPR}.\ttindex{FEXPR} However, its use is discouraged since it is hard to implement efficiently, and most uses can be replaced by macros. At the present time, there are no {\tt FEXPR}s in the core REDUCE system. \section{Standard Lisp Equivalent of Reduce Input} A user can obtain the Standard Lisp equivalent of his {\REDUCE} input by turning on the switch {\tt DEFN}\ttindex{DEFN} (for definition). The system then prints the Lisp translation of his input but does not evaluate it. Normal operation is resumed when {\tt DEFN} is turned off. \section{Communicating with Algebraic Mode}\index{Mode communication} One of the principal motivations for a user of the algebraic facilities of {\REDUCE} to learn about symbolic mode\index{Symbolic mode} is that it gives one access to a wider range of techniques than is possible in algebraic mode\index{Algebraic mode} alone. For example, if a user wishes to use parts of the system defined in the basic system source code, or refine their algebraic code definitions to make them more efficient, then it is necessary to understand the source language in fairly complete detail. Moreover, it is also necessary to know a little more about the way {\REDUCE} operates internally. Basically, {\REDUCE} considers expressions in two forms: prefix form, which follow the normal Lisp rules of function composition, and so-called canonical form, which uses a completely different syntax. Once these details are understood, the most critical problem faced by a user is how to make expressions and procedures communicate between symbolic and algebraic mode. The purpose of this section is to teach a user the basic principles for this. If one wants to evaluate an expression in algebraic mode, and then use that expression in symbolic mode calculations, or vice versa, the easiest way to do this is to assign a variable to that expression whose value is easily obtainable in both modes. To facilitate this, a declaration {\tt SHARE}\ttindex{SHARE} is available. {\tt SHARE} takes a list of identifiers as argument, and marks these variables as having recognizable values in both modes. The declaration may be used in either mode. E.g., \begin{verbatim} share x,y; \end{verbatim} says that {\tt X} and {\tt Y} will receive values to be used in both modes. If a {\tt SHARE} declaration is made for a variable with a previously assigned algebraic value, that value is also made available in symbolic mode. \subsection{Passing Algebraic Mode Values to Symbolic Mode} If one wishes to work with parts of an algebraic mode \index{Algebraic mode} expression in symbolic mode,\index{Symbolic mode} one simply makes an assignment\index{Assignment} of a shared variable to the relevant expression in algebraic mode. For example, if one wishes to work with {\tt (a+b)\verb|^|2}, one would say, in algebraic mode: \begin{verbatim} x := (a+b)^2; \end{verbatim} assuming that {\tt X} was declared shared as above. If we now change to symbolic mode and say \begin{verbatim} x; \end{verbatim} its value will be printed as a prefix form with the syntax: \begin{verbatim} (*SQ <standard quotient> T) \end{verbatim} This particular format reflects the fact that the algebraic mode processor currently likes to transfer prefix forms from command to command, but doesn't like to reconvert standard forms\index{Standard form} (which represent polynomials) and standard quotients back to a true Lisp prefix form for the expression (which would result in excessive computation). So {\tt *SQ} is used to tell the algebraic processor that it is dealing with a prefix form which is really a standard quotient\index{Standard quotient} and the second argument ({\tt T} or {\tt NIL}) tells it whether it needs further processing (essentially, an {\em already simplified\/} flag). So to get the true standard quotient form in symbolic mode, one needs {\tt CADR} of the variable. E.g., \begin{verbatim} z := cadr x; \end{verbatim} would store in {\tt Z} the standard quotient form for {\tt (a+b)\verb|^|2}. Once you have this expression, you can now manipulate it as you wish. To facilitate this, a standard set of selectors\index{Selector} and constructors\index{Constructor} are available for getting at parts of the form. Those presently defined are as follows: \extendedmanual{\newpage} \begin{center} \vspace{10pt} {\large REDUCE Selectors\par} %\end{center} %\begin{center} \renewcommand{\arraystretch}{1.5} \begin{tabular}{lp{\rboxwidth}} {\tt DENR} & denominator of standard quotient \\ % {\tt LC} & leading coefficient of polynomial \\ % {\tt LDEG} & leading degree of polynomial \\ % {\tt LPOW} & leading power of polynomial \\ % {\tt LT} & leading term of polynomial \\ % {\tt MVAR} & main variable of polynomial \\ % {\tt NUMR} & numerator (of standard quotient) \\ % {\tt PDEG} & degree of a power \\ % {\tt RED} & reductum of polynomial \\ % {\tt TC} & coefficient of a term \\ % {\tt TDEG} & degree of a term \\ % {\tt TPOW} & power of a term \end{tabular} \end{center} \begin{center} \vspace{10pt} {\large REDUCE Constructors \par} %\end{center} %\begin{center} \renewcommand{\arraystretch}{1.5} \begin{tabular}{lp{\redboxwidth}} \verb|.+| & add a term to a polynomial \\ % \verb|./| & divide (two polynomials to get quotient) \\ \verb|.*| & multiply power by coefficient to produce term \\ % \verb|.^| & raise a variable to a power \end{tabular} \end{center} For example, to find the numerator of the standard quotient above, one could say: \begin{verbatim} numr z; \end{verbatim} or to find the leading term of the numerator: \begin{verbatim} lt numr z; \end{verbatim} Conversion between various data structures is facilitated by the use of a set of functions defined for this purpose. Those currently implemented include: {\renewcommand{\arraystretch}{1.5} \begin{tabular}{lp{\reduceboxwidth}} {\tt !*A2F} & convert an algebraic expression to a standard form. If result is rational, an error results; \\ % {\tt !*A2K} & converts an algebraic expression to a kernel. If this is not possible, an error results; \\ % {\tt !*F2A} & converts a standard form to an algebraic expression; \\ % {\tt !*F2Q} & convert a standard form to a standard quotient; \\ % {\tt !*K2F} & convert a kernel to a standard form; \\ {\tt !*K2Q} & convert a kernel to a standard quotient; \\ % {\tt !*P2F} & convert a standard power to a standard form; \\ % {\tt !*P2Q} & convert a standard power to a standard quotient; \\ % {\tt !*Q2F} & convert a standard quotient to a standard form. If the quotient denominator is not 1, an error results; \\ % {\tt !*Q2K} & convert a standard quotient to a kernel. If this is not possible, an error results; \\ % {\tt !*T2F} & convert a standard term to a standard form \\ % {\tt !*T2Q} & convert a standard term to a standard quotient. \end{tabular}} \subsection{Passing Symbolic Mode Values to Algebraic Mode} In order to pass the value of a shared variable from symbolic mode to algebraic mode, the only thing to do is make sure that the value in symbolic mode is a prefix expression. E.g., one uses {\tt (expt (plus a b) 2)} for {\tt (a+b)\verb|^|2}, or the format ({\tt *sq <standard quotient> t}) as described above. However, if you have been working with parts of a standard form they will probably not be in this form. In that case, you can do the following: \begin{enumerate} \item If it is a standard quotient, call {\tt PREPSQ} on it. This takes a standard quotient as argument, and returns a prefix expression. Alternatively, you can call {\tt MK!*SQ} on it, which returns a prefix form like ({\tt *SQ <standard quotient> T)} and avoids translation of the expression into a true prefix form. \item If it is a standard form, call {\tt PREPF} on it. This takes a standard form as argument, and returns the equivalent prefix expression. Alternatively, you can convert it to a standard quotient and then call {\tt MK!*SQ}. \item If it is a part of a standard form, you must usually first build up a standard form out of it, and then go to step 2. The conversion functions described earlier may be used for this purpose. For example, \begin{enumerate} \item If {\tt Z} is an expression which is a term, {\tt !*T2F Z} is a standard form. \item If {\tt Z} is a standard power, {\tt !*P2F Z} is a standard form. \item If {\tt Z} is a variable, you can pass it direct to algebraic mode. \end{enumerate} \end{enumerate} For example, to pass the leading term of {\tt (a+b)\verb|^|2} back to algebraic mode, one could say: \begin{verbatim} y:= mk!*sq !*t2q lt numr z; \end{verbatim} where {\tt Y} has been declared shared as above. If you now go back to algebraic mode, you can work with {\tt Y} in the usual way. \subsection{Complete Example} The following is the complete code for doing the above steps. The end result will be that the square of the leading term of $(a+b)^{2}$ is calculated. %%\begin{tabular}{lp{\rboxwidth}} %%{\tt share x,y;} & {\tt \% declare {\tt X} and %%{\tt Y} as shared} \\ %%{\tt x := (a+b)\verb|^|2;} & {\tt \% store (a+b)\verb|^|2 in X} \\ %%{\tt symbolic;} & {\tt \% transfer to symbolic mode} \\ %%{\tt z := cadr x;} & {\tt \% store a true standard quotient \newline %% \% in Z} \\[1.7pt] %%{\tt lt numr z;} & {\tt \% print the leading term of the \newline %% \% numerator of Z} \\ %%{\tt y := mk!*sq !*t2q numr z;} & {\tt \% store the %% prefix form of this \newline %% \% leading term in Y} \\ %%{\tt algebraic;} & {\tt \% return to algebraic mode} \\ %%{\tt y\verb|^|2;} & {\tt \% evaluate square of the leading \newline %%\% term of (a+b)\verb|^|2} %%\end{tabular} \begin{verbatim} share x,y; % declare X and Y as shared x := (a+b)^2; % store (a+b)^2 in X symbolic; % transfer to symbolic mode z := cadr x; % store a true standard quotient in Z lt numr z; % print the leading term of the % numerator of Z y := mk!*sq !*t2q numr z; % store the prefix form of this % leading term in Y algebraic; % return to algebraic mode y^2; % evaluate square of the leading term % of (a+b)^2 \end{verbatim} \subsection{Defining Procedures for Intermode Communication} If one wishes to define a procedure in symbolic mode for use as an operator in algebraic mode, it is necessary to declare this fact to the system by using the declaration {\tt OPERATOR}\ttindex{OPERATOR} in symbolic mode. Thus \begin{verbatim} symbolic operator leadterm; \end{verbatim} would declare the procedure {\tt LEADTERM} as an algebraic operator. This declaration {\em must\/} be made in symbolic mode as the effect in algebraic mode is different. The value of such a procedure must be a prefix form. The algebraic processor will pass arguments to such procedures in prefix form. Therefore if you want to work with the arguments as standard quotients you must first convert them to that form by using the function {\tt SIMP!*}. This function takes a prefix form as argument and returns the evaluated standard quotient. For example, if you want to define a procedure {\tt LEADTERM} which gives the leading term of an algebraic expression, one could do this as follows: \begin{samepage} \begin{verbatim} symbolic operator leadterm; % Declare LEADTERM as a symbolic % mode procedure to be used in % algebraic mode. symbolic procedure leadterm u; % Define LEADTERM. mk!*sq !*t2q lt numr simp!* u; \end{verbatim} \end{samepage} Note that this operator has a different effect than the operator {\tt LTERM} \ttindex{LTERM}. In the latter case, the calculation is done with respect to the second argument of the operator. In the example here, we simply extract the leading term with respect to the system's choice of main variable. Finally, if you wish to use the algebraic evaluator on an argument in a symbolic mode definition, the function {\tt REVAL} can be used. The one argument of {\tt REVAL} must be the prefix form of an expression. {\tt REVAL} returns the evaluated expression as a true Lisp prefix form.