Reduce (computer algebra system)
REDUCE is a general-purpose computer algebra system originally geared towards applications in physics. The development of REDUCE was started in 1963 by Anthony C. Hearn. Since then, many scientists from all over the world[2] have contributed to its development. REDUCE was open-sourced in December 2008[3] and is available for free under a modified BSD license on SourceForge. Previously it had cost $695. REDUCE is written entirely in its own Lisp dialect called Standard Lisp,[4] expressed in an ALGOL-like syntax called RLISP that is also used as the basis for REDUCE's user-level language. Implementations of REDUCE are available on most variants of Unix, Linux, Microsoft Windows, or Apple Macintosh systems by using an underlying Portable Standard Lisp (PSL) or Codemist Standard Lisp (CSL) implementation. CSL REDUCE offers a graphical user interface. REDUCE can also be built on other Lisps, such as Common Lisp. The Julia package Reduce.jl[5] uses REDUCE as a backend and implements its semantics in Julia style. Features
SyntaxThe REDUCE language is a high-level structured programming language based on ALGOL 60 (but with Standard Lisp semantics), although it does not support all ALGOL 60 syntax. It is similar to Pascal, which evolved from ALGOL 60, and Modula, which evolved from Pascal. REDUCE is a free-form language, meaning that spacing and line breaks are not significant, but consequently input statements must be separated from each other and all input must be terminated with either a semi-colon ( Identifiers and stringsProgramming languages use identifiers to name constructs such as variables and functions, and strings to store text. A REDUCE identifier must begin with a letter and can be followed by letters, digits and underscore characters ( REDUCE source code was originally written in all upper-case letters, as were all programming languages in the 1960s. (Hence, the name REDUCE is normally written in all upper-case.) However, modern REDUCE is case-insensitive (by default), which means that it ignores the case of letters, and it is normally written in lower-case. (The REDUCE source code has been converted to lower case.) The exceptions to this rule are that case is preserved within strings and when letters in identifiers are preceded by an exclamation mark ( Hello World programsBelow is a REDUCE "Hello, World!" program, which is almost as short as such a program could possibly be! "Hello, World!";
REDUCE displays the output Hello, World! Another REDUCE "Hello, World!" program, which is slightly longer than the version above, uses an identifier as follows !Hello!,! !World!!;
CSL REDUCE displays the same output as shown above. (Other REDUCE GUIs may italicise this output on the grounds that it is an identifier rather than a string.) Statements and expressionsBecause REDUCE inherits Lisp semantics, all programming constructs have values. Therefore, the only distinction between statements and expressions is that the value of an expression is used but the value of a statement is not. The terms statement and expression are interchangeable, although a few constructs always return the Lisp value There are two ways to group several statements or expressions into a single unit that is syntactically equivalent to a single statement or expression, which is necessary to facilitate structured programming. One is the Structured programmingREDUCE supports conditional and repetition statements, some of which are controlled by a boolean expression, which is any expression whose value can be either true or false, such as . (The REDUCE user-level language does not explicitly support constants representing true or false although, as in C and related languages, 0 has the boolean value false, whereas 1 and many other non-zero values have the boolean value true.) Conditional statements: if ... then ... elseThe conditional statement has the form
which can optionally be followed by
For example, the following conditional statement ensures that the value of , assumed to be numerical, is positive. (It effectively implements the absolute value function.) if n < 0 then n := -n
The following conditional statement, used as an expression, avoids an error that would be caused by dividing by 0. recip_x := if x = 0 then infinity else 1/x
Repetition statements: for ...The
where variable names a variable whose value can be used within statement, and initial, increment and final are numbers (preferably integers). The value of variable is initialized to initial and statement is executed, then the value of variable is repeatedly increased by increment and the statement executed again, provided the value of variable is not greater than final. The common special case "initial The following n := 5;
fac := 1$ for r := 2 : n do fac := fac*r; fac;
Another version of the The following n := 5;
for r := 2 : n product r;
Repetition statements: while ... do; repeat ... untilThe two loop statements
are closely related to the conditional statement and execute statement repeatedly a number of times that need not be known in advance. Their difference is that The following n := 5;
fac := n$ while n > 1 do fac := fac*(n := n - 1); fac;
CommentsREDUCE has three comment conventions. It inherits the comment statement from ALGOL 60, which looks like this: comment This is a multi-line comment that ends at the next separator, so it cannot contain separators; Comment statements mostly appear in older code. It inherits the % This is a single-line comment that ends at the end of the line. % It can appear on a line after code and % can contain the separators ";" and "$".
REDUCE also supports a C-style /* This is a multi-line comment that can appear anywhere a space could and can contain the separators ";" and "$". */ Programming paradigmsREDUCE's user-level language supports several programming paradigms, as illustrated in the algebraic programming examples below. Since it is based on Lisp, which is a functional programming language, REDUCE supports functional programming and all statements have values (although they are not always useful). REDUCE also supports procedural programming by ignoring statement values. Algebraic computation usually proceeds by transforming a mathematical expression into an equivalent but different form. This is called simplification, even though the result might be much longer. (The name REDUCE is a pun on this problem of intermediate expression swell!) In REDUCE, simplification occurs automatically when an expression is entered or computed, controlled by simplification rules and switches. In this way, REDUCE supports rule-based programming, which is the classic REDUCE programming paradigm. In early versions of REDUCE, rules and switches could only be set globally, but modern REDUCE also supports local setting of rules and switches, meaning that they control the simplification of only one expression. REDUCE programs often contain a mix of programming paradigms. Algebraic programming examplesThe screenshot shows simple interactive use. As a simple programming example, consider the problem of computing the th Taylor polynomial of the function about the point , which is given by the formula . Here, denotes the th derivative of evaluated at the point and denotes the factorial of . (However, note that REDUCE includes sophisticated facilities for power-series expansion.) As an example of functional programming in REDUCE, here is an easy way to compute the 5th Taylor polynomial of about 0. In the following code, the control variable for r := 0:5 sum sub(x = 0, df(sin x, x, r))*x^r/factorial r;
produces by default the output[7] This is correct, but it doesn't look much like a Taylor series. That can be fixed by changing a few output-control switches and then evaluating the special variable off allfac; on revpri, div; ws;
As an example of procedural programming in REDUCE, here is a procedure to compute the general Taylor polynomial, which works for functions that are well-behaved at the expansion point . procedure my_taylor(f, x, x0, n);
% Return the nth Taylor polynomial of f
% as a function of x about x0.
begin scalar result := sub(x = x0, f), mul := 1;
for r := 1:n do <<
f := df(f, x);
mul := mul*(x - x0)/r;
result := result + sub(x = x0, f)*mul
>>;
return result
end;
The procedure is called The procedure may be called as follows to compute the same Taylor polynomial as above. my_taylor(sin x, x, 0, 5);
File and package handlingREDUCE GUIs provide menu support for some or all of the file and package handling described below. File handlingIn order to develop non-trivial computations, it is convenient to store source code in a file and have REDUCE read it instead of interactive input. REDUCE input should be plain text (not rich text as produced by word-processing applications). REDUCE filenames are arbitrary. The REDUCE source code uses the filename extension ;end; as an end-of-file marker. This is something of a historical quirk but it avoids potential warning messages. Apart from that, an input file can contain whatever might be entered interactively into REDUCE. The command
inputs each of the named files in succession into REDUCE, essentially as if their contents had been entered interactively, after which REDUCE waits for further interactive input. If the separator used to terminate this command is a semi-colon ( REDUCE filenames can be either absolute or relative to the current directory; when using a REDUCE GUI absolute filenames are safer because it is not obvious what the current directory is! Filenames can be specified as either strings or identifiers; strings (in double quotes) are usually more convenient because otherwise filename elements such as directory separators and dots must be escaped with an exclamation mark ( REDUCE output can be directed to a file instead of the interactive display by executing the command
Output redirection can be terminated permanenty by executing the command
or temporarily by executing the command
There are similar mechanisms for directing a compiled version of the REDUCE input to a file and loading compiled code, which is the basis for building REDUCE and can be used to extend it. Loading packagesREDUCE is composed of a number of packages; some are pre-loaded, some are auto-loaded when needed, and some must be explicitly loaded before they can be used. The command
loads each of the named packages in succession into REDUCE. Package names are not filenames; they are simple identifiers that do not need any exclamation marks, so they are normally input as identifiers, although they can be input as strings. A package consists of one or more files of compiled Lisp code, and the Types and variable scopeREDUCE inherits dynamic scoping from Lisp, which means that data have types but variables themselves do not: the type of a variable is the type of the data assigned to it. The simplest REDUCE data types are Standard Lisp atomic types such as identifiers, machine numbers (i.e. "small" integers and floating-point numbers supported directly by the computer hardware), and strings. Most other REDUCE data types are represented internally as Lisp lists whose first element ( mat((1, 2), (3, 4));
produces the display and the internal representation of this matrix is the Lisp list (mat (1 2) (3 4)) The main algebraic objects used in REDUCE are quotients of two possibly-multivariate polynomials, the indeterminates of which, called kernels, may in fact be functions of one or more variables, e.g. the input z := (x + y^2)/f(x,y);
produces the display REDUCE uses two representations for such algebraic objects. One is called prefix form, which is just the Standard Lisp code for the expression and is convenient for operations such as input and output; e.g. for it is (quotient (plus x (expt y 2)) (f x y)) The other is called standard quotient form, which is better for performing algebraic manipulations such as addition; e.g. for it is (!*sq ((((x . 1) . 1) ((y . 2) . 1)) (((f x y) . 1) . 1)) t) REDUCE converts between these two representations as necessary, but tries to retain standard quotient form as much as possible to avoid the conversion overhead. Because variables have no types there are no variable type declarations in REDUCE, but there are variable scope declarations. The scope of a variable refers to the range of a program throughout which it has the same significance. By default, REDUCE variables are automatically global in scope, meaning that they have the same significance everywhere, i.e. once a variable has been assigned a value, it will evaluate to that same value everywhere. Variables can be declared to have scope limited to a particular block of code by delimiting that block of code by the keywords
Each variable so declared can optionally be followed by an assignment operator ( The There are two other variable declarations that are used only in the implementation of REDUCE, i.e. in symbolic mode. The REDUCE
A GraphicsREDUCE supports graphical display[9] via gnuplot, which is an independent portable open-source graphics package that is included in all REDUCE binary distributions. The REDUCE GNUPLOT package supports the display of curves or surfaces defined by formulas and/or data sets via the command Available implementations and supported platformsREDUCE is available from SourceForge. Binary distributions are released[1] a few times a year with no fixed schedule as snapshots of the Subversion repository, and also offer compressed archive snapshots of the full source code. SourceForge can be set up to notify users when a new release is available. In 2024, binary distributions were released for 64-bit versions of macOS, Linux (Debian and Red Hat based systems) and Microsoft Windows. The installers either include or are available for both CSL- and PSL-REDUCE, and may include the REDUCE source code. REDUCE can be built from the source code on a larger range of platforms and on other Lisp systems, such as Common Lisp.[10] See also
References
External links
|