Manual Reduce
Manual Reduce
User’s Manual
Free Version
https://reduce-algebra.sourceforge.io/
Reproduction of this manual is allowed, provided that the source of the material is
clearly acknowledged, and the copyright notice is retained.
Contents
Abstract 27
1 Introductory Information 31
2 Structure of Programs 35
2.1 The REDUCE Standard Character Set . . . . . . . . . . . . . . . 35
2.2 Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.3 Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2.4 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.5 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.6 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
2.7 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3 Expressions 45
3.1 Scalar Expressions . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.2 Integer Expressions . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.3 Boolean Expressions . . . . . . . . . . . . . . . . . . . . . . . . 47
3.4 Equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.5 Proper Statements as Expressions . . . . . . . . . . . . . . . . . 49
4 Lists 51
4.1 Operations on Lists . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.1.1 LIST . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
4.1.2 FIRST . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
1
2 CONTENTS
4.1.3 SECOND . . . . . . . . . . . . . . . . . . . . . . . . . . 52
4.1.4 THIRD . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
4.1.5 REST . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
4.1.6 . (Cons) Operator . . . . . . . . . . . . . . . . . . . . . . 52
4.1.7 APPEND . . . . . . . . . . . . . . . . . . . . . . . . . . 52
4.1.8 REVERSE . . . . . . . . . . . . . . . . . . . . . . . . . 53
4.1.9 List Arguments of Other Operators . . . . . . . . . . . . 53
4.1.10 Caveats and Examples . . . . . . . . . . . . . . . . . . . 53
5 Statements 55
5.1 Assignment Statements . . . . . . . . . . . . . . . . . . . . . . . 56
5.1.1 Set and Unset Statements . . . . . . . . . . . . . . . . . . 56
5.2 Group Statements . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.3 Conditional Statements . . . . . . . . . . . . . . . . . . . . . . . 57
5.4 FOR Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
5.5 WHILE . . . DO . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
5.6 REPEAT . . . UNTIL . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.7 Compound Statements . . . . . . . . . . . . . . . . . . . . . . . 62
5.7.1 Compound Statements with GO TO . . . . . . . . . . . . 63
5.7.2 Labels and GO TO Statements . . . . . . . . . . . . . . . 64
5.7.3 RETURN Statements . . . . . . . . . . . . . . . . . . . . 64
7.1.1 ABS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
7.1.2 CEILING . . . . . . . . . . . . . . . . . . . . . . . . . . 72
7.1.3 CONJ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
7.1.4 FACTORIAL . . . . . . . . . . . . . . . . . . . . . . . . 73
7.1.5 FIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
7.1.6 FLOOR . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
7.1.7 IMPART . . . . . . . . . . . . . . . . . . . . . . . . . . 73
7.1.8 MAX/MIN . . . . . . . . . . . . . . . . . . . . . . . . . 74
7.1.9 NEXTPRIME . . . . . . . . . . . . . . . . . . . . . . . . 74
7.1.10 RANDOM . . . . . . . . . . . . . . . . . . . . . . . . . 74
7.1.11 RANDOM_NEW_SEED . . . . . . . . . . . . . . . . . . 74
7.1.12 REPART . . . . . . . . . . . . . . . . . . . . . . . . . . 75
7.1.13 ROUND . . . . . . . . . . . . . . . . . . . . . . . . . . 75
7.1.14 SIGN . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
7.2 Mathematical Functions . . . . . . . . . . . . . . . . . . . . . . . 76
7.3 Bernoulli Numbers and Euler Numbers . . . . . . . . . . . . . . 80
7.4 Fibonacci Numbers and Fibonacci Polynomials . . . . . . . . . . 80
7.5 Motzkin numbers . . . . . . . . . . . . . . . . . . . . . . . . . . 81
7.6 CHANGEVAR operator . . . . . . . . . . . . . . . . . . . . . . 81
7.6.1 CHANGEVAR example: The 2-dim. Laplace Equation . . . 83
7.6.2 Another CHANGEVAR example: An Euler Equation . . . . 83
7.7 CONTINUED_FRACTION Operator . . . . . . . . . . . . . . . 84
7.8 DF Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
7.8.1 Switches influencing differentiation . . . . . . . . . . . . 87
7.8.2 Adding Differentiation Rules . . . . . . . . . . . . . . . . 88
7.9 INT Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
7.9.1 Options . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
7.9.2 Advanced Use . . . . . . . . . . . . . . . . . . . . . . . 90
7.9.3 References . . . . . . . . . . . . . . . . . . . . . . . . . 91
7.10 LENGTH Operator . . . . . . . . . . . . . . . . . . . . . . . . . 91
4 CONTENTS
15 Procedures 185
15.1 Procedure Heading . . . . . . . . . . . . . . . . . . . . . . . . . 186
15.2 Procedure Body . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
15.3 Matrix-valued Procedures . . . . . . . . . . . . . . . . . . . . . . 188
15.4 Using LET Inside Procedures . . . . . . . . . . . . . . . . . . . . 189
15.5 LET Rules as Procedures . . . . . . . . . . . . . . . . . . . . . . 190
15.6 REMEMBER Statement . . . . . . . . . . . . . . . . . . . . . . 191
Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706
16.42NCPOLY: Non–commutative polynomial ideals . . . . . . . . . . 706
16.42.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 706
16.42.2 Setup, Cleanup . . . . . . . . . . . . . . . . . . . . . . . 706
16.42.3 Left and right ideals . . . . . . . . . . . . . . . . . . . . 708
16.42.4 Gröbner bases . . . . . . . . . . . . . . . . . . . . . . . . 708
16.42.5 Left or right polynomial division . . . . . . . . . . . . . . 709
16.42.6 Left or right polynomial reduction . . . . . . . . . . . . . 710
16.42.7 Factorization . . . . . . . . . . . . . . . . . . . . . . . . 710
16.42.8 Output of expressions . . . . . . . . . . . . . . . . . . . 711
16.43NORMFORM: Computation of matrix normal forms . . . . . . . 713
16.43.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 713
16.43.2 Smith normal form . . . . . . . . . . . . . . . . . . . . . 714
16.43.3 smithex_int . . . . . . . . . . . . . . . . . . . . . . . . . 715
16.43.4 frobenius . . . . . . . . . . . . . . . . . . . . . . . . . . 716
16.43.5 ratjordan . . . . . . . . . . . . . . . . . . . . . . . . . . 717
16.43.6 jordansymbolic . . . . . . . . . . . . . . . . . . . . . . . 718
16.43.7 jordan . . . . . . . . . . . . . . . . . . . . . . . . . . . . 720
16.43.8 Algebraic extensions: Using the ARNUM package . . . . . 721
16.43.9 Modular arithmetic . . . . . . . . . . . . . . . . . . . . . 722
Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . 723
16.44NUMERIC: Solving numerical problems . . . . . . . . . . . . . 724
16.44.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . 724
16.44.2 Minima . . . . . . . . . . . . . . . . . . . . . . . . . . . 725
16.44.3 Roots of Functions/ Solutions of Equations . . . . . . . . 726
16.44.4 Integrals . . . . . . . . . . . . . . . . . . . . . . . . . . . 727
16.44.5 Ordinary Differential Equations . . . . . . . . . . . . . . 728
16.44.6 Bounds of a Function . . . . . . . . . . . . . . . . . . . . 730
16.44.7 Chebyshev Curve Fitting . . . . . . . . . . . . . . . . . . 731
16.44.8 General Curve Fitting . . . . . . . . . . . . . . . . . . . 732
CONTENTS 17
16.48.3 S(exp,{temp1 -> sub1, temp2 -> sub2, . . . }, rept, depth) . 779
16.48.4 temp :- exp and temp ::- exp . . . . . . . . . . . . . . . . 780
16.48.5 Arep({rep1,rep2,. . . }) . . . . . . . . . . . . . . . . . . . 781
16.48.6 Drep({rep1,rep2,..}) . . . . . . . . . . . . . . . . . . . . 781
16.48.7 Switches . . . . . . . . . . . . . . . . . . . . . . . . . . 781
16.49QHULL: Compute the complex hull . . . . . . . . . . . . . . . . 783
16.50QSUM: Indefinite and Definite Summation of q-hypergeometric
Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 784
16.50.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 784
16.50.2 Elementary q-Functions . . . . . . . . . . . . . . . . . . 784
16.50.3 q-Gosper Algorithm . . . . . . . . . . . . . . . . . . . . 785
16.50.4 q-Zeilberger Algorithm . . . . . . . . . . . . . . . . . . . 786
16.50.5 REDUCE operator QGOSPER . . . . . . . . . . . . . . . 787
16.50.6 REDUCE operator QSUMRECURSION . . . . . . . . . . 789
16.50.7 Simplification Operators . . . . . . . . . . . . . . . . . . 794
16.50.8 Global Variables and Switches . . . . . . . . . . . . . . . 795
16.50.9 Messages . . . . . . . . . . . . . . . . . . . . . . . . . . 796
Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . 797
16.51RANDPOLY: A random polynomial generator . . . . . . . . . . . 799
16.51.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 799
16.51.2 Basic use of randpoly . . . . . . . . . . . . . . . . . . 800
16.51.3 Advanced use of randpoly . . . . . . . . . . . . . . . . 801
16.51.4 Subsidiary functions: rand, proc, random . . . . . . . . . 802
16.51.5 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 804
16.51.6 Appendix: Algorithmic background . . . . . . . . . . . . 805
16.52RATAPRX: Rational Approximations Package for REDUCE . . . 809
16.52.1 Periodic Decimal Representation . . . . . . . . . . . . . . 809
16.52.2 Continued Fractions . . . . . . . . . . . . . . . . . . . . 811
16.52.3 Padé Approximation . . . . . . . . . . . . . . . . . . . . 820
Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . 824
CONTENTS 19
This document provides the user with a description of the algebraic programming
system REDUCE. The capabilities of this system include:
8. factorization of polynomials,
27
28 CONTENTS
Acknowledgment
The production of this version of the manual has been the result of the contribu-
tions of a large number of individuals who have taken the time and effort to suggest
improvements to previous versions, and to draft new sections. Particular thanks
are due to Gerry Rayna, who provided a draft rewrite of most of the first half of
the manual. Other people who have made significant contributions have included
John Fitch, Martin Griss, Stan Kameny, Jed Marti, Herbert Melenk, Don Morri-
son, Arthur Norman, Eberhard Schrüfer, Larry Seward and Walter Tietze. Finally,
Richard Hitt produced a TEX version of the REDUCE 3.3 manual, which has been
a useful guide for the production of the LATEX version of this manual.
29
30 CONTENTS
Chapter 1
Introductory Information
where the version number and the system release date will change from time to
time. It proceeds to execute the commands in user’s startup (reducerc) file, if
such a file is present, then prompts the user for input by:
1:
31
32 CHAPTER 1. INTRODUCTORY INFORMATION
You can now type a REDUCE statement, terminated by a semicolon to indicate the
end of the expression, for example:
(x+y+z)^2;
2 2 2
X + 2*X*Y + 2*X*Z + Y + 2*Y*Z + Z
Let us review this simple example to learn a little more about the way that RE-
DUCE works. First, we note that REDUCE deals with variables, and constants
like other computer languages, but that in evaluating the former, a variable can
stand for itself. Expression evaluation normally follows the rules of high school
algebra, so the only surprise in the above example might be that the expression was
expanded. REDUCE normally expands expressions where possible, collecting like
terms and ordering the variables in a specific manner. However, expansion, order-
ing of variables, format of output and so on is under control of the user, and various
declarations are available to manipulate these.
Another characteristic of the above example is the use of lower case on input and
upper case on output. In fact, input may be in either mode, but output is usually in
lower case. To make the difference between input and output more distinct in this
manual, all expressions intended for input will be shown in lower case and output
in upper case. However, for stylistic reasons, we represent all single identifiers in
the text in upper case.
Finally, the numerical prompt can be used to reference the result in a later compu-
tation.
As a further illustration of the system features, the user should try:
815915283247897734345611269596115894272000000000
factorial 40;
more, the FOR statement in the above is illustrative of a whole range of combining
forms that REDUCE supports for the convenience of the user.
Among the many options in REDUCE is the use of other number systems, such as
multiple precision floating point with any specified number of digits — of use if
roundoff in, say, the 100th digit is all that can be tolerated.
In many cases, it is necessary to use the results of one calculation in succeeding
calculations. One way to do this is via an assignment for a variable, such as
u := (x+y+z)^2;
If we now use U in later calculations, the value of the right-hand side of the above
will be used.
The results of a given calculation are also saved in the variable WS (for WorkSpace),
so this can be used in the next calculation for further processing.
For example, the expression
df(ws,x);
following the previous evaluation will calculate the derivative of (x+y+z)^2 with
respect to X. Alternatively,
int(ws,y);
matrix m(2,2);
m := mat((a,b),(c,d));
gives its elements values. Expressions that include M and make algebraic sense
may now be evaluated, such as 1/m to give the inverse, 2*m - u*m^2 to give us
another matrix and det(m) to give us the determinant of M.
REDUCE has a wide range of substitution capabilities. The system knows about
elementary functions, but does not automatically invoke many of their well-known
properties. For example, products of trigonometrical functions are not converted
automatically into multiple angle expressions, but if the user wants this, he can say,
for example:
(sin(a+b)+cos(a+b))*(sin(a-b)-cos(a-b))
34 CHAPTER 1. INTRODUCTORY INFORMATION
where the tilde in front of the variables X and Y indicates that the rules apply for
all values of those variables. The result of this calculation is
-(COS(2*A) + SIN(2*B))
See also the user-contributed packages ASSIST (chapter 16.5), CAMAL (chap-
ter 16.10) and TRIGSIMP (chapter 16.76).
Another very commonly used capability of the system, and an illustration of one of
the many output modes of REDUCE, is the ability to output results in a FORTRAN
compatible form. Such results can then be used in a FORTRAN based numerical
calculation. This is particularly useful as a way of generating algebraic formulas
to be used as the basis of extensive numerical calculations.
For example, the statements
on fort;
df(log(x)*(sin(x)+cos(x))/sqrt(x),x,2);
ANS=(-4.*LOG(X)*COS(X)*X**2-4.*LOG(X)*COS(X)*X+3.*
. LOG(X)*COS(X)-4.*LOG(X)*SIN(X)*X**2+4.*LOG(X)*
. SIN(X)*X+3.*LOG(X)*SIN(X)+8.*COS(X)*X-8.*COS(X)-8.
. *SIN(X)*X-8.*SIN(X))/(4.*SQRT(X)*X**2)
Structure of Programs
The basic characters which are used to build REDUCE symbols are the following:
With the exception of strings and characters preceded by an exclamation mark, the
case of characters is ignored: depending of the underlying LISP they will all be
converted internally into lower case or upper case: ALPHA, Alpha and alpha
represent the same symbol. Most implementations allow you to switch this con-
version off. The operating instructions for a particular implementation should be
consulted on this point. For portability, we shall limit ourselves to the standard
character set in this exposition.
35
36 CHAPTER 2. STRUCTURE OF PROGRAMS
2.2 Numbers
There are several different types of numbers available in REDUCE. Integers consist
of a signed or unsigned sequence of decimal digits written without a decimal point,
for example:
e.g. 32. +32.0 0.32E2 and 320.E-1 are all representations of 32.
The declaration SCIENTIFIC_NOTATION controls the output format of float-
ing point numbers. At the default settings, any number with five or less dig-
its before the decimal point is printed in a fixed-point notation, e.g., 12345.6.
Numbers with more than five digits are printed in scientific notation, e.g.,
1.234567E+5. Similarly, by default, any number with eleven or more zeros
after the decimal point is printed in scientific notation. To change these defaults,
SCIENTIFIC_NOTATION can be used in one of two ways.
SCIENTIFIC_NOTATION m;
where m is a positive integer, sets the printing format so that a number with more
than m digits before the decimal point, or m or more zeros after the decimal point,
is printed in scientific notation.
SCIENTIFIC_NOTATION{m,n},
with m and n both positive integers, sets the format so that a number with more
2.3. IDENTIFIERS 37
than m digits before the decimal point, or n or more zeros after the decimal point
is printed in scientific notation.
CAUTION: The unsigned part of any number may not begin with a decimal point,
as this causes confusion with the CONS (.) operator, i.e., NOT ALLOWED ARE:
.5 -.23 +.12; use 0.5 -0.23 +0.12 instead.
2.3 Identifiers
a az p1 q23p a_very_long_variable
_a
is not.
A sequence of alphanumeric characters in which the first is a digit is interpreted as
a product. For example, 2ab3c is interpreted as 2*ab3c. There is one exception
to this: If the first letter after a digit is E, the system will try to interpret that part of
the sequence as a real number, which may fail in some cases. For example, 2E12
is the real number 2.0 ∗ 1012 , 2e3c is 2000.0*C, and 2ebc gives an error.
Special characters, such as -, *, and blank, may be used in identifiers too, even as
the first character, but each must be preceded by an exclamation mark in input. For
example:
CAUTION: Many system identifiers have such special characters in their names
(especially * and =). If the user accidentally picks the name of one of them for his
own purposes it may have catastrophic consequences for his REDUCE run. Users
are therefore advised to avoid such names.
Identifiers are used as variables, labels and to name arrays, operators and proce-
dures.
38 CHAPTER 2. STRUCTURE OF PROGRAMS
Restrictions
The reserved words listed in section (A may not be used as identifiers. No spaces
may appear within an identifier, and an identifier may not extend over a line of text.
2.4 Variables
Every variable is named by an identifier, and is given a specific type. The type is
of no concern to the ordinary user. Most variables are allowed to have the default
type, called scalar. These can receive, as values, the representation of any ordinary
algebraic expression. In the absence of such a value, they stand for themselves.
Reserved Variables
Other reserved variables, such as LOW_POW, described in other sections, are listed
in Appendix A.
Using these reserved variables inappropriately will lead to errors.
There are also internal variables used by REDUCE that have similar restrictions.
These usually have an asterisk in their names, so it is unlikely a casual user would
use one. An example of such a variable is K!* used in the asymptotic command
package.
Certain words are reserved in REDUCE. They may only be used in the manner
intended. A list of these is given in the section “Reserved Identifiers”. There are,
of course, an impossibly large number of such names to keep in mind. The reader
may therefore want to make himself a copy of the list, deleting the names he doesn’t
think he is likely to use by mistake.
2.5 Strings
Strings are used in WRITE statements, in other output statements (such as error
messages), and to name files. A string consists of any number of characters en-
closed in double quotes. For example:
"A String".
40 CHAPTER 2. STRUCTURE OF PROGRAMS
Lower case characters within a string are not converted to upper case.
The string "" represents the empty string. A double quote may be included in a
string by preceding it by another double quote. Thus "a""b" is the string a"b,
and """" is the string consisting of the single character ".
2.6 Comments
Text can be included in program listings for the convenience of human readers, in
such a way that REDUCE pays no attention to it. There are two ways to do this:
1. Everything from the word COMMENT to the next statement terminator, nor-
mally ; or $, is ignored. Such comments can be placed anywhere a blank
could properly appear. (Note that END and >> are not treated as COMMENT
delimiters!)
2. Everything from the symbol % to the end of the line on which it appears is
ignored. Such comments can be placed as the last part of any line. Statement
terminators have no special meaning in such comments. Remember to put
a semicolon before the % if the earlier part of the line is intended to be so
terminated. Remember also to begin each line of a multi-line % comment
with a % sign.
2.7 Operators
Operators in REDUCE are specified by name and type. There are two types, in-
fix and prefix. Operators can be purely abstract, just symbols with no properties;
they can have values assigned (using := or simple LET declarations) for specific
arguments; they can have properties declared for some collection of arguments
(using more general LET declarations); or they can be fully defined (usually by a
procedure declaration).
Infix operators have a definite precedence with respect to one another, and normally
occur between their arguments. For example:
a + b - c (spaces optional)
x<y and y=z (spaces required where shown)
Spaces can be freely inserted between operators and variables or operators and
operators. They are required only where operator names are spelled out with let-
ters (such as the AND in the example) and must be unambiguously separated from
another such or from a variable (like Y). Wherever one space can be used, so can
any larger number.
2.7. OPERATORS 41
Prefix operators occur to the left of their arguments, which are written as a list
enclosed in parentheses and separated by commas, as with normal mathematical
functions, e.g.,
cos(u)
df(x^2,x)
q(v+w)
Unmatched parentheses, incorrect groupings of infix operators and the like, natu-
rally lead to syntax errors. The parentheses can be omitted (replaced by a space
following the operator name) if the operator is unary and the argument is a single
symbol or begins with a prefix operator name:
but
A unary prefix operator has a precedence higher than any infix operator, including
unary infix operators. In other words, REDUCE will always interpret cos y +
3 as (cos y) + 3 rather than as cos(y + 3).
Infix operators may also be used in a prefix format on input, e.g., +(a,b,c). On
output, however, such expressions will always be printed in infix form (i.e., a +
b + c for this example).
A number of prefix operators are built into the system with predefined properties.
Users may also add new operators and define their rules for simplification. The
built in operators are described in another section.
The following infix operators are built into the system. They are all defined inter-
nally as procedures.
hassignment operatori −→ :=
hlogical operatori −→ or | and | member | memq
hrelational operatori −→ = | neq | eq | >= | > | <= | <
hsubstitution operatori −→ where
harithmetic operatori −→ + | - | * | / | ^ | **
hconstruction operatori −→ .
MEMQ and EQ are not used in the algebraic mode of REDUCE. They are explained
in the section on symbolic mode. WHERE is described in the section on substitu-
tions.
In previous versions of REDUCE, not was also defined as an infix operator. In the
present version it is a regular prefix operator, and interchangeable with null.
For compatibility with the intermediate language used by REDUCE, each special
character infix operator has an alternative alphanumeric identifier associated with
it. These identifiers may be used interchangeably with the corresponding special
character names on input. This correspondence is as follows:
Note: NEQ is used to mean not equal. There is no special symbol provided for it.
The above operators are binary, except NOT which is unary and + and * which
are nary (i.e., taking an arbitrary number of arguments). In addition, - and / may
be used as unary operators, e.g., /2 means the same as 1/2. Any other operator is
parsed as a binary operator using a left association rule. Thus a/b/c is interpreted
as (a/b)/c. There are two exceptions to this rule: := and . are right associa-
tive. Example: a:=b:=c is interpreted as a:=(b:=c). Unlike ALGOL and
PASCAL, ^ is left associative. In other words, a^b^c is interpreted as (a^b)^c.
The operators <, <=, >, >= can only be used for making comparisons between
numbers. No meaning is currently assigned to this kind of comparison between
general expressions.
2.7. OPERATORS 43
Expressions
x
x^3 - 2*y/(2*z^2 - df(x,z))
(p^2 + m^2)^(1/2)*log (y/m)
a(5) + b(i,q)
The symbol ** may be used as an alternative to the caret symbol (^) for forming
powers, particularly in those systems that do not support a caret symbol.
Statement expressions, usually in parentheses, can also form part of a scalar ex-
pression, as in the example
w + (c:=x+y) + z .
When the algebraic value of an expression is needed, REDUCE determines it, start-
ing with the algebraic values of the parts, roughly as follows:
Variables and operator symbols with an argument list have the algebraic values
45
46 CHAPTER 3. EXPRESSIONS
they were last assigned, or if never assigned stand for themselves. However, array
elements have the algebraic values they were last assigned, or, if never assigned,
are taken to be 0.
Procedures are evaluated with the values of their actual parameters.
In evaluating expressions, the standard rules of algebra are applied. Unfortunately,
this algebraic evaluation of an expression is not as unambiguous as is numerical
evaluation. This process is generally referred to as “simplification” in the sense that
the evaluation usually but not always produces a simplified form for the expression.
There are many options available to the user for carrying out such simplification.
If the user doesn’t specify any method, the default method is used. The default
evaluation of an expression involves expansion of the expression and collection
of like terms, ordering of the terms, evaluation of derivatives and other functions
and substitution for any expressions which have values assigned or declared (see
assignments and LET statements). In many cases, this is all that the user needs.
The declarations by which the user can exercise some control over the way in which
the evaluation is performed are explained in other sections. For example, if a real
(floating point) number is encountered during evaluation, the system will normally
convert it into a ratio of two integers. If the user wants to use real arithmetic,
he can effect this by the command on rounded;. Other modes for coefficient
arithmetic are described elsewhere.
If an illegal action occurs during evaluation (such as division by zero) or functions
are called with the wrong number of arguments, and so on, an appropriate error
message is generated.
These are expressions which, because of the values of the constants and variables
in them, evaluate to whole numbers.
Examples:
j + k - 2 * j^2
is an integer expression when J and K have values that are integers, or if not integers
are such that “the variables and fractions cancel out”, as in
hexpressionihrelational operatorihexpressioni
or
hboolean operatori(hargumentsi)
or
PRIMEP(U) true if U is a prime object, i.e., any object other than 0 and
plus or minus 1 which is only exactly divisible by itself or
a unit.
Examples:
j<1
x>0 or x=-2
numberp x
fixp x and evenp x
numberp x and x neq 0
48 CHAPTER 3. EXPRESSIONS
Boolean expressions can only appear directly within IF, FOR, WHILE, and UNTIL
statements, as described in other sections. Such expressions cannot be used in place
of ordinary algebraic expressions, or assigned to a variable.
NB: For those familiar with symbolic mode, the meaning of some of these oper-
ators is different in that mode. For example, NUMBERP is true only for integers and
reals in symbolic mode.
When two or more boolean expressions are combined with AND, they are evaluated
one by one until a false expression is found. The rest are not evaluated. Thus
does not attempt to make the x>y comparison unless X and Y are both verified to
be numbers.
Similarly, evaluation of a sequence of boolean expressions connected by OR stops
as soon as a true expression is found.
NB: In a boolean expression, and in a place where a boolean expression is expected,
the algebraic value 0 is interpreted as false, while all other algebraic values are
converted to true. So in algebraic mode a procedure can be written for direct usage
in boolean expressions, returning say 1 or 0 as its value as in
procedure polynomialp(u,x);
if den(u)=1 and deg(u,x)>=1 then 1 else 0;
In addition, any procedure that does not have a defined return value (for example,
a block without a RETURN statement in it) has the boolean value false.
3.4 Equations
hexpressioni=hexpressioni.
In addition to their role as boolean expressions, they can also be used as arguments
to several operators (e.g., SOLVE), and can be returned as values.
Under normal circumstances, the right-hand-side of the equation is evaluated but
not the left-hand-side. This also applies to any substitutions made by the SUB
3.5. PROPER STATEMENTS AS EXPRESSIONS 49
2 * (x := a+b)
y := 2 * (x := a+b);
Lists
{a,b,c}
{1,a-b,c=d}
{{a},{{b,c},d},e}.
{}.
Several operators in the system return their results as lists, and a user can create
new lists using braces and commas. Alternatively, one can use the operator LIST
to construct a list. An important class of operations on lists are MAP and SELECT
operations. For details, please refer to the chapters on MAP, SELECT and the FOR
command. See also the documentation on the ASSIST (chapter 16.5) package.
To facilitate the use of lists, a number of operators are also available for manip-
ulating them. PART(hlisti,n) for example will return the nth element of a
list. LENGTH will return the length of a list. Several operators are also defined
uniquely for lists. For those familiar with them, these operators in fact mirror the
operations defined for Lisp lists. These operators are as follows:
51
52 CHAPTER 4. LISTS
4.1.1 LIST
The operator LIST is an alternative to the usage of curly brackets. LIST accepts an
arbitrary number of arguments and returns a list of its arguments. This operator is
useful in cases where operators have to be passed as arguments. E.g.,
4.1.2 FIRST
This operator returns the first member of a list. An error occurs if the argument is
not a list, or the list is empty.
4.1.3 SECOND
SECOND returns the second member of a list. An error occurs if the argument is
not a list or has no second element.
4.1.4 THIRD
This operator returns the third member of a list. An error occurs if the argument is
not a list or has no third element.
4.1.5 REST
REST returns its argument with the first element removed. An error occurs if the
argument is not a list, or is empty.
This operator adds (“conses”) an expression to the front of a list. For example:
4.1.7 APPEND
This operator appends its first argument to its second to form a new list. Examples:
4.1.8 REVERSE
The operator REVERSE returns its argument with the elements in the reverse or-
der. It only applies to the top level list, not any lower level lists that may occur.
Examples are:
If an operator other than those specifically defined for lists is given a single argu-
ment that is a list, then the result of this operation will be a list in which that
operator is applied to each element of the list. For example, the result of evaluating
log{a,b,c} is the expression {LOG(A),LOG(B),LOG(C)}.
There are two ways to inhibit this operator distribution. Firstly, the switch
LISTARGS, if on, will globally inhibit such distribution. Secondly, one can in-
hibit this distribution for a specific operator by the declaration LISTARGP. For
example, with the declaration listargp log, log{a,b,c} would evaluate to
LOG({A,B,C}).
If an operator has more than one argument, no such distribution occurs.
Some of the natural list operations such as member or delete are available only
after loading the package ASSIST (chapter 16.5).
Please note that a non-list as second argument to CONS (a "dotted pair" in LISP
terms) is not allowed and causes an "invalid as list" error.
a := 17 . 4;
Also, the initialization of a scalar variable is not the empty list – one has to set list
type variables explicitly, as in the following example:
load_package assist;
luckies := {};
for k:=1:n do list_1_n := k . list_1_n;
for k:=1:m do
<< hit := part(list_1_n,random(n-k+1) + 1);
list_1_n := delete(hit,list_1_n);
luckies := hit . luckies >>;
return luckies;
end;
% In Germany, try lotto (49,6);
procedure allcoeffs(q,lis);
% q : polynomial, lis: list of vars
allcoeffs1 (list q,lis);
procedure allcoeffs1(q,lis);
if lis={} then q else
allcoeffs1(foreach qq in q join coeff(qq,first lis),
rest lis);
Chapter 5
Statements
A statement is any combination of reserved words and expressions, and has the
syntax
hterminatori −→ ; | $
The division of the program into lines is arbitrary. Several statements can be on
one line, or one statement can be freely broken onto several lines. If the program
is run interactively, statements ending with ; or $ are not processed until an end-of-
line character is encountered. This character can vary from system to system, but
is normally the Return key on an ASCII terminal. Specific systems may also use
additional keys as statement terminators.
If a statement is a proper statement, the appropriate action takes place.
Depending on the nature of the proper statement some result or response may or
may not be printed out, and the response may or may not depend on the terminator
used.
If a statement is an expression, it is evaluated. If the terminator is a semicolon, the
result is printed. If the terminator is a dollar sign, the result is not printed. Because
it is not usually possible to know in advance how large an expression will be, no
explicit format statements are offered to the user. However, a variety of output
declarations are available so that the output can be produced in different forms.
These output declarations are explained in Section 8.3.3.
The following sub-sections describe the types of proper statements in REDUCE.
55
56 CHAPTER 5. STATEMENTS
The hexpressioni on the left side is normally the name of a variable, an operator
symbol with its list of arguments filled in, or an array name with the proper number
of integer subscript values within the array bounds. For example:
a1 := b + c
h(l,m) := x-2*y (where h is an operator)
k(3,5) := x-2*y (where k is a 2-dim. array)
More general assignments such as a+b := c are also allowed. The effect of these
is explained in Section 11.2.5.
An assignment statement causes the expression on the right-hand-side to be evalu-
ated. If the left-hand-side is a variable, the value of the right-hand-side is assigned
to that unevaluated variable. If the left-hand-side is an operator or array expression,
the arguments of that operator or array are evaluated, but no other simplification
done. The evaluated right-hand-side is then assigned to the resulting expression.
For example, if a is a single-dimensional array, a(1+1) := b assigns the value
b to the array element a(2).
If a semicolon is used as the terminator when an assignment is issued as a command
(i.e. not as a part of a group statement or procedure or other similar construct), the
left-hand side symbol of the assignment statement is printed out, followed by a
“:=”, followed by the value of the expression on the right.
It is also possible to write a multiple assignment statement:
hexpressioni:= . . . :=hexpressioni:=hexpressioni
In this form, each hexpressioni but the last is set to the value of the last hexpressioni.
If a semicolon is used as a terminator, each expression except the last is printed
followed by a “:=” ending with the value of the last expression.
In some cases, it is desirable to perform an assignment in which both the left- and
right-hand sides of an assignment are evaluated. In this case, the SET statement
can be used with the syntax:
SET(hexpressioni,hexpressioni);
5.2. GROUP STATEMENTS 57
j := 23;
set(mkid(a,j),x);
UNSET(hexpressioni);
j := 23;
unset(mkid(a,j));
The group statement is a construct used where REDUCE expects a single state-
ment, but a series of actions needs to be performed. It is formed by enclosing one
or more statements (of any kind) between the symbols << and >>, separated by
semicolons or dollar signs – it doesn’t matter which. The statements are executed
one after another.
Examples will be given in the sections on IF and other types of statements in which
the << . . . >> construct is useful.
If the last statement in the enclosed group has a value, then that is also the value
of the group statement. Care must be taken not to have a semicolon or dollar sign
after the last grouped statement, if the value of the group is relevant: such an extra
terminator causes the group to have the value NIL or zero.
The boolean expression is evaluated. If this is true, the first hstatementi is executed.
If it is false, the second is.
58 CHAPTER 5. STATEMENTS
Examples:
is equivalent to:
IF <a> THEN <b> ELSE (IF <c> THEN <d> ELSE <e>)
parses as
The FOR statement is used to define a variety of program loops. Its general syntax
is as follows:
hnumberi
STEP UNTIL
hvari := hnumberi hnumberi
:
FOR hactioni hexprni
IN
EACH hvari hlisti
ON
where
The assignment form of the FOR statement defines an iteration over the indicated
numerical range. If expressions that do not evaluate to numbers are used in the
designated places, an error will result.
The FOR EACH form of the FOR statement is designed to iterate down a list.
Again, an error will occur if a list is not used.
The action DO means that hexprni is simply evaluated and no value kept; the state-
ment returning 0 in this case (or no value at the top level). COLLECT means that
the results of evaluating hexprni each time are linked together to make a list, and
JOIN means that the values of hexprni are themselves lists that are joined to make
one list (similar to CONC in Lisp). Finally, PRODUCT and SUM form the respective
combined value out of the values of hexprni.
In all cases, hexprni is evaluated algebraically within the scope of the current value
of hvari. If hactioni is DO, then nothing else happens. In other cases, hactioni is
a binary operator that causes a result to be built up and returned by FOR. In those
cases, the loop is initialized to a default value (0 for SUM, 1 for PRODUCT, and an
empty list for the other actions). The test for the end condition is made before any
action is taken. As in Pascal, if the variable is out of range in the assignment case,
or the hlisti is empty in the FOR EACH case, hexprni is not evaluated at all.
Examples:
step 1 until
60 CHAPTER 5. STATEMENTS
3. The following sets C to the sum of the squares of 1,3,5,7,9; and D to the
expression x*(x+1)*(x+2)*(x+3)*(x+4):
4. The following forms a list of the squares of the elements of the list
{a,b,c}:
5. The following forms a list of the listed squares of the elements of the list
{a,b,c} (i.e., {{A^2},{B^2},{C^2}}):
6. The following also forms a list of the squares of the elements of the list
{a,b,c}, since the JOIN operation joins the individual lists into one list:
The control variable used in the FOR statement is actually a new variable, not
related to the variable of the same name outside the FOR statement. In other words,
executing a statement for i:= . . . doesn’t change the system’s assumption that
i2 = −1. Furthermore, in algebraic mode, the value of the control variable is
substituted in hexprni only if it occurs explicitly in that expression. It will not
replace a variable of the same name in the value of that expression. For example:
5.5 WHILE . . . DO
The FOR . . . DO feature allows easy coding of a repeated operation in which the
number of repetitions is known in advance. If the criterion for repetition is more
complicated, WHILE . . . DO can often be used. Its syntax is:
The WHILE . . . DO controls the single statement following DO. If several state-
ments are to be repeated, as is almost always the case, they must be grouped using
the << . . . >> or BEGIN . . . END as in the example below.
The WHILE condition is tested each time before the action following the DO is
attempted. If the condition is false to begin with, the action is not performed at all.
Make sure that what is to be tested has an appropriate value initially.
Example:
Suppose we want to add up a series of terms, generated one by one, until we reach
a term which is less than 1/1000 in value. For our simple example, let us suppose
the first term equals 1 and each term is obtained from the one before by taking one
third of it and adding one third its square. We would write:
ex:=0; term:=1;
while num(term - 1/1000) >= 0 do
<<ex := ex+term; term:=(term + term^2)/3>>;
ex;
As long as TERM is greater than or equal to (>=) 1/1000 it will be added to EX and
the next TERM calculated. As soon as TERM becomes less than 1/1000 the WHILE
test fails and the TERM will not be added.
REPEAT . . . UNTIL is very similar in purpose to WHILE . . . DO. Its syntax is:
1. The test is performed after the controlled statement (or group of statements)
is executed, so the controlled statement is always executed at least once.
2. The test is a test for when to stop rather than when to continue, so its “polar-
ity” is the opposite of that in WHILE . . . DO.
62 CHAPTER 5. STATEMENTS
ex:=0; term:=1;
repeat <<ex := ex+term; term := (term + term^2)/3>>
until num(term - 1/1000) < 0;
ex;
In this case, the answer will be the same as before, because in neither case is a term
added to EX which is less than 1/1000.
Often the desired process can best (or only) be described as a series of steps to be
carried out one after the other. In many cases, this can be achieved by use of the
group statement. However, each step often provides some intermediate result, until
at the end we have the final result wanted. Alternatively, iterations on the steps are
needed that are not possible with constructs such as WHILE or REPEAT statements.
In such cases the steps of the process must be enclosed between the words BEGIN
and END forming what is technically called a block or compound statement. Such a
compound statement can in fact be used wherever a group statement appears. The
converse is not true: BEGIN ...END can be used in ways that << . . . >> cannot.
If intermediate results must be formed, local variables must be provided in which
to store them. Local means that their values are deleted as soon as the block’s
operations are complete, and there is no conflict with variables outside the block
that happen to have the same name. Local variables are created by a SCALAR
declaration immediately after the BEGIN:
scalar a,b,c,z;
If more convenient, several SCALAR declarations can be given one after another:
scalar a,b,c;
scalar z;
In place of SCALAR one can also use the declarations INTEGER or REAL. In the
present version of REDUCE variables declared INTEGER are expected to have
only integer values, and are initialized to 0. REAL variables on the other hand are
currently treated as algebraic mode SCALARs.
CAUTION: INTEGER, REAL and SCALAR declarations can only be given imme-
diately after a BEGIN. An error will result if they are used after other statements
in a block (including ARRAY and OPERATOR declarations, which are global in
scope), or outside the top-most block (e.g., at the top level). All variables declared
5.7. COMPOUND STATEMENTS 63
It is possible to have more complicated structures inside the BEGIN . . . END brack-
ets than indicated in the previous example. That the individual lines of the program
need not be assignment statements, but could be almost any other kind of state-
ment or command, needs no explanation. For example, conditional statements,
and WHILE and REPEAT constructions, have an obvious role in defining more
intricate blocks.
If these structured constructs don’t suffice, it is possible to use labels and GO TOs
within a compound statement, and also to use RETURN in places within the block
other than just before the END. The following subsections discuss these matters in
detail. For many readers the following example, presenting one possible definition
64 CHAPTER 5. STATEMENTS
begin scalar m;
m:=1;
l: if n=0 then return m;
m:=m*n;
n:=n-1;
go to l
end;
return x+y;
return m;
return;
Note that parentheses are not required around the x+y, although they are permitted.
The last example is equivalent to return 0 or return nil, depending on
whether the block is used as part of an expression or not.
Since RETURN actually moves up only one block level, in a sense the casual user
is not expected to understand, we tabulate some cautions concerning its use.
1. RETURN can be used on the top level inside the compound statement, i.e. as
one of the statements bracketed together by the BEGIN . . . END
2. RETURN can be used within a top level << . . . >> construction within the
compound statement. In this case, the RETURN transfers control out of both
the group statement and the compound statement.
begin scalar y;
y := for i:=0:99 do if a(i)=x then return b(i);
...
hcommandi −→ hstatementihterminatori
hterminatori −→ ; | $
Some REDUCE commands and declarations are described in the following sub-
sections.
array a(10),b(2,3,4);
Array indices each range from 0 to the value declared. An element of an array is
referred to in standard FORTRAN notation, e.g. A(2).
We can also use an expression for defining an array bound, provided the value of
the expression is a positive integer. For example, if X has the value 10 and Y the
value 7 then array c(5*x+y) is the same as array c(57).
If an array is referenced by an index outside its range, an error occurs. If the array
is to be one-dimensional, and the bound a number or a variable (not a more general
expression) the parentheses may be omitted:
67
68 CHAPTER 6. COMMANDS AND DECLARATIONS
The operator LENGTH applied to an array name returns a list of its dimensions.
All array elements are initialized to 0 at declaration time. In other words, an array
element has an instant evaluation property and cannot stand for itself. If this is
required, then an operator should be used instead.
Array declarations can appear anywhere in a program. Once a symbol is declared
to name an array, it can not also be used as a variable, or to name an operator or
a procedure. It can however be re-declared to be an array, and its size may be
changed at that time. An array name can also continue to be used as a parameter in
a procedure, or a local variable in a compound statement, although this use is not
recommended, since it can lead to user confusion over the type of the variable.
Arrays once declared are global in scope, and so can then be referenced anywhere
in the program. In other words, unlike arrays in most other languages, a declara-
tion within a block (or a procedure) does not limit the scope of the array to that
block, nor does the array go away on exiting the block (use CLEAR instead for this
purpose).
The ON and OFF declarations are available to the user for controlling various sys-
tem options. Each option is represented by a switch name. ON and OFF take a list
of switch names as argument and turn them on and off respectively, e.g.,
on time;
causes the system to print a message after each command giving the elapsed CPU
time since the last command, or since TIME was last turned off, or the session be-
gan. Another useful switch with interactive use is DEMO, which causes the system
to pause after each command in a file (with the exception of comments) until a
Return is typed on the terminal. This enables a user to set up a demonstration
file and step through it command by command.
As with most declarations, arguments to ON and OFF may be strung together sep-
arated by commas. For example,
off time,demo;
will turn off both the time messages and the demonstration switch.
We note here that while most ON and OFF commands are obeyed almost instanta-
neously, some trigger time-consuming actions such as reading in necessary mod-
ules from secondary storage.
A diagnostic message is printed if ON or OFF are used with a switch that is not
6.3. END 69
known to the system. For example, if you misspell DEMO and type
on demq;
6.3 END
The command BYE; (or alternatively QUIT;) stops the execution of REDUCE,
closes all open output files, and returns you to the calling program (usually the
operating system). Your REDUCE session is normally destroyed.
SHOWTIME; prints the elapsed time since the last call of this command or, on its
first call, since the current REDUCE session began. The time is normally given
in milliseconds and gives the time as measured by a system clock. The operations
covered by this measure are system dependent.
The command DEFINE allows a user to supply a new name for any identifier or
replace it by any well-formed expression. Its argument is a list of expressions of
the form
70 CHAPTER 6. COMMANDS AND DECLARATIONS
Example:
define be==,x=y+z;
means that BE will be interpreted as an equal sign, and X as the expression y+z
from then on. This renaming is done at parse time, and therefore takes precedence
over any other replacement declared for the same identifier. It stays in effect until
the end of the REDUCE run.
The identifiers ALGEBRAIC and SYMBOLIC have properties which prevent
DEFINE from being used on them. To define ALG to be a synonym for
ALGEBRAIC, use the more complicated construction
put(’alg,’newnam,’algebraic);
Chapter 7
In the following subsections are descriptions of the most useful prefix operators
built into REDUCE that are not defined in other sections (such as substitution
operators). Some are fully defined internally as procedures; others are more nearly
abstract operators, with only some of their properties known to the system.
In many cases, an operator is described by a prototypical header line as follows.
Each formal parameter is given a name and followed by its allowed type. The
names of classes referred to in the definition are printed in lower case, and param-
eter names in upper case. If a parameter type is not commonly used, it may be
a specific set enclosed in brackets { . . . }. Operators that accept formal param-
eter lists of arbitrary length have the parameter and type class enclosed in square
brackets indicating that zero or more occurrences of that argument are permitted.
Optional parameters and their type classes are enclosed in angle brackets.
REDUCE includes a number of functions that are analogs of those found in most
numerical systems. With numerical arguments, such functions return the expected
result. However, they may also be called with non-numerical arguments. In such
cases, except where noted, the system attempts to simplify the expression as far as
it can. In such cases, a residual expression involving the original operator usually
remains. These operators are as follows:
7.1.1 ABS
ABS returns the absolute value of its single argument, if that argument has a nu-
merical value. A non-numerical argument is returned as an absolute value, with an
71
72 CHAPTER 7. BUILT-IN PREFIX OPERATORS
overall numerical coefficient taken outside the absolute value operator. For exam-
ple:
7.1.2 CEILING
This operator returns the ceiling (i.e., the least integer greater than the given argu-
ment) if its single argument has a numerical value. A non-numerical argument is
returned as an expression in the original operator. For example:
ceiling(-5/4) -> -1
ceiling(-a) -> CEILING(-A)
7.1.3 CONJ
This returns the complex conjugate of an expression, if that argument has a nu-
merical value. By default the complex conjugate of a non-numerical argument is
returned as an expression in the operators REPART and IMPART. For example:
However, if rules have been previously defined for the complex conjugate(s) of one
or more non-numerical terms appearing in the argument, these rules are applied and
the expansion in terms of the operators REPART and IMPART is suppressed.
For example:
realvalued a,b;
conj(a+i*b) -> a-b*i
let conj z => z!*, conj c => c!*;
conj(a+b*z*z!*+z*c!*) -> a+b*z*z* + c*z*
conj atan z -> atan(z*)
Note that in defining the rule conj z => z!*, the rule conj z!* => z
is (in effect) automatically defined. Note also that the standard elementary
functions and their inverses (where appropriate) are automatically defined to be
SELFCONJUGATE so that conj(f(z)) => f(conj(z)).
7.1. NUMERICAL OPERATORS 73
7.1.4 FACTORIAL
7.1.5 FIX
This operator returns the fixed value (i.e., the integer part of the given argument) if
its single argument has a numerical value. A non-numerical argument is returned
as an expression in the original operator. For example:
fix(-5/4) -> -1
fix(a) -> FIX(A)
7.1.6 FLOOR
This operator returns the floor (i.e., the greatest integer less than the given argu-
ment) if its single argument has a numerical value. A non-numerical argument is
returned as an expression in the original operator. For example:
floor(-5/4) -> -2
floor(a) -> FLOOR(A)
7.1.7 IMPART
This operator returns the imaginary part of an expression, if that argument has an
numerical value. A non-numerical argument is returned as an expression in the
operators REPART and IMPART. For example:
impart(1+i) -> 1
impart(sin(3+4*i)) -> cos(3)*sinh(4)
impart(log(2+i)) -> atan(1/2)
impart(asin(1+i)) -> acosh(sqrt(5)+2)/2
impart(a+i*b) -> impart(a) + repart(b)
74 CHAPTER 7. BUILT-IN PREFIX OPERATORS
7.1.8 MAX/MIN
MAX and MIN can take an arbitrary number of expressions as their arguments.
If all arguments evaluate to numerical values, the maximum or minimum of the
argument list is returned. If any argument is non-numeric, an appropriately reduced
expression is returned. For example:
max(2,-3,4,5) -> 5
min(2,-2) -> -2.
max(a,2,3) -> MAX(A,3)
min(x) -> X
7.1.9 NEXTPRIME
NEXTPRIME returns the next prime greater than its integer argument, using a prob-
abilistic algorithm. A type error occurs if the value of the argument is not an inte-
ger. For example:
nextprime(5) -> 7
nextprime(-2) -> 2
nextprime(-7) -> -5
nextprime 1000000 -> 1000003
7.1.10 RANDOM
random(5) -> 3
random(1000) -> 191
7.1.11 RANDOM_NEW_SEED
7.1.12 REPART
This returns the real part of an expression, if that argument has an numerical value.
A non-numerical argument is returned as an expression in the operators REPART
and IMPART. For example:
repart(1+i) -> 1
repart(sin(3+4*i)) -> cosh(4)*sin(3)
repart(log(2+i)) -> log(5)/2
repart(asin(1+i)) -> acos(sqrt(5)-2)/2
repart(a+i*b) -> - impart(b) + repart(a)
7.1.13 ROUND
This operator returns the rounded value (i.e, the nearest integer) of its single argu-
ment if that argument has a numerical value. A non-numeric argument is returned
as an expression in the original operator. For example:
round(-5/4) -> -1
round(a) -> ROUND(A)
7.1.14 SIGN
SIGN tries to evaluate the sign of its argument. If this is possible SIGN returns
one of 1, 0 or -1. Otherwise, the result is the original form or a simplified variant.
For example:
sign(-5) -> -1
sign(-a^2*b) -> -SIGN(B)
Note that even powers of formal expressions are assumed to be positive only as
long as the switch COMPLEX is off.
76 CHAPTER 7. BUILT-IN PREFIX OPERATORS
REDUCE knows that the following represent mathematical functions that can take
arbitrary scalar expressions as their argument(s):
where LOG is the natural logarithm, and LOGB has two arguments of which the
second is the logarithmic base.
The derivatives of all these functions are also known to the system.
REDUCE knows various elementary identities and properties of these functions.
For example:
Beside these identities, there are a lot of simplifications for elementary funct-
ions defined in the REDUCE system as rulelists. In order to view these, the
SHOWRULES operator can be used, e.g.
SHOWRULES tan;
~x + ~~k*pi x k
tan(-------------) => - cot(--- + i*pi*impart(---)) when abs(repart(
~~d d d
7.2. MATHEMATICAL FUNCTIONS 77
~~w + ~~k*pi w k k
tan(--------------) => tan(--- + (--- - fix(repart(---)))*pi)
~~d d d d
k
when ((ratnump(rp) and abs(rp)>=1) where rp => repart(---)),
d
tan(atan(~x)) => x,
2
df(tan(~x),~x) => 1 + tan(x) }
ON EXPANDLOGS; LOG(3*Y);
These switches affect the logarithmic functions LOG10 (base 10) and LOGB (ar-
bitrary base) as well.
At the present time, it is possible to have both switches on at once, which could
78 CHAPTER 7. BUILT-IN PREFIX OPERATORS
lead to infinite recursion. However, an expression is switched from one form to the
other in this case. Users should not rely on this behavior, since it may change in
the next release.
The current version of REDUCE does a poor job of simplifying surds. In particular,
expressions involving the product of variables raised to non-integer powers do not
usually have their powers combined internally, even though they are printed as if
those powers were combined. For example, the expression
x^(1/3)*x^(1/6);
will print as
SQRT(X)
but will have an internal form containing the two exponentiated terms. If you
now subtract sqrt(x) from this expression, you will not get zero. Instead, the
confusing form
SQRT(X) - SQRT(X)
sqrt(-8a^2*b)
becomes
2*a*sqrt(-2*b).
Note that such simplifications can cause trouble if A is eventually given a value
that is a negative number. If it is important that the positive property of the square
root and higher even roots always be preserved, the switch PRECISE should be
set on (the default value). This causes any non-numerical factors taken out of surds
to be represented by their absolute value form. With PRECISE on then, the above
example would become
7.2. MATHEMATICAL FUNCTIONS 79
2*abs(a)*sqrt(-2*b).
√
However, this is incorrect in the complex domain, where the x2 is not identical
to |x|. To avoid the above simplification, the switch PRECISE_COMPLEX should
be set on (default is off). For example:
on precise_complex; sqrt(-8a^2*b);
2
2*sqrt( - 2*a *b)
The statement that REDUCE knows very little about these functions applies only
in the mathematically exact off rounded mode. If ROUNDED is on, any of the
functions
when given a numerical argument has its value calculated to the current degree of
floating point precision. In addition, real (non-integer valued) powers of numbers
will also be evaluated.
If the COMPLEX switch is turned on in addition to ROUNDED, these funct-
ions will also calculate a real or complex result, again to the current degree of
floating point precision, if given complex arguments. For example, with on
rounded,complex;
For log and the inverse trig. and hyperbolic functions which are multi-valued,
the principal value is returned. The branch cuts chosen (except for acot) are now
those recommended by W. Kahan (Branch Cuts for Complex Elementary Funct-
ions, or Much Ado About Nothing’s Sign Bit, in The State of the Art in Numerical
Analysis, A. Iserles, M.J.D. Powell Eds., Clarendon Press, Oxford, 1987).
The exception for acot is necessary as elsewhere in Reduce acot(−z) is taken to
be π − acot(z) rather than − acot(z). The branch cuts are:
80 CHAPTER 7. BUILT-IN PREFIX OPERATORS
log: {r | r ∈ R ∧ r < 0}
asin, acos: {r | r ∈ R ∧ (r > 1 ∨ r < −1)}
acsc, asec: {r | r ∈ R ∧ r 6= 0 ∧ r > −1 ∧ r < 1}
atan, acot: {r ∗ i | r ∈ R ∧ (r > 1 ∨ r < −1)}
asinh: {r ∗ i | r ∈ R ∧ (r ≥ 1 ∨ r ≤ −1)}
acsch: {r ∗ i | r ∈ R ∧ r 6= 0 ∧ r ≥ −1 ∧ r ≤ 1}
acosh: {r | r ∈ R ∧ r < 1}
asech: {r | r ∈ R ∧ (r > 1 ∨ r < 0)}
atanh: {r | r ∈ R ∧ (r > 1 ∨ r < −1)}
acoth: {r | r ∈ R ∧ r > −1 ∧ r < 1}
The unary operator Bernoulli provides notation and computation for Bernoulli
numbers. Bernoulli(n) evaluates to the nth Bernoulli number; all of the odd
Bernoulli numbers, except Bernoulli(1), are zero.
The algorithms are based upon those by Herbert Wilf, presented by Sandra
Fillebrown.[1]. If the ROUNDED switch is off, the algorithms are exactly those;
if it is on, some further rounding may be done to prevent computation of redundant
digits. Hence, these functions are particularly fast when used to approximate the
Bernoulli numbers in rounded mode.
Euler numbers are computed by the unary operator Euler, which return the nth Eu-
ler number. The computation is derived directly from Pascal’s triangle of binomial
coefficients.
The unary operator Fibonacci provides notation and computation for Fibonacci
numbers. Fibonacci(n) evaluates to the nth Fibonacci number. If n is a posi-
tive or negative integer, it will be evaluated following the definition:
F0 = 0; F1 = 1; Fn = Fn−1 + Fn−2
Fibonacci Polynomials are computed by the binary operator FibonacciP. Fibonac-
ciP(n,x) returns the nth Fibonaccip polynomial in the variable x. If n is a positive
or negative integer, it will be evaluated following the definition:
F0 (x) = 0; F1 (x) = 1; Fn (x) = xFn−1 (x) + Fn−2 (x)
7.5. MOTZKIN NUMBERS 81
Author: G. Üçoluk.
The operator CHANGEVAR does a variable transformation in a set of differential
equations. Syntax:
changevar(u,y,x=e^y,df(u(x),x) - log(x));
changevar({u},{y},{x=e^y},{df(u(x),x) - log(x)});
except for one difference: the first command returns the transformed differential
equation, the second one a list with a single element.
The switch DISPJACOBIAN governs the display the entries of the inverse Jaco-
bian, it is OFF per default.
The mathematics behind the change of independent variable(s) in differential
equations is quite straightforward. It is basically the application of the chain rule.
If the dependent variable of the differential equation is F , the independent vari-
ables are xi and the new independent variables are ui (where i=1...n) then the first
derivatives are:
∂F ∂F ∂uj
=
∂xi ∂uj ∂xi
82 CHAPTER 7. BUILT-IN PREFIX OPERATORS
xi = fi (u1 , . . . , un )
The first thought might be solving the above given equations for uj and then dif-
ferentiating them with respect to xi , then again making use of the equations above,
substituting new variables for the old ones in the calculated derivatives. This is
not always a preferable way to proceed. Mainly because the functions fi may not
always be easily invertible. Another approach that makes use of the Jacobian is
better. Consider the above given equations which relate the old variables to the
new ones. Let us differentiate them:
∂xj ∂fj
=
∂xi ∂xi
∂fj ∂uk
δij =
∂uk ∂xi
The first derivative is nothing but the (j, k) th entry of the Jacobian matrix.
So if we speak in matrix language
1=J·D
If the Jacobian has a non-vanishing determinant then it is invertible and we are able
to write from the matrix equation above:
D = J−1
∂ui
= J−1 ij
∂xj
The higher derivatives are obtained by the successive application of the chain rule
and using the definitions of the old variables in terms of the new ones. It can be
easily verified that the only derivatives that are needed to be calculated are the first
order ones which are obtained above.
7.6. CHANGEVAR OPERATOR 83
∂2u ∂2u
+ 2 =0
∂x2 ∂y
Now assume we want to obtain the polar coordinate form of Laplace equation. The
change of variables is:
x = r cos θ, y = r sin θ
Here we could omit the curly braces in the first and last arguments (because those
lists have only one member) and the curly braces in the third argument (because
they are optional), but you cannot leave off the curly braces in the second argument.
So one could equivalently write
If you have tried out the above example, you will notice that the denominator con-
tains a cos2 θ + sin2 θ which is actually equal to 1. This has of course nothing to
do with CHANGEVAR. One has to be overcome these pattern matching problems
by the conventional methods REDUCE provides (a rule, for example, will fix it).
Secondly you will notice that your u(x,y) operator has changed to u(r,theta)
in the result. Nothing magical about this. That is just what we do with pencil and
paper. u(r,theta) represents the the transformed dependent variable.
x = eu
continued_fraction(hnumi)
continued_fraction(hnumi,hsizei)
continued_fraction(hnumi,hsizei,hnumtermsi)
The result is the special operator contfrac with three arguments: the original
number to be expanded hnumi, secondly the rational number approximation (the
final convergent) and thirdly a list of continuents of the continued fraction (iė. a
list of pairs of partial numerators and denominators)
Note that, although with the current algorithm all the partial numerators have the
value 1, they are stored in the list of continuents. This is for compatibility with
the output of other continued fractions functions cfrac and cf_euler. This
facilitates pretty-printing and the implementation of various equivalence transfor-
mations all of which are documented in the continued fraction subsection of the
RATAPRX manual (Section 16.51).
Precision: the second optional parameter hsizei is an upper bound for the absolute
value of the denominator of the convergent.
7.7. CONTINUED_FRACTION OPERATOR 85
Number of terms: the third optional parameter hnumtermsi is the maximum num-
ber of terms (continuents) to be generated.
If both optional parameters omitted, the expansion performed is exact for rational
number arguments and for irrational or rounded arguments it is up to the current
system precision. If both optional parameters are given the expansion is halted
when the desired precision is reached or when the specified maximum number of
terms have been generated whichever is the sooner. If the size parameter is zero, its
value is ignored. Thus to obtain a continued fraction expansion to, for example, 10
terms one would specify the hsizei parameter to be 0 and the hnumtermsi parameter
to be 10.
Note that the operator contfrac is not normally seen as the output is pretty-
printed, unless the number of continuents generated is larger than 12.
Examples:
continued_fraction(6/11);
6 1
{----,exact,---------------}
11 1
1 + ---------
1
1 + ---
5
continued_fraction(pi,1000);
355 1
{pi,-----,3 + ----------------}
113 1
7 + ----------
1
15 + ---
1
continued_fraction(pi,0,6);
104348 1
{pi,--------,3 + ------------------------------}
33215 1
7 + ------------------------
1
15 + -----------------
1
86 CHAPTER 7. BUILT-IN PREFIX OPERATORS
1 + -----------
1
292 + ---
1
continued_fraction(pi,1000,3);
333 1
{pi,-----,3 + ----------}
106 1
7 + ----
15
continued_fraction(pi,1000,6);
355 1
{pi,-----,3 + ----------------}
113 1
7 + ----------
1
15 + ---
1
continued_fraction e;
{e,
13580623
----------,
4996032
7.8 DF Operator
df(y,x) = ∂y/∂x
df(y,x,2) = ∂ 2 y/∂x2
df(y,x1,2,x2,x3,2) = ∂ 5 y/∂x21 ∂x2 ∂x23 .
The evaluation of df(y,x) proceeds as follows: first, the values of Y and X are
found. Let us assume that X has no assigned value, so its value is X. Each term
or other part of the value of Y that contains the variable X is differentiated by the
standard rules. If Z is another variable, not X itself, then its derivative with respect
to X is taken to be 0, unless Z has previously been declared to DEPEND on X, in
which case the derivative is reported as the symbol df(z,x).
provided U depends only on the one variable X. This simplification removes the
non-commutative aspect of the derivative.
If the switch EXPANDDF is turned on then REDUCE uses the chain rule to expand
symbolic derivatives of indirectly dependent variables provided the result is unam-
biguous, i.e. provided there is no direct dependence. It is off by default. Thus, for
example, given
88 CHAPTER 7. BUILT-IN PREFIX OPERATORS
whereas after
DEPEND F,X;
DF(F,X) does not expand at all (since the result would be ambiguous and the
algorithm would loop).
Turning on the switch ALLOWDFINT allows “differentiation under the integral
sign”, i.e.
if this results in a simplification. If the switch DFINT is also turned on then this
happens regardless of whether the result simplifies. Both switches are off by de-
fault.
The LET statement can be used to introduce rules for differentiation of user-defined
operators. Its general form is
where
(This is how the tan differentiation rule appears in the REDUCE source.)
Notice that all dummy arguments of the relevant operator must be declared arbi-
trary by the FOR ALL command, and that rules may be supplied for operators with
any number of arguments. If no differentiation rule appears for an argument in an
operator, the differentiation routines will return as result an expression in terms
of DF. For example, if the rule for the differentiation with respect to the second
argument of F is not supplied, the evaluation of df(f(x,z),z) would leave this
expression unchanged. (No DEPEND declaration is needed here, since f(x,z)
obviously “depends on” Z.)
Once such a rule has been defined for a given operator, any future differentiation
rules for that operator must be defined with the same number of arguments for that
operator, otherwise we get the error message
INT(hEXPRN:algebraici,hVAR:kerneli) : algebraic.
This will return correctly the indefinite integral for expressions comprising poly-
nomials, log functions, exponential functions and tan and atan. The arbitrary con-
stant is not represented. If the integral cannot be done in closed terms, it returns a
formal integral for the answer in one of two ways:
The program checks that the second argument is a variable and gives an error if it
is not.
90 CHAPTER 7. BUILT-IN PREFIX OPERATORS
Note: If the int operator is called with 4 arguments, REDUCE will implicitly call
the definite integration package (DEFINT) and this package will interpret the third
and fourth arguments as the lower and upper limit of integration, respectively. For
details, consult the documentation on the D EFINT package.
7.9.1 Options
The switch TRINT when on will trace the operation of the algorithm. It produces
a great deal of output in a somewhat illegible form, and is not of much interest to
the general user. It is normally off.
The switch TRINTSUBST when on will trace the heuristic attempts to solve the
integral by substitution. It is normally off.
If the switch FAILHARD is on the algorithm will terminate with an error if the
integral cannot be done in closed terms, rather than return a formal integration
form. FAILHARD is normally off.
The switch NOLNR suppresses the use of the linear properties of integration in
cases when the integral cannot be found in closed terms. It is normally off.
The switch NOINTSUBST disables the heuristic attempts to solve the integral by
substitution. It is normally off.
If a function appears in the integrand that is not one of the functions EXP, ERF,
TAN, ATAN, LOG, DILOG then the algorithm will make an attempt to inte-
grate the argument if it can, differentiate it and reach a known function. However
the answer cannot be guaranteed in this case. If a function is known to be alge-
braically independent of this set it can be flagged transcendental by
flag(’(trilog),’transcendental);
in which case this function will be added to the permitted field descriptors for a
genuine decision procedure. If this is done the user is responsible for the mathe-
matical correctness of his actions.
The standard version does not deal with algebraic extensions. Thus integration
of expressions involving square roots and other like things can lead to trouble. A
contributed package that supports integration of functions involving square roots is
available, however (ALGINT, chapter 16.1). In addition there is a definite integra-
tion package, DEFINT( chapter 16.18).
7.10. LENGTH OPERATOR 91
7.9.3 References
LENGTH is a generic operator for finding the length of various objects in the sys-
tem. The meaning depends on the type of the object. In particular, the length
of an algebraic expression is the number of additive top-level terms its expanded
representation.
Examples:
length(a+b) -> 2
length(2) -> 1.
Other objects that support a length operator include arrays, lists and matrices. The
explicit meaning in these cases is included in the description of these objects.
The MAP operator applies a uniform evaluation pattern to all members of a com-
posite structure: a matrix, a list, or the arguments of an operator expression. The
evaluation pattern can be a unary procedure, an operator, or an algebraic expression
with one free variable.
It is used with the syntax:
MAP(FNC:function,OBJ:object)
Here OBJ is a list, a matrix or an operator expression. FNC can be one of the
following:
2. an algebraic expression with exactly one free variable, i.e. a variable pre-
ceded by the tilde symbol. The expression is evaluated for each element of
OBJ, with the element substituted for the free variable;
3. a replacement rule of the form var => rep where var is a variable (a
kernel without a subscript) and rep is an expression that contains var. The
replacement expression rep is evaluated for each element of OBJ with the
element substituted for var. The variable var may be optionally preceded
by a tilde.
The rule form for FNC is needed when more than one free variable occurs.
Examples:
[ 3 6 ]
[ x x ]
[---- ----]
[ 3 6 ]
[ ]
[ 5 6 ]
[ x x ]
[---- ----]
[ 5 6 ]
You can use MAP in nested expressions. However, you cannot apply MAP to a
non-composite object, e.g. an identifier or a number.
MKID(U:id,V:id|non-negative integer):id
for example
mkid(a,3) -> A3
mkid(apple,s) -> APPLES
7.13. THE POCHHAMMER NOTATION 93
set(mkid(a,3),3);
will give A3 the value 2. Similarly, the UNSET statement can be used to remove
the value from these identifiers, for example
unset(mkid(a,3));
(a)0 = 1,
(a)k = a(a + 1)(a + 2) · · · (a + k − 1).
Γ(a + k)
(a)k =
Γ(a)
With ROUNDED off, this expression is evaluated numerically if a and k are both
integral, and otherwise may be simplified where appropriate. The simplification
rules are based upon algorithms supplied by Wolfram Koepf.
7.14 PF Operator
2 - 2 2
{-------,-------,--------------} .
X + 2 X + 1 2
X + 2*X + 1
If you want the denominators in factored form, use off exp;. Thus, with
2/((x+1)^2*(x+2)) in the workspace, the commands off exp; pf(ws,x);
give the result
2 - 2 2
{-------,-------,----------} .
X + 2 X + 1 2
(X + 1)
To recombine the terms, FOR EACH . . . SUM can be used. So with the above list
in the workspace, for each j in ws sum j; returns the result
2
------------------
2
(X + 2)*(X + 1)
Alternatively, one can use the operations on lists to extract any desired term.
The SELECT operator extracts from a list, or from the arguments of an n–ary
operator, elements corresponding to a boolean predicate. It is used with the syntax:
SELECT(hFNC:functioni, hLST:listi)
2. an algebraic expression with exactly one free variable, i.e. a variable pre-
ceded by the tilde symbol. The expression is evaluated for each element of
hLSTi, with the element substituted for the free variable;
7.15. SELECT OPERATOR 95
3. a replacement rule of the form hvari => hrepi where hvari is a variable (a
kernel without subscript) and hrepi is an expression that contains hvari. hrepi
is evaluated for each element of LST with the element substituted for hvari.
hvari may be optionally preceded by a tilde.
The rule form for FNC is needed when more than one free variable occurs.
The result of evaluating FNC is interpreted as a boolean value corresponding to the
conventions of REDUCE. These values are composed with the leading operator of
the input expression.
Examples:
solve(log(sin(x+3))^5 = 8,x);
solve(a*log(sin(x+3))^5 - b, sin(x+3));
solve({a*x+y=3,y=-2},{x,y});
solve(x^7-x^6+x^2=1,x)
6
-> {X=ROOT_OF(X_ + X_ + 1,X_,TAG_1),X=1}
7.16. SOLVE OPERATOR 97
The TAG argument is used to uniquely identify those particular solutions. Solution
multiplicities are stored in the global variable ROOT_MULTIPLICITIES rather
than the solution list. The value of this variable is a list of the multiplicities of the
solutions for the last call of SOLVE. For example,
solve(x^2=2x-1,x); root_multiplicities;
{X=1}
{2}
on multiplicities; solve(x^2=2x-1,x);
{X=1,X=1}
solve(cos(x) + log(x),x);
{X=ROOT_OF(COS(X_) + LOG(X_),X_,TAG_1)} .
solve(-a*x^3+a*x^2+x^4-x^3-4*x^2+4,x);
2 3
{X=ROOT_OF(A*X_ - X_ + 4*X_ + 4,X_,TAG_2),X=1}
sub(a=-1,ws);
{X=ONE_OF({2,-1,-2},TAG_2),X=1}
expand_cases ws;
{X=2,X=-1,X=-2,X=1}
Since roots of cubics and quartics can often be very messy, a switch FULLROOTS
is available, that, when off (the default), will prevent the production of a result in
closed form. The ROOT_OF construct will be used in this case instead.
In constructing the solutions of cubics and quartics, trigonometrical forms are used
where appropriate. This option is under the control of a switch TRIGFORM, which
is normally on.
The following example illustrates the use of these facilities:
let xx = solve(x^3+x+1,x);
xx;
3
{X=ROOT_OF(X_ + X_ + 1,X_)}
on fullroots;
xx;
- SQRT(31)*I
ATAN(---------------)
3*SQRT(3)
{X=(I*(SQRT(3)*SIN(-----------------------)
3
7.16. SOLVE OPERATOR 99
- SQRT(31)*I
ATAN(---------------)
3*SQRT(3)
- COS(-----------------------)))/SQRT(3),
3
- SQRT(31)*I
ATAN(---------------)
3*SQRT(3)
X=( - I*(SQRT(3)*SIN(-----------------------)
3
- SQRT(31)*I
ATAN(---------------)
3*SQRT(3)
+ COS(-----------------------)))/SQRT(
3
3),
- SQRT(31)*I
ATAN(---------------)
3*SQRT(3)
2*COS(-----------------------)*I
3
X=----------------------------------}
SQRT(3)
off trigform;
xx;
2/3
{X=( - (SQRT(31) - 3*SQRT(3)) *SQRT(3)*I
2/3 2/3
- (SQRT(31) - 3*SQRT(3)) - 2 *SQRT(3)*I
1/6
*3 ),
2/3
100 CHAPTER 7. BUILT-IN PREFIX OPERATORS
2/3 2/3
- (SQRT(31) - 3*SQRT(3)) + 2 *SQRT(3)*I
1/6
*3 ),
2/3 2/3
(SQRT(31) - 3*SQRT(3)) - 2
X=-------------------------------------}
1/3 1/3 1/6
(SQRT(31) - 3*SQRT(3)) *6 *3
put(’sinh,’inverse,’asinh);
put(’asinh,’inverse,’sinh);
that the absolute value of the imaginary part does not exceed π; but checks (perhaps
involving user response for non-numerical arguments) could be introduced using
LET statements for these operators.
solve({x=2*z,z=2*y},{z});
requirements;
{x - 4*y}
solve({x=a*z+1,0=b*z-y},{z,x});
y a*y + b
{{z=---,x=---------}}
b b
which is not valid for all possible values of the parameters. The variable
1
The difference between linear and non–linear inconsistent systems is based on the algorithms
which produce this information as a side effect when attempting to find a formal solution; example:
solve({x = a, x = b, y = c, y = d}, {x, y} gives a set {a − b, c − d} while solve({x2 = a, x2 =
b, y 2 = c, y 2 = d}, {x, y} leads to {a − b}.
102 CHAPTER 7. BUILT-IN PREFIX OPERATORS
ASSUMPTIONS contains then a list of restrictions: the solutions are valid only
as long as none of these expressions vanishes. Any zero of one of them represents
a special case that is not covered by the formal solution. In the above case the value
is
assumptions;
{b}
which excludes formally the case b = 0; obviously this special parameter value
makes the system singular. The set of assumptions is complete for both, linear and
non–linear systems.
SOLVE rearranges the variable sequence to reduce the (expected) computing time.
This behavior is controlled by the switch VAROPT, which is on by default. If it is
turned off, the supplied variable sequence is used or the system kernel ordering is
taken if the variable list is omitted. The effect is demonstrated by an example:
s:= {y^3+3x=0,x^2+y^2=1};
solve(s,{y,x});
6 2
{{y=root_of(y_ + 9*y_ - 9,y_),
3
- y
x=-------}}
3
6 4 2
{{x=root_of(x_ - 3*x_ + 12*x_ - 1,x_),
4 2
x*( - x + 2*x - 10)
y=-----------------------}}
3
In the first case, solve forms the solution as a set of pairs (yi , x(yi )) because the
degree of x is higher – such a rearrangement makes the internal computation of the
Gröbner basis generally faster. For the second case the explicitly given variable
7.17. EVEN AND ODD OPERATORS 103
sequence is used such that the solution has now the form (xi , y(xi )). Controlling
the variable sequence is especially important if the system has one or more free
variables. As an alternative to turning off varopt, a partial dependency among
the variables can be declared using the depend statement: solve then rearranges
the variable sequence but keeps any variable ahead of those on which it depends.
on varopt;
s:={a^3+b,b^2+c}$
solve(s,{a,b,c});
3 6
{{a=arbcomplex(1),b= - a ,c= - a }}
{{c=arbcomplex(2),
6
a=root_of(a_ + c,a_),
3
b= - a }}
Here solve is forced to put c after a and after b, but there is no obstacle to inter-
changing a and b.
An operator can be declared to be even or odd in its first argument by the declara-
tions EVEN and ODD respectively. Expressions involving an operator declared in
this manner are transformed if the first argument contains a minus sign. Any other
arguments are not affected. In addition, if say F is declared odd, then f(0) is
replaced by zero unless F is also declared non zero by the declaration NONZERO.
For example, the declarations
mean that
An operator can be declared to be linear in its first argument over powers of its
second argument. If an operator F is so declared, F of any sum is broken up into
sums of Fs, and any factors that are not powers of the variable are taken outside.
This means that F must have (at least) two arguments. In addition, the second
argument must be an identifier (or more generally a kernel), not an expression.
Example:
If F were declared linear, then
5
f(a*x^5+b*x+c,x) -> F(X ,X)*A + F(X,X)*B + F(1,X)*C
More precisely, not only will the variable and its powers remain within the scope
of the F operator, but so will any variable and its powers that had been declared
to DEPEND on the prescribed variable; and so would any expression that contains
that variable or a dependent variable on any level, e.g. cos(sin(x)).
To declare operators F and G to be linear operators, use:
linear f,g;
The analysis is done of the first argument with respect to the second; any other
arguments are ignored. It uses the following rules of evaluation:
f(0) -> 0
f(-y,x) -> -F(Y,X)
f(y+z,x) -> F(Y,X)+F(Z,X)
f(y*z,x) -> Z*F(Y,X) if Z does not depend on X
f(y/z,x) -> F(Y,X)/Z if Z does not depend on X
The use of such linear operators can be seen in the paper Fox, J.A. and A. C. Hearn,
“Analytic Computation of Some Integrals in Fourth Order Quantum Electrodynam-
ics” Journ. Comp. Phys. 14 (1974) 301-317, which contains a complete listing of
7.19. NON-COMMUTING OPERATORS 105
a program for definite integration of some expressions that arise in fourth order
quantum electrodynamics.
noncom u,v;
would introduce the commutator of u(x) and u(y) for all X and Y. Note that
since ordp(x,x) is true, the equality check is necessary in the degenerate case
to avoid a circular loop in the rule.
symmetric u,v;
means that any expression involving the top level operators U or V will have its
arguments reordered to conform to the internal order used by REDUCE. The user
can change this order for kernels by the command KORDER.
106 CHAPTER 7. BUILT-IN PREFIX OPERATORS
antisymmetric l,m;
means that any expression involving the top level operators L or M will have its
arguments reordered to conform to the internal order of the system, and the sign
of the expression changed if there are an odd number of argument interchanges
necessary to bring about the new order.
For example, l(x,m(1,2)) would become -l(-m(2,1),x) since one inter-
change occurs with each operator. An expression like l(x,x) would also be
replaced by 0.
The user may add new prefix operators to the system by using the declaration
OPERATOR. For example:
operator h,g1,arctan;
Users can add new infix operators by using the declarations INFIX and PRECEDENCE.
For example,
infix mm;
precedence mm,-;
The declaration infix mm; would allow one to use the symbol MM as an infix
operator:
a mm b instead of mm(a,b).
The declaration precedence mm,-; says that MM should be inserted into the
infix operator precedence list just after the − operator. This gives it higher prece-
dence than − and lower precedence than * . Thus
a - b mm c - d means a - (b mm c) - d,
while
a * b mm c * d means (a * b) mm (c * d).
Both infix and prefix operators have no transformation properties unless LET state-
ments or procedure declarations are used to assign a meaning.
We should note here that infix operators so defined are always binary:
a mm b mm c means (a mm b) mm c.
There are several facilities in REDUCE, such as the differentiation operator and
the linear operator facility, that can utilize knowledge of the dependency between
various variables, or kernels. Such dependency may be expressed by the command
DEPEND. This takes an arbitrary number of arguments and sets up a dependency
of the first argument on the remaining arguments. For example,
depend x,y,z;
depend z,cos(x),y;
108 CHAPTER 7. BUILT-IN PREFIX OPERATORS
nodepend z,cos(x);
depend {x,y,z},u,v,{theta},time;
is equivalent to
depend x,u,v;
depend y,u,v;
depend z,u,v;
depend theta,time;
Chapter 8
In this section, we consider a variety of commands and operators that permit the
user to obtain various parts of algebraic expressions and also display their structure
in a variety of forms. Also presented are some additional concepts in the REDUCE
design that help the user gain a better understanding of the structure of the system.
8.1 Kernels
REDUCE is designed so that each operator in the system has an evaluation (or
simplification) function associated with it that transforms the expression into an
internal canonical form. This form, which bears little resemblance to the original
expression, is described in detail in Hearn, A. C., “REDUCE 2: A System and Lan-
guage for Algebraic Manipulation,” Proc. of the Second Symposium on Symbolic
and Algebraic Manipulation, ACM, New York (1971) 128-133.
The evaluation function may transform its arguments in one of two alternative
ways. First, it may convert the expression into other operators in the system, leav-
ing no functions of the original operator for further manipulation. This is in a sense
true of the evaluation functions associated with the operators +, * and / , for ex-
ample, because the canonical form does not include these operators explicitly. It
is also true of an operator such as the determinant operator DET because the rel-
evant evaluation function calculates the appropriate determinant, and the operator
DET no longer appears. On the other hand, the evaluation process may leave some
residual functions of the relevant operator. For example, with the operator COS,
a residual expression like COS(X) may remain after evaluation unless a rule for
the reduction of cosines into exponentials, for example, were introduced. These
residual functions of an operator are termed kernels and are stored uniquely like
109
110 CHAPTER 8. DISPLAY AND STRUCTURING OF EXPRESSIONS
a
cos(x*y)
log(sin(x))
whereas
a*b
(a+b)^4
are not.
We see that kernel forms can usually be used as generalized variables, and most
algebraic properties associated with variables may also be associated with kernels.
Several mechanisms are available for saving and retrieving previously evaluated
expressions. The simplest of these refers to the last algebraic expression simpli-
fied. When an assignment of an algebraic expression is made, or an expression is
evaluated at the top level, (i.e., not inside a compound statement or procedure) the
results of the evaluation are automatically saved in a variable WS that we shall refer
to as the workspace. (More precisely, the expression is assigned to the variable WS
that is then available for further manipulation.)
8.3. OUTPUT OF EXPRESSIONS 111
Example:
If we evaluate the expression (x+y)^2 at the top level and next wish to differen-
tiate it with respect to Y, we can simply say
df(ws,y);
SAVEAS hexpressioni
For example, after the differentiation in the last example, the workspace holds the
expression 2*x+2*y. If we wish to assign this to the variable Z we can now say
saveas z;
If the user wishes to save the expression in a form that allows him to use some of
its variables as arbitrary parameters, the FOR ALL command can be used.
Example:
with the above expression would mean that h(z) evaluates to 2*Y+2*Z.
A further method for referencing more than the last expression is described in
chapter 13 on interactive use of REDUCE.
is normally printed in an expanded form, filling the whole output line with terms.
Certain output declarations, however, can be used to affect this format. To begin
with, we look at an operator for changing the length of the output line.
LINELENGTH(NUM:integer):integer
and sets the output line length to the integer NUM. It returns the previous output line
length (so that it can be stored for later resetting of the output line if needed).
We now describe a number of switches and declarations that are available for con-
trolling output formats. It should be noted, however, that the transformation of
large expressions to produce these varied output formats can take a lot of comput-
ing time and space. If a user wishes to speed up the printing of the output in such
cases, he can turn off the switch PRI. If this is done, then output is produced in
one fixed format, which basically reflects the internal form of the expression, and
none of the options below apply. PRI is normally on.
With PRI on, the output declarations and switches available are as follows:
ORDER Declaration
The declaration ORDER may be used to order variables on output. The syntax is:
order v1,...vn;
order x,y,z;
orders X ahead of Y, Y ahead of Z and all three ahead of other variables not given
an order. order nil; resets the output order to the system default. The order
of variables may be changed by further calls of ORDER, but then the reordered
variables would have an order lower than those in earlier ORDER calls. Thus,
order x,y,z;
order y,x;
8.3. OUTPUT OF EXPRESSIONS 113
FACTOR Declaration
factor x;
2 2
X + 2*X*(Y + 1) + Y + 2*Y + 1
All expressions involving a given prefix operator may also be factored by putting
the operator name in the list of factored identifiers. For example:
factor x,cos,sin(x);
causes all powers of X and SIN(X) and all functions of COS to be factored.
Note that FACTOR does not affect the order of its arguments. You should also use
ORDER if this is important.
The declaration remfac v1,...,vn; removes the factoring flag from the ex-
pressions v1 through vn.
In addition to these declarations, the form of the output can be modified by switch-
ing various output control switches using the declarations ON and OFF. We shall
illustrate the use of these switches by an example, namely the printing of the ex-
pression
x^2*(y^2+2*y)+x*(y^2+z)/(2*a) .
ALLFAC Switch
This switch will cause the system to search the whole expression, or any sub-
expression enclosed in parentheses, for simple multiplicative factors and print them
outside the parentheses. Thus our expression with ALLFAC off will print as
2 2 2 2
(2*X *Y *A + 4*X *Y*A + X*Y + X*Z)/(2*A)
2 2
X*(2*X*Y *A + 4*X*Y*A + Y + Z)/(2*A) .
ALLFAC is normally on, and is on in the following examples, except where other-
wise stated.
DIV Switch
This switch makes the system search the denominator of an expression for simple
factors that it divides into the numerator, so that rational fractions and negative
powers appear in the output. With DIV on, our expression would print as
2 2 (-1) (-1)
X*(X*Y + 2*X*Y + 1/2*Y *A + 1/2*A *Z) .
HORNER Switch
This switch causes the system to print polynomials according to Horner’s rule.
With HORNER on, our expression prints as
2
X*(Y + Z + 2*(Y + 2)*A*X*Y)/(2*A) .
LIST Switch
This switch causes the system to print each term in any sum on a separate line.
With LIST on, our expression prints as
8.3. OUTPUT OF EXPRESSIONS 115
2
X*(2*X*Y *A
+ 4*X*Y*A
2
+ Y
+ Z)/(2*A) .
NOSPLIT Switch
Under normal circumstances, the printing routines try to break an expression across
lines at a natural point. This is a fairly expensive process. If you are not overly
concerned about where the end-of-line breaks come, you can speed up the printing
of expressions by turning off the switch NOSPLIT. This switch is normally on.
RAT Switch
This switch is only useful with expressions in which variables are factored with
FACTOR. With this mode, the overall denominator of the expression is printed
with each factored sub-expression. We assume a prior declaration factor x; in
the following output. We first print the expression with RAT set to off:
2 2
(2*X *Y*A*(Y + 2) + X*(Y + Z))/(2*A) .
2 2
X *Y*(Y + 2) + X*(Y + Z)/(2*A) .
2 (-1) 2
X *Y*(Y + 2) + 1/2*X*A *(Y + Z) .
Finally, with X factored, RAT on and ALLFAC off we retrieve the original structure
116 CHAPTER 8. DISPLAY AND STRUCTURING OF EXPRESSIONS
2 2 2
X *(Y + 2*Y) + X*(Y + Z)/(2*A) .
RATPRI Switch
If the numerator and denominator of an expression can each be printed in one line,
the output routines will print them in a two dimensional notation, with numerator
and denominator on separate lines and a line of dashes in between. For example,
(a+b)/2 will print as
A + B
-----
2
Turning this switch off causes such expressions to be output in a linear form.
REVPRI Switch
The normal ordering of terms in output is from highest to lowest power. In some
situations (e.g., when a power series is output), the opposite ordering is more con-
venient. The switch REVPRI if on causes such a reverse ordering of terms. For
example, the expression y*(x+1)^2+(y+3)^2 will normally print as
2 2
X *Y + 2*X*Y + Y + 7*Y + 9
2 2
9 + 7*Y + Y + 2*X*Y + X *Y.
The WRITE command consists of the word WRITE followed by one or more items
separated by commas, and followed by a terminator. There are three kinds of items
that can be used:
The items specified by a single WRITE statement print side by side on one line.
(The line is broken automatically if it is too long.) Strings print exactly as quoted.
The WRITE command itself however does not return a value.
The print line is closed at the end of a WRITE command evaluation. Therefore the
command WRITE ""; (specifying nothing to be printed except the empty string)
causes a line to be skipped.
Examples:
The blanks between the 5 and B, and the 3 and T, come from the blanks in
the quoted strings.
3. To print a table of the squares of the integers from 1 to 20, and at the same
time store them in positions 1 to 20 of an array A:
118 CHAPTER 8. DISPLAY AND STRUCTURING OF EXPRESSIONS
4. The following more complete example calculates the famous f and g se-
ries, first reported in Sconzo, P., LeSchack, A. R., and Tobey, R., “Symbolic
Computation of f and g Series by Computer”, Astronomical Journal 70 (May
1965).
x1:= -sig*(mu+2*eps)$
x2:= eps - 2*sig^2$
x3:= -3*mu*sig$
f:= 1$
g:= 0$
for i:= 1 step 1 until 10 do begin
f1:= -mu*g+x1*df(f,eps)+x2*df(f,sig)+x3*df(f,mu);
write "f(",i,") := ",f1;
g1:= f+x1*df(g,eps)+x2*df(g,sig)+x3*df(g,mu);
write "g(",i,") := ",g1;
f:=f1$
g:=g1$
end;
A portion of the output, to illustrate the printout from the WRITE command,
is as follows:
2
F(4) := MU*(3*EPS - 15*SIG + MU)
G(4) := 6*SIG*MU
2
F(5) := 15*SIG*MU*( - 3*EPS + 7*SIG - MU)
2
G(5) := MU*(9*EPS - 45*SIG + MU)
on fort;
out "forfil";
write "C this is a fortran program";
write " 1 format(e13.5)";
write " u=1.23";
write " v=2.17";
write " w=5.2";
x:=(u+v+w)^11;
write "C it was foolish to expand this expression";
write " print 1,x";
120 CHAPTER 8. DISPLAY AND STRUCTURING OF EXPRESSIONS
There are a number of methods available to change the default format of the FOR-
TRAN output.
The breakup of the expression into subparts is such that the number of continuation
lines produced is less than a given number. This number can be modified by the
assignment
card_no := hnumberi;
where hnumberi is the total number of cards allowed in a statement. The default
value of CARD_NO is 20.
The width of the output expression is also adjustable by the assignment
fort_width := hintegeri;
FORT_WIDTH which sets the total width of a given line to hintegeri. The initial
FORTRAN output width is 70.
REDUCE automatically inserts a decimal point after each isolated integer coeffi-
cient in a FORTRAN expression (so that, for example, 4 becomes 4. ). To prevent
this, set the PERIOD mode switch to OFF.
FORTRAN output is normally produced in lower case. If upper case is desired, the
switch FORTUPPER should be turned on.
Finally, the default name ANS assigned to an unnamed expression and its subparts
can be changed by the operator VARNAME. This takes a single identifier as argu-
ment, which then replaces ANS as the expression name. The value of VARNAME is
its argument.
Further facilities for the production of FORTRAN and other language output are
provided by the SCOPE and GENTRAN packagesdescribed in chapters 16.26 and
16.62.
It is often useful to save an expression on an external file for use later as input
in further calculations. The commands for opening and closing output files are
explained elsewhere. However, we see in the examples on output of expressions
that the standard “natural” method of printing expressions is not compatible with
the input syntax. So to print the expression in an input compatible form we must
122 CHAPTER 8. DISPLAY AND STRUCTURING OF EXPRESSIONS
inhibit this natural style by turning off the switch NAT. If this is done, a dollar sign
will also be printed at the end of the expression.
Example:
The following sequence of commands
In those cases where the final result has a complicated form, it is often convenient
to display the skeletal structure of the answer. The operator STRUCTR, that takes
a single expression as argument, will do this for you. Its syntax is:
STRUCTR(EXPRN:algebraic[,ID1:identifier[,ID2:identifier]]);
The structure is printed effectively as a tree, in which the subparts are laid out with
auxiliary names. If the optional ID1 is absent, the auxiliary names are prefixed by
the root ANS. This root may be changed by the operator VARNAME. If the optional
ID1 is present, and is an array name, the subparts are named as elements of that
array, otherwise ID1 is used as the root prefix. (The second optional argument
ID2 is explained later.)
The EXPRN can be either a scalar or a matrix expression. Use of any other will
result in an error.
Example:
Let us suppose that the workspace contains ((A+B)^2+C)^3+D. Then the input
STRUCTR WS; will (with EXP off) result in the output:
ANS3
where
3
ANS3 := ANS2 + D
2
8.4. CHANGING THE INTERNAL ORDER OF VARIABLES 123
ANS2 := ANS1 + C
ANS1 := A + B
The workspace remains unchanged after this operation, since STRUCTR in the de-
fault situation returns no value (if STRUCTR is used as a sub-expression, its value
is taken to be 0). In addition, the sub-expressions are normally only displayed and
not retained. If you wish to access the sub-expressions with their displayed names,
the switch SAVESTRUCTR should be turned on. In this case, STRUCTR returns a
list whose first element is a representation for the expression, and subsequent ele-
ments are the sub-expression relations. Thus, with SAVESTRUCTR on, STRUCTR
WS in the above example would return
3 2
{ANS3,ANS3=ANS2 + D,ANS2=ANS1 + C,ANS1=A + B}
The PART operator can be used to retrieve the required parts of the expression. For
example, to get the value of ANS2 in the above, one could say:
part(ws,3,2);
If FORT is on, then the results are printed in the reverse order; the algorithm in fact
guaranteeing that no sub-expression will be referenced before it is defined. The
second optional argument ID2 may also be used in this case to name the actual
expression (or expressions in the case of a matrix argument).
Example:
Let us suppose that M, a 2 by 1 matrix, contains the elements ((a+b)^2 + c)^3
+ d and (a + b)*(c + d) respectively, and that V has been declared to be an
array. With EXP off and FORT on, the statement structr(2*m,v,k); will
result in the output
V(1)=A+B
V(2)=V(1)**2+C
V(3)=V(2)**3+D
V(4)=C+D
K(1,1)=2.*V(3)
K(2,1)=2.*V(1)*V(4)
The internal ordering of variables (more specifically kernels) can have a significant
effect on the space and time associated with a calculation. In its default state, RE-
124 CHAPTER 8. DISPLAY AND STRUCTURING OF EXPRESSIONS
DUCE uses a specific order for this which may vary between sessions. However,
it is possible for the user to change this internal order by means of the declaration
KORDER. The syntax for this is:
korder v1,...,vn;
where the Vi are kernels. With this declaration, the Vi are ordered internally ahead
of any other kernels in the system. V1 has the highest order, V2 the next highest,
and so on. A further call of KORDER replaces a previous one. KORDER NIL;
resets the internal order to the system default.
Unlike the ORDER declaration, that has a purely cosmetic effect on the way results
are printed, the use of KORDER can have a significant effect on computation time.
In critical cases then, the user can experiment with the ordering of the variables
used to determine the optimum set for a given problem.
There are many occasions where it is desirable to obtain a specific part of an ex-
pression, or even change such a part to another expression. A number of operators
are available in REDUCE for this purpose, and will be described in this section. In
addition, operators for obtaining specific parts of polynomials and rational funct-
ions (such as a denominator) are described in another section.
Syntax:
COEFF(EXPRN:polynomial,VAR:kernel)
COEFF is an operator that partitions EXPRN into its various coefficients with re-
spect to VAR and returns them as a list, with the coefficient independent of VAR
first.
Under normal circumstances, an error results if EXPRN is not a polynomial in VAR,
although the coefficients themselves can be rational as long as they do not depend
on VAR. However, if the switch RATARG is on, denominators are not checked for
dependence on VAR, and are taken to be part of the coefficients.
Example:
coeff((y^2+z)^3/z,y);
2
{Z ,0,3*Z,0,3,0,1/Z}.
whereas
coeff((y^2+z)^3/y,y);
3 2
{Z /Y,0,3*Z /Y,0,3*Z/Y,0,1/Y}
if RATARG is on.
The length of the result of COEFF is the highest power of VAR encountered plus
1. In the above examples it is 7. In addition, the variable HIGH_POW is set to
the highest non-zero power found in EXPRN during the evaluation, and LOW_POW
to the lowest non-zero power, or zero if there is a constant term. If EXPRN is a
constant, then HIGH_POW and LOW_POW are both set to zero.
The COEFFN operator is designed to give the user a particular coefficient of a vari-
able in a polynomial, as opposed to COEFF that returns all coefficients. COEFFN
is used with the syntax
COEFFN(EXPRN:polynomial,VAR:kernel,N:integer)
Syntax:
PART(EXPRN:algebraic[,INTEXP:integer])
This operator works on the form of the expression as printed or as it would have
been printed at that point in the calculation bearing in mind all the relevant switch
settings at that point. The reader therefore needs some familiarity with the way
that expressions are represented in prefix form in REDUCE to use these operators
effectively. Furthermore, it is assumed that PRI is ON at that point in the calcula-
tion. The reason for this is that with PRI off, an expression is printed by walking
the tree representing the expression internally. To save space, it is never actually
126 CHAPTER 8. DISPLAY AND STRUCTURING OF EXPRESSIONS
transformed into the equivalent prefix expression as occurs when PRI is on. How-
ever, the operations on polynomials described elsewhere can be equally well used
in this case to obtain the relevant parts.
The evaluation proceeds recursively down the integer expression list. In other
words,
PART(hexpressioni,hinteger1i,hinteger2i)
→ PART(PART(hexpressioni,hinteger1i),hinteger2i)
PART(hexpressioni) → hexpressioni.
INTEXP can be any expression that evaluates to an integer. If the integer is pos-
itive, then that term of the expression is found. If the integer is 0, the operator
is returned. Finally, if the integer is negative, the counting is from the tail of the
expression rather than the head.
For example, if the expression a+b is printed as A+B (i.e., the ordering of the
variables is alphabetical), then
part(a+b,2) -> B
part(a+b,-1) -> B
and
part(a+b,0) -> PLUS
arglength(a+b+c) -> 3
arglength(f()) -> 0
arglength(a) -> -1
PART may also be used to substitute for a given part of an expression. In this case,
the PART construct appears on the left-hand side of an assignment statement, and
the expression to replace the given part on the right-hand side.
For example, with the normal settings of the REDUCE switches:
xx := a+b;
part(xx,2) := c; -> A+C
part(c+d,0) := -; -> C-D
8.5. OBTAINING PARTS OF ALGEBRAIC EXPRESSIONS 127
Note that xx in the above is not changed by this substitution. In addition, un-
like expressions such as array and matrix elements that have an instant evaluation
property, the values of part(xx,2) and part(c+d,0) are also not changed.
128 CHAPTER 8. DISPLAY AND STRUCTURING OF EXPRESSIONS
Chapter 9
Many operations in computer algebra are concerned with polynomials and rational
functions. In this section, we review some of the switches and operators available
for this purpose. These are in addition to those that work on general expressions
(such as DF and INT) described elsewhere. In the case of operators, the arguments
are first simplified before the operations are applied. In addition, they operate
only on arguments of prescribed types, and produce a type mismatch error if given
arguments which cannot be interpreted in the required mode with the current switch
settings. For example, if an argument is required to be a kernel and a/2 is used
(with no other rules for A), an error
will result.
With the exception of those that select various parts of a polynomial or rational
function, these operations have potentially significant effects on the space and time
associated with a given calculation. The user should therefore experiment with
their use in a given calculation in order to determine the optimum set for a given
problem.
One such operation provided by the system is an operator LENGTH which returns
the number of top level terms in the numerator of its argument. For example,
length ((a+b+c)^3/(c+d));
has the value 10. To get the number of terms in the denominator, one would first
select the denominator by the operator DEN and then call LENGTH, as in
Other operations currently supported, the relevant switches and operators, and the
129
130 CHAPTER 9. POLYNOMIALS AND RATIONALS
(a+b)*(a+2*b)
and
a^2+3*a*b+2*b^2
will both simplify to the latter form. With EXP off, they would remain unchanged,
unless the complete factoring (ALLFAC) option were in force. EXP is normally on.
Several operators that expect a polynomial as an argument behave differently when
EXP is off, since there is often only one term at the top level. For example, with
EXP off
length((a+b+c)^3/(c+d));
FACTORIZE(EXPRN:polynomial[,INTEXP:prime integer]):list,
the optional argument of which will be described later. Thus to find and display all
factors of the cyclotomic polynomial x105 − 1, one could write:
factorize(x^105-1);
The result is a list of factor,exponent pairs. In the above example, there is no overall
numerical factor in the result, so the results will consist only of polynomials in x.
The number of such polynomials can be found by using the operator LENGTH. If
there is a numerical factor, as in factorizing 12x2 − 12, that factor will appear as
the first member of the result. It will however not be factored further. Prime factors
of such numbers can be found, using a probabilistic algorithm, by turning on the
switch IFACTOR. For example,
on ifactor; factorize(12x^2-12);
setmod 7;
on modular;
factorize(x^4+1);
The factorization module is provided with a trace facility that may be useful as a
way of monitoring progress on large problems, and of satisfying curiosity about the
internal workings of the package. The most simple use of this is enabled by issuing
the REDUCE command on trfac; . Following this, all calls to the factorizer
will generate informative messages reporting on such things as the reduction of
multivariate to univariate cases, the choice of a prime and the reconstruction of
full factors from their images. Further levels of detail in the trace are intended
mainly for system tuners and for the investigation of suspected bugs. For example,
TRALLFAC gives tracing information at all levels of detail. The switch that can
be set by on timings; makes it possible for one who is familiar with the algo-
rithms used to determine what part of the factorization code is consuming the most
resources. on overview; reduces the amount of detail presented in other forms
of trace. Other forms of trace output are enabled by directives of the form
symbolic set!-trace!-factor(<number>,<filename>);
where useful numbers are 1, 2, 3 and 100, 101, ... . This facility is intended to make
it possible to discover in fairly great detail what just some small part of the code has
been doing — the numbers refer mainly to depths of recursion when the factorizer
calls itself, and to the split between its work forming and factorizing images and
reconstructing full factors from these. If NIL is used in place of a filename the
trace output requested is directed to the standard output stream. After use of this
trace facility the generated trace files should be closed by calling
symbolic close!-trace!-files();
NOTE: Using the factorizer with MCD off will result in an error.
Facilities are available in REDUCE for cancelling common factors in the numer-
ators and denominators of expressions, at the option of the user. The system will
perform this greatest common divisor computation if the switch GCD is on. (GCD
is normally off.)
9.3. CANCELLATION OF COMMON FACTORS 133
A check is automatically made, however, for common variable and numerical prod-
ucts in the numerators and denominators of expressions, and the appropriate can-
cellations made.
When GCD is on, and EXP is off, a check is made for square free factors in an
expression. This includes separating out and independently checking the content
of a given polynomial where appropriate. (For an explanation of these terms, see
Anthony C. Hearn, “Non-Modular Computation of Polynomial GCDs Using Trial
Division”, Proc. EUROSAM 79, published as Lecture Notes on Comp. Science,
Springer-Verlag, Berlin, No 72 (1979) 227-239.)
Example: With EXP off and GCD on, the polynomial a*c+a*d+b*c+b*d would
be returned as (A+B)*(C+D).
Under normal circumstances, GCDs are computed using an algorithm described in
the above paper. It is also possible in REDUCE to compute GCDs using an al-
ternative algorithm, called the EZGCD Algorithm, which uses modular arithmetic.
The switch EZGCD, if on in addition to GCD, makes this happen.
In non-trivial cases, the EZGCD algorithm is almost always better than the basic
algorithm, often by orders of magnitude. We therefore strongly advise users to
use the EZGCD switch where they have the resources available for supporting the
package.
For a description of the EZGCD algorithm, see J. Moses and D.Y.Y. Yun, “The EZ
GCD Algorithm”, Proc. ACM 1973, ACM, New York (1973) 159-166.
NOTE: This package shares code with the factorizer, so a certain amount of trace
information can be produced using the factorizer trace switches.
An implementation of the heuristic GCD algorithm, first introduced by B.W. Char,
K.O. Geddes and G.H. Gonnet, as described in J.H. Davenport and J. Padget,
“HEUGCD: How Elementary Upperbounds Generate Cheaper Data”, Proc. of EU-
ROCAL ’85, Vol 2, 18-28, published as Lecture Notes on Comp. Science, No. 204,
Springer-Verlag, Berlin, 1985, is also available on an experimental basis. To use
this algorithm, the switch HEUGCD should be on in addition to GCD. Note that if
both EZGCD and HEUGCD are on, the former takes precedence.
GCD(EXPRN1:polynomial,EXPRN2:polynomial):polynomial,
returns the greatest common divisor of the two polynomials EXPRN1 and EXPRN2.
Examples:
134 CHAPTER 9. POLYNOMIALS AND RATIONALS
LCM(EXPRN1:polynomial,EXPRN2:polynomial):polynomial,
returns the least common multiple of the two polynomials EXPRN1 and EXPRN2.
Examples:
When two rational functions are added, REDUCE normally produces an expression
over a common denominator. However, if the user does not want denominators
combined, he or she can turn off the switch MCD which controls this process. The
latter switch is particularly useful if no greatest common divisor calculations are
desired, or excessive differentiation of rational functions is required.
CAUTION: With MCD off, results are not guaranteed to come out in either normal
or canonical form. In other words, an expression equivalent to zero may in fact not
be simplified to zero. This option is therefore most useful for avoiding expression
swell during intermediate parts of a calculation.
MCD is normally on.
9.6. DIVIDE AND MOD / REMAINDER OPERATORS 135
remainder(EXPRN1:polynomial,EXPRN2:polynomial):polynomial.
It returns the remainder when EXPRN1 is divided by EXPRN2. This is the true
remainder based on the internal ordering of the variables, and not the pseudo-
remainder.
Examples:
CAUTION: In the default case, remainders are calculated over the integers. If you
need the remainder with respect to another domain, it must be declared explicitly.
Example:
2
2*y
divide(EXPRN1:polynomial,EXPRN2:polynomial):
list(polynomial,polynomial).
and returns both the quotient and the remainder together as the first and second
elements of a list, e.g.
2
{x + y,2*y }
136 CHAPTER 9. POLYNOMIALS AND RATIONALS
2
{x + y,2*y }
All Euclidean division operators (when used in prefix form, and including the
standard remainder operator) accept an optional third argument, which spec-
ifies the main variable to be used during the division. The default is the leading
kernel in the current global ordering. Specifying the main variable does not change
the ordering of any other variables involved, nor does it change the global environ-
ment. For example
2
2*x
2
{ - (x + y),2*x }
Specifying x as main variable gives the same behaviour as the default shown ear-
lier, i.e.
2
{x + y,2*y }
2
2*y
The polynomial division discussed above is normally most useful for a univariate
polynomial over a field, otherwise the division is likely to fail giving trivially a zero
quotient and a remainder equal to the dividend. (A ring of univariate polynomials
is a Euclidean domain only if the coefficient ring is a field.) For example, over the
9.7. POLYNOMIAL PSEUDO-DIVISION 137
integers:
2 2
{0,x + y }
2
{x + y,2*y }
2
{x + y,2*y }
2
{ - (x + y),2*x }
If the leading coefficient of the divisor is a unit (invertible element) of the coeffi-
cient ring then division and pseudo-division should be identical, otherwise they are
not, e.g.
2 2
{0,x + y }
2
{2*(x + y),8*y }
The pseudo-division gives essentially the same result as would division over the
field of fractions of the coefficient ring (apart from the overall factors [contents] of
the quotient and remainder), e.g.
on rational;
1 2
{---*(x + y),2*y }
2
2
{2*(x + y),8*y }
off rational;
2 2
x + y
***** --------- invalid as polynomial
2
perform any actual division at all (which proves that it applies over a ring). It is
more efficient than the naive algorithm, and it also has the advantage that it works
over coefficient domains in which REDUCE may not be able to perform in prac-
tice divisions that are possible mathematically. An example of this is coefficient
√
domains involving algebraic numbers, such as the integers extended by 2, as
illustrated in the file polydiv.tst.
The implementation attempts to be reasonably efficient, except that it always com-
putes the quotient internally even when only the remainder is required (as does the
standard remainder operator).
RESULTANT(EXPRN1:polynomial,EXPRN2:polynomial,VAR:kernel):
polynomial.
It computes the resultant of the two given polynomials with respect to the given
variable, the coefficients of the polynomials can be taken from any domain. The
result can be identified as the determinant of a Sylvester matrix, but can often
also be thought of informally as the result obtained when the given variable is
eliminated between the two input polynomials. If the two input polynomials have
a non-trivial GCD their resultant vanishes.
The switch BEZOUT controls the computation of the resultants. It is off by default.
In this case a subresultant algorithm is used. If the switch Bezout is turned on,
the resultant is computed via the Bezout Matrix. However, in the latter case, only
polynomial coefficients are permitted.
The sign conventions used by the resultant function follow those in R. Loos, “Com-
puting in Algebraic Extensions” in “Computer Algebra — Symbolic and Algebraic
Computation”, Second Ed., Edited by B. Buchberger, G.E. Collins and R. Loos,
Springer-Verlag, 1983. Namely, with A and B not dependent on X:
deg(p)*deg(q)
resultant(p(x),q(x),x)= (-1) *resultant(q,p,x)
deg(p)
resultant(a,p(x),x) = a
resultant(a,b,x) = 1
140 CHAPTER 9. POLYNOMIALS AND RATIONALS
Examples:
2
resultant(x/r*u+y,u*y,u) -> - y
load arnum;
defpoly sqrt2**2 - 2;
or in a modular domain:
setmod 17;
on modular;
resultant(2x+1,3x+4,x) -> 5
DECOMPOSE(EXPRN:polynomial):list.
For example:
decompose(x^8-88*x^7+2924*x^6-43912*x^5+263431*x^4-
218900*x^3+65690*x^2-7700*x+234)
2 2 2
-> {U + 35*U + 234, U=V + 10*V, V=X - 22*X}
2
decompose(u^2+v^2+2u*v+1) -> {W + 1, W=U + V}
Users should note however that, unlike factorization, this decomposition is not
unique.
9.10. INTERPOL OPERATOR 141
Syntax:
INTERPOL(hvaluesi,hvariablei,metapoints);
where hvaluesi and hpointsi are lists of equal length and <variable> is an alge-
braic expression (preferably a kernel).
INTERPOL generates an interpolation polynomial f in the given variable of degree
length(hvaluesi)-1. The unique polynomial f is defined by the property that for
corresponding elements v of hvaluesi and p of hpointsi the relation f (p) = v holds.
The Aitken-Neville interpolation algorithm is used which guarantees a stable result
even with rounded numbers and an ill-conditioned problem.
DEG(EXPRN:polynomial,VAR:kernel):integer.
It returns the leading degree of the polynomial EXPRN in the variable VAR. If VAR
does not occur as a variable in EXPRN, 0 is returned.
Examples:
deg((a+b)*(c+2*d)^2,a) -> 1
deg((a+b)*(c+2*d)^2,d) -> 2
deg((a+b)*(c+2*d)^2,e) -> 0.
deg((a+b)^3/a,a) -> 3
since in this case, the denominator A is considered part of the coefficients of the
numerator in A. With RATARG off, however, an error would result in this case.
DEN(EXPRN:rational):polynomial.
LCOF(EXPRN:polynomial,VAR:kernel):polynomial.
It returns the leading coefficient of the polynomial EXPRN in the variable VAR. If
VAR does not occur as a variable in EXPRN, EXPRN is returned. Examples:
Syntax:
LPOWER(EXPRN:polynomial,VAR:kernel):polynomial.
LPOWER returns the leading power of EXPRN with respect to VAR. If EXPRN
does not depend on VAR, 1 is returned.
9.11. OBTAINING PARTS OF POLYNOMIALS AND RATIONALS 143
Examples:
lpower((a+b)*(c+2*d)^2,a) -> A
lpower((a+b)*(c+2*d)^2,d) -> D**2
lpower((a+b)*(c+2*d),e) -> 1
Syntax:
LTERM(EXPRN:polynomial,VAR:kernel):polynomial.
LTERM returns the leading term of EXPRN with respect to VAR. If EXPRN does
not depend on VAR, EXPRN is returned.
Examples:
Syntax:
MAINVAR(EXPRN:polynomial):expression.
mainvar((a+b)*(c+2*d)^2) -> A
mainvar(2) -> 0
Syntax:
144 CHAPTER 9. POLYNOMIALS AND RATIONALS
NUM(EXPRN:rational):polynomial.
num(x/y^2) -> X
num(100/6) -> 50
num(a/4+b/6) -> 3*A+2*B
num(a+b) -> A+B
Syntax:
REDUCT(EXPRN:polynomial,VAR:kernel):polynomial.
Returns the reductum of EXPRN with respect to VAR (i.e., the part of EXPRN left
after the leading term is removed). If EXPRN does not depend on the variable VAR,
0 is returned.
Examples:
Syntax:
totaldeg(a*x^2+b*x+c, x) => 2
totaldeg(a*x^2+b*x+c, {a,b,c}) => 1
totaldeg(a*x^2+b*x+c, {x, a}) => 3
totaldeg(a*x^2+b*x+c, {x,b}) => 2
totaldeg(a*x^2+b*x+c, {p,q,r}) => 0
variable. The denominator of u is ignored, and "degree" here does not pay attention
to fractional powers. Mentions of a kernel within the argument to any operator or
function (eg sin, cos, log, sqrt) are ignored. Really u is expected to be just a
polynomial.
REDUCE allows for a variety of numerical domains for the numerical coefficients
of polynomials used in calculations. The default mode is integer arithmetic, al-
though the possibility of using real coefficients has been discussed elsewhere. Ra-
tional coefficients have also been available by using integer coefficients in both the
numerator and denominator of an expression, using the ON DIV option to print the
coefficients as rationals. However, REDUCE includes several other coefficient opt-
ions in its basic version which we shall describe in this section. All such coefficient
modes are supported in a table-driven manner so that it is straightforward to extend
the range of possibilities. A description of how to do this is given in R.J. Brad-
ford, A.C. Hearn, J.A. Padget and E. Schrüfer, “Enlarging the REDUCE Domain
of Computation,” Proc. of SYMSAC ’86, ACM, New York (1986), 100–106.
The switch ROUNDED permits the use of arbitrary sized real coefficients in poly-
nomial expressions. The actual precision of these coefficients can be set by the
operator PRECISION. For example, precision 50; sets the precision to fifty
decimal digits. The default precision is system dependent and can be found by
precision 0;. In this mode, denominators are automatically made monic, and
an appropriate adjustment is made to the numerator.
Example: With ROUNDED on, the input expression a/2 would be converted into a
rational expression whose numerator is 0.5*A and denominator 1.
146 CHAPTER 9. POLYNOMIALS AND RATIONALS
Rounded numbers are normally printed to the specified precision. However, if the
user wishes to print such numbers with less precision, the printing precision can be
set by the command PRINT_PRECISION. For example, print_precision
5; will cause such numbers to be printed with five digits maximum.
Under normal circumstances when ROUNDED is on, REDUCE converts the number
1.0 to the integer 1. If this is not desired, the switch NOCONVERT can be turned
on.
Numbers that are stored internally as bigfloats are normally printed with a space
between every five digits to improve readability. If this feature is not required, it
can be suppressed by turning off the switch BFSPACE.
Further information on the bigfloat arithmetic may be found in T. Sasaki, “Man-
ual for Arbitrary Precision Real Arithmetic System in REDUCE”, Department of
Computer Science, University of Utah, Technical Note No. TR-8 (1979).
When a real number is input, it is normally truncated to the precision in effect
at the time the number is read. If it is desired to keep the full precision of all
numbers input, the switch ADJPREC (for adjust precision) can be turned on. While
on, ADJPREC will automatically increase the precision, when necessary, to match
that of any integer or real input, and a message printed to inform the user of the
precision increase.
When ROUNDED is on, rational numbers are normally converted to rounded rep-
resentation. However, if a user wishes to keep such numbers in a rational form
until used in an operation that returns a real number, the switch ROUNDALL can be
turned off. This switch is normally on.
Results from rounded calculations are returned in rounded form with two excep-
tions: if the result is recognized as 0 or 1 to the current precision, the integer result
is returned.
9.12. POLYNOMIAL COEFFICIENT ARITHMETIC 147
Although REDUCE routinely treats the square of the variable i as equivalent to −1,
this is not sufficient to reduce expressions involving i to lowest terms, or to factor
such expressions over the complex numbers. For example, in the default case,
factorize(a^2+1);
{{A**2+1,1}}
and
(a^2+b^2)/(a+i*b)
is not reduced further. However, if the switch COMPLEX is turned on, full complex
148 CHAPTER 9. POLYNOMIALS AND RATIONALS
arithmetic is then carried out. In other words, the above factorization will give the
result
ROOT_VAL(EXPRN:univariate polynomial):list.
on rounded; root_val(x^3-x-1);
- 0.662358978622,1.32471795724}
Chapter 10
The declaration REALVALUED may be used to restrict variables to the real num-
bers. The syntax is:
realvalued v1,...vn;
For such variables the operator IMPART gives the result zero. Thus, with
realvalued x,y;
impart h(w);
149
150 CHAPTER 10. ASSIGNING AND TESTING ALGEBRAIC PROPERTIES
impart(h(w))
Such declarations are not needed for the standard elementary functions.
To remove the propery from a variable or an operator use the declaration
NOTREALVALUED with the syntax:
notrealvalued v1,...vn;
realvalued x;
write if realvaluedp(sin x) then "yes" else "no";
write if realvaluedp(sin z) then "yes" else "no";
would print first yes and then no. For general expressions test the impart for
checking the value range:
impart(w*w);
2*x*y
selfconjugate f1,...fn;
Such declarations are not needed for the standard elementary functions nor for
the inverses atan, acot, asinh, acsch. The remaining inverse functions
log, asin, acos, atanh, acosh etc. and sqrt fail to be self-conjugate
on their branch cuts (which are all subsets of the real axis).
10.3. DECLARING EXPRESSIONS POSITIVE OR NEGATIVE 151
Detailed knowlege about the sign of expressions allows REDUCE to simplify ex-
pressions involving exponentials or ABS. You can express assumptions about the
positivity or negativity of expressions by rules for the operator SIGN. Examples:
abs(a*b*c);
abs(a*b*c);
abs(c)*a*b
on precise; sqrt(x^2-2x+1);
abs(x - 1)
ws where sign(x-1)=>1;
x - 1
Here factors with known sign are factored out of an ABS expression.
on precise; on factor;
(q*x-2q)^w;
w
((x - 2)*q)
ws where sign(x-2)=>1;
w w
q *(x - 2)
In this case the factor (x − 2)w may be extracted from the base of the exponential
because it is known to be positive.
Note that REDUCE knows a lot about sign propagation. For example, with x and y
also x + y, x + y + π and (x + e)/y 2 are known as positive. Nevertheless, it is often
necessary to declare additionally the sign of a combined expression. E.g. at present
a positivity declaration of x − 2 does not automatically lead to sign evaluation for
152 CHAPTER 10. ASSIGNING AND TESTING ALGEBRAIC PROPERTIES
x − 1 or for x.
Chapter 11
Substitution Commands
Syntax:
hVAR:kerneli = hEXPRN:algebraici
2 2
sub({x=a+y,y=y+1},x^2+y^2) -> A + 2*A*Y + 2*Y + 2*Y + 1
153
154 CHAPTER 11. SUBSTITUTION COMMANDS
2 2
sub(s,x^2+y^2) -> A + 2*A*Y + 2*Y + 2*Y + 1
Note that the global assignments x:=a+y, etc., do not take place.
EXPRN1 can be any valid algebraic expression whose type is such that a substi-
tution process is defined for it (e.g., scalar expressions, lists and matrices). An
error will occur if an expression of an invalid type for substitution occurs either in
EXPRN or EXPRN1.
The braces around the substitution list may also be omitted, as in:
2 2
sub(x=a+y,y=y+1,x^2+y^2) -> A + 2*A*Y + 2*Y + 2*Y + 1
Unlike substitutions introduced via SUB, LET rules are global in scope and stay in
effect until replaced or CLEARed.
The simplest use of the LET statement is in the form
where hsubstitution listi is a list of rules separated by commas, each of the form:
hvariablei = hexpressioni
or
or
For example,
l+m => n,
w^3 => 2*z - 3,
z^10 => 0}
The list brackets can be left out if preferred. The above rules could also have been
entered as seven separate LET statements.
After such LET rules have been input, X will always be evaluated as the square of
Y, and so on. This is so even if at the time the LET rule was input, the variable Y
had a value other than Y. (In contrast, the assignment x:=y^2 will set X equal to
the square of the current value of Y, which could be quite different.)
The rule let a*b=c means that whenever A and B are both factors in an ex-
pression their product will be replaced by C. For example, a^5*b^7*w would be
replaced by c^5*b^2*w.
The rule for l+m will not only replace all occurrences of l+m by N, but will also
normally replace L by n-m, but not M by n-l. A more complete description of this
case is given in Section 11.2.5.
The rule pertaining to w^3 will apply to any power of W greater than or equal to
the third.
Note especially the last example, let z^10=0. This declaration means, in effect:
ignore the tenth or any higher power of Z. Such declarations, when appropriate,
often speed up a computation to a considerable degree. (See Section 11.4 for more
details.)
Any new operators occurring in such LET rules will be automatically declared
OPERATOR by the system, if the rules are being read from a file. If they are being
entered interactively, the system will ask DECLARE . . . OPERATOR? . Answer Y
or N and hit Return .
In each of these examples, substitutions are only made for the explicit expressions
given; i.e., none of the variables may be considered arbitrary in any sense. For
example, the command
let h(u,v) = u - v;
will cause h(u,v) to evaluate to U - V, but will not affect h(u,z) or H with
any arguments other than precisely the symbols U,V.
These simple LET rules are on the same logical level as assignments made with
the := operator. An assignment x := p+q cancels a rule let x = y^2 made
earlier, and vice versa.
CAUTION: A recursive rule such as
let x = x + 1;
156 CHAPTER 11. SUBSTITUTION COMMANDS
let l = m + n, n = l + r;
would lead to the same error. As a result, if you try to evaluate an X, L or N defined
as above, you will get an error such as
Array and matrix elements can appear on the left-hand side of a LET statement.
However, because of their instant evaluation property, it is the value of the element
that is substituted for, rather than the element itself. E.g.,
array a(5);
a(2) := b;
let a(2) = c;
results in B being substituted by C; the assignment for a(2) does not change.
Finally, if an error occurs in any equation in a LET statement (including generalized
statements involving FOR ALL and SUCH THAT), the remaining rules are not
evaluated.
e.g.,
fewer argument places, not two, the LET would have no effect, and no error would
result.
The second declaration would cause k(a,y) to be evaluated as a^y, but would
have no effect on k(a,z) since the rule didn’t say FOR ALL Y . . . .
Where we used X and Y in the examples, any variables could have been used. This
use of a variable doesn’t affect the value it may have outside the LET statement.
However, you should remember what variables you actually used. If you want
to delete the rule subsequently, you must use the same variables in the CLEAR
command.
It is possible to use more complicated expressions as a template for a LET state-
ment, as explained in the section on substitutions for general expressions. In nearly
all cases, the rule will be accepted, and a consistent application made by the sys-
tem. However, if there is a sole constant or a sole free variable on the left-hand side
of a rule (e.g., let 2=3 or for all x let x=2), then the system is unable
to handle the rule, and the error message
will be issued. Any variable listed in the FOR ALL part will have its symbol
preceded by an equal sign: X in the above example will appear as =X. An error will
also occur if a variable in the FOR ALL part is not properly matched on both sides
of the LET equation.
The user may remove all assignments and substitution rules from any expression
by the command CLEAR, in the form
158 CHAPTER 11. SUBSTITUTION COMMANDS
e.g.
clear x, h(x,y);
Because of their instant evaluation property, array and matrix elements cannot be
cleared with CLEAR. For example, if A is an array, you must say
a(3) := 0;
rather than
clear a(3);
CLEAR is not the only way to delete a LET rule. A new LET rule identical to
the first, but with a different expression after the equal sign, replaces the first.
Replacements are also made in other cases where the existing rule would be in
conflict with the new rule. For example, a rule for x^4 would replace a rule for
x^5. The user should however be cautioned against having several LET rules in
11.2. LET RULES 159
effect that relate to the same expression. No guarantee can be given as to which
rules will be applied by REDUCE or in what order. It is best to CLEAR an old rule
before entering a new related LET rule.
The examples of substitutions discussed in other sections have involved very sim-
ple rules. However, the substitution mechanism used in REDUCE is very general,
and can handle arbitrarily complicated rules without difficulty.
The general substitution mechanism used in REDUCE is discussed in Hearn, A.
C., “REDUCE, A User-Oriented Interactive System for Algebraic Simplification,”
Interactive Systems for Experimental Applied Mathematics, (edited by M. Klerer
and J. Reinfelds), Academic Press, New York (1968), 79-90, and Hearn. A. C.,
“The Problem of Substitution,” Proc. 1968 Summer Institute on Symbolic Mathe-
matical Computation, IBM Programming Laboratory Report FSC 69-0312 (1969).
For the reasons given in these references, REDUCE does not attempt to imple-
ment a general pattern matching algorithm. However, the present system uses far
more sophisticated techniques than those discussed in the above papers. It is now
possible for the rules appearing in arguments of LET to have the form
where any rule to which a sensible meaning can be assigned is permitted. How-
ever, this meaning can vary according to the form of hsubstitution expressioni. The
semantic rules associated with the application of the substitution are completely
consistent, but somewhat complicated by the pragmatic need to perform such sub-
stitutions as efficiently as possible. The following rules explain how the majority
of the cases are handled.
To begin with, the hsubstitution expressioni is first partly simplified by collecting
like terms and putting identifiers (and kernels) in the system order. However, no
substitutions are performed on any part of the expression with the exception of
expressions with the instant evaluation property, such as array and matrix elements,
whose actual values are used. It should also be noted that the system order used is
not changeable by the user, even with the KORDER command. Specific cases are
then handled as follows:
2. If the operator * appears at the top level of the simplified left-hand side, then
any constant arguments in that expression are moved to the right-hand side
160 CHAPTER 11. SUBSTITUTION COMMANDS
of the rule. The remaining left-hand side is then added to the appropriate
table. For example,
let 2*x*y=3
becomes
let x*y=3/2
so that x*y is added to the product substitution table, and when this rule is
applied, the expression x*y becomes 3/2, but X or Y by themselves are not
replaced.
become
One problem that can occur in this case is that if a quantified expression is moved
to the right-hand side, a given free variable might no longer appear on the left-hand
side, resulting in an error because of the unmatched free variable. E.g.,
would become
The left-hand side of the first rule will become X, and the second 0. Thus the first
rule will be instantiated as a substitution for X, and the second will result in an
error.
The order in which a list of rules is applied is not easily understandable without
a detailed knowledge of the system simplification protocol. It is also possible for
11.3. RULE LISTS 161
Note, however, that the arbitrary variable names in this case must be the same as
those used in defining the substitution.
For example,
The tilde preceding a variable marks that variable as free for that rule, much as a
variable in a FOR ALL clause in a LET statement. The first occurrence of that
variable in each relevant rule must be so marked on input, otherwise inconsistent
results can occur. For example, the rule list
designed to replace products of cosines, would not be correct, since the second
rule would only apply to the explicit argument X. Later occurrences in the same
rule may also be marked, but this is optional (internally, all such rules are stored
with each relevant variable explicitly marked). The optional WHEN clause allows
constraints to be placed on the application of the rule, much as the SUCH THAT
clause in a LET statement.
A rule list may be named, for example
Such named rule lists may be inspected as needed. E.g., the command trig1;
would cause the above list to be printed.
Rule lists may be used in two ways. They can be globally instantiated by means of
the command LET. For example,
let trig1;
would cause the above list of rules to be globally active from then on until cancelled
by the command CLEARRULES, as in
clearrules trig1;
The second way to use rule lists is to invoke them locally by means of a WHERE
clause. For example
cos(a)*cos(b+c)
where {cos(~x)*cos(~y) => (cos(x+y)+cos(x-y))/2};
or
<expression>
WHERE <rule>|<rule list>(,<rule>|<rule list> ...)
cos(a)*cos(b+c)
where cos(~x)*cos(~y) => (cos(x+y)+cos(x-y))/2;
The effect of this construct is that the rule list(s) in the WHERE clause only apply to
the expression on the left of WHERE. They have no effect outside the expression. In
particular, they do not affect previously defined WHERE clauses or LET statements.
For example, the sequence
let a=2;
a where a=>4;
a;
Although WHERE has a precedence less than any other infix operator, it still binds
higher than keywords such as ELSE, THEN, DO, REPEAT and so on. Thus the
expression
will parse as
164 CHAPTER 11. SUBSTITUTION COMMANDS
Some advanced features of the rule list mechanism make it possible to write more
complicated rules than those discussed so far, and in many cases to write more
compact rule lists. These features are:
• Free operators
A free operator in the left hand side of a pattern will match any operator with the
same number of arguments. The free operator is written in the same style as a
variable. For example, the implementation of the product rule of differentiation
can be written as:
let prule;
diff(sin(z)*cos(z),z);
cos(z)*diff(sin(z),z) + diff(cos(z),z)*sin(z)
The double slash operator may be used as an alternative to a single slash (quotient)
in order to match quotients properly. E.g., in the example of the Gamma function
above, one can use:
11.3. RULE LISTS 165
gammarule :=
{gamma(~z)//(~c*gamma(~zz)) => gamma(z)/(c*gamma(zz-1)*zz)
when fixp(zz -z) and (zz -z) >0,
gamma(~z)//gamma(~zz) => gamma(z)/(gamma(zz-1)*zz)
when fixp(zz -z) and (zz -z) >0};
let gammarule;
gamma(z)/gamma(z+3);
1
----------------------
3 2
z + 6*z + 11*z + 6
The above example suffers from the fact that two rules had to be written in order
to perform the required operation. This can be simplified by the use of double tilde
variables. E.g. the rule list
GGrule := {
gamma(~z)//(~~c*gamma(~zz)) => gamma(z)/(c*gamma(zz-1)*zz)
when fixp(zz -z) and (zz -z) >0};
will implement the same operation in a much more compact way. In general, dou-
ble tilde variables are bound to the neutral element with respect to the operation in
which they are used.
Pattern given Argument used Binding
f(z,z);
% BUT:
ff(z,z);
ff(z,z)
ff(3*z,z);
3*ff(z,z)
showrules log;
{LOG(E) => 1,
LOG(1) => 0,
~X
LOG(E ) => ~X,
1
DF(LOG(~X),~X) => ----}
~X
Such rules can then be manipulated further as with any list. For example rhs
first ws; has the value 1. Note that an operator may have other properties that
cannot be displayed in such a form, such as the fact it is an odd function, or has a
definition defined as a procedure.
that the order is arbitrary. However, if only one operator is involved, the order of
application of the rules for this operator can be determined from the following:
1. Rules containing at least one free variable apply before all rules without free
variables.
2. Rules activated in the most recent LET command are applied first.
3. LET with several entries generate the same order of application as a corre-
sponding sequence of commands with one rule or rule set each.
4. Within a rule set, the rules containing at least one free variable are applied in
their given order. In other words, the first member of the list is applied first.
5. Consistent with the first item, any rule in a rule list that contains no free
variables is applied after all rules containing free variables.
Example: The following rule set enables the computation of exact values of the
Gamma function:
operator gamma,gamma_error;
gamma_rules :=
{gamma(~x)=>sqrt(pi)/2 when x=1/2,
gamma(~n)=>factorial(n-1) when fixp n and n>0,
gamma(~n)=>gamma_error(n) when fixp n,
gamma(~x)=>(x-1)*gamma(x-1) when fixp(2*x) and x>1,
gamma(~x)=>gamma(x+1)/x when fixp(2*x)};
Here, rule by rule, cases of known or definitely uncomputable values are sorted out;
e.g. the rule leading to the error expression will be applied for negative integers
only, since the positive integers are caught by the preceding rule, and the last rule
will apply for negative odd multiples of 1/2 only. Alternatively the first rule could
have been written as
but then the case x = 1/2 should be excluded in the WHEN part of the last rule
explicitly because a rule without free variables cannot take precedence over the
other rules.
to avoid unnecessary computation. The command LET may be used to do this. For
example, if only powers of X up to x^7 are needed, the command
let x^8 = 0;
where hnumberi must be a positive integer (not just evaluate to a positive integer).
This command assigns the weight hnumberi to the relevant kernel form. A check
is then made in all algebraic evaluations to see if the total weight of the term is
greater than the weight level assigned to the calculation. If it is, the term is deleted.
To compute the total weight of a product, the individual weights of each kernel
form are multiplied by their corresponding powers and then added.
The weight level of the system is initially set to 1. The user may change this setting
by the command
wtlevel <number>;
which sets hnumberi as the new weight level of the system. meta must evaluate to
a positive integer. WTLEVEL will also allow NIL as an argument, in which case
the current weight level is returned.
Chapter 12
12.1 IN Command
This command takes a list of file names as argument and directs the system to
input each file (that should contain REDUCE statements and commands) into the
system. File names can either be an identifier or a string. The explicit format of
these will be system dependent and, in many cases, site dependent. The explicit
instructions for the implementation being used should therefore be consulted for
further details. For example:
in f1,"ggg.rr.s";
will first load file f1, then ggg.rr.s. When a semicolon is used as the terminator
of the IN statement, the statements in the file are echoed on the terminal or written
on the current output file. If $ is used as the terminator, the input is not shown.
Echoing of all or part of the input file can be prevented, even if a semicolon was
used, by placing an off echo; command in the input file.
Files to be read using IN should end with ;END;. Note the two semicolons! First
of all, this is protection against obscure difficulties the user will have if there are,
by mistake, more BEGINs than ENDs on the file. Secondly, it triggers some file
control book-keeping which may improve system efficiency. If END is omitted, an
error message "End-of-file read" will occur.
169
170 CHAPTER 12. FILE HANDLING COMMANDS
While a file is being loaded, the special identifier !__LINE__ is replaced by the
number of the current line in the file currently being read. Similarly, !__FILE__
is replaced by the name of the file currently being read.
This command takes a single file name as argument, and directs output to that
file from then on, until another OUT changes the output file, or SHUT closes it.
Output can go to only one file at a time, although many can be open. If the file
has previously been used for output during the current job, and not SHUT, the new
output is appended to the end of the file. Any existing file is erased before its first
use for output in a job, or if it had been SHUT before the new OUT.
To output on the terminal without closing the output file, the reserved file name T
(for terminal) may be used. For example, out ofile; will direct output to the
file OFILE and out t; will direct output to the user’s terminal.
The output sent to the file will be in the same form that it would have on the
terminal. In particular x^2 would appear on two lines, an X on the lower line and
a 2 on the line above. If the purpose of the output file is to save results to be read
in later, this is not an appropriate form. We first must turn off the NAT switch that
specifies that output should be in standard mathematical notation.
Example: To create a file ABCD from which it will be possible to read – using IN
– the value of the expression XYZ:
This command takes a list of names of files that have been previously opened via
an OUT statement and closes them. Most systems require this action by the user
before he ends the REDUCE job (if not sooner), otherwise the output may be lost.
If a file is shut and a further OUT command issued for the same file, the file is
12.4. REDUCE STARTUP FILE 171
At the start of a REDUCE session, the system checks for the existence of a user’s
startup file, and executes the REDUCE statements in it. This is equivalent to in-
putting the file with the IN command.
To find the directory/folder where the file resides, the system checks the existence
of the following environment variables:
1. HOME,
If none of these are set, the current directory is used. The file itself must be named
either .reducerc or reduce.rc1 .
1
If none of these exist, the system checks for a file called reduce.INI in the current directory.
This is historical and may be removed in future.
172 CHAPTER 12. FILE HANDLING COMMANDS
Chapter 13
173
174 CHAPTER 13. COMMANDS FOR INTERACTIVE USE
inputs and the results of all interactive computations during a given session. These
results are referenced by the command number that REDUCE prints automatically
in interactive mode. To use an input expression in a new computation, one writes
input(n), where n is the command number. To use an output expression, one
writes WS(n). WS references the previous command. E.g., if command number 1
was INT(X-1,X); and the result of command number 7 was X-1, then
2*input(1)-ws(7)^2;
2*ws(1)-ws(7)^2;
would yield the same result, but without a recomputation of the integral.
The operator DISPLAY is available to display previous inputs. If its argument
is a positive integer, n say, then the previous n inputs are displayed. If its argu-
ment is ALL (or in fact any non-numerical expression), then all previous inputs are
displayed.
It is possible when working interactively to edit any REDUCE input that comes
from the user’s terminal, and also some user-defined procedure definitions. At the
top level, one can access any previous command string by the command ed(n),
where n is the desired command number as prompted by the system in interactive
mode. ED; (i.e. no argument) accesses the previous command.
After ED has been called, you can now edit the displayed string using a string editor
with the following commands:
B move pointer to beginning
Chcharacteri replace next character by hcharacteri
D delete next character
E end editing and reread text
Fhcharacteri move pointer to next occurrence of
hcharacteri
Ihstringihescapei insert hstringi in front of pointer
Khcharacteri delete all characters until hcharacteri
P print string from current pointer
Q give up with error exit
Shstringihescapei search for first occurrence of hstringi, po-
sitioning pointer just before it
space or X move pointer right one character.
13.3. INTERACTIVE FILE CONTROL 175
The above table can be displayed online by typing a question mark followed by a
carriage return to the editor. The editor prompts with an angle bracket. Commands
can be combined on a single line, and all command sequences must be followed by
a carriage return to become effective.
Thus, to change the command x := a+1; to x := a+2; and cause it to be
executed, the following edit command sequence could be used:
f1c2e<return>.
The interactive editor may also be used to edit a user-defined procedure that has
not been compiled. To do this, one says:
editdef hidi;
where hidi is the name of the procedure. The procedure definition will then be
displayed in editing mode, and may then be edited and redefined on exiting from
the editor.
Some versions of REDUCE now include input editing that uses the capabilities of
modern window systems. Please consult your system dependent documentation to
see if this is possible. Such editing techniques are usually much easier to use then
ED or EDITDEF.
If input is coming from an external file, the system treats it as a batch processed
calculation. If the user desires interactive response in this case, he can include the
command ON INT; in the file. Likewise, he can issue the command off int;
in the main program if he does not desire continual questioning from the system.
Regardless of the setting of INT, input commands from a file are not kept in the
system, and so cannot be edited using ED. However, many implementations of RE-
DUCE provide a link to an external system editor that can be used for such editing.
The specific instructions for the particular implementation should be consulted for
information on this.
Two commands are available in REDUCE for interactive use of files. PAUSE; may
be inserted at any point in an input file. When this command is encountered on
input, the system prints the message CONT? on the user’s terminal and halts. If the
user responds Y (for yes), the calculation continues from that point in the file. If the
user responds N (for no), control is returned to the terminal, and the user can input
further statements and commands. Later on he can use the command cont; to
transfer control back to the point in the file following the last PAUSE encountered.
A top-level pause; from the user’s terminal has no effect.
176 CHAPTER 13. COMMANDS FOR INTERACTIVE USE
Chapter 14
Matrix Calculations
A very powerful feature of REDUCE is the ease with which matrix calculations
can be performed. To extend our syntax to this class of calculations we need to
add another prefix operator, MAT, and a further variable and expression type as
follows:
177
178 CHAPTER 14. MATRIX CALCULATIONS
matrix x(2,1),y(3,4),z;
These follow the normal rules of matrix algebra as defined by the following syntax:
y
y^2*x-3*y^(-2)*x
y + mat((1,a),(b,c))/2
The computation of the quotient of two matrices normally uses a two-step elimina-
tion method due to Bareiss. An alternative method using Cramer’s method is also
available. This is usually less efficient than the Bareiss method unless the matrices
are large and dense, although we have no solid statistics on this as yet. To use
Cramer’s method instead, the switch CRAMER should be turned on.
The operator LENGTH applied to a matrix returns a list of the number of rows and
columns in the matrix. Other operators useful in matrix calculations are defined in
the following subsections. Attention is also drawn to the LINALG (section 16.37)
and NORMFORM (section 16.43) packages.
Syntax:
DET(EXPRN:matrix_expression):algebraic.
The operator DET is used to represent the determinant of a square matrix expres-
sion. E.g.,
det(y^2)
is a scalar expression whose value is the determinant of the square of the matrix Y,
and
det mat((a,b,c),(d,e,f),(g,h,j));
Determinant expressions have the instant evaluation property. In other words, the
statement
sets the value of the determinant to 2, and does not set up a rule for the determinant
itself.
Syntax:
MATEIGEN(EXPRN:matrix_expression,ID):list.
mateigen(mat((2,-1,1),(0,1,1),(-1,1,1)),eta);
{{ETA - 1,2,
[ARBCOMPLEX(1)]
[ ]
[ARBCOMPLEX(1)]
[ ]
[ 0 ]
},
{ETA - 2,1,
[ 0 ]
[ ]
[ARBCOMPLEX(2)]
[ ]
[ARBCOMPLEX(2)]
14.4. OPERATORS WITH MATRIX ARGUMENTS 181
}}
14.4.3 TP Operator
Syntax:
TP(EXPRN:matrix_expression):matrix.
This operator takes a single matrix argument and returns its transpose.
Syntax:
TRACE(EXPRN:matrix_expression):algebraic.
Syntax:
COFACTOR(EXPRN:matrix_expression,ROW:integer,COLUMN:integer):
algebraic
The operator COFACTOR returns the cofactor of the element in row ROW and col-
umn COLUMN of the matrix MATRIX. Errors occur if ROW or COLUMN do not
simplify to integer expressions or if MATRIX is not square.
Syntax:
NULLSPACE(EXPRN:matrix_expression):list
rank of a matrix expression can also be found more directly by the RANK operator
described below.
Example: The command
nullspace mat((1,2,3,4),(5,6,7,8));
{
[ 1 ]
[ ]
[ 0 ]
[ ]
[ - 3]
[ ]
[ 2 ]
,
[ 0 ]
[ ]
[ 1 ]
[ ]
[ - 2]
[ ]
[ 1 ]
}
Syntax:
RANK(EXPRN:matrix_expression):integer
RANK calculates the rank of its argument, that, like NULLSPACE can either be a
standard matrix expression, or a list of lists, that can be interpreted either as a row
matrix or a set of equations.
Example:
14.5. MATRIX ASSIGNMENTS 183
rank mat((a,b,c),(d,e,f));
a11*x(1) + a12*x(2) = y1
a21*x(1) + a22*x(2) = y2
we simply write
x := 1/mat((a11,a12),(a21,a22))*mat((y1),(y2));
Procedures
It is often useful to name a statement for repeated use in calculations with varying
parameters, or to define a complete evaluation procedure for an operator. REDUCE
offers a procedural declaration for this purpose. Its general syntax is:
where
is printed. If this occurs, and the user is not redefining his own procedure, he is
well advised to rename it, and possibly start over (because he has already redefined
some internal procedure whose correct functioning may be required for his job!)
185
186 CHAPTER 15. PROCEDURES
All required procedures should be defined at the top level, since they have global
scope throughout a program. In particular, an attempt to define a procedure within
a procedure will cause an error to occur.
procedure abc;
procedure abc(x);
or
procedure abc x;
procedure abc(x,y,z);
Referring to the last example, if later in some expression being evaluated the sym-
bols abc(u,p*q,123) appear, the operations of the procedure body will be
carried out as if X had the same value as U does, Y the same value as p*q does,
and Z the value 123. The values of X, Y, Z, after the procedure body operations are
completed are unchanged. So, normally, are the values of U, P, Q, and (of course)
123. (This is technically referred to as call by value.)
The reader will have noted the word normally a few lines earlier. The call by value
protections can be bypassed if necessary, as described elsewhere.
15.2. PROCEDURE BODY 187
Following the delimiter that ends the procedure heading must be a single statement
defining the action to be performed or the value to be delivered. A terminator must
follow the statement. If it is a semicolon, the name of the procedure just defined is
printed. It is not printed if a dollar sign is used.
If the result wanted is given by a formula of some kind, the body is just that for-
mula, using the variables in the procedure heading.
Simple Example:
If f(x) is to mean (x+5)*(x+6)/(x+7), the entire procedure definition could
read
procedure f x; (x+5)*(x+6)/(x+7);
Put into words, the Legendre polynomial pn (x) is the result of substituting y = 0
in the nth partial derivative with respect to y of a certain fraction involving x and
y, then dividing that by n!.
This verbal formula can easily be written in REDUCE:
procedure p(n,x);
sub(y=0,df(1/(y^2-2*x*y+1)^(1/2),y,n))
/(for i:=1:n product i);
2p(2,w);
2
3*W - 1 .
188 CHAPTER 15. PROCEDURES
If the desired process is best described as a series of steps, then a group or com-
pound statement can be used.
Example:
The above Legendre polynomial example can be rewritten as a series of steps in-
stead of a single formula as follows:
procedure p(n,x);
begin scalar seed,deriv,top,fact;
seed:=1/(y^2 - 2*x*y +1)^(1/2);
deriv:=df(seed,y,n);
top:=sub(y=0,deriv);
fact:=for i:=1:n product i;
return top/fact
end;
Procedures may also be defined recursively. In other words, the procedure body can
include references to the procedure name itself, or to other procedures that them-
selves reference the given procedure. As an example, we can define the Legendre
polynomial through its standard recurrence relation:
procedure p(n,x);
if n<0 then rederr "Invalid argument to P(N,X)"
else if n=0 then 1
else if n=1 then x
else ((2*n-1)*x*p(n-1,x)-(n-1)*p(n-2,x))/n;
The operator REDERR in the above example provides for a simple error exit from
an algebraic procedure (and also a block). It can take a string as argument.
It should be noted however that all the above definitions of p(n,x) are quite
inefficient if extensive use is to be made of such polynomials, since each call ef-
fectively recomputes all lower order polynomials. It would be better to store these
expressions in an array, and then use say the recurrence relation to compute only
those polynomials that have not already been derived. We leave it as an exercise
for the reader to write such a definition.
Normally, procedures can only return scalar values. In order for a procedure to
return a matrix, it has to be declared of type MATRIXPROC:
mat((0,-w(3,1),w(2,1)),
(w(3,1),0,-w(1,1)),
(-w(2,1), w(1,1), 0));
Following this declaration, the call to SkewSym1 can be used as a matrix, e.g.
X := SkewSym1(mat((qx),(qy),(qz)));
[ 0 - qz qy ]
[ ]
x := [ qz 0 - qx]
[ ]
[ - qy qx 0 ]
X * mat((rx),(ry),(rz));
[ qy*rz - qz*ry ]
[ ]
[ - qx*rz + qz*rx]
[ ]
[ qx*ry - qy*rx ]
let x = 123;
then it is the variable that is the value of X that is changed. This effect also occurs
with local variables defined in a block. If the value of X is not a variable, but a
more general expression, then it is that expression that is used on the left-hand side
of the LET statement. For example, if X had the value p*q, it is as if let p*q =
123 had been executed.
190 CHAPTER 15. PROCEDURES
The LET statement offers an alternative syntax and semantics for procedure defi-
nition.
In place of
x := 123;
in the PROCEDURE case it is a variable holding a copy of the first actual argument
that is changed. The actual argument is not changed.
In the LET case, the actual argument is changed. Thus, if ABC is defined using
LET, and abc(u,v,w) is evaluated, the value of U changes to 123. That is, the
LET form of definition allows the user to bypass the protections that are enforced
by the call by value conventions of standard PROCEDURE definitions.
Example: We take our earlier FACTORIAL procedure and write it as a LET state-
ment.
The reader will notice that we introduced a new local variable, S, and set it equal
to N. The original form of the procedure contained the statement n:=n-1;. If the
user asked for the value of factorial(5) then N would correspond to, not just
have the value of, 5, and REDUCE would object to trying to execute the statement
5 := 5 − 1.
If PQR is a procedure with no parameters,
15.6. REMEMBER STATEMENT 191
procedure pqr;
<procedure body>;
To call procedure PQR, if defined in the latter form, the empty parentheses would
not be used: use PQR not PQR() where a call on the procedure is needed.
The two notations for a procedure with no arguments can be combined. PQR can
be defined in the standard PROCEDURE form. Then a LET statement
would allow a user to use PQR instead of PQR() in calling the procedure.
A feature available with LET-defined procedures and not with procedures defined
in the standard way is the possibility of defining partial functions.
REMEMBER (PROCNAME:procedure);
known examples.
remember h;
100
remember a;
A(3,3);
Chapter 16
load_package algint;
193
194 CHAPTER 16. USER CONTRIBUTED PACKAGES
int(sqrt(x+sqrt(x**2+1))/x,x);
If one later wishes to integrate expressions without using the facilities of this pack-
age, the switch ALGINT should be turned off.
The switches supported by the standard integrator (e.g., TRINT) are also sup-
ported by this package. In addition, the switch TRA, if on, will give further tracing
information about the specific functioning of the algebraic integrator.
There is no additional documentation for this package.
Author: James H. Davenport.
195
of the symmetry conditions which is the strength of the program LIEPDE (for a
comparison with another program see [4]).
The novelty described in this paper are programs aiming at the final third step:
Applying symmetries for
Programs which run on their own but also allow interactive user control are indis-
pensible for these calculations. On one hand the calculations can become quite
lengthy, like variable transformations of PDEs (of higher order, with many vari-
ables). On the other hand the freedom of choosing the right linear combination
of symmetries and choosing the optimal new symmetry- and similarity variables
makes it necessary to ‘play’ with the problem interactively.
The focus in this paper is directed on questions of implementation and efficiency,
no principally new mathematics is presented.
In the following subsections a review of the first two steps of the symmetry method
is given as well as the third, i.e. the application step is outlined. Each of the re-
maining sections is devoted to one procedure.
HA = 0 (16.1)
x̃i = xi + εξ i , ỹ α = y α + εη α (16.2)
Dηjα1 ...jk−1 Dξ i
ηjα1 ...jk−1 jk = α
− yij1 ...jk−1
(16.3)
Dxk Dxk
197
where D/Dxk means total differentiation w.r.t. xk and from now on lower latin
indices of functions y α , (and later uα ) denote partial differentiation w.r.t. the inde-
pendent variables xi , (and later v i ). The complete symmetry condition then takes
the form
∂HA
ηjα1 ...jn .
∂yjα1 ...jn
The second method is applied in LIEPDE. Already the formulation of the remain-
ing conditions is speeded up considerably through this iteration process. These
methods can be applied if systems of DEs or single PDEs of at least second order
are investigated concerning symmetries.
The second step in applying the whole method consists in solving the determining
conditions (16.4), (16.5), (16.3) which are linear homogeneous PDEs for ξ i , η α .
The complete solution of this system is not algorithmic any more because the so-
lution of a general linear PDE-system is as difficult as the solution of its non-linear
characteristic ODE-system which is not covered by algorithms so far.
Still algorithms are used successfully to simplify the PDE-system by calculating
its standard normal form and by integrating exact PDEs if they turn up in this sim-
plification process [4]. One problem in this respect, for example, concerns the
optimization of the symbiosis of both algorithms. By that we mean the ranking of
priorities between integrating, adding integrability conditions and doing simplifi-
cations by substitutions - all depending on the length of expressions and the overall
structure of the PDE-system. Also the extension of the class of PDEs which can be
integrated exactly is a problem to be pursuit further.
The program LIEPDE which formulates the symmetry conditions calls the pro-
gram CRACK to solve them. This is done in a number of successive calls in order
to formulate and solve some first order PDEs of the overdetermined system first and
use their solution to formulate and solve the next subset of conditions as described
in the previous subsection. Also, LIEPDE can work on DEs that contain paramet-
ric constants and parametric functions. An ansatz for the symmetry generators can
be formulated. For more details see [4] or [17].
The procedure LIEPDE is called through
LIEPDE(problem,symtype,flist,inequ);
All parameters are lists.
The first parameter specifies the DEs to be investigated:
problem has the form {equations, ulist, xlist} where
Equations can be given as a list of single differential expressions and then the
program will try to bring them into the ‘solved form’ df(ui,..)=... auto-
matically. If equations are given in the solved form then the above conditions are
checked and execution is stopped it they are not satisfied. An easy way to get the
equations in the desired form is to use
FIRST SOLVE({eq1,eq2,...},{one highest derivative for each function
u})
(see the example of the Karpman equations in LIEPDE.TST). The example of the
Burgers equation in LIEPDE.TST demonstrates that the number of symmetries
for a given maximal order of the infinitesimal generators depends on the derivative
chosen for the LHS.
The second parameter symtype of LIEPDE is a list { } that specifies the symmetry
to be calculated. symtype can have the following values and meanings:
LIEPDE.TST.
{xi!_x1 =...,...,
eta!_u1=...,...} It is possible to specify an ansatz for the symmetry. Such
an ansatz must specify all ξ i for all independent variables and
all η α for all dependent variables in terms of differential
expressions which may involve unknown functions/constants.
The dependences of the unknown functions have to be declared
in advance by using the DEPEND command. For example,
DEPEND f, t, x, u$
specifies f to be a function of t, x, u. If one wants to have f as
a function of derivatives of u(t, x), say f depending on utxx ,
then one cannot write
DEPEND f, df(u,t,x,2)$
but instead must write
DEPEND f, u!‘1!‘2!‘2$
assuming xlist has been specified as {t,x}. Because t is the
first variable and x is the second variable in xlist and u is
differentiated oncs wrt. t and twice wrt. x we therefore
use u!‘1!‘2!‘2. The character ! is the escape character
to allow special characters like ‘ to occur in an identifier.
For generalized symmetries one usually sets all ξ i = 0.
Then the η α are equal to the characteristic functions.
• all unknown functions and constants in the ansatz xi!_.. and eta!_..
if that has been specified in symtype.
The fourth parameter inequ of LIEPDE is a list { } that includes all non-vanishing
expressions which represent inequalities for the functions in flist.
The result of LIEPDE is a list with 3 elements, each of which is a list:
The first list contains remaining unsolved symmetry conditions coni . It is the empty
list {} if all conditions have been solved. The second list gives the symmetry
generators, i.e. expressions for ξi and ηj . The last list contains all free constants
and functions occuring in the first and second list.
201
If infinitesimal symmetries have been found then the program APPLYSYM can use
them for the following purposes:
X = ∂v1 . (16.6)
The general solutions of (16.7), (16.8) involve free functions of p+q−1 arguments.
From the general solution of equation (16.8), p + q − 1 functionally independent
special solutions have to be selected (v 2 , . . . , v p and u1 , . . . , uq ), whereas from
(16.7) only one solution v 1 is needed. Together, the expressions for the symmetry
and similarity variables must define a non-singular transformation x, y → u, v.
Different special solutions selected at this stage will result in different resulting
DEs which are equivalent under point transformations but may look quite differ-
ently. A transformation that is more difficult than another one will in general only
complicate the new DE(s) compared with the simpler transformation. We therefore
seek the simplest possible special solutions of (16.7), (16.8). They also have to be
simple because the transformation has to be inverted to solve for the old variables
in order to do the transformations.
The following steps are performed in the corresponding mode of the program
APPLYSYM:
• The user is asked to specify a symmetry by selecting one symmetry from all
the known symmetries or by specifying a linear combination of them.
• Through a call of the procedure QUASILINPDE (described in a later sec-
tion) the two linear first order PDEs (16.7), (16.8) are investigated and, if
possible, solved.
• From the general solution of (16.7) 1 special solution is selected and from
(16.8) p + q − 1 special solutions are selected which should be as simple as
possible.
• The user is asked whether the symmetry variable should be one of the inde-
pendent variables (as it has been assumed so far) or one of the new functions
(then only derivatives of this function and not the function itself turn up in
the new DE(s)).
• Through a call of the procedure DETRAFO the transformation xi , y α →
v j , uβ of the DE(s) HA = 0 is finally done.
• The program returns to the starting menu.
0 = F (xi , y α ) = F (xi (v j , uβ ), y α (v j , uβ )) = F̄ (v j , uβ )
203
follows that
0 = F̄ (v 1 + c, v r , uβ ) = F̄ (v 1 (xi , y α ) + c, v r (xi , y α ), uβ (xi , y α ))
defines implicitly a generalized solution y α = y α (xi , c).
This generalization works only if ∂v1 F̄ 6= 0 and if F̄ does not already have a
constant additive to v 1 .
The method above needs to know xi = xi (uβ , v j ), y α = y α (uβ , v j ) and uα =
uα (xj , y β ), v α = v α (xj , y β ) which may be practically impossible. Better is, to
integrate xi , y α along X:
dx̄i dȳ α
= ξ i (x̄j (ε), ȳ β (ε)), = η α (x̄j (ε), ȳ β (ε)) (16.9)
dε dε
with initial values x̄i = xi , ȳ α = y α for ε = 0. (This ODE-system is the character-
istic system of (16.8).)
Knowing only the finite transformations
x̄i = x̄i (xj , y β , ε), ȳ α = ȳ α (xj , y β , ε) (16.10)
gives immediately the inverse transformation x̄i = x̄i (xj , y β , ε), ȳ α =
ȳ α (xj , y β , ε) just by ε → −ε and renaming xi , y α ↔ x̄i , ȳ α .
The special solution 0 = F (xi , y α ) is generalized by the new constant ε through
0 = F (xi , y α ) = F (xi (x̄j , ȳ β , ε), y α (x̄j , ȳ β , ε))
after dropping the ¯.
The steps performed in the corresponding mode of the program APPLYSYM show
features of both techniques:
• The user is asked to specify a symmetry by selecting one symmetry from all
the known symmetries or by specifying a linear combination of them.
• The special solution to be generalized and the name of the new constant have
to be put in.
• Through a call of the procedure QUASILINPDE, the PDE (16.7) is solved
which amounts to a solution of its characteristic ODE system (16.9) where
v 1 = ε.
• QUASILINPDE returns a list of constant expressions
ci = ci (xk , y β , ε), 1 ≤ i ≤ p + q (16.11)
which are solved for xj = xj (ci , ε), y α = y α (ci , ε) to obtain the general-
ized solution through
0 = F (xj , y α ) = F (xj (ci (xk , y β , 0), ε), y α (ci (xk , y β , 0), ε)).
204 CHAPTER 16. USER CONTRIBUTED PACKAGES
• The new solution is availabe for further generalizations w.r.t. other symme-
tries.
If one would like to generalize a given special solution with m new constants be-
cause m symmetries are known, then one could run the whole program m times,
each time with a different symmetry or one could run the program once with a lin-
ear combination of m symmetry generators which again is a symmetry generator.
Running the program once adds one constant but we have in addition m − 1 arbi-
trary constants in the linear combination of the symmetries, so m new constants are
added. Usually one will generalize the solution gradually to make solving (16.9)
gradually more difficult.
Syntax
The list that is the first argument of APPLYSYM is the same as the first argument of
LIEPDE and the second argument is the list that LIEPDE returns without its first
element (the unsolved conditions). An example is given below.
What APPLYSYM returns depends on the last performed modus. After modus 1
the return is
{{newde, newfun, newvar}, trafo}
where
g = dU/dρ (16.13)
h = ρg − 1 (16.14)
depend h,r;
prob:={{-20*h**4+16*h**6+3*r**2*h*df(h,r,2)+5*r*h*df(h,r)
-20*h**3*r*df(h,r)+4*h**2-5*r**2*df(h,r)**2},
{h}, {r}};
sym:=liepde(prob, {"point"},{},{});
end;
gives
3 2
sym := {{}, {xi_r= - c10*r - c11*r, eta_h=c10*h*r }, {c10,c11}}.
All conditions have been solved because the first element of sym is {}. The two
existing symmetries are therefore
newde:=applysym(prob,rest sym);
The interactive session is given below with the user input following the prompt
‘Input:3:’ or following ‘?’. (Empty lines have been deleted.)
206 CHAPTER 16. USER CONTRIBUTED PACKAGES
We could have entered ‘sy_(2);’ or a combination of both as well with the calcula-
tion running then differently.
This was the input part, now the real calculation starts.
0= - df(u_,r)*r
2
0= - r *(df(h,r)*r + h)
for the functions: h(r) u_(r).
For the following calculation only a single special solution of the PDE is neces-
sary and this has to be specified from the general solution by choosing a special
function ff. (This function is called ff to prevent a clash with names of user
variables/functions.) In principle any choice of ff would work, if it defines a non-
singular coordinate transformation, i.e. here r must be a function of u_. If we have
q independent variables and p functions of them then ff has p + q arguments.
Because of the condition 0 =ff one has essentially the freedom of choosing a
function of p + q − 1 arguments freely. This freedom is also necessary to select
p + q − 1 different functions ff and to find as many functionally independent so-
lutions u_ which all become the new similarity variables. q of them become the
new functions uα and p − 1 of them the new variables v 2 , . . . , v p . Here we have
p = q = 1 (one single ODE).
Though the program could have done that alone, once the general solution ff(..)
is known, the user can interfere here to enter a simpler solution, if possible.
2 2 2
- 2*h *r *u_ + h
0 = ff(h*r,--------------------)
2
with arbitrary function ff(..).
A suggestion for this function ff(..) yields:
2 2
h *( - 2*r *u_ + 1)
0 = ---------------------
2
Do you like this choice? (Y or N)
?y
Similar to above.
We so far assumed that the symmetry variable is one of the new variables, but,
of course we also could choose it to be one of the new functions. If it is one
of the functions then only derivatives of this function occur in the new DE, not
the function itself. If it is one of the variables then this variable will not occur
explicitly.
In our case we prefer (without strong reason) to have the function as symmetry vari-
able. We therefore answered with ‘no’. As a consequence, u and v will exchange
names such that still all new functions have the name u and the new variables have
name v:
3 6 2 3
{{{3*df(u,v,2)*v - 16*df(u,v) *v - 20*df(u,v) *v + 5*df(u,v)},
{u},
{v}},
sqrt(u)*sqrt(2)
{r=-----------------, h=sqrt(u)*sqrt(2)*v }}
2*u
p = du/dw (16.19)
where c1 , c2 = const. and c1 = c̃1/4 . Finally, the metric function U (p) is obtained as an
integral from (16.13),(16.14).
210 CHAPTER 16. USER CONTRIBUTED PACKAGES
Limitations of APPLYSYM
Restrictions of the applicability of the program APPLYSYM result from limitations of the
program QUASILINPDE described in a section below. Essentially this means that sym-
metry generators may only be polynomially non-linear in xi , y α . Though even then the
solvability can not be guaranteed, the generators of Lie-symmetries are mostly very simple
such that the resulting PDE (16.22) and the corresponding characteristic ODE-system have
good chances to be solvable.
Apart from these limitations implied through the solution of differential equations with
CRACK and algebraic equations with SOLVE the program APPLYSYM itself is free
of restrictions, i.e. if once new versions of CRACK, SOLVE would be available then
APPLYSYM would not have to be changed.
Currently, whenever a computational step could not be performed the user is informed and
has the possibility of entering interactively the solution of the unsolved algebraic system
or the unsolved linear PDE.
1. The first step in solving a quasilinear PDE (16.22) is the formulation of the corre-
sponding characteristic ODE-system
dwi
= ai (wj , φ) (16.23)
dε
dφ
= b(wj , φ) (16.24)
dε
for φ, wi regarded now as functions of one variable ε.
Because the ai and b do not depend explicitly on ε, one of the equations
(16.23),(16.24) with non-vanishing right hand side can be used to divide all others
through it and by that having a system with one less ODE to solve. If the equation
to divide through is one of (16.23) then the remaining system would be
dwi ai
= , i = 1, 2, . . . k − 1, k + 1, . . . n (16.25)
dwk ak
dφ b
= (16.26)
dwk ak
with the independent variable wk instead of ε. If instead we divide through equation
(16.24) then the remaining system would be
dwi ai
= , i = 1, 2, . . . n (16.27)
dφ b
211
then according to the general theory for solving first order PDEs, ε has to be elim-
inated from one of the equations and to be substituted in the others to have left n
equations. Also the constant that turns up additively to ε is to be set to zero. Both
tasks are automatically fulfilled, if, as described above, ε is already eliminated from
the beginning by dividing all equations of (16.23), (16.24) through one of them.
On either way one ends up with n equations
0 = gi (φ, wj , ck ), i, j, k = 1 . . . n (16.29)
involving n constants ck .
The final step is to solve (16.29) for the ci to obtain
ci = ci (φ, w1 , . . . , wn ) i = 1, . . . n. (16.30)
The final solution φ = φ(wi ) of the PDE (16.22) is then given implicitly through
Syntax
• de is the differential expression which vanishes due to the PDE de = 0 or, de may
be the differential equation itself in the form . . . = . . . .
• fun is the unknown function.
• varlist is the list of variables of fun.
Examples
Example 1:
To solve the quasilinear first order PDE
1 = xu,x +uu,y −zu,z
for the function u = u(x, y, z), the input would be
depend u,x,y,z;
de:=x*df(u,x)+u*df(u,y)-z*df(u,z) - 1;
varlist:={x,y,z};
QUASILINPDE(de,u,varlist);
QUASILINPDE returns the result that for an arbitrary function F, the equation
x+y z
0=F , e (x − y)
ez
defines the general solution for z.
Example 3:
For the linear inhomogeneous PDE (3.8) from [15]
QUASILINPDE returns the result that for an arbitrary function F, the equation
0 = F (w, y + z, ln(x)(y + z) − y)
w = f (y + z, ln(x)(y + z) − y)
Limitations of QUASILINPDE
Finally, after having found the finite transformations, the program APPLYSYM calls
the procedure DETRAFO to perform the transformations. DETRAFO can also be
used alone to do point- or higher order transformations which involve a consid-
erable computational effort if the differential order of the expression to be trans-
formed is high and if many dependent and independent variables are involved. This
might be especially useful if one wants to experiment and try out different coordi-
nate transformations interactively, using DETRAFO as standalone procedure.
214 CHAPTER 16. USER CONTRIBUTED PACKAGES
To run DETRAFO, the old functions y α and old variables xi must be known explic-
itly in terms of algebraic or differential expressions of the new functions uβ and
new variables v j . Then for point transformations the identity
dy α = y α ,vi +y α ,uβ uβ ,vi dv i (16.31)
= y α ,xj dxj (16.32)
= y α ,xj xj ,vi +xj ,uβ uβ ,vi dv i (16.33)
with det dxj /dv i 6= 0 because of the regularity of the transformation which is
y α = y α (v i , uβ , uβ ,vj , . . .)
xk = xk (v i , uβ , uβ ,vj , . . .).
Syntax
• The second list is the list of old functions ofun expressed as expressions fex
in terms of new functions nfun and new independent variables nvar.
• Similarly the third list expresses the old independent variables ovar as ex-
pressions vex in terms of new functions nfun and new independent variables
nvar.
215
• The last two lists include the new functions nfun and new independent vari-
ables nvar.
Names for ofun, ovar, nfun and nvar can be arbitrarily chosen.
As the result DETRAFO returns the first argument of its input, i.e. the list
{ex 1 , ex 2 , . . . , ex m }
Limitations of DETRAFO
The only requirement is that the old independent variables xi and old functions
y α must be given explicitly in terms of new variables v j and new functions uβ
as indicated in the syntax. Then all calculations involve only differentiations and
basic algebra.
Bibliography
[1] W. Hereman, Chapter 13 in vol 3 of the CRC Handbook of Lie Group Anal-
ysis of Differential Equations, Ed.: N.H. Ibragimov, CRC Press, Boca Raton,
Florida (1995). Systems described in this paper are among others:
DELiA (Alexei Bocharov et.al.) Pascal
DIFFGROB2 (Liz Mansfield) Maple
DIMSYM (James Sherring and Geoff Prince) REDUCE
HSYM (Vladimir Gerdt) Reduce
LIE (V. Eliseev, R.N. Fedorova and V.V. Kornyak) Reduce
LIE (Alan Head) muMath
Lie (Gerd Baumann) Mathematica
LIEDF/INFSYM (Peter Gragert and Paul Kersten) Reduce
Liesymm (John Carminati, John Devitt and Greg Fee) Maple
MathSym (Scott Herod) Mathematica
NUSY (Clara Nucci) Reduce
PDELIE (Peter Vafeades) Macsyma
SPDE (Fritz Schwarz) Reduce and Axiom
SYM_DE (Stanly Steinberg) Macsyma
Symmgroup.c (Dominique Berube and Marc de Montigny) Mathematica
STANDARD FORM (Gregory Reid and Alan Wittkopf) Maple
SYMCAL (Gregory Reid) Macsyma and Maple
SYMMGRP.MAX (Benoit Champagne, Willy Hereman and Pavel Winter-
nitz) Macsyma
LIE package (Khai Vu) Maple
216 CHAPTER 16. USER CONTRIBUTED PACKAGES
[17] T. Wolf, A. Brand, The Computer Algebra Package CRACK for Investigating
PDEs, Manual for the package CRACK in the REDUCE network library and
in Proceedings of ERCIM School on Partial Differential Equations and Group
Theory, April 1992 in Bonn, GMD Bonn.
This package provides facilities for handling algebraic numbers as polynomial co-
efficients in REDUCE calculations. It includes facilities for introducing indetermi-
nates to represent algebraic numbers, for calculating splitting fields, and for factor-
ing and finding greatest common divisors in such domains.
Author: Eberhard Schrüfer.
Algebraic numbers are the solutions of an irreducible polynomial over some
ground domain. The algebraic number i (imaginary unit), for example, would
be defined by the polynomial i2 + 1. The arithmetic of algebraic number s can be
viewed as a polynomial arithmetic modulo the defining polynomial.
Given a defining polynomial for an algebraic number a
an + pn−1 an−1 + ... + p0
All algebraic numbers which can be built up from a are then of the form:
rn−1 an−1 + rn−2 an−2 + ... + r0
where the rj ’s are rational numbers.
The operation of addition is defined by
(rn−1 an−1 + rn−2 an−2 + ...) + (sn−1 an−1 + sn−2 an−2 + ...) =
(rn−1 + sn−1 )an−1 + (rn−2 + sn−2 )an−2 + ...
(rn−1 an−1 + rn−2 an−2 + ...) × (sn−1 an−1 + sn−2 an−2 + ...) =
rn−1 sn−1 a2n−2 + ... modulo an + pn−1 an−1 + ... + p0
= qn−1 an−1 + qn−2 an−2 + ...
The ti are linear in the qj . Equating equal powers of a yields a linear system for
the quotient coefficients qj .
With this, all field operations for the algebraic numbers are available. The transla-
tion into algorithms is straightforward. For an implementation we have to decide
on a data structure for an algebraic number. We have chosen the representation
REDUCE normally uses for polynomials, the so-called standard form. Since our
polynomials have in general rational coefficients, we must allow for a rational num-
ber domain inside the algebraic number.
This representation allows us to use the REDUCE functions for adding and multi-
plying polynomials on the tail of the tagged algebraic number. Also, the routines
for solving linear equations can easily be used for the calculation of quotients.
We are still left with the problem of introducing a particular algebraic number. In
the current version this is done by giving the defining polynomial to the statement
defpoly. The algebraic number sqrt(2), for example, can be introduced by
defpoly sqrt2**2 - 2;
This statement associates a simplification function for the translation of the vari-
able in the defining polynomial into its tagged internal form and also generates a
power reduction rule used by the operations times and quotient for the reduction
of their result modulo the defining polynomial. A basis for the representation of
an algebraic number is also set up by the statement. In the working version, the
basis is a list of powers of the indeterminate of the defining polynomial up to one
less then its degree. Experiments with integral bases, however, have been very
encouraging, and these bases might be available in a later version. If the defining
polynomial is not monic, it will be made so by an appropriate substitution.
Example 1
defpoly sqrt2**2-2;
220 CHAPTER 16. USER CONTRIBUTED PACKAGES
1/(sqrt2+1);
sqrt2 - 1
(x**2+2*sqrt2*x+2)/(x+sqrt2);
x + sqrt2
on gcd;
(x**3+(sqrt2-2)*x**2-(2*sqrt2+3)*x-3*sqrt2)/(x**2-2);
2
(x - 2*x - 3)/(x - sqrt2)
off gcd;
sqrt(x**2-2*sqrt2*x*y+2*y**2);
abs(x - sqrt2*y)
Until now we have dealt with only a single algebraic number. In practice this is not
sufficient as very often several algebraic numbers appear in an expression. There
are two possibilities for handling this: one can use multivariate extensions [2] or
one can construct a defining polynomial that contains all specified extensions. This
package implements the latter case (the so called primitive representation). The
algorithm we use for the construction of the primitive element is the same as given
by Trager [3]. In the implementation, multiple extensions can be given as a list
of equations to the statement defpoly, which, among other things, adds the new
extension to the previously defined one. All algebraic numbers are then expressed
in terms of the primitive element.
Example 2
defpoly sqrt2**2-2,cbrt5**3-5;
6 4 3 2
a1 - 6*a1 - 10*a1 + 12*a1 - 60*a1 + 17
sqrt2;
5 4 3 2
221
735/1187*a1 - 1820/1187
sqrt2**2;
2
222 CHAPTER 16. USER CONTRIBUTED PACKAGES
defpoly a**2-5;
on factor;
x**2 + x - 1;
split_field(x**3-3*x+7);
6 4 2
a2 - 18*a2 + 81*a2 + 1215
4 2
{1/126*a2 - 5/42*a2 - 1/2*a2 + 2/7,
4 2
- (1/63*a2 - 5/21*a2 + 4/7),
4 2
1/126*a2 - 5/42*a2 + 1/2*a2 + 2/7}
223
3
x - 3*x + 7
Bibliography
ASSERT admits to add to symbolic mode RLISP code assertions (partly) specify-
ing types of the arguments and results of RLISP expr procedures. These types can
be associated with functions testing the validity of the respective arguments during
runtime.
Author: Thomas Sturm.
typedef any;
typedef number checked by numberp;
typedef sf checked by sfpx;
typedef sq checked by sqp;
The first one defines a type any, which is not possibly checked by any function.
This is useful, e.g., for functions which admit any argument at one position but at
others rely on certain types or guarantee certain result types, e.g.,
procedure cellcnt(a);
% a is any, returns a number.
if not pairp a then 0 else cellcnt car a + cellcnt cdr a + 1;
The other ones define a type number, which can be checked by the RLISP func-
tion numberp, a type sf for standard forms, which can be checked by the function
sfpx provided by ASSERT, and similarly a type for standard quotients.
225
All type checking functions take one argument and return extended Boolean, i.e.,
non-nil iff their argument is of the corresponding type.
16.4.3 Assertions
Note that on the argument side parenthesis are mandatory also with only one argu-
ment. This notation is inspired by Haskell but avoids the intuition of currying.1
Assertions can be dynamically checked only for expr procedures. When making
assertions for other types of procedures, a warning is issued and the assertion has
the status of a comment.
It is important that assertions via assert come after the definitions of the used types
via typedef and also after the definition of the procedures they make assertions
on.
A natural order for adding type definitions and assertions to the source code files
would be to have all typedefs at the beginning of a module and assertions immedi-
ately after the respective functions. Fig. 16.1 illustrates this. Note that for dynamic
checking of the assertions the switch assert has to be on during the translation
of the module; i.e., either when reading it with in or during compilation. For com-
pilation this can be achieved by commenting in the on assert at the beginning
or by parameterizing the Lisp-specific compilation scripts in a suitable way.
An alternative option is to have type definitions and assertions for specific packages
right after load_package in batch files as illustrated in Fig. 16.2.
Recall that with the switch assert off at translation time, all type definitions and
assertions have the status of comments. We are now going to discuss how these
statements are processed with assert on.
typedef marks the type identifier as a valid type and possibly associates the given
typechecking function with it. Technically, the property list of the type identifier is
used for both purposes.
assert encapsulates the procedure that it asserts on into another one, which
1
This notation has benn suggested by C. Zengler
226 CHAPTER 16. USER CONTRIBUTED PACKAGES
module sizetools;
load!-package ’assert;
% on assert;
typedef any;
typedef number checked by number;
procedure cellcnt(a);
% a is any, returns a number.
if not pairp a then 0 else cellcnt car a + cellcnt cdr a + 1;
% ...
endmodule;
end; % of file
load_package sizetools;
load_package assert;
on assert;
lisp <<
typedef any;
typedef number checked by numberp;
assert_analyze();
end; % of file
checks the types of the arguments and of the result to the extent that there are
typechecking functions given. Whenever some argument does not pass the test by
the typechecking function, there is a warning message issued. Furthermore, the
following numbers are counted for each asserted function:
These numbers can be printed anytime in either symbolic or algebraic mode using
the command assert_analyze(). This command at the same time resets all
the counters.
Fig. 16.3 shows an interactive sample session.
16.4.5 Switches
As discussed above, the switch assert controls at translation time whether or not
assertions are dynamically checked.
There is a switch assertbreak, which is off by default. When on, there are not
only warnings issued for assertion violations but the computations is interrupted
with a corresponding error.
The statistical counting of procedure calls and assertion violations is toggled by
the switch assertstatistics, which is on by default.
16.4.6 Efficiency
1: symbolic$
2* load_package assert$
3* on assert$
(negsq)
(addsq)
*** assertion negsq: (sq) -> sq violated by result (((y . -1) . -1))
*** assertion addsq: (sq,sq) -> sq violated by arg2 (((y . -1) . -1))
*** assertion addsq: (sq,sq) -> sq violated by result (((y . -1) . -1))
9* assert_analyze()$
------------------------------------------------------------------------
function #calls #bad calls #assertion violations
------------------------------------------------------------------------
addsq 2 1 2
negsq 2 1 2
------------------------------------------------------------------------
sum 4 2 4
------------------------------------------------------------------------
Our assertions could be used also for a static type analysis of source code. In
that case, the type checking functions become irrelevant. On the other hand, the
introduction of variouse unchecked types becomes meaningful.
In a model, where the source code is systematically annotated with assertions, it
is technically no problem to generalize the specification of procedure definitions
such that assertions become implicit. For instance, one could optionally admit
procedure definitions like the following:
procedure cellcnt(a:any):number;
if not pairp a then 0 else cellcnt car a + cellcnt cdr a + 1;
230 CHAPTER 16. USER CONTRIBUTED PACKAGES
ASSIST contains a large number of additional general purpose functions that allow
a user to better adapt REDUCE to various calculational strategies and to make the
programming task more straightforward and more efficient.
Author: Hubert Caprasse.
16.5.1 Introduction
An elementary help facility is available both within the MS-DOS and Windows
environments. It is independent of the help facility of REDUCE itself. It includes
two functions:
ASSIST is a function which takes no argument. If entered, it returns the informa-
tions required for a proper use of ASSISTHELP.
ASSISTHELP takes one argument.
i. If the argument is the identifier assist, the function returns the information
necessary to retrieve the names of all the available functions.
ii. If the argument is an integer equal to one of the section numbers of the
present documentation. The names of the functions described in that section
are obtained.
231
There is, presently, no possibility to retrieve the number and the type of the
arguments of a given function.
The package contains several modules. Their content reflects closely the various
categories of facilities listed below. Some functions do already exist inside the
KERNEL of REDUCE. However, their range of applicability is extended.
• Control of Switches:
SWITCHES SWITCHORG
• Operations on Sets:
• Handling of Polynomials:
ALG_TO_SYMB SYMB_TO_ALG
DISTRIBUTE LEADTERM REDEXPR MONOM
LOWESTDEG DIVPOL SPLITTERMS SPLITPLUSMINUS
LIST_TO_ARRAY ARRAY_TO_LIST
• Handling of Matrices:
SWITCHORG resets the switches enumerated above to the status they had when
starting REDUCE .
Additional functions for list manipulations are provided and some already defined
functions in the kernel of REDUCE are modified to properly generalize them to
the available new structure BAG.
MKLIST n ; n is an INTEGER
p + q = n.
The function KERNLIST transforms any prefix of a kernel into the list
prefix. The output list is a copy:
iv. The function ELMULT returns an integer which is the multiplicity of its
first argument inside the list which is its second argument. The function
FREQUENCY gives a list of pairs whose second element indicates the num-
ber of times the first element appears inside the original list:
ELMULT(x,{a,b,x,f,x}) ==> 2
v. The function INSERT allows one to insert a given object into a list at the
desired position.
The functions INSERT_KEEP_ORDER and MERGE_LIST allow one to
keep a given ordering when inserting one element inside a list or when merg-
ing two lists. Both have 3 arguments. The last one is the name of a binary
boolean ordering function:
ll:={1,2,3}$
Notice that MERGE_LIST will act correctly only if the two lists are well
ordered themselves.
vi. Algebraic lists can be read from right to left or left to right. They look sym-
metrical. One would like to dispose of manipulation functions which reflect
this. So, to the already defined functions FIRST and REST are added the
functions LAST and BELAST. LAST gives the last element of the list while
BELAST gives the list without its last element.
Various additional functions are provided. They are:
1. If one applies it on the left of a list, it acts as the CONS function. Note
however that blank spaces are required around the dot:
2. If one applies it on the right of a list, it has the same effect as the PART
operator:
{a,b,c}.2; ==> b
236 CHAPTER 16. USER CONTRIBUTED PACKAGES
ll:={{a,b}}$
ll1:=ll.1; ==> {a,b}
ll.0; ==> list
0 . ll; ==> {0,{a,b}}
POSITION(b,ll3); ==> 2
lp:={{a,1},{b,2},{c,3}}$
lpp:=APPEND(lp,lp)$
vii. The function SUBSTITUTE has three arguments. The first is the object to
be substituted, the second is the object which must be replaced by the first,
and the third is the list in which the substitution must be made. Substitution
is made to all levels. It is a more elementary function than SUB but its
capabilities are less. When dealing with algebraic quantities, it is important
to make sure that all objects involved in the function have either the prefix
lisp or the standard quotient representation otherwise it will not properly
work.
238 CHAPTER 16. USER CONTRIBUTED PACKAGES
The LIST structure of REDUCE is very convenient for manipulating groups of ob-
jects which are, a priori, unknown. This structure is endowed with other properties
such as “mapping” i.e. the fact that if OP is an operator one gets, by default,
It is not permitted to submit lists to the operations valid on rings so that, for exam-
ple, lists cannot be indeterminates of polynomials.
Very frequently too, procedure arguments cannot be lists. At the other extreme,
so to say, one has the KERNEL structure associated with the algebraic declaration
operator . This structure behaves as an “unbreakable” one and, for that reason,
behaves like an ordinary identifier. It may generally be bound to all non-numeric
procedure parameters and it may appear as an ordinary indeterminate inside poly-
nomials.
The BAG structure is intermediate between a list and an operator. From the operator
it borrows the property of being a KERNEL and, therefore, may be an indetermi-
nate of a polynomial. From the list structure it borrows the property of being a
composite object.
Definition:
A bag is an object endowed with the following properties:
2. Its content may be handled in an analogous way as the content of a list. The
important difference is that during these manipulations the name of the bag
is kept.
3. Properties may be given to the envelope. For instance, one may declare it
NONCOM or SYMMETRIC etc. . . .
Available Functions:
PUTBAG id1,id2,....idn;
CLEARBAG id1,...idn;
ii. The boolean function BAGP detects the bag property. Here is an example:
aa:=bag(x,y,z)$
iii. The functions listed below may act both on lists or bags. Moreover, functions
subsequently defined for SETS also work for a bag when its content is a set.
Here is a list of the main ones:
However, since they keep track of the envelope, they act somewhat differ-
ently. Remember that
Here are a few examples (more examples are given inside the test file):
aa:=op(x,y,z)$
When “appending” two bags with different envelopes, the resulting bag
gets the name of the one bound to the first parameter of APPEND. When
APPENDN is used, the output is always a list.
The function LENGTH gives the number of objects contained in the bag.
iv. The connection between the list and the bag structures is made easy thanks
to KERNLIST which transforms a bag into a list and thanks to the coercion
function LISTBAG which transforms a list into a bag. This function has 2
arguments and is used as follows:
Functions for sets exist at the level of symbolic mode. The package makes them
available in algebraic mode but also generalizes them so that they can be applied
to bag-like objects as well.
241
They have two arguments which must be sets otherwise an error message
is issued. Their meaning is transparent from their name. They respectively
give the union, the intersection, the difference and the symmetric difference
of two sets.
Functions in this sections have various purposes. They have all been used many
times in applications in some form or another. The form given to them in this
package is adjusted to maximize their range of applications.
DELLASTDIGIT takes an integer as argument and strips it from its last digit.
The function == is a short and convenient notation for the SET function. In
fact it is a generalization of it to allow one to deal also with KERNELS:
operator op;
op(x):=abs(x)$
op(x) == x; ==> x
op(x); ==> x
abs(x); ==> x
243
MKRANDTABL({3,4},10,ar); ==>
{3,4}
{{1,2,3},{2,3,1},{3,1,2}}
PERM_TO_NUM({4,3,2,1},{1,2,3,4}) ==> 23
ll:={a,b,c}$
SYMMETRIZE(ll,op,cyclicpermlist); ==>
Notice that, taking for the first argument a list of lists gives rise to an ex-
pression where each kernel has a list as argument. Another peculiarity of
this function is the fact that, unless a pattern matching is made on the oper-
ator OP, it needs to be reevaluated. This peculiarity is convenient when OP
is an abstract operator if one wants to control the subsequent simplification
process. Here is an illustration:
245
op(a,b,c):=a*b*c$
SYMMETRIZE(ll,op,cyclicpermlist); ==>
SYMMETRIZE(ll,op,cyclicpermlist); ==>
It is important to realise that using these functions for kernels or bags may
be dangerous since they are destructive. If it is necessary, it is recommended
to first apply KERNLIST to them to act on a copy.
The function EXTREMUM is a generalization of the already defined functions
MIN, MAX to include general orderings. It is a 2 argument function. The
first is the list and the second is the ordering function. With the list ll
defined in the last example, one gets
246 CHAPTER 16. USER CONTRIBUTED PACKAGES
EXTREMUM(ll,ordp); ==> 1
iii. There are four functions to identify dependencies. FUNCVAR takes any ex-
pression as argument and returns the set of variables on which it depends.
Constants are eliminated.
depend a,x,y;
The functions EXPLICIT and IMPLICIT make explicit or implicit the de-
pendencies. This example shows how they work:
These are useful when one wants to trace the names of the independent vari-
ables and (or) the nature of the dependencies.
KORDERLIST is a zero argument function which displays the actual order-
ing.
korder x,y,z;
l:={1,a,b,"st")$
vi. Coercion.
Since lists and arrays have quite distinct behaviour and storage properties,
it is interesting to coerce lists into arrays and vice-versa in order to fully
exploit the advantages of both datatypes. The functions ARRAY_TO_LIST
and LIST_TO_ARRAY are provided to do that easily. The first function has
the array identifier as its unique argument. The second function has three
arguments. The first is the list, the second is the dimension of the array
and the third is the identifier which defines it. If the chosen dimension is
not compatible with the the list depth, an error message is issued. As an
illustration suppose that ar is an array whose components are 1,2,3,4. then
LIST_TO_ARRAY({1,2,3,4},1,arr}; ==>
In spite of the fact that many facets of the handling of property lists is easily acces-
sible in algebraic mode, it is useful to provide analogous functions genuine to the
algebraic mode. The reason is that, altering property lists of objects, may easily
destroy the integrity of the system. The functions, which are here described, do
ignore the property list and flags already defined by the system itself. They gen-
erate and track the addtional properties and flags that the user issues using them.
They offer him the possibility to work on property lists so that he can design a
programming style of the “conceptual” type.
PUTFLAG({z1,z2},flag1_name,t); ==> t
PUTFLAG(z2,flag1_name,0) ==>
DISPLAYFLAG z2 ; ==> {}
CLEARFLAG is a command which clears all flags associated with the iden-
tifiers id1 , . . . , idn .
ii. Properties are handled by similar functions. PUTPROP has four arguments.
The second argument is, here, the indicator of the property. The third argu-
ment may be any valid expression. The fourth one is also T or 0.
PUTPROP(z1,property,x^2,t); ==> z1
PUTPROP(LIST(idp1,idp2,..),<propname>,<value>,T);
2
DISPLAYPROP(z1,property); ==> {property,x }
Here we describe additional functions which improve user control on the environ-
ment.
i. The first set of functions is composed of unary and binary boolean functions.
They are:
250 CHAPTER 16. USER CONTRIBUTED PACKAGES
ALATOMP x; x is anything.
ALKERNP x; x is anything.
DEPVARP(x,v); x is anything.
(v is an atom or a kernel)
ALATOMP has the value T iff x is an integer or an identifier after it has been
evaluated down to the bottom.
ALKERNP has the value T iff x is a kernel after it has been evaluated down
to the bottom.
DEPVARP returns T iff the expression x depends on v at any level.
The above functions together with PRECP have been declared operator func-
tions to ease the verification of their value.
NORDP is equal to NOT ORDP.
ii. The next functions allow one to analyze and to clean the environment of
REDUCE created by the user while working interactively. Two functions
are provided:
SHOW allows the user to get the various identifiers already assigned and to
see their type. SUPPRESS selectively clears the used identifiers or clears
them all. It is to be stressed that identifiers assigned from the input of files
are ignored. Both functions have one argument and the same options for this
argument:
The option all is the most convenient for SHOW but, with it, it may takes
some time to get the answer after one has worked several hours. When en-
tering REDUCE the option all for SHOW gives:
251
a:=b:=1$
iii. The CLEAR function of the system does not do a complete cleaning of
OPERATORS and FUNCTIONS . The following two functions do a more
complete cleaning and, also, automatically takes into account the user flag
and properties that the functions PUTFLAG and PUTPROP may have intro-
duced.
Their names are CLEAROP and CLEARFUNCTIONS. CLEAROP takes one
operator as its argument.
CLEARFUNCTIONS is a nary command. If one issues
The functions with names a1,a2, ... ,an are cleared. One should
be careful when using this facility since the only functions which cannot be
erased are those which are protected with the lose flag.
252 CHAPTER 16. USER CONTRIBUTED PACKAGES
The module contains some utility functions to handle standard quotients and sev-
eral new facilities to manipulate polynomials.
ll:={a,{b,{c},d,e},{{{z}}}}$
pol:=x++y+z$
korder y,x,z;
iii. Two complementary functions LOWESTDEG and DIVPOL are provided. The
first takes a polynomial as its first argument and the name of an indeterminate
as its second argument. It returns the lowest degree in that indeterminate.
The second function takes two polynomials and returns both the quotient
and its remainder.
The functions TRIGREDUCE and TRIGEXPAND and the equivalent ones for hy-
perbolic functions HYPREDUCE and HYPEXPAND make the transformations to
254 CHAPTER 16. USER CONTRIBUTED PACKAGES
aa:=sin(x+y)$
aa:=(sin(x)^2+cos(x)^2)^3$
bb:=1+sin(x)^3$
- SIN(3*X) + 3*SIN(X) + 4
---------------------------
4
3 2
SIN(X) - 3*SIN(X)*COS(X) + 3*SIN(X) + 4
-------------------------------------------
4
255
l:={1,2,3}$
ll:=list(a,b,c)$
MINVECT(l,ll); ==> { - A + 1, - B + 2, - C + 3}
MPVECT(l,ll,l); ==> 0
Grassman variables are often used in physics. For them the multiplication oper-
ation is associative, distributive but anticommutative. The KERNEL of REDUCE
does not provide it. However, implementing it in full generality would almost cer-
tainly decrease the overall efficiency of the system. This small module together
with the declaration of antisymmetry for operators is enough to deal with most cal-
culations. The reason is, that a product of similar anticommuting kernels can easily
be transformed into an antisymmetric operator with as many indices as the number
of these kernels. Moreover, one may also issue pattern matching rules to imple-
ment the anticommutativity of the product. The functions in this module represent
the minimum functionality required to identify them and to handle their specific
features.
PUTGRASS is a (nary) command which give identifiers the property of being the
names of Grassmann kernels. REMGRASS removes this property.
GRASSP is a boolean function which detects grassmann kernels.
256 CHAPTER 16. USER CONTRIBUTED PACKAGES
GRASSPARITY takes a monom as argument and gives its parity. If the monom is
a simple grassmann kernel it returns 1.
GHOSTFACTOR has two arguments. Each one is a monom. It is equal to
(-1)**(GRASSPARITY u * GRASSPARITY v)
grassmann kernel
aa:=eta(1)*eta(2)-eta(2)*eta(1); ==>
AA := - ETA(2)*ETA(1) + ETA(1)*ETA(2)
GHOSTFACTOR(eta(1),eta(2)); ==> -1
grasskernel:=
{eta(~x)*eta(~y) => -eta y * eta x when nordp(x,y),
(~x)*(~x) => 0 when grassp x};
exp:=eta(1)^2$
i. Often, one needs to construct some UNIT matrix of a given dimension. This
257
where M1,...Mi are names of matrices and n1, n2, ..., ni are
integers .
MKIDM is a generalization of MKID. It allows one to connect two or several
matrices. If u and u1 are two matrices, one can go from one to the other:
u1; ==>
[1 0]
[ ]
[0 1]
mkidm(u,1); ==>
[1 0]
[ ]
[0 1]
This function allows one to make loops on matrices like in the following
illustration. If U, U1, U2,.., U5 are matrices:
can be issued.
ii. The next functions map matrices on bag-like or list-like objects and con-
versely they generate matrices from bags or lists.
COERCEMAT transforms the matrix U into a list of lists. The entry is
COERCEMAT(U,id)
258 CHAPTER 16. USER CONTRIBUTED PACKAGES
BAGLMAT(bgl,U)
ii. The functions SUBMAT, MATEXTR, MATEXTC take parts of a given ma-
trix.
SUBMAT has three arguments. The entry is
SUBMAT(U,nr,nc)
The first is the matrix name, and the other two are the row and column num-
bers. It gives the submatrix obtained from U by deleting the row nr and the
column nc. When one of them is equal to zero only column nc or row nr
is deleted.
MATEXTR and MATEXTC extract a row or a column and place it into a list-
like or bag-like object. The entries are
MATEXTR(U,VN,nr)
MATEXTC(U,VN,nc)
MATSUBR(U,bgl,nr)
MATSUBC(U,bgl,nc)
The meaning of the variables U, nr, nc is the same as above while bgl
is a list-like or bag-like vector. Its length should be compatible with the
dimensions of the matrix.
HCONCMAT VCONCMAT concatenate two matrices. The entries are
HCONCMAT(U,V)
VCONCMAT(U,V)
TPMAT(U,V) or U TPMAT V
HERMAT(U,HU)
iv. SETELMAT GETELMAT are functions of two integers. The first one resets
the element (i,j) while the second one extracts an element identified by
(i,j). They may be useful when dealing with matrices inside procedures.
260 CHAPTER 16. USER CONTRIBUTED PACKAGES
This package provides REDUCE with the ability to perform vector algebra using
the same notation as scalar algebra. The basic algebraic operations are supported,
as are differentiation and integration of vectors with respect to scalar variables,
cross product and dot product, component manipulation and application of scalar
functions (e.g. cosine) to a vector to yield a vector result.
Author: David Harper.
16.6.1 Introduction
This package 2 is written in RLISP (the LISP meta-language) and is intended for
use with REDUCE 3.4. It provides REDUCE with the ability to perform vector
algebra using the same notation as scalar algebra. The basic algebraic operations
are supported, as are differentiation and integration of vectors with respect to scalar
variables, cross product and dot product, component manipulation and application
of scalar functions (e.g. cosine) to a vector to yield a vector result.
A set of vector calculus operators are provided for use with any orthogonal curvi-
linear coordinate system. These operators are gradient, divergence, curl and del-
squared (Laplacian). The Laplacian operator can take scalar or vector arguments.
Several important coordinate systems are pre-defined and can be invoked by name.
It is also possible to create new coordinate systems by specifying the names of the
coordinates and the values of the scale factors.
Any name may be declared to be a vector, provided that it has not previously been
declared as a matrix or an array. To declare a list of names to be vectors use the
VEC command:
VEC A,B,C;
declares the variables A, B and C to be vectors. If they have already been assigned
(scalar) values, these will be lost.
When a vector is declared using the VEC command, it does not have an initial
value.
If a vector value is assigned to a scalar variable, then that variable will automati-
cally be declared as a vector and the user will be notified that this has happened.
2
Reference: Computer Physics Communications, 54, 295-305 (1989)
261
A vector may be initialised using the AVEC function which takes three scalar argu-
ments and returns a vector made up from those scalars. For example
(In the examples which follow, V, V1, V2 etc are assumed to be vectors while S,
S1, S2 etc are scalars.)
The scalar algebra operators +,-,* and / may be used with vector operands accord-
ing to the rules of vector algebra. Thus multiplication and division of a vector by
a scalar are both allowed, but it is an error to multiply or divide one vector by
another.
V := V1 + V2 - V3; Addition and subtraction
V := S1*3*V1; Scalar multiplication
V := V1/S; Scalar division
V := -V1; Negation
Vector multiplication is carried out using the infix operators DOT and CROSS.
These are defined to have higher precedence than scalar multiplication and divi-
sion.
V := V1 CROSS V2; Cross product
S := V1 DOT V2; Dot product
V := V1 CROSS V2 + V3;
V := (V1 CROSS V2) + V3;
The last two expressions are equivalent due to the precedence of the CROSS oper-
ator.
The modulus of a vector may be calculated using the VMOD operator.
S := VMOD V;
A unit vector may be generated from any vector using the VMOD operator.
V1 := V/(VMOD V);
Components may be extracted from any vector using index notation in the same
way as an array.
262 CHAPTER 16. USER CONTRIBUTED PACKAGES
V(1) := B;
The vector calculus operators div, grad and curl are recognised. The Laplacian
operator is also available and may be applied to scalar and vector arguments.
V := GRAD S; Gradient of a scalar field
S := DIV V; Divergence of a vector field
V := CURL V1; Curl of a vector field
S := DELSQ S1; Laplacian of a scalar field
V := DELSQ V1; Laplacian of a vector field
These operators may be used in any orthogonal curvilinear coordinate system. The
user may alter the names of the coordinates and the values of the scale factors.
Initially the coordinates are X, Y and Z and the scale factors are all unity.
There are two special vectors : COORDS contains the names of the coordinates in
the current system and HFACTORS contains the values of the scale factors.
The coordinate names may be changed using the COORDINATES operator.
COORDINATES R,THETA,PHI;
SCALEFACTORS(1,R,R*SIN(THETA));
SYMBOLIC !*CSYSTEMS;
GETCSYSTEM ’CARTESIAN;
Note the quote which prefixes the name of the coordinate system. This is required
because GETCSYSTEM (and its complement PUTCSYSTEM) is a SYMBOLIC pro-
cedure which requires a literal argument.
REDUCE responds by typing a list of the coordinate names in that coordinate
system. The example above would produce the response
(X Y Z)
whilst
GETCSYSTEM ’SPHERICAL;
would produce
(R THETA PHI)
Note that any attempt to invoke a coordinate system is subject to the same restric-
264 CHAPTER 16. USER CONTRIBUTED PACKAGES
COORDINATES X,Y,Z;
SCALEFACTORS(H1,H2,H3);
PUTCSYSTEM ’GENERAL;
GETCSYSTEM ’GENERAL;
Several functions are provided to perform volume and line integrals. These operate
in any orthogonal curvilinear coordinate system and make use of the scale factors
described in the previous section.
Definite integrals of scalar and vector expressions may be calculated using the
DEFINT function.
Example 6
To calculate the definite integral of sin(x)2 between 0 and 2π we enter
DEFINT(SIN(X)**2,X,0,2*PI);
This function is a simple extension of the INT function taking two extra arguments,
the lower and upper bounds of integration respectively.
Definite volume integrals may be calculated using the VOLINTEGRAL function
whose syntax is as follows :
VOLINTEGRAL(integrand, vector lower-bound, vector upper-bound);
Example 7
In spherical polar coordinates we may calculate the volume of a sphere by integrat-
ing unity over the range r=0 to RR, θ=0 to PI, φ=0 to 2*π as follows :
265
VOLINTORDER := AVEC(2,0,1);
VLB := AVEC(0,0,0);
VUB := AVEC(P*Z,H,2*PI);
VOLINTEGRAL(1,VLB,VUB);
(At this stage, we replace P*H by RR, the base radius of the cone, to obtain the
result in its more familiar form.)
Line integrals may be calculated using the LINEINT and DEFLINEINT funct-
ions. Their general syntax is
LINEINT(vector-function, vector-curve, variable);
DEFLINENINT(vector-function, vector-curve, variable, lower-bound,
upper-bound);
where
Example 9
In spherical polar coordinates, we may integrate round a line of constant theta
(‘latitude’) to find the length of such a line. The vector function is thus the tangent
to the ‘line of latitude’, (0,0,1) and the path is (0,LAT,PHI) where PHI is the
independent variable. We show how to obtain the definite integral i.e. from φ = 0
to 2π :
DEFLINEINT(AVEC(0,0,1),AVEC(0,LAT,PHI),PHI,0,2*PI);
Most of the procedures in this package are defined in symbolic mode and are in-
voked by the REDUCE expression-evaluator when a vector expression is encoun-
tered. It is not generally possible to define procedures which accept or return vector
values in algebraic mode. This is a consequence of the way in which the REDUCE
interpreter operates and it affects other non-scalar data types as well : arrays cannot
be passed as algebraic procedure arguments, for example.
16.6.7 Acknowledgements
This package was written whilst the author was the U.K. Computer Algebra Sup-
port Officer at the University of Liverpool Computer Laboratory.
267
16.7.1 Introduction
Involutive polynomial bases are redundant Gröbner bases of special structure with
some additional useful features in comparison with reduced Gröbner bases [1].
Apart from numerous applications of involutive bases [2] the involutive algo-
rithms [3] provide an efficient method for computing reduced Gröbner bases. A
reduced Gröbner basis is a well-determined subset of an involutive basis and can
be easily extracted from the latter without any extra reductions. All this takes place
not only in rings of commutative polynomials but also in Boolean rings.
Boolean Gröbner basis already have already revealed their value and usability in
practice. The first impressive demonstration of practicability of Boolean Gröbner
bases was breaking the first HFE (Hidden Fields Equations) challenge in the public
key cryptography done in [4] by computing a Boolean Gröbner basis for the system
of quadratic polynomials in 80 variables. Since that time the Boolean Gröbner
bases application area has widen drastically and nowadays there is also a number
of quite successful examples of using Gröbner bases for solving SAT problems.
During our research we had developed [5, 6, 7] Boolean involutive algorithms
based on Janet and Pommaret divisions and applied them to computation of
Boolean Gröbner bases. Our implementation of both divisions has experimentally
demonstrated computational superiority of the Pommaret division implementation.
This package BIBASIS is the result of our thorough research in the field of Boolean
Gröbner bases. BIBASIS implements the involutive algorithm based on Pommaret
division in a multivariate Boolean ring.
In section 2 the Boolean ring and its peculiarities are shortly introduced. In section
3 we briefly argue why the involutive algorithm and Pommaret division are good
for Boolean ring while the Buhberger’s algorithm is not. And finally in section 4
we give the full description of BIBASIS package capabilities and illustrate it by
examples.
Boolean ring perfectly goes with its name, it is a ring of Boolean functions of n
variables, i.e mappings from {0, 1}n to {0, 1}n . Considering these variables are
X := {x1 , . . . , xn } and F2 is the finite field of two elements {0, 1}, Boolean ring
268 CHAPTER 16. USER CONTRIBUTED PACKAGES
∀ b ∈ B [X] : b2 = b , b + b = 0.
Elements in B [X] are Boolean polynomials and can be represented as finite sums
X Y
x
j x∈ Ωj ⊆ X
Detailed description of involutive algorithm can found in [3]. Here we note that
result of both involutive and Buhberger’s algorithms depend on chosen monomial
ordering. At that the ordering must be admissible, i.e.
m 6= 1 ⇐⇒ m 1, m1 m2 ⇐⇒ m1 m m2 m ∀ m, m1 , m2 .
But as one can easily check the second condition of admissibility does not hold for
any monomial ordering in Boolean ring:
∗x
1
x1 x2 −−−−→ x1 ∗ x1 x2 ∗ x2 −−→ x1 ≺ x1 x2
Though B [X] is a principal ideal ring, boolean singleton {p} is not necessarily a
Gröbner basis of ideal < p >, for example:
That the reason why one cannot apply the Buhberger’s algorithm directly in a
Boolean ring, using instead a ring F2 [X] and the field binomials x21 + x1 , . . . , x2n +
xn .
The involutive algorithm based on Janet division has the same disadvantage unlike
the Pommaret division algorithm as shown in [5]. The Pommaret division algo-
rithm can be applied directly in a Boolean ring and admits effective data structures
for monomial representation.
269
1: load_package bibasis;
The current version of the BIBASIS user interface consists only of 2 functions:
bibasis and bibasis_print_statistics.
The bibasis is the function that performs all the computation and has the fol-
lowing syntax:
bibasis(initial_polynomial_list, variables_list,
monomial_ordering, reduce_to_groebner);
Input:
See Examples 2—4 to check that Gröbner (as well as involutive) basis de-
pends on monomial ordering.
Output:
bibasis_print_statistics();
270 CHAPTER 16. USER CONTRIBUTED PACKAGES
This function prints out a brief statistics for the last invocation of bibasis func-
tion. See Example 7.
16.7.5 Examples
Example 1:
1: load_package bibasis;
2: bibasis({x+2*y}, {x,y}, lex, t);
{x}
Example 2:
1: load_package bibasis;
2: variables :={x0,x1,x2,x3,x4}$
3: polynomials := {x0*x3+x1*x2,x2*x4+x0}$
4: bibasis(polynomials, variables, lex, t);
{x0 + x2*x4,x2*(x1 + x3*x4)}
Example 3:
1: load_package bibasis;
2: variables :={x0,x1,x2,x3,x4}$
3: polynomials := {x0*x3+x1*x2,x2*x4+x0}$
4: bibasis(polynomials, variables, deglex, t);
{x1*x2*(x3 + 1),
x1*(x0 + x2),
x0*(x2 + 1),
x0*x3 + x1*x2,
x0*(x4 + 1),
x2*x4 + x0}
Example 4:
1: load_package bibasis;
2: variables :={x0,x1,x2,x3,x4}$
3: polynomials := {x0*x3+x1*x2,x2*x4+x0}$
4: bibasis(polynomials, variables, degrevlex, t);
{x0*(x1 + x3),
x0*(x2 + 1),
271
x1*x2 + x0*x3,
x0*(x4 + 1),
x2*x4 + x0}
272 CHAPTER 16. USER CONTRIBUTED PACKAGES
Example 5:
1: load_package bibasis;
2: variables :={x,y,z}$
3: polinomials := {x, z}$
4: bibasis(polinomials, variables, degrevlex, t);
{x,z}
Example 6:
1: load_package bibasis;
2: variables :={x,y,z}$
3: polinomials := {x, z}$
4: bibasis(polinomials, variables, degrevlex, nil);
{x,z,y*z}
Example 7:
1: load_package bibasis;
2: variables :={u0,u1,u2,u3,u4,u5,u6,u7,u8,u9}$
3: polinomials := {u0*u1+u1*u2+u1+u2*u3+u3*u4+u4*u5+u5*u6+u6*u7+u7*u8+
3: u0*u2+u1+u1*u3+u2*u4+u2+u3*u5+u4*u6+u5*u7+u6*u8+u7*
3: u0*u3+u1*u2+u1*u4+u2*u5+u3*u6+u3+u4*u7+u5*u8+u6*u9,
3: u0*u4+u1*u3+u1*u5+u2+u2*u6+u3*u7+u4*u8+u4+u5*u9,
3: u0*u5+u1*u4+u1*u6+u2*u3+u2*u7+u3*u8+u4*u9+u5,
3: u0*u6+u1*u5+u1*u7+u2*u4+u2*u8+u3+u3*u9+u6,
3: u0*u7+u1*u6+u1*u8+u2*u5+u2*u9+u3*u4+u7,
3: u0*u8+u1*u7+u1*u9+u2*u6+u3*u5+u4+u8,
3: u0+u1+u2+u3+u4+u5+u6+u7+u8+u9+1}$
4: bibasis(polinomials, variables, degrevlex, t);
{u3*u6,
u3*u7,
u7*(u6 + 1),
u3*u8,
u6*u8 + u6 + u7,
u7*u8,
u3*(u9 + 1),
u6*u9 + u7,
u7*(u9 + 1),
u8*u9 + u6 + u7 + u8,
u0 + u3 + u6 + u9 + 1,
u1 + u7,
273
u2 + u7 + u8,
u4 + u6 + u8,
u5 + u6 + u7 + u8}
5: bibasis_print_statistics();
Variables order = u0 > u1 > u2 > u3 > u4 > u5 > u6 > u7 > u8 > u9
Normal forms calculated = 216
Non-zero normal forms = 85
Reductions made = 4488
Time: 270 ms
GC time: 0 ms
Bibliography
[2] W.M.Seiler. Involution: The Formal Theory of Differential Equations and its
Applications in Computer Algebra. Algorithms and Computation in Mathe-
matics, 24, Springer, 2010. arXiv:math.AC/0501111
[6] V.P.Gerdt and M.V.Zinin. Involutive Method for Computing Gröbner Bases
over F2 . Programming and Computer Software, Vol.34, No. 4, 2008, 191–
203.
[7] Vladimir Gerdt, Mikhail Zinin and Yuri Blinkov. On computation of Boolean
involutive bases, Proceedings of International Conference Polynomial Com-
puter Algebra 2009, pp. 17-24 (International Euler Institute, April 7-12, 2009,
St. Peterburg, Russia)
274 CHAPTER 16. USER CONTRIBUTED PACKAGES
This package supports the computation with boolean expressions in the proposi-
tional calculus. The data objects are composed from algebraic expressions con-
nected by the infix boolean operators and, or, implies, equiv, and the unary prefix
operator not. Boolean allows you to simplify expressions built from these oper-
ators, and to test properties like equivalence, subset property etc.
Author: Herbert Melenk.
16.8.1 Introduction
The package Boolean supports the computation with boolean expressions in the
propositional calculus. The data objects are composed from algebraic expressions
(“atomic parts”, “leafs”) connected by the infix boolean operators and, or, im-
plies, equiv, and the unary prefix operator not. Boolean allows you to simplify
expressions built from these operators, and to test properties like equivalence, sub-
set property etc. Also the reduction of a boolean expression by a partial evaluation
and combination of its atomic parts is supported.
Brackets are used to override the operator precedence as usual. The leafs or atoms
of a boolean expression are those parts which do not contain a leading boolean
operator. These are considered as constants during the boolean evaluation. There
are two pre-defined values:
• true, t or 1
• false, nil or 0
These represent the boolean constants. In a result form they are used only as 1 and
0.
275
The disjunctive normal form is used by default. It represents the “natural” view
and allows us to represent any form free or parentheses. Alternatively a conjunc-
tive normal form can be selected as simplification target, which is a form with
leading operator and. To produce that form add the keyword and as an additional
argument to a call of boolean.
Usually the result is a fully reduced disjunctive or conjuntive normal form, where
all redundant elements have been eliminated following the rules
a ∧ b ∨ ¬a ∧ b ←→ b
a ∨ b ∧ ¬a ∨ b ←→ b
Internally the full normal forms are computed as intermediate result; in these forms
each term contains all leaf expressions, each one exactly once. This unreduced
form is returned when you set the additional keyword full:
\/ not(a)/\not(b)/\not(c))
If the leafs of the boolean expression are algebraic expressions which may eval-
uate to logical values because the environment has changed (e.g. variables have
been bound), you can re–investigate the expression using the operator testbool
with the boolean expression as argument. This operator tries to evaluate all leaf
expressions in REDUCE boolean style. As many terms as possible are replaced
by their boolean values; the others remain unchanged. The resulting expression is
contracted to a minimal form. The result 1 (= true) or 0 (=false) signals that the
complete expression could be evaluated.
In the following example the leafs are built as numeric greater test. For using > in
the expressions the greater sign must be declared operator first. The error messages
are meaningless.
operator >;
fm:=boolean(x>v or not (u>v));
->
fm := boolean(not(u>v) \/ x>v)
v:=10$
testbool fm;
->
boolean(not(u>10) \/ x>10)
x:=3$
testbool fm;
->
boolean(not(u>10))
x:=17$
277
testbool fm;
->
1
278 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.9.1 Introduction
For a detailed description of special symbolic mode procedures one should consult
the source code and the comments therein. In this manual we can give only a brief
description of the main ideas incorporated into the package CALI. We concentrate
on the data structure design and the description of the more advanced algorithms.
For sample computations from several fields of commutative algebra the reader
may consult also the cali.tst file.
Below we will use freely without further explanation the notions common for text
books and papers about constructive commutative algebra, assuming the reader to
be familiar with the corresponding ideas and concepts. For further references see
e.g. the text books [2], [7] and [21] or the survey papers [5], [6] and [27].
cali.chg
a detailed report of changes from v. 2.1 to v. 2.2. and 2.2.1
cali.log
the output file, that cali.tst should produce with
load_package cali;
out "logfile"$
in "cali.tst";
shut "logfile"$
cali.red
the CALI source file.
cali.tex
this manual.
cali.tst
a test file with various examples and applications of CALI.
CALI should be precompiled as usual, i.e. either using the makefasl utility of RE-
DUCE or “by hand” via
faslout "cali"$
in "cali.red"$
faslend$
load_package cali;
281
Upon successful loading CALI responds with a message containing the version
number and the last update of the distribution.
Feel free to contact me by email if You have problems to get CALI started.
Also comments, hints, bug reports etc. are welcome.
From a certain point of view one of the major disadvantage of the current RLISP
(and the underlying PSL) language is the fact that it supports modularity and data
encapsulation only in a rudimentary way. Since all parts of code loaded into a
session are visible all the time, name conflicts between different packages may
occur, will occur (even not issuing a warning message), and are hard to prevent,
since packages are developed (and are still developing) by different research groups
at different places and different time.
A (yet rudimentary) concept of REDUCE packages and modules indicates the di-
rection into what the REDUCE designers are looking for a solution for this general
problem.
CALI (2.0 and higher) follows a name concept for internal procedures to mimick
data encapsulation at a semantical level. We hope this way on the one hand to
resolve the conflicts described above at least for the internal part of CALI and on
the other hand to anticipate a desirable future and already foregoing development
of REDUCE towards a true modularity.
The package CALI is divided into several modules, each of them introducing either
a single new data type together with basic facilities, constructors, and selectors or
a collection of algorithms subject to a common problem. Each module contains in-
ternal procedures, conceptually hidden by this module, local procedures, designed
for a CALI wide use, and global procedures, exported by CALI into the general
(algebraic or symbolic) environment of REDUCE. A header module cali contains
all (fluid) global variables and switches defined by the pacakge CALI.
Along these lines the CALI procedures available in symbolic mode are divided into
three types with the following naming convention:
module!=procedure
internal to the given module.
module_procedure
exported by the given module into the local CALI environment.
282 CHAPTER 16. USER CONTRIBUTED PACKAGES
procedure!*
a global procedure usually having a semantically equivalent procedure (possi-
bly with another parameter list) without trailing asterisk in algebraic mode.
There are also symbolic mode equivalents without trailing asterisk, if the algebraic
procedure is not a psopfn, but a symbolic operator. They transfer data to CALI’s
internal structure and call the corresponding procedure with trailing asterisk. CALI
2.2 distinguishes between algebraic and symbolic calls of such a procedure. In
symbolic mode such a procedure calls the corresponding procedure with trailing
asterisk directly without data transfer.
CALI 2.2 follows also a more concise concept for global variables. There are three
types of them:
The major changes in v. 2.1 reflect the experience we’ve got from the use of CALI
2.0. The following changes are worth mentioning explicitely:
1. The algebraic rule concept was adapted to CALI. It allows to supply rule
based coefficient domains. This is a more efficient way to deal with (easy)
algebraic numbers than through the arnum package.
2. listtest and listminimize provide an unified concept for different list opera-
tions previously scattered in the source text.
283
3. There are several new quotient algorithms at the symbolic level (both the
general element and the intersection approaches are available) and new fea-
tures for the computation of equidimensional hull and equidimensional rad-
ical.
4. A new module scripts offers advanced applications of Gröbner bases.
5. Several advanced procedures initialize a Gröbner basis computation over a
certain intermediate base ring or term order as e.g. eliminate, resolve, matin-
tersect or all primary decomposition procedures. Interrupting a computation
in v. 2.1 now restores the original values of CALI’s global variables, since
all intermediate procedures work with local copies of the global variables.4
This doesn’t apply to advanced procedures that change the current base ring
as e.g. blowup, preimage, sym etc.
Version 2.2 (beside bug fixes) incorporates several new facilities of constructive
non linear algebra that we investigated the last two years, as e.g. dual bases, the
Gröbner factorizer, triangular systems, and local standard bases. Essential changes
concern the following topics:
1. The CALI modules red and groeb were rewritten and the module mora was
removed. This is due to new theoretical insight into standard bases theory
as e.g. described in [13] or [14]. The Gröbner basis algorithm is reorganized
as a Gröbner driver with simplifier and base lists, that involves different ver-
sions of polynomial reduction according to the setting via gbtestversion. It
applies now to both noetherian and non noetherian term orders in a unified
way.
The switches and were removed.
2. The Gröbner factorizer was thoroughly revised, extended along the lines ex-
plained in [15], and collected into a separate module groebf . It now allows a
list of constraints also in algebraic mode. Two versions of an extended Gröb-
ner factorizer produce triangular systems, i.e. a decomposition into quasi
prime components, see [16], that are well suited for further (numerical) eval-
uation. There is also a version of the Gröbner factorizer that allows a list of
problems as input. This is especially useful, if a system is splitted with re-
spect to a “cheap” (e.g. degrevlex) term order and the pieces are recomputed
with respect to a “hard” (e.g. pure lex) term order.
The extended Gröbner factorizer involves, after change to dimension zero,
the computation of triangular systems. The corresponding module triang
4
Note that recovering the base ring this way may cause some trouble since the intermediate ring,
installed with setring, changed possibly the internal variable order set by setkorder.
284 CHAPTER 16. USER CONTRIBUTED PACKAGES
extends the facilities for zero dimensional ideals and modules in the module
odim.
4. dpmats now have a gb-tag that indicates, whether the given ideal or module
basis is already a Gröbner basis. This avoids certain Gröbner basis recompu-
tations especially during advanced algorithms as e.g. prime decomposition.
In the algebraic interface Gröbner bases are computed automatically when
needed rather than to issue an error message as in v. 2.1. So one can call mod-
equalp or dim etc. not having computed Gröbner bases in advance. Note that
such automatic computation can be avoided with setgbasis.
5. Hilbert series are now weighted Hilbert series, since e.g. for blow up rings
the generating ideal is multigraded. Usual Hilbert series are computed as in
v. 2.1 with respect to the ecart vector. Weighted Hilbert series accept a list
of (integer) weight lists as second parameter.
6. There are some name and conceptual changes to existing procedures and
variables to have a more concise semantic concept. This concerns
7. The revlex term order is now the reverse lexicographic term order on the
reversely ordered variables. This is consistent with other computer algebra
systems (e.g. SINGULAR or AXIOM)5 and implies the same order on the
variables for deglex and degrevlex term orders (this was the main reason to
change the definition).
8. Ideals of minors, pfaffians and related stuff are now implemented as exten-
sion of the internal matrix package and collected into a separate module
5
But different to the currently distibuted groebner package in REDUCE. Note that the compu-
tations in [15] were done before these changes.
285
calimat. Thus they allow more general expressions, especially with vari-
able exponents, as general REDUCE matrices do. So one can define generic
ideals as e.g. ideals of minors or pfaffians of matrices, containing generic
expressions as elements. They must be specified for further use in CALI
substituting general exponents by integers.
The main change concerns the primary decomposition algorithm, where I fixed a
serious bug for deciding, which embedded primes are really embedded6 . During
that remake I incorporated also the Gröbner factorizer to compute isolated primes.
Since REDUCE has no multivariate modular factorizer, the switch factorprimes
may be turned off to switch to the former algorithm.
Some minor bugs are fixed, too, e.g. the bug that made radical crashing.
This section gives a short introduction into the data type design of CALI at dif-
ferent levels. First (§1 and 2) we describe CALI’s way of algorithmic translation
of the abstract algebraic objects ring of polynomials, ideal and (finitely generated)
module. Then (§3 and 4) we describe the algebraic mode interface of CALI and
the switches and global variables to drive a session. In the next chapter we give a
more detailed overview of the basic (symbolic mode) data structures involved with
CALI. We refer to the appendix for a short summary of the commands available in
algebraic mode.
an ecart vector
A list of positive integers corresponding to the variable names.
A base ring may be defined (in algebraic mode) through the command
setring <ring>
with < ring > ::= { vars, tord, tag [, ecart ] } resp.
his sets the global (symbolic) variable cali!=basering. Here vars is the list of
variable names, tord a (possibly empty) list of weight lists, the degree vectors,
and tag the tag LEX or REVLEX. Optionally one can supply ecart, a list of
positive integers of the same length as vars, to set an ecart vector different from
the default one (see below).
The degree vectors must have the same length as vars. If (w1 . . . wk ) is the list
of degree vectors then
or
xa < xb :⇔ ∃ j ∀ i > j : ai = bi and aj > bj (revlex.)
degreeorder vars,
that returns tord = {{1, . . . , 1}}.
localorder vars,
that returns tord = {{−1, . . . , −1}} (a non Noetherian term order for compu-
tations in local rings).
eliminationorder(vars,elimvars),
that returns a term order for elimination of the variables in elimvars, a sub-
set of all vars. It’s recommended to combine it with the tag REVLEX.
blockorder(vars,integerlist),
that returns the list of degree vectors for the block order with block lengths
given in the integerlist. Note that these numbers should sum up to the
length of the variable list supplied as the first argument.
Examples:
vars:={x,y,z};
tord:=degreeorder vars; % Returns {{1,1,1}}.
setring(vars,tord,lex); % GRADLEX in the groebner package.
% or
% or
vars:={a,b,c,x,y,z};
tord:=eliminationorder(vars,{x,y,z});
tord:=reverse blockorder(vars,{3,3});
% Return both {{0,0,0,1,1,1},{1,1,1,0,0,0}}.
setring(vars,tord,revlex);
{{t,x,y,z},{{1,1,1,1}},revlex,{1,1,1,1}},
i.e. S = k[t, x, y, z] supplied with the degree wise reverse lexicographic term order.
getring m
returns the ring attached to the object with the identifier m. E.g.
288 CHAPTER 16. USER CONTRIBUTED PACKAGES
setring getring m
(re)sets the base ring to the base ring of the formerly defined object (ideal or
module) m.
getring()
returns the currently active base ring.
CALI defines also an ecart vector, attaching to each variable a positive weight with
respect to that homogenizations and related algorithms are executed. It may be set
optionally by the user during the setring command. (Default: If the term order is a
(positive) degree order then the ecart is the first degree vector, otherwise each ecart
equals 1).
The ecart vector is used in several places for efficiency reason (Gröbner basis com-
putation with the sugar strategy) or for termination (local standard bases). If the
input is homogeneous the ecart vector should reflect this homogeneity rather than
the first degree vector to obtain the best possible performance. For a discussion
of local computations with encoupled ecart vector see [13]. In general the ecart
vector is recommended to be chosen in such a way that the input examples become
close to be homogeneous. Homogenizations and Hilbert series are computed with
respect to this ecart vector.
f : S r −→ S c
f (v) := v · M for v ∈ S r .
There are two modules, connected with such a map, im f , the submodule of S c
generated by the rows of M , and coker f (= S c /im f ). Conceptually we will
identify M with im f for the basic algebra, and with coker f for more advanced
topics of commutative algebra (Hilbert series, dimension, resolution etc.) follow-
ing widely accepted conventions.
With respect to a fixed basis {e1 , . . . , ec } one can define module term orders on
S c , Gröbner bases of submodules of S c etc. They generalize the corresponding
notions for ideal bases. See [8] or [22] for a detailed introduction to this area of
computational commutative algebra. This allows to define joint facilities for both
289
ideals and submodules of free modules. Moreover computing syzygies the latter
come in in a natural way.
CALI handles ideal and module bases in a unique way representing them as rows
of a dpmat (distributive polynomial matrix). It attaches to each unit vector ei a
monomial xai , the i-th column degree and represents the rows of a dpmat M as
lists of module terms xa ei , sorted with respect to a module term order, that may be
roughly8 described as
or xa xai = xb xaj
and
i < j (lex.) resp. i > j (revlex.)
Every dpmat M has its own column degrees (no default !). They are managed
through a global (symbolic) variable cali!=degrees.
getdegrees m
returns the column degrees of the object with identifier m.
getdegrees()
returns the current setting of cali!=degrees.
To distinguish between ideals and modules the former are represented as a dpmat
with c = 0 (and hence without column degrees). If I ⊂ S is such an ideal one has
to distinguish between the ideal I (with c = 0, allowing special ideal operations as
e.g. ideal multiplication) and the submodule I of the free one dimensional module
S 1 (with c = 1, allowing matrix operations as e.g. transposition, matrix multiplica-
tion etc.). ideal2mat converts an (algebraic) list of polynomials into an (algebraic)
matrix column whereas mat2list collects all matrix entries into a list.
8
The correct definition is even more difficult.
290 CHAPTER 16. USER CONTRIBUTED PACKAGES
After the initialization of the base ring bounded identifiers for ideals or modules
should be declared via
setmodule(name,matrix value)
resp.
setideal(name,list of polynomials)
This way the corresponding internal representation (as dpmat) is attached to name
as the property basis, the prefix form as its value and the current base ring as the
property ring.
Performing any algebraic operation on objects defined this way their ring will be
compared with the current base ring (including the term order). If they are different
an error message occurs. If m is a valid name, after resetting the base ring
setmodule(m1,m)
reevaluates m with respect to the new base ring (since the value of m is its prefix
form) and assigns the reordered dpmat to m1 clearing all information previously
computed for m1 (m1 and m may coincide).
All computations are performed with respect to the ring S = k[xv ∈ vars] over
the field k. Nevertheless by efficiency reasons base coefficients are represented in
a denominator free way as standard forms. Hence the computational properties of
the base coefficient domain depend on the dmode and also on auxiliary variables,
contained in the expressions, but not in the variable list. They are assumed to be
parameters.
Best performance will be obtained with integer or modular domain modes, but one
can also try algebraic numbers as coefficients as e.g. generated by sqrt or the
291
We recommend to use setrules for computations with algebraic numbers since they
are better adapted to the data structure of CALI than the algebraic numbers pro-
vided by the arnum package. Note, that due to the zero decision problem compli-
cated setrules based computations may produce wrong results if base coefficient’s
pseudo division is involved (as e.g. with dp_pseudodivmod). In this case we rec-
ommend to enlarge the variable set and add the defining equations of the algebraic
numbers to the equations of the problem9 .
The standard domain (Integer) doesn’t allow denominators for input. setideal
clears automatically the common denominator of each input expression whereas
a polynomial matrix with true rational coefficients will be rejected by setmodule.
One can save/initialize ideal and module bases together with their accompanying
data (base ring, degrees) to/from a file:
savemat(m,name)
resp.
initmat name
execute the file transfer from/to disk files with the specified file name. e.g.
savemat(m,"myfile");
9
A qring facility for the computation over quotient rings will be incorporated into future versions.
292 CHAPTER 16. USER CONTRIBUTED PACKAGES
saves the base ring and the ideal basis of m to the file “myfile” whereas
setideal(m,initmat "myfile");
sets the current base ring (via a call to setring) to the base ring of m saved at
“myfile” and then recovers the basis of m from the same file.
There are several switches, (fluid) global variables, a trace facility, and global pa-
rameters on the property list of the package name cali to control CALI’s compu-
tations.
Switches
bcsimp
on: Cancel out gcd’s of base coefficients. (Default: on)
detectunits
on: replace polynomials of the form
hmonomiali∗hpolynomial uniti by hmonomiali during interreductions and
standard basis computations.
Affects only local computations. (Default: off)
factorprimes
on: Invoke the Gröbner factorizer during computation of isolated primes. (De-
fault: on). Note that REDUCE lacks a modular multivariate factorizer, hence
for modular prime decomposition computations this switch has to be turned
off.
factorunits
on: factor polynomials and remove polynomial unit factors during interreduc-
tions and standard basis computations.
Affects only local computations. (Default: off)
hardzerotest
on: try an additional algebraic simplification of base coefficients at each base
coefficient’s zero test. Useful only for advanced base coefficient domains with-
out canonical REDUCE representation. May slow down the computation dras-
tically. (Default: off)
293
lexefgb
on: Use the pure lexicographic term order and zerosolve during reduction to
dimension zero in the extended Gröbner factorizer. This is a single, but possi-
bly hard task compared to the degrevlex invocation of zerosolve1. See [16] for
a discussion of different zero dimensional solver strategies. (Default: off)
Noetherian
on: choose algorithms for Noetherian term orders.
off: choose algorithms for local term orders.
(Default: on)
red_total
on: compute total normal forms, i.e. apply reduction (Noetherian term orders)
or reduction with bounded ecart (non Noetherian term orders to tail terms of
polynomials, too.
off: Do only top reduction.
(Default: on)
setcalitrace <n>
changes the trace intensity. Set n = 2 for a sparse tracing (a dot for each
reduction step). Other good suggestions are the values 30 or 40 for tracing
the Gröbner algorithm or n > 70 for tracing the normal form algorithm. The
higher n the more intermediate information will be given.
setcaliprintterms <n>
sets the number of terms that are printed in intermediate polynomials. Note
that this does not affect the output of whole dpmats. The output of polynomials
with more than n terms (n > 0) breaks off and continues with ellipses.
clearcaliprintterms()
clears the printterms value forcing full intermediate output (according to
the current trace level).
Global Variables
cali!=basering
294 CHAPTER 16. USER CONTRIBUTED PACKAGES
cali!=degrees
The currently active module component degrees initialized e.g. by setdegrees.
cali!=monset
A list of variable names considered as non zero divisors during Gröbner ba-
sis computations initialized e.g. by setmonset. Useful e.g. for binomial ideals
defining monomial varieties or other prime ideals.
Entries on the Property List of cali This approach is new for v. 2.2. Infor-
mation concerning the state of the computational model as e.g. trace intensity, base
coefficient rules, or algorithm versions are stored as values on the property list of
the package name cali. This concerns
efgb
Changed by the switch lexefgb.
groeb!=rf
Reduction function invoked during the Gröbner algorithm. It can be changed
with gbtestversion < n > (n = 1, 2, 3, default is 1).
hf!=hf
Variant for the computation of the Hilbert series numerator. It can be changed
with hftestversion < n > (n = 1, 2, default is 1).
rules
Algebraic “replaceby” rules introduced to CALI with the setrules command.
In the following we describe the data structure layers underlying the dpmat rep-
resentation in CALI and some important (symbolic) procedures to handle them.
295
We refer to the source code and the comments therein for a more complete survey
about the procedures available for different data types.
Base coefficients as implemented in the module bcsf are standard forms in the vari-
ables outside the variable list of the current ring. All computations are executed
"denominator free" over the corresponding quotient field, i.e. gcd’s are canceled
out without request. To avoid this set the switch bcsimp off.10 In the given imple-
mentation we use the s.f. procedure qremf for effective divisibility test. We had
some trouble with it under on factor.
Additionally it is possible to supply the parameters occuring as base coefficients
with a (global) set of algebraic rules.11
setrules!* r
converts an algebraic mode rules list r as e.g. used in WHERE statements into
the internal CALI format.
The base ring is defined by its name list, the degree matrix (a list of lists
of integers), the ring tag (LEX or REVLEX), and the ecart. The name list
contains a phantom name cali!=mk for the module component at place 0.
The module ring exports among others the selectors ring_names, ring_degrees,
ring_tag, ring_ecart, the test function ring_isnoetherian and the transfer pro-
cedures from/to an (appropriate, printable by mathprint) algebraic prefix form
ring_from_a (including extensive tests of the supplied parameters for consistency)
and ring_2a.
The following procedures allow to define a base ring:
10
This induces a rapid base coefficient’s growth and doesn’t yield Z-Gröbner bases in the sense of
[10] since the S-pair criteria are different.
11
This is different from the LET rule mechanism since they must be present in symbolic mode.
Hence for a simultaneous application of the same rules in algebraic mode outside CALI they must
additionally be declared in the usual way.
296 CHAPTER 16. USER CONTRIBUTED PACKAGES
setring!* <ring>
sets cali!=basering and checks for consistency with the switch Noetherian. It
also sets through setkorder the current variable list as main variables. It is
strongly recommended to use setring!* . . . instead of cali!=basering:=. . . .
ring_sum(a,b)
returns a ring, that is constructed in the following way: Its variable list is the
union of the (disjoint) lists of the variables of the rings a and b (in this order)
whereas the degree list is the union of the (appropriately shifted) degree lists of
b and a (inLthis order). The ring tag is that of a. Hence it returns (essentially)
the ring b a if b has a degree part (e.g. useful Lfor elimination problems,
introducing “big” new variables) and the ring a b if b has no degree part
(introducing “small” new variables).
ring_rlp(r,u)
u is a subset of the names of the ring r. Returns the ring r, but with a term
order “first degrevlex on u, then the order on r”.
ring_lp(r,u)
As rlp, but with a term order “first lex on u, then the order on r”.
Example:
vars:=’(x y z)
setring!* ring_define(vars,degreeorder!* vars,’lex,’(1 1 1));
% GRADLEX in the groebner package.
Monomials
As procedures there are selectors for the module component, the exponent and
the degree parts, comparison procedures, procedures for the management of the
module component and the degree vector, monomial arithmetic, transfer from/to
prefix form, and more special tools.
CALI uses a distributive representation as a list of terms for both polynomials and
polynomial vectors, where a term is a dotted pair
(< monomial > . < base coef f icient >).
P
The ecart of a polynomial (vector) f = ti with (module) terms ti is defined as
max(ec(ti )) − ec(lt(ti )),
see [13]. Here ec(ti ) denotes the ecart of the term ti , i.e. the scalar product of the
exponent vector of ti (including the monomial weight of the module generator)
with the ecart vector of the current base ring.
As procedures there are selectors, dpoly arithmetic including the management of
the module component, procedures for reordering (and reevaluating) polynomials
wrt. new term order degrees, for extracting common base coefficient or monomial
factors, for transfer from/to prefix form and for homogenization and dehomoge-
nization (wrt. the current ecart vector).
Two advanced procedures use ideal theory ingredients:
dp_pseudodivmod(g,f)
returns a dpoly list {q, r, z} such that z · g = q · f + r and z is a dpoly unit
(i.e. a scalar for Noetherian term orders). For non Noetherian term orders the
necessary modifications are described in [14].
g, f and r belong to the same free module or ideal.
dpgcd(a,b)
computes the gcd of two dpolys a and b by the syzygy method: The syzygy
module of {a, b} is generated by a single element [−b0 a0 ] with a = ga0 , b =
gb0 , where g is the gcd of a and b. Since it uses dpoly pseudodivision it may
work not properly with setrules.
298 CHAPTER 16. USER CONTRIBUTED PACKAGES
Base Lists
Ideal bases are one of the main ingredients for dpmats. They are represented as
lists of base elements and contain together with each dpoly entry the following
information:
• the dpoly, its ecart (as the main sort criterion), and length.
The representation part is managed during normal form computations and other
row arithmetic of dpmats appropriately with the following procedures:
bas_setrelations b
sets the relation part of the base element i in the base list b to ei .
bas_removerelations b
removes all relations, i.e. replaces them with the zero polynomial vector.
bas_getrelations b
gets the relation part of b as a separate base list.
Further there are procedures for selection and construction of base elements and for
the manipulation of lists of base elements as e.g. sorting, renumbering, reordering,
simplification, deleting zero base elements, transfer from/to prefix form, homoge-
nization and dehomogenization.
Dpoly Matrices
Ideals and matrices, represented as dpmats, are the central data type of the CALI
package, as already explained above. Every dpmat m combines the following in-
formation:
The module dpmat contains selectors, constructors, and the algorithms for the basic
management of this data structure as e.g. file transfer, transfer from/to algebraic
prefix forms, reordering, simplification, extracting row degrees and leading terms,
dpmat matrix arithmetic, homogenization and dehomogenization.
The modules matop and quot collect more advanced procedures for the algebraic
management of dpmats.
In v. 2.2 minors, Jacobian matrix, and Pfaffians are available for general REDUCE
matrices. They are collected in the module calimat and allow to define procedures
in more generality, especially allowing variable exponents in polynomial expres-
sions. Such a generalization is especially useful for the investigation of whole
classes of examples that may be obtained from a generic one by specialization. In
the following m is a matrix given in algebraic prefix form.
matjac(m,l)
returns the Jacobian matrix of the ideal m (given as an algebraic mode list)
with respect to the variable list l.
minors(m,k)
returns the matrix of k-minors of the matrix m.
ideal_of_minors(m,k)
returns the ideal of the k-minors of the matrix m.
pfaffian m
returns the pfaffian of a skewsymmetric matrix m.
ideal_of_pfaffians(m,k)
returns the ideal of the 2k-pfaffians of the skewsymmetric matrix m.
random_linear_form(vars,bound)
returns a random linear form in algebraic prefix form in the supplied variables
vars with integer coefficients bounded by the supplied bound.
300 CHAPTER 16. USER CONTRIBUTED PACKAGES
singular_locus!*(m,c)
returns the singular locus of m (as dpmat). m must be an ideal of codimension
c given as a list of polynomials in prefix form. Singular_locus computes
the ideal generated by the corresponding Jacobian and m itself.
Below we give a short explanation of the main algorithmic ideas of CALI and the
way they are implemented and may be accessed (symbolically).
Normal form algorithms reduce polynomials (or polynomial vectors) with respect
to a given finite set of generators of an ideal or module. The result is not unique ex-
cept for a total normal form with respect to a Gröbner basis. Furthermore different
reduction strategies may yield significant differences in computing time.
CALI reduces by first matching, usually keeping base lists sorted with respect to
the sort predicate red_better. In v. 2.2 we sort solely by the dpoly length, since
the introduction of red_TopRedBE, i.e. reduction with bounded ecart, guarantees
termination also for non Noetherian term orders. Overload red_better for other
reduction strategies.
The main procedures of the newly designed reduction package are the following:
red_TopRedBE(bas,model)
Top reduction with bounded ecart of the base element model by the base list
bas, i.e. only reducing the top term and only with base elements with ecart
bounded by that of model.
red_TopRed(bas,model)
Top reduction of model, but without restrictions.
red_TailRed(bas,model)
Make tail reduction on model, i.e. top reduction on the tail terms. For conver-
gence this uses reduction with bounded ecart for non Noetherian term orders
and full reduction otherwise.
red_TopInterreduce bas
Reduces the base list bas with red_T opRed until it has pairwise incompa-
rable leading terms, computes correct representation parts, but does no tail
reduction.
red_Interreduce bas
Does top and, if on red_total, also tail interreduction on the base list bas.
Usually, e.g. for ideal generation problems, there is no need to care about the mul-
tiplier u. If nevertheless one needs its value, the base element f may be prepared
with red_prepare to collect this information in the 0-slot of its representation part.
Extract this information with red_extract.
red_redpol(bas,model)
combines this tool with a total reduction of the base element model and returns
a dotted pair
(< reduced model > . < dpoly unit multiplier >).
302 CHAPTER 16. USER CONTRIBUTED PACKAGES
interreduce!* m
that returns an interreduced basis of the dpmat m.
mod!*(f,m)
that returns the dotted pair (h.u) where h is the pseudo normal form of the
dpoly f modulo the dpmat m and u the corresponding polynomial unit multi-
plier.
normalform!*(a,b)
that returns {a1 , r, z} with a1 = z ∗ a − r ∗ b where the rows of the dpmat a1
are the normalforms of the rows of the dpmat a with respect to the dpmat b.
For local standard bases the ideal generated by the basic polynomials may have
components not passing through the origin. Although they do not contribute to the
ideal in Loc(S) = Sm they usually heavily increase the necessary computational
effort. Hence for local term orders one should try to remove polynomial units
as soon as they are detected. To remove them from base elements in an early
stage of the computation one can either try the (cheap) test, whether f ∈ S is of
the form hmonomiali ∗ hpolynomial uniti or factor f completely and remove
polynomial unit factors. For base elements this may be done with bas_detectunits
or bas_factorunits.
Moreover there are two switches detectunits and factorunits, both off by default,
that force such automatic simplifications during more advanced computations.
The procedure deleteunits!* tries explicitely to factor the basis polynomials of a
dpmat and to remove polynomial units occuring as one of the factors.
There is now a unique module groeb that contains the Gröbner resp. standard basis
algorithms with syzygy computation facility and related topics. There are common
procedures (working for both Noetherian and non Noetherian term orders)
gbasis!* m
that returns a minimal Gröbner or standard basis of the dpmat m,
syzygies!* m
that returns an interreduced basis of the first syzygy module of the dpmat m
and
303
syzygies1!* m
that returns a (not yet interreduced) basis of the syzygy module of the dpmat
m.
These procedures start the outer Gröbner engine (now also common for both
Noetherian and non Noetherian term orders)
groeb_stbasis(m,mgb,ch,syz)
The next layer manages the preparation of the representation parts of the base el-
ements to carry the syzygy information, calls the general internal driver, and ex-
tracts the relevant information from the result of that computation. The general
internal driver branches according to different reduction functions into several ver-
sions. Upto now there are three different strategies for the reduction procedures for
the S-polynomial reduction (different versions may be chosen via gbtestversion):
1. Total reduction with local simplifier lists. For local term orders this is (al-
most) Mora’s first version for the tangent cone (the default).
2. Total reduction with global simplifier list. For local term orders this is (al-
most) Mora’s SimpStBasis, see [26].
The first two versions (almost) coincide for Noetherian term orders. The third
version reduces only with bounded ecart, thus forcing more pairs to be treated than
necessary, but usually less expensive to be reduced. It is not yet well understood,
whether this idea is of practical importance.
groeb_lazystbasis calls the lazy standard basis driver instead, that implements
Mora’s lazy algorithm, see [26]. As groeb_homstbasis, the computation of Gröb-
ner and standard bases via homogenization (Lazard’s approach), it is not fully in-
tegrated into the algebraic interface. Use
homstbasis!* m
for the invocation of the homogenization approach to compute a standard basis
of the dpmat m and
304 CHAPTER 16. USER CONTRIBUTED PACKAGES
lazystbasis!* m
for the lazy algorithm.
Experts commonly agree that the classical approach is better for “computable”
examples, but computations done by the author on large examples indicate, that
both approaches are in fact independent.
The pair list management uses the sugar strategy, see [11], with respect to the
current ecart vector. If the input is homogeneous and the ecart vector reflects this
homogeneity then pairs are sorted by ascending degree. Hence no superfluous base
elements will be computed in this case. In general the sugar strategy performs best
if the ecart vector is chosen to make the input close to be homogeneous.
There is another global variable cali!=monset that may contain a list of vari-
able names (a subset of the variable names of the current base ring). During the
“pure” Gröbner algorithm (without syzygy and representation computations) com-
mon monomial factors containing only these variables will be canceled out. This
shortcut is useful if some of the variables are known to be non zero divisors as e.g.
in most implicitation problems.
setmonset!* vars
initializes cali!=monset with a given list of variables vars.
The Gröbner tools as e.g. pair criteria, pair list update, pair management and S-
polynomial construction are available.
groeb_mingb m
extracts a minimal Gröbner basis from the dpmat m, removing base elements
with leading terms, divisible by other leading terms.
groeb_minimize(bas,syz)
minimizes the dpmat pair (bas, syz) deleting superfluous base elements from
bas using syzygies from syz containing unit entries.
Q
Its Zariski closure is the zero set of I(B) :< C >.
The Gröbner factorizer solves the following problem:
The module groebf and the module triang contain algorithms related to that prob-
lem, triangular systems, and their generalizations as described in [15] and [16].
V. 2.2 thus heavily extends the algorithmic possibilities that were implemented in
former releases of CALI.
Note that, different to v. 2.1, we work with constraint lists.
groebfactor!*(bas,con)
returns for the dpmat ideal bas and the constraint list con (of dpolys) a minimal
list of (dpmat, constraint list) pairs with the desired property.
listgroebfactor!* l
proceeds a whole list of dpmats (without constraints) at once and strips off
constraints at the end.
The postprocessing involves a change to dimension zero and invokes (zero dimen-
sional) triangular system computations from the module triang. In a first step
groebf_zeroprimes1 incorporates the square free parts of certain univariate poly-
nomials into these systems and strips off the constraints (since relative sets of ze-
roes in dimension zero are Zariski closed), using a splitting approach analogous
to the Gröbner factorizer. In a second step, according to the switch lexefgb, either
zerosolve!* or zerosolve1!* converts these intermediate results into lists of trian-
gular systems in prefix form. If lexefgb is off (the default), the zero dimensional
term order is degrevlex and zerosolve1!*, the “slow turn to lex” is involved, for
on lexefgb the pure lexicographic term order and zerosolve!*, Möllers original
approach, see [23], are used. Note that for this term order we need only a single
Gröbner basis computation at this level.
A third version, zerosolve2!*, mixes the first approach with the FGLM change of
term orders. It is not incorporated into the extended Gröbner factorizer.
Gröbner and local standard bases are the heart of several basic algorithms in ideal
theory, see e.g. [2, 6.2.]. CALI offers the following facilities:
submodulep!*(m,n)
tests the dpmat m for being a submodule of the dpmat n reducing the basis
elements of m with respect to n. The result will be correct provided n is a
Gröbner basis.
modequalp!*(m,n)
= submodulep!*(m,n) and submodulep!*(n,m).
eliminate!*(m,<variable list>)
307
CALI offers several quotient algorithms. They rest on the computation of quotients
by a single element of the following kind: Assume M ⊂ S c , v ∈ S c , f ∈ S. Then
there are
CALI uses the elimination approach [7, 4.4.] and [2, 6.38] for their computation:
matquot!*(M,f)
returns the module or ideal quotient M : (f ) depending on f .
matqquot!*(M,f)
returns the stable quotient M : (f )∞ .
dp_pseudodivmod(g,f)
that returns a dpoly list {q, r, z} such that z · g = q · f + r with a dpoly unit
z. (g, f and r must belong to the same free module). This is done uniformly
for noetherian and local term orders with an extended normal form algorithm
as described in [14].
In the same way one defines the quotient of a module by another module (both
embedded in a common free module S c ), the quotient of a module by an ideal, and
the stable quotient of a module by an ideal. Algorithms for their computation can
be obtained from the corresponding algorithms for a single element as divisor either
by the generic element method [8] or as an intersection [2, 6.31]. CALI offers both
approaches (X=1 or 2 below) at the symbolic level, but for true quotients only the
latter one is integrated into the algebraic mode interface.
12
This can be done for ideals and modules in an unique way. Hence idealintersect!* has been
removed in v. 2.1.
308 CHAPTER 16. USER CONTRIBUTED PACKAGES
idealquotientX!*(M,I)
returns the ideal quotient M : I of the dpmat M by the dpmat ideal I.
modulequotientX!*(M,N)
returns the module quotient M : N of the dpmat M by the dpmat N .
annihilatorX!* M
returns the annihilator of coker M , i.e. the module quotient S c : M , if M is a
submodule of S c .
matstabquot!*(M,I)
returns the stable quotient M : I ∞ (only by the general element method).
Monomial Ideals
Monomial ideals occur as ideals of leading terms of (ideal’s) Gröbner bases and
also as components of leading term modules of submodules of free modules, see
[12], and reflect some properties of the original ideal/module. Several parameters
of the original ideal or module may be read off from it as e.g. dimension and Hilbert
series.
The module moid contains the corresponding algorithms on monomial ideals.
Monomial ideals are lists of monomials, kept sorted by descending lexicographic
order as proposed in [1].
moid_primes u
returns the minimal primes (as a list of lists of variable names) of the monomial
ideal u using an adaption of the algorithm, proposed in [1] for the computation
of the codimension.
indepvarsets!* m
returns (based on moid_primes) the list of strongly independent sets of m, see
[19] and [12] for definitions.
dim!* m
returns the dimension of coker m as the size of the largest independent set.
codim!* m
returns the codimension of coker m.
309
easyindepset!* m
returns a maximal with respect to inclusion independent set of m.
easydim!* m
is a fast dimension algorithm (based on easyindepset), that will be correct if m
is (radically) unmixed. Since it is significantly faster than the general dimen-
sion algorithm13 , it should be used, if all maximal independent sets are known
to be of equal cardinality (as e.g. for prime or unmixed ideals, see [12]).
Hilbert Series
CALI v. 2.2 now offers also weighted Hilbert series, i.e. series that may reflect
multihomogeneity of ideals and modules. For this purpose a weighted Hilbert se-
ries has a list of (integer) degree vectors as second parameter, and the ideal(s) of
leading terms are evaluated wrt. these weights. For the output and polynomial
arithmetic, involved during the computation of the Hilbert series numerator, the
different weight levels are mapped onto the first variables of the current ring. If
w is such a weight vector list and I is a monomial ideal in the polynomial ring
S = k[xv : v ∈ V ] we get (using multi exponent notation)
X Q(t)
H(S/I, t) := |{xa 6∈ I : w(a) = α}| · tα = Q
α v∈V 1 − tw(xv )
hf_whilb(m,w)
returns the weighted Hilbert series numerator Q(t) of m according to the ver-
sion chosen with hftestversion.
13
This algorithm is of linear time as opposed to the problem to determine the dimension of an
arbitrary monomial ideal, that is known to be NP-hard in the number of variables, see [1].
310 CHAPTER 16. USER CONTRIBUTED PACKAGES
WeightedHilbertSeries!*(m,w)
returns the weighted Hilbert series reduced rational function of m as s.q.
HilbertSeries!*(m,w)
returns the Hilbert series reduced rational function of m wrt. the ecart vector
of the current ring as s.q.
hf_whilb3(u,w) and hf_whs_from_resolution(u,w)
compute the weighted Hilbert series numerator and the corresponding reduced
rational function from (the column degrees of) a given resolution u.
degree!* m
returns the value of the numerator of the reduced Hilbert series of m at t = 1.
i.e. the sum of its coefficients. For the standard ecart this is the degree of
coker m.
Resolutions
Resolve!*(m,d)
computes a minimal resolution of the dpmat m, i.e. a list of dpmats
{s0 , s1 , s2 , . . .}, where sk is the k-th syzygy module of m, upto part sd .
BettiNumbers!* c and GradedBettiNumbers!* c
returns the Betti numbers resp. the graded Betti numbers of the resolution c, i.e.
the list of the lengths resp. the degree lists (according to the ecart) themselves
of the dpmats in c.
There are several algorithms that either force the reduction of a given problem to
dimension zero or work only for zero dimensional ideals or modules. The module
odim offers such algorithms. It contains, e.g.
311
dimzerop!* m
that tests a dpmat m for being zero dimensional.
getkbase!* m
that returns a (monomial) k-vector space basis of Coker m provided m is a
Gröbner basis.
odim_borderbasis m
that returns a border basis, see [20], of the zero dimensional dpmat m as a list
of base elements.
odim_parameter m
that returns a parameter of the dpmat m, i.e. a variable x ∈ vars such that
k[x] Ann S c /m = (0), or nil if m is zero dimensional.
T
odim_up(a,m)
that returns an univariate polynomial (of smallest possible degree if m is a
gbasis) in the variable a, that belongs to the zero dimensional dpmat ideal m,
using Buchberger’s approach [5].
The algorithms of the module prime implement the ideas of [10] with modifica-
tions along [18] and their natural generalizations to modules as e.g. explained in
[28]. Version 2.2.1 fixes a serious bug detecting superfluous embedded primary
components, see section 16.9.1, and contains now a second primary decomposition
algorithm, based on ideal separation, as standard. For a discussion about embedded
primes and the ideal separation approach, see [17].
CALI contains also algorithms for the computation of the unmixed part of a given
module and the unmixed radical of a given ideal (along the same lines). We fol-
lowed the stepwise recursion decreasing dimension in each step by 1 as proposed in
(the final version of) [10] rather than the “one step” method described in [2] since
handling leading coefficients, i.e. standard forms, depending on several variables
is a quite hard job for REDUCE14 .
In the following procedures m must be a Gröbner basis.
zeroradical!* m
returns the radical of the zero dimensional ideal m, using squarefree decom-
position of univariate polynomials.
14
prime!=decompose2 implements this strategy in the symbolic mode layer.
312 CHAPTER 16. USER CONTRIBUTED PACKAGES
zeroprimes!* m
computes as in [10] the list of prime ideals of Ann F/M if m is zero dimen-
sional, using the (sparse) general position argument from [19].
zeroprimarydecomposition!* m
computes the primary components of the zero dimensional dpmat m using
prime splitting with the prime ideals of Ann F/M . It returns a list of pairs
with first entry the primary component and second entry the corresponding
associated prime ideal.
isprime!* m
a (one step) primality test for ideals, extracted from [10].
isolatedprimes!* m
computes (only) the isolated prime ideals of Ann F/M .
radical!* m
computes the radical of the dpmat ideal m, reducing as in [10] to the zero
dimensional case.
easyprimarydecomposition!* m
computes the primary components of the dpmat m, if it has no embedded
components. The algorithm uses prime splitting with the isolated prime ideals
of Ann F/M . It returns a list of pairs as in zeroprimarydecomposition!*.
primarydecomposition!* m
computes the primary components of the dpmat m along the lines of [10]. It
returns a list of two-element lists as in zeroprimarydecomposition!*.
unmixedradical!* m
returns the unmixed radical, i.e. the intersection of the isolated primes of top
dimension, associated to the dpmat ideal m.
eqhull!* m
returns the equidimensional hull, i.e. the intersection of the top dimensional
primary components of the dpmat m.
Advanced Algorithms
The module scripts just under further development offers some advanced topics of
the Gröbner bases theory. It introduces the new data structure of a map between
base rings:
313
A ring map
φ : R −→ S
for R = k[ri ], S = k[sj ] is represented in symbolic mode as a list
preimage!*(m,map)
computes the preimage of the ideal m in algebraic prefix form under the given
polynomial map and sets the current base ring to the preimage ring. Returns
the result also in algebraic prefix form.
ratpreimage!*(m,map)
computes the closure of the preimage of the ideal m in algebraic prefix form
under the given rational map and sets the current base ring to the preimage
ring. Returns the result also in algebraic prefix form.
affine_monomial_curve!*(l,vars)
l is a list of integers, vars a list of variable names of the same length as l. The
procedure sets the current base ring and returns the defining ideal of the affine
monomial curve with generic point (ti : i ∈ l) computing the corresponding
preimage.
analytic_spread!* M
Computes the analytic spread of M , i.e. the dimension of the exceptional fiber
R(M )/mR(M ) of the blowup along M over the irrelevant ideal m of the
current base ring.
assgrad!*(M,N,vars)
314 CHAPTER 16. USER CONTRIBUTED PACKAGES
over the ring R = S/M , where M and N are dpmat ideals defined over the cur-
rent base ring S. vars is a list of new variable names one for each generator
of N . They are used to create a second ring T with degree order corresponding
to the ecart of the row degrees of N and a ring map
φ : S ⊕ T −→ S.
φ : S ⊕ R −→ S.
It returns a dpmat ideal J such that (S ⊕R)/J is the desired symmetric algebra
over the new current base ring S ⊕ R.
minimal_generators!* m
315
returns a set of minimal generators of the dpmat m inspecting the first syzygy
module.
nzdp!*(f,m)
tests whether the dpoly f is a non zero divisor on coker m. m must be a
Gröbner basis.
symbolic_power!*(m,d)
returns the dth symbolic power of the prime dpmat ideal m as the equidimen-
sional hull of the dth true power. (Hence applies also to unmixed ideals.)
varopt!* m
finds a heuristically optimal variable order by the approach in [4] and returns
the corresponding list of variables.
Dual Bases
For the general ideas underlying the dual bases approach see e.g. [20]. This pa-
per explains, that constructive problems from very different areas of commutative
algebra can be formulated in a unified way as the computation of a basis for the
intersection of the kernels of a finite number of linear functionals generating a dual
S-module. Our implementation honours this point of view, presenting two gen-
eral drivers dualbases and dualhbases for the computation of such bases (even as
submodules of a free module M = S m ) with affine resp. projective dimension
zero.
Such a collection of N linear functionals
L : M = S m −→ k N
varlessp. Different applications need more entries on the property list of cali
to manage the communication between the driver and the calling routine.
dualhbases realizes the same idea for (homogeneous) ideals and modules of (pro-
jective) dimension zero. It produces zerodimensional “slices” with ascending de-
gree until it reaches a supremum supplied by the user, see [20] for details.
affine_points!* m
m is a matrix of domain elements (in algebraic prefix form) with as many
columns as the current base ring has ring variables. This procedure returns the
defining ideal of the collection of points in affine space with coordinates given
by the rows of m. Note that m may contain parameters. In this case k is treated
as rational function field.
change_termorder!*(m,r) and change_termorder1!*(m,r)
m is a Gröbner basis of a zero dimensional ideal wrt. the current base ring.
These procedures change the current ring to r and compute the Gröbner basis
of m wrt. the new ring r. The former uses a precomputed border basis.
proj_points!* m
m is a matrix of domain elements (in algebraic prefix form) with as many
columns as the current base ring has ring variables. This procedure returns
the defining ideal of the collection of points in projective space with ho-
mogeneous coordinates given by the rows of m. Note that m may as for
affine_points contain parameters.
resolution. For the mechanism of bounded identifier see the section “Algebraic
Mode Interface”.
affine_monomial_curve(l,vars)
l is a list of integers, vars a list of variable names of the same length as l. The
procedure sets the current base ring and returns the defining ideal of the affine
monomial curve with generic point (ti : i ∈ l).
affine_points m
m is a matrix of domain elements (in algebraic prefix form) with as many
columns as the current base ring has ring variables. This procedure returns the
defining ideal of the collection of points in affine space with coordinates given
by the rows of m. Note that m may contain parameters. In this case k is treated
as rational function field.
analytic_spread m
Computes the analytic spread of m.
annihilator m
returns the annihilator of the dpmat m ⊆ S c , i.e. Ann S c /M .
assgrad(M,N,vars)
Computes the associated graded ring grR (N ) over R = S/M , where S is the
current base ring. vars is a list of new variable names, one for each generator
of N . They are used to create a second ring T to return an ideal J such that
(S ⊕ T )/J is the desired associated graded ring over the new current base ring
S ⊕ T.
bettiNumbers gbr
extracts the list of Betti numbers from the resolution of gbr.
blowup(M,N,vars)
Computes the blow up R(N ) of N over the ring R = S/M , where S is the
current base ring. vars is a list of new variable names, one for each generator
of N . They are used to create a second ring T to return an ideal J such that
(S ⊕ T )/J is the desired blowup ring over the new current base ring S ⊕ T .
change_termorder(m,r) and change_termorder1(m,r)
Change the current ring to r and compute the Gröbner basis of m wrt. the
new ring r by the FGLM approach. The former uses internally a precomputed
border basis.
318 CHAPTER 16. USER CONTRIBUTED PACKAGES
codim gb
returns the codimension of S c /gb.
degree gb
returns the multiplicity of gb as the sum of the coefficients of the (classical)
Hilbert series numerator.
degsfromresolution gbr
returns the list of column degrees from the minimal resolution of gbr.
deleteunits m
factors each basis element of the dpmat ideal m and removes factors that are
polynomial units. Applies only to non Noetherian term orders.
dim gb
returns the dimension of S c /gb.
dimzerop gb
tests whether S c /gb is zerodimensional.
directsum(m1,m2,...)
returns the direct sum of the modules m1, m2, . . ., embedded into the direct
sum of the corresponding free modules.
dpgcd(f,g)
returns the gcd of two polynomials f and g, computed by the syzygy method.
eliminate(m,<variable list>)
computes the elimination ideal/module eliminating the variables in the given
variable list (a subset of the variables of the current base ring). Changes tem-
porarily the term order to degrevlex.
eqhull m
returns the equidimensional hull of the dpmat m.
getkbase gb
returns a k-vector space basis of S c /gb, consisting of module terms, provided
gb is zerodimensional.
getleadterms gb
returns the dpmat of leading terms of a Gröbner resp. local standard basis of
gb.
GradedBettinumbers gbr
extracts the list of degree lists of the free summands in a minimal resolution of
gbr.
groebfactor(m[,c])
returns for the dpmat ideal m and an optional constraint list c a (reduced) list
of dpmats such that the union of their zeroes is exactly Z(m, c). Factors all
polynomials involved in the Gröbner algorithms of the partial results.
HilbertSeries gb
returns the Hilbert series of gb with respect to the current ecart vector.
homstbasis m
computes the standard basis of m by Lazard’s homogenization approach.
320 CHAPTER 16. USER CONTRIBUTED PACKAGES
ideal2mat m
converts the ideal (=list of polynomials) m into a column vector.
ideal_of_minors(mat,k)
computes the generators for the ideal of k-minors of the matrix mat.
ideal_of_pfaffians(mat,k)
computes the generators for the ideal of the 2k-pfaffians of the skewsymmetric
matrix mat.
idealpower(m,n)
returns the interreduced basis of the ideal power mn with respect to the integer
n ≥ 0.
idealprod(m1,m2,...)
returns the interreduced basis of the ideal product m1 · m2 · . . . of the ideals
m1, m2, . . ..
idealquotient(m1,m2)
returns the ideal quotient m1 : m2 of the module m1 ⊆ S c by the ideal m2.
idealsum(m1,m2,...)
returns the interreduced basis of the ideal sum m1 + m2 + . . ..
indepvarsets gb
returns the list of strongly independent sets of gb with respect to the current
term order, see [19] for a definition in the case of ideals and [12] for submod-
ules of free modules.
initmat(m,<file name>
initializes the dpmat m together with its base ring, term order and column
degrees from a file.
interreduce m
returns the interreduced module basis given by the rows of m, i.e. a basis with
pairwise indivisible leading terms.
isolatedprimes m
returns the list of isolated primes of the dpmat m, i.e. the isolated primes of
Ann S c /M .
321
isprime gb
tests the ideal gb to be prime.
iszeroradical gb
tests the zerodimensional ideal gb to be radical.
lazystbasis m
computes the standard basis of m by the lazy algorithm, see e.g. [26].
listgroebfactor in
computes for the list in of ideal bases
S a list out of Gröbner
S bases by the Gröb-
ner factorization method, such that m∈in Z(m) = m∈out Z(m).
mat2list m
converts the matrix m into a list of its entries.
matappend(m1,m2,...)
collects the rows of the dpmats m1, m2, . . . to a common matrix. m1, m2, . . .
must be submodules of the same free module, i.e. have equal column degrees
(and size).
mathomogenize(m,var) 18
matjac(m,<variable list>)
returns the Jacobian matrix of the ideal m with respect to the supplied variable
list
matqquot(m,f)
returns the stable quotient m : (f )∞ of the dpmat m by the polynomial f ∈ S.
matquot(m,f)
returns the quotient m : (f ) of the dpmat m by the polynomial f ∈ S.
18
Dehomogenize with sub(z=1,m) if z is the homogenizing variable.
322 CHAPTER 16. USER CONTRIBUTED PACKAGES
matstabquot(m1,id)
returns the stable quotient m1 : id∞ of the dpmat m1 by the ideal id.
matsum(m1,m2,...)
returns the interreduced basis of the module sum m1 + m2 + . . . in a common
free module.
minimal_generators m
returns a set of minimal generators of the dpmat m.
minors(m,b)
returns the matrix of minors of size b × b of the matrix m.
a mod m
computes the (true) normal form(s), i.e. a standard quotient representation, of
a modulo the dpmat m. a may be either a polynomial or a polynomial list
(c = 0) or a matrix (c > 0) of the correct number of columns.
modequalp(gb1,gb2)
tests, whether gb1 and gb2 are equal (returns YES or NO).
modulequotient(m1,m2)
returns the module quotient m1 : m2 of two dpmats m1, m2 in a common free
module.
normalform(m1,m2)
returns a list of three dpmats {m3, r, z}, where m3 is the normalform of m1
modulo m2, z a scalar matrix of polynomial units (i.e. polynomials of degree
0 in the noetherian case and polynomials with leading term of degree 0 in the
tangent cone case), and r the relation matrix, such that
m3 = z ∗ m1 + r ∗ m2.
nzdp(f,m)
tests whether the dpoly f is a non zero divisor on coker m.
pfaffian mat
returns the pfaffian of a skewsymmetric matrix mat.
323
preimage(m,map)
computes the preimage of the ideal m under the given polynomial map and
sets the current base ring to the preimage ring.
primarydecomposition m
returns the primary decomposition of the dpmat m as a list of
{component, associated prime} pairs.
proj_monomial_curve(l,vars)
l is a list of integers, vars a list of variable names of the same length as l.
The procedure sets the current base ring and returns the defining ideal of the
projective monomial curve with generic point (sd−i · ti : i ∈ l) in R where
d = max{x : x ∈ l}.
proj_points m
m is a matrix of domain elements (in algebraic prefix form) with as many
columns as the current base ring has ring variables. This procedure returns
the defining ideal of the collection of points in projective space with ho-
mogeneous coordinates given by the rows of m. Note that m may as for
affine_points contain parameters.
radical m
returns the radical of the dpmat ideal m.
random_linear_form(vars,bound)
returns a random linear form in the variables vars with integer coefficients
less than the supplied bound.
ratpreimage(m,map)
computes the closure of the preimage of the ideal m under the given rational
map and sets the current base ring to the preimage ring.
resolve(m[,d])
returns the first d members of the minimal resolution of the bounded identifier
m as a list of matrices. If the resolution has less than d non zero members,
only those are collected. (Default: d = 100)
savemat(m,<file name>)
save the dpmat m together with the settings of it base ring, term order and
column degrees to a file.
324 CHAPTER 16. USER CONTRIBUTED PACKAGES
setgbasis m
declares the rows of the bounded identifier m to be already a Gröbner resp. lo-
cal standard basis thus avoiding a possibly time consuming Gröbner or stand-
ard basis computation.
sieve(m,<variable list>)
sieves out all base elements with leading terms having a factor contained in
the specified variable list (a subset of the variables of the current base ring).
Useful for elimination problems solved “by hand”.
singular_locus(M,c)
returns the defining ideal of the singular locus of Spec S/M where M is an
ideal of codimension c, adding to M the generators of the ideal of the c-minors
of the Jacobian of M .
submodulep(m,gb)
tests, whether m is a submodule of gb (returns YES or NO).
sym(M,vars)
Computes the symmetric algebra Sym(M ) where M is an ideal defined over
the current base ring S. vars is a list of new variable names, one for each
generator of M . They are used to create a second ring R to return an ideal
J such that (S ⊕ R)/J is the desired symmetric algebra over the new current
base ring S ⊕ R.
symbolic_power(m,d)
returns the dth symbolic power of the prime dpmat ideal m.
syzygies m
returns the first syzygy module of the bounded identifier m.
tangentcone gb
returns the tangent cone part, i.e. the homogeneous part of highest degree with
respect to the first degree vector of the term order from the Gröbner basis
elements of the dpmat gb. The term order must be a degree order.
unmixedradical m
returns the unmixed radical of the dpmat ideal m.
325
varopt m
finds a heuristically optimal variable order, see [4].
zeroradical gb
returns the radical of the zerodimensional ideal gb.
Bibliography
[12] H.-G. Gräbe: Two remarks on independent sets. J. Alg. Comb. 2 (1993), 137
- 145.
[13] H.-G. Gräbe: The tangent cone algorithm and homogenization. J. Pure Ap-
plied Alg.97 (1994), 303 - 312.
[15] H.-G. Gräbe: On factorized Gröbner bases. Report Nr. 6 (1994), Inst. f.
Informatik, Univ. Leipzig.
To appear in: Proc. “Computer Algebra in Science and Engineering”, Biele-
feld 1994.
[16] H.-G. Gräbe: Triangular systems and factorized Gröbner bases. Report Nr.
7 (1995), Inst. f. Informatik, Univ. Leipzig.
[17] H.-G. Gräbe: Factorized Gröbner bases and primary decomposition. To ap-
pear.
[20] M. Marinari, H.-M. Möller, T. Mora: Gröbner bases of ideals given by dual
bases. In: Proc. ISSAC’91, ACM Press 1991, 55 - 63.
[22] H.-M. Möller, F. Mora: New constructive methods in classical ideal theory.
J. Alg. 100 (1986), 138 -178.
[25] T. Mora: Seven variations on standard bases. Preprint, Univ. Genova, 1988.
16.10.1 Introduction
A number of years ago there emerged the divide between general-purpose algebra
systems and special purpose one. Here we investigate how far the improvements
in software and more predominantly hardware have enabled the general systems
to perform as well as the earlier special ones. It is similar in some respects to the
Possion program for MACSYMA [8] which was written in response to a similar
challenge.
The particular subject for investigation is the Fourier series manipulator which had
its origins in the Cambridge University Institute for Theoretical Astronomy, and
later became the F subsystem of CAMAL [3, 10]. In the late 1960s this system
was used for both the Delaunay Lunar Theory [7, 2] and the Hill Lunar Theory
[5], as well as other related calculations. Its particular area of application had a
number of peculiar operations on which the general speed depended. These are
outlined below in the section describing how CAMAL worked. There have been a
number of subsequent special systems for celestial mechanics, but these tend to be
restricted to the group of the originator.
The main body of the paper describes an experiment to create within the REDUCE
system a sub-system for the efficient manipulation of Fourier series. This prototype
program is then assessed against both the normal (general) REDUCE and the extant
CAMAL results. The tests are run on a number of small problems typical of those
for which CAMAL was used, and one medium-sized problem, the calculation of
the Lunar Disturbing Function. The mathematical background to this problem is
also presented for completeness. It is important as a problem as it is the first stage
330 CHAPTER 16. USER CONTRIBUTED PACKAGES
The Cambridge Algebra System was initially written in assembler for the Titan
computer, but later was rewritten a number of times, and matured in BCPL, a ver-
sion which was ported to IBM mainframes and a number of microcomputers. In
this section a brief review of the main data structures and special algorithms is
presented.
The function was coded by a single bit in the Coefficient field. This gives a
particularly compact representation. For example the Fourier term sin(u − 2v +
w − 3x) would be represented as
where "1" is a pointer to the representation of the polynomial 1. In all this rep-
resentation of the term took 48 bytes. As the complexity of a term increased the
store requirements to no grow much; the expression (7/4)ae3 f 5 cos(u−2v +3w −
4x + 5y + 6z) also takes 48 bytes. There is a canonicalisation operation to ensure
that the leading angle is positive, and sin(0) gets removed. It should be noted that
331
Automatic Linearisation
In CAMAL these transformations are coded directly into the multiplication rou-
tines, and no action is necessary on the part of the user to invoke them. Of course
they cannot be turned off either.
In CAMAL these operations were coded directly, and independently of the differ-
entiation and integration of the polynomial coefficients.
Harmonic Substitution
and then assuming that the value A is small it can be replaced by its expansion:
If a truncation is set for large powers of the polynomial variables then the series
will terminate. In CAMAL the HSUB operation took five arguments; the original
expression, the angle for which there is a substitution, the new angular part, the
expression part (A in the above), and the number of terms required.
The actual coding of the operation was not as expressed above, but by the use of
Taylor’s theorem. As has been noted above the differentiation of a harmonic series
is particularly easy.
Truncation of Series
A = a0 + a1 + a2 + . . .
B = b0 + b1 + b2 + . . .
ai (b0 + b1 + b2 + . . .)
then if for some j the product ai bj vanishes, then so will all products ai bk for
k > j. This means that the later terms need not be generated. In the product of
1 + x + x2 + x3 + . . . + x10 and 1 + y + y 2 + y 3 + . . . + y 1 0 to a total order of 10
instead of generating 100 term products only 55 are needed. The ordering can also
make the merging of the new terms into the answer easier.
For the purposes of this work it was necessary to reproduce as many of the ideas
of CAMAL as feasible within the REDUCE framework and philosophy. It was not
intended at this stage to produce a complete product, and so for simplicity a number
of compromises were made with the “no restrictions” principle in REDUCE and
the space and time efficiency of CAMAL. This section describes the basic design
decisions.
Data Structures
In a fashion similar to CAMAL a two level data representation is used. The coef-
ficients are the standard quotients of REDUCE, and their representation need not
concern us further. The angular part is similar to that of CAMAL, but the ability to
pack angle multipliers and use a single bit for the function are not readily available
in Standard LISP, so instead a longer vector is used. Two versions were written.
One used a balanced tree rather than a linear list for the Fourier terms, this being a
feature of CAMAL which was considered but never coded. The other uses a simple
linear representation for sums. The angle multipliers are held in a separate vector
in order to allow for future flexibility. This leads to a representation as a vector of
length 6 or 4;
where the Angles field is a vector of length 8, for the multipliers. It was decided
to forego packing as for portability we do not know how many to pack into a small
334 CHAPTER 16. USER CONTRIBUTED PACKAGES
integer. The tree system used is AVL, which needs 2 bits to maintain balance infor-
mation, but these are coded as a complete integer field in the vector. We can expect
the improvements implicit in a binary tree to be advantageous for large expressions,
but the additional overhead may reduce its utility for smaller expressions.
A separate vector is kept relating the position of an angle to its print name, and
on the property list of each angle the allocation of its position is kept. So long as
the user declares which variables are to be treated as angles this mechanism gives
flexibility which was lacking in CAMAL.
Linearisation
As in the CAMAL system the linearisation of products of sines and cosines is done
not by pattern matching but by direct calculation at the heart of the product func-
tion, where the transformations (1) through (3) are made in the product of terms
function. A side effect of this is that there are no simple relations which can be used
from within the Fourier multiplication, and so a full addition of partial products is
required. There is no need to apply linearisations elsewhere as a special case. Ad-
dition, differentiation and integration cannot generate such products, and where
they can occur in substitution the natural algorithm uses the internal multiplication
function anyway.
Substitution
The first of these is straightforward, and does not require any further comment.
The second substitution requires a little more care, but is not significantly difficult
to implement. The method follows the algorithm used in CAMAL, using TAYLOR
series. Indeed this is the main special case for substitution.
The problem is the last case. Typically many variables used in a Fourier series
program have had a WEIGHT assigned to them. This means that substitution must
take account of any possible WEIGHTs for variables. The standard code in RE-
DUCE does this in effect by translating the expression to prefix form, and recal-
culating the value. A Fourier series has a large number of coefficients, and so this
operations are repeated rather too often. At present this is the largest problem area
335
with the internal code, as will be seen in the discussion of the Disturbing Function
calculation.
The Fourier module needs to be seen as part of REDUCE rather than as a separate
language. This can be seen as having internal and external parts.
Internal Interface
The Fourier expressions need to co-exist with the normal REDUCE syntax and
semantics. The prototype version does this by (ab)using the module method, based
in part on the TPS code [1]. Of course Fourier series are not constant, and so are
not really domain elements. However by asserting that Fourier series form a ring
of constants REDUCE can arrange to direct basic operations to the Fourier code
for addition, subtraction, multiplication and the like.
The main interface which needs to be provided is a simplification function for
Fourier expressions. This needs to provide compilation for linear sums of angles,
as well as constructing sine and cosine functions, and creating canonical forms.
User Interface
The creation of HDIFF and HINT functions for differentiation disguises this. An
unsatisfactory aspect of the interface is that the tokens SIN and COS are already in
use. The prototype uses the operator form
fourier sin(u)
The REDUCE test file contains a simple example of a Fourier calculation, deter-
mining the value of (a1 cos(wt) + a3 cos(3wt) + b1 sin(wt) + b3 sin(3wt))3 . For
the purposes of this system this is too trivial to do more than confirm the correct
answers.
The simplest non-trivial calculation for a Fourier series manipulator is to solve
Kepler’s equation for the eccentric anomoly E in terms of the mean anomoly u,
and the eccentricity of an orbit e, considered as a small quantity
E = u + e sin E
bige := fourier 0;
for k:=1:n do <<
wtlevel k;
bige:=fourier e * hsub(fourier(sin u), u, u, bige, k);
>>;
write "Kepler Eqn solution:", bige$
These results were with the linear representation of Fourier series. The tree rep-
resentation was slightly slower. The ten-fold speed-up for the 13th order is most
satisfactory.
Fourier series manipulators are primarily designed for large-scale calculations, but
for the demonstration purposes of this project a medium problem is considered.
The first stage in calculating the orbit of the Moon using the Delaunay theory (of
perturbed elliptic motion for the restricted 3-body problem) is to calculate the en-
ergy of the Moon’s motion about the Earth — the Hamiltonian of the system. This
is the calculation we use for comparisons.
Mathematical Background
The full calculation is described in detail in [6], but a brief description is given here
for completeness, and to grasp the extent of the calculation.
338 CHAPTER 16. USER CONTRIBUTED PACKAGES
Referring to the figure 1 which gives the cordinate system, the basic equations are
There are similar equations to (7) to (10) for the quantities r0 , a0 , e0 , l0 , E 0 and f 0
which refer to the position of the Sun rather than the Moon. The problem is to
calculate the expression R as an expansion in terms of the quantities e, e0 , γ, a/a0 ,
l, g, h, l0 , g 0 and h0 . The first three quantities are small quantities of the first order,
and a/a0 is of second order.
The steps required are
Results
The Lunar Disturbing function was calculated by a direct coding of the previous
sections’ mathematics. The program was taken from Barton and Fitch [4] with
just small changes to generalise it for any order, and to make it acceptable for
Reduce3.4. The Fourier program followed the same pattern, but obviously used
the HSUB operation as appropriate and the harmonic integration. It is very similar
to the CAMAL program in [4].
The disturbing function was calculated to orders 2, 4 and 6 using Cambridge LISP
on an HLH Orion 1/05 (Intergraph Clipper), with the three programs α) Reduce3.4,
β) Reduce3.4 + Camal Linear Module and γ) Reduce3.4 + Camal AVL Module.
339
The timings for CPU seconds (excluding garbage collection time) are summarised
the following table:
If these numbers are normalised so REDUCE calculating the DDF is 100 units for
each order the table becomes
From this we conclude that a doubling of speed is about correct, and although the
balanced tree system is slower as the problem size increases the gap between it and
the simpler linear system is narrowing.
It is disappointing that the ratio is not better, nor the absolute time less. It is worth
noting in this context that Jefferys claimed that the sixth order DDF took 30s on a
CDC6600 with TRIGMAN in 1970 [11], and Barton and Fitch took about 1s for
the second order DDF on TITAN with CAMAL [4]. A closer look at the relative
times for individual sections of the program shows that the substitution case of
replacing a polynomial variable by a Fourier series is only marginally faster than
the simple REDUCE program. In the DDF program this operation is only used
once in a major form, substituting into the Legendre polynomials, which have been
previously calculated by Rodrigues formula. This suggests that we replace this
with the recurrence relationship.
Making this change actually slows down the normal REDUCE by a small amount
but makes a significant change to the Fourier module; it reduces the run time for
the 6th order DDF from 3084.62s to 2002.02s. This gives some indication of the
problems with benchmarks. What is clear is that the current implementation of
substitution of a Fourier series for a polynomial variable is inadequate.
16.10.7 Conclusion
The Fourier module is far from complete. The operations necessary for the solution
of Duffing’s and Hill’s equations are not yet written, although they should not
cause much problem. The main defficiency is the treatment of series truncation;
at present it relies on the REDUCE WTLEVEL mechanism, and this seems too
340 CHAPTER 16. USER CONTRIBUTED PACKAGES
array p(n/2+2);
harmonic u,v,w,x,y,z;
weight e=1, b=1, d=1, a=1;
on fourier;
for i := 2:n/2+2 do <<
wtlevel n+4-2i; p(i) := hsub(p(i), h, xx) >>;
wtlevel n;
for i:=n/2+2 step -1 until 3 do
p(n/2+2):=fourier(a*a)*zz*p(n/2+2)+p(i-1);
yy*p(n/2+2);
342 CHAPTER 16. USER CONTRIBUTED PACKAGES
Bibliography
[5] Stephen R. Bourne. Literal expressions for the co-ordinates of the moon. I.
the first degree terms. Celestial Mechanics, 6:167–186, 1972.
This package creates an environment which allows the user to manipulate and sim-
plify expressions containing various indexed objects like tensors, spinors, fields
and quantum fields.
Author: Hubert Caprasse.
16.11.1 Introduction
1. Several invariant elementary tensors which are always used in the applica-
tions involving the use of indexed objects like delta, epsilon, eta
and the generalized delta function.
In this package, one cannot find algorithms or even specific objects (i.e. like the
covariant derivative or the SU(3) group structure constants) which are of used either
in nuclear and particle physics. The objective of the package is simply to allow the
user to easily formulate his algorithms in the notations he likes most. The package
344 CHAPTER 16. USER CONTRIBUTED PACKAGES
When CANTENS is loaded, the packages ASSIST and DUMMY are also loaded.
One can work either in a single space environment or in a multiple space environ-
ment. After the package is loaded, the single space environment is set and a unique
space is defined. It is euclidian, and has a symbolic dimension equal to dim. The
single space environment is determined by the switch ONESPACE which is turned
on. One can verify the above assertions as follows :
345
signature ?; => 0
One can introduce a pseudoeuclidian metric for the above space by the command
SIGNATURE and verify that the signature is indeed 1:
signature 1;
signature ?; => 1
In principle the signature may be set to any positive integer. However, presently,
the package cannot handle signatures larger than 1. One gets the Minkowski-like
space metric
1 0 0 0
0 −1 0 0
0 0 −1 0
0 0 0 −1
which corresponds to the convention of high energy physicists. It is possible to
change it into the astrophysicists convention using the command GLOBAL_SIGN:
global_sign ?; => 1
global_sign (-1);
global_sign ?; => -1
This means that the actual metric is now (−1, 1, 1, 1). The space dimension may,
of course, be assigned at will using the function WHOLESPACE_DIM. Below, it is
assigned to 4:
wholespace_dim 4; ==> 4
When the switch ONESPACE is turned off, the system assumes that this default
space is non-existent and, therefore, that the user is going to define the space(s) in
which he wants to work. Unexpected error messages will occur if it is not done.
Once the switch is turned off many more functions become active. A few of them
are available in the algebraic mode to allow the user to properly conctruct and
control the properties of the various (sub-)spaces he is going to define and, also, to
assign symbolic indices to some of them.
DEFINE_SPACES is the space constructor and wholespace is a reserved identi-
346 CHAPTER 16. USER CONTRIBUTED PACKAGES
fier which is meant to be the name of the global space if subspaces are introduced.
Suppose we want to define a unique space, we can choose for its any name but
choosing wholespace will be more efficient. On the other hand, it leaves open
the possibility to introduce subspaces in a more transparent way. So one writes, for
instance,:
define_spaces wholespace=
The arguments inside the list, assign respectively the dimension, the signature and
the range of the numeric indices which is allowed. Notice that the range starts from
0 and not from 1. This is made to conform with the usual convention for spaces of
signature equal to 1. However, this is not compulsory. Notice that the declaration
of the indexrange may be omitted if this is the only defined space. There are two
other options which may replace the signature option, namely euclidian and
affine. They have both an obvious significance.
In the subsequent example, an eleven dimension global space is defined and two
subspaces of this space are specified. Notice that no indexrange has been declared
for the entire space. However, the indexrange declaration is compulsory for sub-
spaces otherwise the package will improperly work when dealing with numeric
indices.
define_spaces mink=
define_spaces eucl=
To remind ones the space context in which one is working, the use of the func-
tion SHOW_SPACES is required. Its output is an algebraic value from which the
user can retrieve all the informations displayed. After the declarations above, this
function gives:
show_spaces(); ==>
{{wholespace,11,signature=1}
{mink,4,signature=1,indexrange=0..3},
347
{eucl,6,euclidian,indexrange=4..9}}
If an input error is made or if one wants to change the space framework, one cannot
directly redefine the relevant space(s). For instance, the input
define_spaces eucl=
whih aims to fill all dimensions present in wholespace tells that the space eucl
cannot be redefined. To redefine it effectively, one is to remove the existing defini-
tion first using the function REM_SPACES which takes any number of space-names
as its argument. Here is the illustration:
show_spaces(); ==>
{{wholespace,11,signature=1},
{mink,4,signature=1,indexrange=0..3}}
define_spaces eucl=
show_spaces(); ==>
{{wholespace,11,signature=1},
{mink,4,signature=1,indexrange=0..3},
{eucl,7,euclidian,indexrange=4..10}}
Here, the user is entirely responsible of the coherence of his construction. The
system does NOT verify it but will incorrectly run if there is a mistake at this level.
When two spaces are direct product of each other (as the color and Minkowski
348 CHAPTER 16. USER CONTRIBUTED PACKAGES
mk_ids_belong_space(<list of indices>,
<space | subspace identifier>)
For example, within the above declared spaces one could write:
mk_ids_belong_space({a0,a1,a2,a3},mink); ==> t
mk_ids_belong_space({x,y,z,u,v},eucl); ==> t
Definition
The generic tensors handled by CANTENS are objects much more general than
usual tensors. The reason is that they are not supposed to obey well defined trans-
formation properties under a change of coordinates. They are only indexed quan-
tities. The indices are either contravariantly (upper indices) or covariantly (lower
indices) placed. They can be symbolic or numeric. When a given index is found
both in one upper and in one lower place, it is supposed to be summed over all
space-coordinates it belongs to viz. it is a dummy index and automatically recog-
nized as such. So they are supposed to obey the summation rules of tensor calcu-
lus. This why and only why they are called tensors. Moreover, aside from indices
they may also depend implicitly or explicitly on any number of variables. Within
this definition, tensors may also be spinors, they can be non-commutative or anti-
commutative, they may also be algebra generators and represent fields or quantum
349
fields.
te(3,a,-4,b,-c,7); ==>
3 a b 7
te
4 c
te(3,a,{x,y},-4,b,-c,7); ==>
3 a b 7
te (x,y)
4 c
te(3,a,-4,b,{u,v},-c,7); ==>
3 a b 7
te (u,v)
4 c
Notice that the system distinguishes indices from variables on input solely on the
basis that the user puts variables inside a list.
The dependence can also be declared implicit through the REDUCE command
DEPEND which is generalized so as to allow to declare a tensor to depend on
350 CHAPTER 16. USER CONTRIBUTED PACKAGES
another tensor irrespective of its components. It means that only one declaration
is enough to express the dependence with respect to all its components. A simple
example:
tensor te,x;
depend te,x;
df(te(a,-b),x(c)); ==>
a c
df(te ,x )
b
Therefore, when all objects are tensors, the dependence declaration is valid for all
indices.
One can also avoid the trouble to place the explicit variables inside a list if one de-
clare them as variables through the command MAKE_VARIABLES. This property
can also be removed19 using REMOVE_VARIABLES:
te(x,y,a); ==>
a
te (x,y)
remove_variables x; ==> t
te(x,y,a); ==>
x a
te (y)
If one does that one must be careful not to substitute a number to such declared
19
One important feature of this package is its reversibility viz. it gives the user the means to erase
its previous operations at any time. So, most functions described below do possess “removing” action
companions.
351
Dummy indices recognition For all individual tensors met by the evaluator, the
system will analyse the written indices and will detect those which must be con-
sidered dummy according to the usual rules of tensor calculus. Those indices
will be given the dummy property and will no longer be allowed to play the role
of free indices unless the user removes this dummy property. In that way, the
system checks immediately the consistency of an input. Three functions are at
the disposal of the user to control dummy indices. They are DUMMY_INDICES,
REM_DUMMY_INDICES and REM_DUMMY_IDS. The following illustrates their
use as well as the behaviour of the system:
te(a,b,-c,-a); ==>
a b
te
c a
te(a,b,-c,a); ==>
te(a,b,-b,-a); ==>
a b
te
b a
te(d,-d,d); ==>
352 CHAPTER 16. USER CONTRIBUTED PACKAGES
rem_dummy_ids d; ==> t
te(d,d); ==>
d d
te % This is allowed again.
rem_dummy_indices(); ==> t
dummy_indices(); ==> {}
Other verifications of coherence are made when space specifications are introduced
both in the ON and OFF onespace environment. We shall discuss them later.
Substitutions, assignements and rewriting rules The user must be able to ma-
nipulate and give specific characteristics to the generic tensors he has introduced.
Since tensors are essentially REDUCE operators, the usual commands of the sys-
tem are available. However, some limitations are implied by the fact that indices
and, especially numeric indices, must always be properly recognized before any
substitution or manipulation is done. We have gathered below a set of examples
which illustrate all the “delicate” points. First, the substitutions:
sub(a=-c,te(a,b)); ==>
b
te
c
sub(a=-1,te(a,b)); ==>
b
te
1
sub(a=-0,te(a,b)); ==>
353
0 b
te % sub has replaced -0 by 0. wrong!
sub(a=-!0,te(a,b)); ==>
b
te % right
0
The substitution of an index by -0 is the only one case where there is a problem.
The function SUB replaces -0 by 0 because it does not recognize 0 as an index of
course. Such a recognition is context dependent and implies a modification of SUB
for this single exceptional case. Therefore,we have opted, not do do so and to use
the index 0 which is simply !0 instead of 0.
Second, the assignments. Here, we advise the user to rely on the operator==20
instead of the operator :=. Again, the reason is to avoid the problem raised above
in the case of substitutions. := does not evaluate its left hand side so that -0 is not
recognized as an index and simplified to 0 while the == operator evaluates both
its left and right hand sides and does recognize it. The disadvantage of == is that
it demands that a second assignement on a given component be made only after
having suppressed explicitly the first assignement. This is done by the function
REM_VALUE_TENS which can be applied on any component. We stress, however,
that if one is willing to use -!0 instead of -0 as the lower 0 index, the use of := is
perfectly legitimate:
te({x,y},a,-0)==x*y*te(a,-0); ==>
a
te *x*y
0
te({x,y},a,-0); ==>
a
te *x*y
0
te({x,y},a,0); ==>
20
See the ASSIST documentation for its description.
354 CHAPTER 16. USER CONTRIBUTED PACKAGES
a 0
te (x,y)
te({x,y},a,-0)==x*y*te(a,-0); ==>
a
***** te *x*y invalid as setvalue kernel
0
rem_value_tens te({x,y},a,-0);
te({x,y},a,-0); ==>
a
te (x,y)
0
te({x,y},a,-0)==(x+y)*te(a,-0); ==>
a
te *(x + y)
0
In the elementary application below, the use of a tensor avoids the introduction of
two different operators and makes the calculation more readable.
2 2 2 2 2
cos(phi) *sin(th) + cos(th) + sin(phi) *sin(th)
355
rem_value_tens te;
te(2); ==>
2
te
% LET:
let te({x,y},-0)=x*y;
te({x,y},+0); ==>
0
te (x,y)
te({x,u},-0); ==>
te (x,u)
0
te({u},1,-b); ==>
1
te *u
b
te({u},c,-b); ==>
356 CHAPTER 16. USER CONTRIBUTED PACKAGES
c
te *u
b
te({u},b,-b); ==>
b
te *u
b
te({u},a,-a); ==>
a
te (u)
a
te({u},c,-b); ==>
c
te (u)
b
te({x},c,-b); ==>
c
te *x
b
te({x},a,-a); ==>
a
te *x
a
a
357
te({x},0,-!0); ==>
0
te *x % here it applies.
0
% WHERE:
a
rul := {te => sin(a)}
te(1); ==>
1
te
% with variables:
~a
rul1 := {te (~x,~y) => x*y*sin(a)}
Notice that the position of the list of variables inside the rule may be chosen at will.
It is an irrelevant feature of the template. This may be confusing, so, we advise to
write the rules not as above but placing the list of variables in front of all indices
since it is in that canonical form which it is written by the simplification function
of individual tensors.
The characteristics and the behaviour of generic tensors described up to now are
independent of all space specifications. They are complete as long as we confine
to the default space which is active when starting CANTENS. However, as soon as
some space specification is introduced, it has some consequences one the generic
tensor properties. This is true both when ONESPACE is switched ON or OFF. Here
we shall describe how to deal with these features.
When onespace is ON, if the space dimension is set to an integer, numeric in-
dices of any generic tensors are forced to be less or equal that integer if the sig-
nature is 0 or less than that integer if the signature is equal to 1. The following
illustrates what happens.
on onespace;
wholespace_dim 4; ==> 4
signature 0; ==> 0
te(3,a,-b,3); ==>
3 a 3
te
b
359
te(4,a,-b,4); ==>
4 a 4
te
b
sub(a=5,te(3,a,-b,3));
signature 1; ==> 1
te(4,a,-b,4);
te(0,a,-b,3); ==>
0 a 3
te
b
When onespace is OFF, many more possibilities to control the input or to give
specific properties to tensors are open. For instance, it is possible to declare that
a tensor belongs to one of them. It is also possible to declare that some indices
belongs to one of them. It is even possible to do that for numeric indices thanks
to the declaration indexrange included optionally in the space definition generated
by DEFINE_SPACES. First, when onespace is OFF, the run equivalent to the
previous one is like the following:
off onespace;
make_tensor_belong_space(te,wholespace);
360 CHAPTER 16. USER CONTRIBUTED PACKAGES
==> wholespace
te(4,a,-b,6); ==>
te(4,a,-b,5); ==>
4 a 5
te
b
rem_spaces wholespace;
te(a,4,-b); ==>
a 4
te
b
show_spaces(); ==>
{{wholespace,5,signature=1},
{eucl,1,signature=0}}
te(1); ==>
1
te
te(0); ==>
0
te
define_spaces eucl=
te(0); ==>
te(1); ==>
1
te
te(2); ==>
Notice that the error message has also changed accordingly. So, now one can even
constrain the 0 component to belong to an euclidian space.
Let us go back to symbolic indices. By default, any symbolic index belongs
to the global space or to all defined partial spaces. In many cases, this is, of
course, not consistent. So, the possibility exists to declare that one or several
indices belong to a specific (sub-)space. To this end, one is to use the function
MK_IDS_BELONG_SPACE. Its syntax is
mk_ids_belong_space(<list of indices>,
<(sub-)space identifier>)
362 CHAPTER 16. USER CONTRIBUTED PACKAGES
The means provided in the two previous subsection to handle generic tensors al-
ready allow to construct any specific tensor we may need. That the package con-
tains a certain number of them is already justified on the level of conviviality. How-
ever, a more important justification is that some basic tensors are so universaly and
frequently used that a careful programming of these improves considerably the ro-
bustness and the efficiency of most calculations. The choice of the set of specific
tensors is not clearcut. We have tried to keep their number to a minimum but, ex-
perience, may lead us extend it without dificulty. So, up to now, the list of specific
tensors is:
- delta tensor,
- eta Minkowski tensor,
- epsilon tensor,
- del generalised delta tensor,
- metric generic tensor metric.
It is important to realize that the typewriter font names in the list are keywords for
the corresponding tensors and do not necessarily correspond to their actual names.
Indeed, the choice of the names of particular tensors is left to the user. When
startting CANTENS specific tensors are NOT available. They must be activated by
the user using the function MAKE_PARTIC_TENS whose syntax is:
The name chosen may be the same as the keyword. As we shall see, it is never
needed to define more than one delta tensor but it is often needed to define
several epsilon tensors. Hereunder, we describe each of the above tensors espe-
cially their behaviour in a multi-space environment.
363
DELTA tensor
on onespace;
make_partic_tens(delt,delta); ==> t
delt(a,b); ==>
delt(a,-b); ==>
a
delt
b
delt(-b,a); ==>
a
delt
b
delt(-a,b); ==>
b
delt
a
delt(1,-5); ==> 0
wholespace_dim 4; ==> 4
wholespace_dim 3; ==> 3
delt(-a,a); ==> 3
There is a peculiarity of this tensor, viz. it can serve to represent the Dirac delta
function when it has no indices and an explicit variable dependency as hereunder
off onespace;
make_tensor_belong_space(delt,wholespace);
delt(a,-a); ==> 5
delt(0,-0); ==>1
delt(a,-a); ==> 5
delt(0,-a); ==>
The checking of consistency of chosen indices is made in the same way as for
generic tensor. In fact, all the previous functions which act on generic tensors may
365
also affect, in the same way, a specific tensor. For instance, it was compulsory to
explicitly tell that we want DELT to belong to the wholespace overwise, DELT
would remain defined on the default space. In the next sample run, we display the
bloc-diagonal property of the delta tensor.
onespace ?; ==> no
define_spaces wholespace={10,signature=1}$
define_spaces d1={5,euclidian}$
define_spaces d2={2,euclidian}$
mk_ids_belong_space({a},d1); ==> t
mk_ids_belong_space({b},d2); ==> t
delt(c,-b); ==>
c
delt
b
delt(c,-c); ==> 10
delt(b,-b); ==> 2
delt(a,-a); ==> 5
delt(a,-b); ==> 0
The bloc-diagonal property of delt is made active under two conditions. The first
is that the system knows to which space it belongs, the second is that indices must
be declared to belong to a specific space. To enforce the same property on a generic
tensor, we have to make the MAKE_BLOC_DIAGONAL declaration:
366 CHAPTER 16. USER CONTRIBUTED PACKAGES
and to make it active, one proceeds as in the above run. Starting from a fresh
environment, the following sample run is illustrative:
off onespace;
define_spaces wholespace={6,signature=1}$
tensor te;
mk_ids_belong_space({a,b,c},eucl); ==> t
mk_ids_belong_space({m1,m2},mink); ==> t
te(a,b,m1); ==> 0
te(a,b,m2); ==> 0
te(a,b,m2); ==>
a b m2
te
367
on onespace;
make_partic_tens(et,eta); ==> t
signature 0; ==> 0;
et(-b,-a); ==>
off onespace;
et(a,b); ==>
on onespace;
signature 1; ==> 1
et(-b,-a); ==>
et
a b
make_partic_tens(delta,delta); ==> t
The value of its diagonal elements depends on the chosen global sign. The next
run illustrates this:
global_sign ?; ==> 1
et(0,0); ==> 1
et(3,3); ==> - 1
global_sign(-1); ==> -1
et(0,0); ==> - 1
et(3,3); ==> 1
The tensor is of course symmetric . Its indices are checked in the same way as for
a generic tensor. In a multi_space context, the eta tensor must belong to a well
defined space of signature 1:
off onespace;
define_spaces wholespace={4,signature=1}$
make_tensor_belong_space(et,wholespace)$
et(a,-a); ==> 4
If the space to which et belongs to is a subspace, one must also take care to give
a space-identity to dummy indices which may appear inside it. In the following
run, the index a belongs to wholespace if it is not told to the system that it is a
dummy index of the space mink:
% a sits in wholespace:
et(a,-a); ==> 8
mk_ids_belong_space({a},mink); ==> t
% a sits in mink:
et(a,-a); ==> 5
EPSILON tensors
It is an antisymmetric tensor which is the invariant tensor for the unitary group
transformations in n-dimensional complex space which are continuously connected
to the identity transformation. The number of their indices are always stricty equal
to the number of space dimensions. So, to each specific space is associated a
specific epsilon tensor. Its properties are also dependent on the signature of the
space. We describe how to define and manipulate it in the context of a unique space
and, next, in a multi-space context.
make_partic_tens(eps,epsilon); ==> t
eps(a,d,b,-g,e,-f); ==>
a d b e
- eps
g f
eps(a,d,b,-f,e,-f); ==> 0
370 CHAPTER 16. USER CONTRIBUTED PACKAGES
eps(-b,-a); ==>
- eps
a b
signature ?; ==> 0
eps(1,2,3,4); ==> 1
eps(-1,-2,-3,-4); ==> 1
wholespace_dim 3; ==> 3
eps(-1,-2,-3); ==> 1
eps(-1,-2,-3,-4); ==>
eps(-1,-2,-3,-3); ==>
eps(a,b); ==>
eps(a,b,c); ==>
a b c
eps
eps(a,b,b); ==> 0
When the signature is equal to 1, it is known that there exists two conventions
which are linked to the chosen value 1 or -1 of the (0, 1, . . . , n) component. So,
the sytem does evaluate all components in terms of the (0, 1, . . . , n) upper index
component. It is left to the user to assign it to 1 or -1.
371
signature 1; ==> 1
eps(0,1,2); ==>
0 1 2
eps
eps(-0,-1,-2); ==>
0 1 2
eps
wholespace_dim 4; ==> 4
eps(0,1,2,3); ==>
0 1 2 3
eps
eps(-0,-1,-2,-3); ==>
0 1 2 3
- eps
global_sign(-1);
wholespace_dim 3; ==> 3
eps(-0,-1,-2); ==>
0 1 2
- eps
does NOT show the epsilon tensor one may have defined in the ON onespace
context. This is so because the default space has NO name. Starting from a fresh
environment, the following run illustrates this point:
show_epsilons(); ==> {}
make_partic_tens(eps,epsilon); ==> t
show_epsilons(); ==> {}
To make the epsilon tensor defined in the single space environment visible in
the multi-space environment, one needs to associate it to a space. For example:
off onespace;
make_tensor_belong_space(eps,wholespace); ==>
wholespace
make_partic_tens(ep,epsilon); ==>
ep(-1,-2,-3); ==> 1
373
ep(1,2,3); ==> 1
ep(a,b,c,d); ==>
ep(1,2,4); ==>
rem_spaces wholespace;
mk_ids_belong_space({e1,e2,e3},eucl); ==> t
mk_ids_belong_space({a,b,c},wholespace); ==> t
ep(e1,e2,e3); ==>
e1 e2 e3
ep % accepted
ep(e1,e2,z); ==>
e1 e2 z
ep % accepted because z
% not attached to a space.
ep(e1,e2,a);==>
eps(a,b,c); ==>
a b c
eps % accepted because *symbolic*
% space dimension.
374 CHAPTER 16. USER CONTRIBUTED PACKAGES
show_spaces(); ==>
{{eucl,3,signature=0},
{mink,4,signature=1}}
eps(a,b,c,d); ==>
a b c d
eps
eps(e1,b,c,d); ==>
ep(e1,b,c,d); ==>
ep(e1,b,c); ==>
b c e1
375
ep
ep(e1,e2,e3); ==>
e1 e2 e3
ep
The generalized delta function comes from the contraction of two epsilons. It is
totally antisymmetric. Suppose its name has been chosen to be gd, that the space
to which it is attached has dimension n while the name of the chosen delta tensor
is δ, then one can define it as follows:
a1 a1 a1
δb
a1 δba2 . . . δban
δ 2 δ 2 ... δ 2
a1 ,a2 ,...,an b b2 bn
gdb1 ,b2 ,...,bn = .1 .. .. ..
.. . . .
a
δ n δ an . . . δ an
b1 b1 b1
It is, in general uneconomical to explicitly write that determinant except for par-
ticular numeric values of the indices or when almost all upper and lower indices
are recognized as dummy indices. In the sample run below, gd is defined as the
generalized delta function in the default space. The main automatic evaluations are
illustrated. The indices which are summed over are always simplified:
make_partic_tens(delta,delta); ==> t
make_partic_tens(gd,del); ==> t
% immediate simplifications:
gd(1,2,-3,-4); ==> 0
gd(1,2,-1,-2); ==> 1
gd(a,b,-a,-b);
gd(a,b,c,-a,-d,-e); ==>
b c
gd *(dim - 2)
d e
gd(a,b,c,-a,-d,-c); ==>
b 2
delta *(dim - 3*dim + 2)
d
% no simplification:
gd(a,b,c,-d,-e,-f); ==>
a b c
gd
d e f
One can force evaluation in terms of the determinant in all cases. To this end, the
switch EXDELT is provided. It is initially OFF. Switching it ON will most often
give inconveniently large outputs:
on exdelt;
gd(a,b,c,-d,-e,-f); ==>
a b c a b c
delta *delta *delta - delta *delta *delta
d e f d f e
a b c a b c
- delta *delta *delta + delta *delta *delta
e d f e f d
a b c a b c
+ delta *delta *delta - delta *delta *delta
f d e f e d
METRIC tensors
Very often, one has to define a specific metric. The metric-type of tensors in-
clude all generic properties. The first one is their symmetry, the second one is
their equality to the delta tensor when they get mixed indices, the third one is
their optional bloc-diagonality. So, a metric (generic) tensor is generated by the
declaration
make_partic_tens(<tensor-name>,metric);
make_partic_tens(g,metric); ==> t
make_partic_tens(delt,delta); ==> t
g(a,b); ==>
a b
g
g(b,a); ==>
a b
g
g(a,b,c); ==>
g(a,b,{x,y}); ==>
a b
g (x,y)
g(a,-b,{x,z}); ==>
378 CHAPTER 16. USER CONTRIBUTED PACKAGES
a
delt
b
let g({x,y},1,1)=1/2(x+y);
g({x,y},1,1); ==>
x + y
-------
2
rem_value_tens g({x,y},1,1);
g({x,y},1,1); ==>
1 1
g (x,y)
Tensor expressions
Up to now, we have described the behaviour of individual tensors and how they
simplify themselves whenever possible. However, this is far from being sufficient.
In general, one is to deal with objects which involve several tensors together with
various dummy summations between them. We define a tensor expression as an
arbitrary multivariate polynomial. The indeterminates of such a polynomial may
be either an indexed object, an operator, a variable or a rational number. A tensor-
type indeterminate cannot appear to a degree larger than one except if it is a trace.
The following is a tensor expression:
a d g
379
a b c
*eps *op(x,y) + 1
In the above expression, delt and eps are, respectively, the delta and the
epsilon tensors, op is an operator. and delt(x-y) is the Dirac delta func-
tion. Notice that the above expression is not cohérent since the first term has a
variance while the second term is a scalar. Moreover, the dummy index g appears
three times in the first term. In fact, on input, each factor is simplified and each fac-
tor is checked for coherence not more. Therefore, if a dummy summation appears
inside one factor, it will be done whenever possible. Hereunder delt(a,-a) is
summed over:
sub(g=a,aa); ==>
a d a b c
delt(x - y)*delt *delt *eps *eps
r a d e f
*op(x,y)*dim + 1
CANONICAL is an offspring of the function with the same name of the package
DUMMY. It applies to tensor expressions as defined above. When it acts, this funct-
ions has several features which are worth to realise:
1. It tracks the free indices in each term and checks their identity. It identifies
and verify the coherence of the various dummy index summations.
3. It seeks a canonical form for the various simplified terms, makes the compar-
ison between them. In that way it maximises simplifications and generates a
canonical form for the output polynomial.
Dummy indices for individual tensors are kept in the memory of the system. If
they are badly distributed over several tensors, it is CANONICAL which gives an
error message:
bb:=te(a,b,b)*te(-b); ==>
a b b
bb := te *te
b
aa:=te(b,-c)*tf(b,-c); ==>
b b
aa := te *tf % b and c are free.
c c
b b
te * tf
c c
bb:=te(a,c,b)*te(-b)*tf(a)$
21
In DUMMY it does not take them into account
381
a c b a
te *te *tf
b
The message of canonical is clear, the first sublist contains the list of all lower in-
dices, and the second one the list of all upper indices. The index b is repeated three
times. In the second example, b and c are considered as free indices, so they may
be repeated. The last example shows the interference between the check on indi-
vidual tensors and the one of canonical. The use of a as dummy index inside delt
does no longer allow a to be used as a free index in expression bb. To be usable,
one must explicitly remove it as dummy index using REM_DUMMY_INDICES.
Dans le quatrième cas, il n’y a pas de problème puisque b et c sont tous les deux
des indices libres. CANONICAL checks that in a tensor polynomial all do possess
the same variance:
aa:=te(a,c)+x^2; ==>
a c 2
aa := te + x
aa:=te(a,b)+tf(a,c); ==>
a b a c
aa := te + tf
In the message the first two lists of incompatible indices are explicitly indicated.
So, it is not an exhaustive message and a more complete correction may be needed.
Of course, no message of that kind appears if the indices are inside ordinary oper-
ators22
dummy_names b; ==> t
clear_dummy_names; ==> t
For a specific tensor, contravariant dummy indices are place in front of covariant
ones. This already leads to some useful simplifications. For instance:
pp:=te(a,-a)+te(-a,a)+1; ==>
a a
pp := te + te + 1
a a
a
2*te + 1
a
pp:=te(a,-a)+te(-b,b); ==>
b a
pp := te + te
b a
a
2*te
a
22
This is the case inside the DUMMY package.
383
pp:=te(r,a,c,d,-a,f)+te(r,-b,c,d,b,f); ==>
r c d b f r a c d f
pp := te + te
b a
r a c d f
2*te
a
In the second and third example, there is also a renaming of the dummy variable
b whih becomes a. There is a loophole at this point. For some expressions one
will never reach a stable expression. This is the case for the following very simple
monom:
a1:=nt(-a,d)*nt(-c,a); ==>
d a
nt *nt
a c
a d
nt *nt
c a
d a a d
a12 := nt *nt - nt *nt
a c c a
d a a d
- nt *nt + nt *nt % changes sign.
a c c a
In the above example, no canonical form can be reached. When applied twice on
the tensor monom a1 it gives back a1!
No change of dummy index position is allowed if a tensor belongs to an AFFINE
space. With the tensor polynomial pp introduced above one has:
off onespace;
mk_ids_belong_space({a,b},aff); ==> t
r c d a f r a c d f
te + te
a a
Dummy indices are recognized contracted and summed over whenever possible:
aa:=delt(a,-b)*delt(b,-c)*delt(c,-a) + 1; ==>
a b c
aa := delt *delt *delt + 1
b c a
385
aa:=delt(a,-b)*delt(b,-c)*delt(c,-d)*te(d,e)$
a e
te
CANONICAL will not attempt to make contraction with dummy indices included
inside ordinary operators:
operator op;
aa:=delt(a,-b)*op(b,b)$
a
delt *op(b,b)
b
dummy_names b; ==> t
a
delta *op(b,b)
b
make_partic_tens(eta,eta); ==> t
aa:=delta(a,-b)*eta(b,c); ==>
a b c
aa := delt *eta
386 CHAPTER 16. USER CONTRIBUTED PACKAGES
a c
eta
canonical(eta(a,b)*eta(-b,c)); ==>
a c
eta
canonical(eta(a,b)*eta(-b,-c)); ==>
a
delt
c
d f
te
e a
aa:=eta(a,b)*eta(-b,-c)*te(-a,c)+1; ==>
a b c
aa := eta *eta *te + 1
b c a
a
te + 1
a
aa:=eta(a,b)*eta(-b,-c)*delta(-a,c)+
1+eta(a,b)*eta(-b,-c)*te(-a,c)$
387
a
te + dim + 1
a
aa:=g(a,b)*g(-b,-d); ==>
a b
aa := g *g
b d
a
delt
d
aa:=g(a,b)*g(c,d)*eta(-c,-e)*eta(e,f)*te(-f,g); ==>
e f a b c d g
aa := eta *eta *g *g *te
c e f
a b d g
g * te
The epsilon tensor plays an important role in many contexts. CANONICAL realises
the contraction of two epsilons if and only if they belong to the same space. The
proper use of CANONICAL on expressions which contains it requires a prelimi-
nary definition of the tensor DEL. When the signature is 0; the contraction of two
epsilons gives a DEL-like tensor. When the signature is equal to 1, it is equal to
minus a DEL-like tensor. Here we choose 1 for the signature and we work in a
single space. We define the DEL tensor:
388 CHAPTER 16. USER CONTRIBUTED PACKAGES
on onespace;
make_partic_tens(gd,del); ==> t
signature 1; ==> 1
We define the EPSILON tensor and show how CANONICAL contracts expression
containing two23 of them:
aa:=eps(a,b)*eps(-c,-d); ==>
a b
aa := eps *eps
c d
a b
- gd
c d
aa:=eps(a,b)*eps(-a,-b); ==>
a b
aa := eps *eps
a b
on exdelt;
aa:=eps(a,b,c)*eps(-b,-d,-e)$
a c a c
23
No contractions are done on expressions containing three or more epsilons which sit in the same
space. We are not sure whether it is useful to be more general than we are presently.
389
a c a c
- delt *delt *dim + 2*delt * delt
e d e d
Several expressions which contain the epsilon tensor together with other special
tensors are given below as examples to treat with CANONICAL:
a b a c
eps *eta *eta
b c
a b c
aa := eps *te *te
a b
tensor tf,tg;
aa:=eps(a,b,c)*te(-a)*tf(-b)*tg(-c)
+ eps(d,e,f)*te(-d)*tf(-e)*tg(-f); ==>
a b c
2*eps *te *tf *tg
a b c
aa:=eps(a,b,c)*te(-a)*tf(-c)*tg(-b)
+ eps(d,e,f)*te(-d)*tf(-e)*tg(-f)$
Since CANONICAL is able to work inside several spaces, we can introduce also
several epsilons and make the relevant simplifications on each (sub)-spaces. This
is the goal of the next illustration.
off onespace;
define_spaces wholespace=
{dim,signature=1}; ==> t
define_spaces subspace=
{3,signature=0}; ==> t
show_spaces(); ==>
{{wholespace,dim,signature=1},
{subspace,3,signature=0}}
make_partic_tens(eps,epsilon); ==> t
make_partic_tens(kap,epsilon); ==> t
make_tensor_belong_space(eps,wholespace);
==> wholespace
make_tensor_belong_space(kap,subspace);
==> subspace
show_epsilons(); ==>
{{eps,wholespace},{kap,subspace}}
off exdelt;
aa:=kap(a,b,c)*kap(-d,-e,-f)*eps(i,j)*eps(-k,-l)$
a b c i j
- gd * gd
391
d e f k l
If there are no index summation, as in the expression above, one can develop both
terms into the delta tensor with EXDELT switched ON. In fact, the previous calcu-
lation is correct only if there are no dummy index inside the two gd’s. If some of
the indices are dummy, then we must take care of the respective spaces in which
the two gd tensors are considered. Since, the tensor themselves do not belong to
a given space, the space identification can only be made through the indices. This
is enough since the DELTA-like tensor is bloc-diagonal. With aa the result of the
above illustration, one gets, for example,:
mk_ids_belong_space({a,b,c,d,e,f},wholespace)$
mk_ids_belong_space({i,j,k,l},subspace)$
sub(d=a,e=b,k=i,aa); ==>
c j 2
2*delt *delt *( - dim + 3*dim - 2)
f l
sub(k=i,l=j,aa); ==>
a b c
- 6*gd
d e f
Most of the time, indexed objects have some symmetry property. When this prop-
erty is either full symmetry or antisymmetry, there is no difficulty to implement it
using the declarations SYMMETRIC or ANTISYMMETRIC of REDUCE. However,
most often, indexed objects are neither fully symmetric nor fully antisymmetric:
they have partial or mixed symmetries . In the DUMMY package, the declaration
SYMTREE allows to impose such type of symmetries on operators. This command
has been improved and extended to apply to tensors. In order to illustrate it, we
shall take the example of the wellknown Riemann tensor in general relativity. Let
us remind the reader that this tensor has four indices. It is separately antisymmet-
ric with respect to the interchange of the first two indices and with respect to the
interchange of the last two indices. It is symmetric with respect to the interchange
of the first two and the last two indices. In the illustration below, we show how to
express this and how CANONICAL is able to recognize mixed symmetries:
392 CHAPTER 16. USER CONTRIBUTED PACKAGES
tensor r; ==> t
symtree(r,{!+,{!-,1,2},{!-,3,4}});
ra:=r(b,a,c,d); ==>
b a c d
ra := r
a b c d
- r
ra:=r(c,d,a,b); ==>
c d a b
ra := r
a b c d
r
a b
r
c d
r(-c,-c,a,b); ==> 0
ra:=r(-c,-d,c,b); ==>
c b
ra := r
c d
b c
393
- r
c d
In the last illustration, contravariant indices are placed in front of covariant indices
and the contravariant indices are transposed. The superposition of the two partial
symmetries gives a minus sign.
There exists an important (though natural) restriction on the use of SYMTREE
which is linked to the algorithm itself: Integer used to localize indices must start
from 1, be contiguous and monotoneously increasing. For instance, one is not
allow to introduce
symtree(r,{!*,{!+,1,3},{!*,2,4}});
symtree(r,{!*,{!+,1,2},{!*,4,5}};
symtree(r,{!*,{!-,1,3},{!*,2}});
symtree(r,{!*,{!+,1,2},{!*,3,4}});
symtree(r,{!*,{!+,1,2},{!*,3,4,5}});
symtree(r,{!*,{!-,1,2},{!*,3}});
The first declaration endows r with a partial symmetry with respect to the first two
indices.
A side effect of SYMTREE is to restrict the number of indices of a generic tensor.
For instance, the second declaration in the above illustrations makes r depend on
5 indices as illustrated below:
symtree(r,{!*,{!+,1,2},{!*,3,4,5}});
d c e
r % correct
394 CHAPTER 16. USER CONTRIBUTED PACKAGES
a b
d c e
r % The sixth index is forgotten!
a b
Finally, the function REMSYM applied on any tensor identifier removes all symme-
try properties.
Another related question is the frequent need to symmetrize a tensor polynomial.
To fulfill it, the function SYMMETRIZE of the package ASSIST has been im-
proved and generalised. For any kernel (which may be either an operator or a
tensor) that function generates
symmetrize(te(x,y,z,{v}),te,cyclicpermlist); ==>
x y z y z x z x y
te (v) + te (v) + te (v)
symmetrize(te(x,y),te,permutations); ==>
x y y x
te + te
symmetrize(te(x,y),te,permutations,perm_sign); ==>
x y y x
te - te
symmetrize(te(y,x),te,permutations,perm_sign); ==>
x y y x
- te + te
If one wants to symmetrise an expression which is not a kernel, one can also use
395
ex:=te(a,-b,c)*te1(-a,-d,-e); ==>
a c
ex := te *te1
b a d e
lls:=symmetrize(ll,list,cyclicpermlist); ==>
lls := {{b,c,d,e},{c,d,e,b},{d,e,b,c},{e,b,c,d}}
sub(b=i.1,c=i.2,d=i.3,e=i.4,ex); ==>
a c a d
excyc := te *te1 + te *te1
b a d e c a e b
a e a b
+ te *te1 + te *te1
d a b c e a c d
on onespace;
depend te,x;
aa:=df(te(a,-b),x(-b))-df(te(a,-c),x(-c))$
make_partic_tens(eta,eta); ==> t
signature 1;
aa:=df(te(a,-b),x(-b))$
aa:=aa*eta(-a,-d);
a
aa := df(te ,x )*eta
b b a d
a a
df(te ,x )
d
In the last example, after contraction, the covariant dummy index b has been
changed into the contravariant dummy index a. This is allowed since the space
is metric.
397
At the moment the papers [8, 9, 14, 16, 26, 27] have been written using CDE, and
more research by CDE on integrable systems is in progress.
The readers are warmly invited to send questions, comments, etc., both on the
computations and on the technical aspects of installation and configuration of RE-
DUCE, to the author of this document.
Acknowledgements. I’d like to thank Paul H.M. Kersten, who explained to me
how to use the original CDIFF package for several computations of interest in the
Geometry of Differential Equations. When I started writing CDE I was substan-
tially helped by A.C. Norman in understanding many features of Reduce which
were deeply hidden in the source code and not well documented. This also led to
writing a manual of Reduce’s internals for programmers [21]. Moreover, I’d like
to thank the developers of the REDUCE mailing list for their prompt replies with
solutions to my problems. On the mathematical side, I would like to thank J.S.
Krasil’shchik and A.M. Verbovetsky for constant support and stimulating discus-
sions which led me to write the software. Thanks are also due to B.A. Dubrovin,
M. Casati, E.V. Ferapontov, P. Lorenzoni, M. Marvan, V. Novikov, A. Savoldi, A.
Sergyeyev, M.V. Pavlov for many interesting discussions.
16.12.2 Jet space of even and odd variables, and total derivatives
The mathematical theory for jets of even (ie standard) variables and total deriva-
tives can be found in [2, 25].
Let us consider the space Rn × Rm , with coordinates (xλ , ui ), 1 ≤ λ ≤ n, 1 ≤ i ≤
m. We say xλ to be independent variables and ui to be dependent variables. Let
us introduce the jet space J r (n, m). This is the space with coordinates (xλ , uiσ ),
399
∂ |σ| (ui ◦ s)
uiσ ◦ s(x) = .
(∂x1 )σ1 · · · (∂xn )σn
load_package cde;
Then, CDE needs to know the variables and the maximal order of derivatives. The
input can be organized as in the following example:
indep_var:={x,t}$
dep_var:={u,v}$
total_order:=10$
Here
statename:="jetuv_state.red"$
resname:="jetuv_res.red"$
These are the name of the output file for recording the internal state of the program
cde.red (and for debugging purposes), and the name of the file containing results
of the computation.
The main routine in cde.red is called as follows:
cde({indep_var,dep_var,{},total_order},{})$
Here the two empty lists are placeholders; they are of interest for computations with
odd variables/differential equations. The function cde defines derivative symbols
of the type:
u_x,v_t,u_2xt,v_xt,v_2x3t,...
400 CHAPTER 16. USER CONTRIBUTED PACKAGES
Note that the symbol v_tx does not exist in the jet space. Indeed, introducing
all possible permutations of independent variables in indices would increase the
complexity and slow down every computation.
Two lists generated by CDE can be useful: all_der_id and all_odd_id,
which are, respectively, the lists of identifiers of all even and odd variables.
Other lists are generated by CDE, but they are accessible in REDUCE symbolic
mode only. Please check the file global.txt to know the names of the lists.
It can be useful to inspect the output generated by the function cde and the above
lists in particular. All that data can be saved by the function:
save_cde_state(statename)$
The function cde defines total derivatives truncated at the order total_order.
Their coordinate expressions are of the form
∂ ∂
Dλ = + uiσλ i , (16.46)
∂xλ ∂uσ
where σ is a multiindex.
The total derivative of an argument ϕ is invoked as follows:
td(phi,x,2);
td(phi,x,t,3);
the syntax closely follows REDUCE’s syntax for standard derivatives df; the
above expression translates to Dx Dx ϕ, or D{2,0} ϕ in multiindex notation.
When in total derivatives there is a coefficient of order higher than maximal this is
replaced by the identifier letop, which is a function that depends on independent
variables. If such a function (or its derivatives) appears during computations it is
likely that we went too close to the highest order variables that we defined in the
401
file. All results of computations are scanned for the presence of such variables by
default, and if the presence of letop is detected the computation is stopped with
an error message. This usually means that we need to extend the order of the jet
space, just by increasing the number total_order.
Note that in the folder containing all examples there is also a shell script, rrr.sh
(works only under bash, a GNU/Linux command interpreter) which can be used
to run reduce on a given CDE program. When an error message about letop is
issued the script reruns the computation with a new value of total_order one
unity higher than the previous one.
The function that checks an expression for the presence of letop is check_letop.
If you wish to switch off this kind of check in order to increase the speed, the switch
checkord must be set off:
off checkord;
noexpand_td();
expand_td();
CDE can also compute on jets of supermanifolds. The theory can be found in
[11, 12, 15]. The input can be organized as follows:
indep_var:={x,t}$
dep_var:={u,v}$
odd_var:={p,q}
total_order:=10$
cde({indep_var,dep_var,odd_var,total_order},{})$
will create the jet space of the supermanifold described by the independent vari-
ables and the even and odd dependent variables, up to the order total_order.
Total derivatives truncated at the order total_order will also include odd
derivatives:
∂ ∂ ∂
Dλ = + uiσλ i + piσλ i , (16.47)
∂xλ ∂uσ ∂pσ
402 CHAPTER 16. USER CONTRIBUTED PACKAGES
ext(p,p_2xt),ext(p_x,q_t,q_x2t),...
ext(3,23),ext(1,3,5),...
as all odd variables and their derivatives are indexed by integers. Note that p
and ext(p) are just the same. The odd product of two expressions ϕ and ψ is
achieved by the CDIFF function
super_product(phi,psi);
df_odd(phi,p);
We now give the equation in the form of one or more derivatives equated to right-
hand side expressions. The left-hand side derivatives are called principal, and the
remaining derivatives are called parametric24 . Parametric coordinates are coor-
dinates on the equation manifold and its differential consequences, and principal
coordinates are determined by the differential equation and its differential conse-
quences. For scalar evolutionary equations with two independent variables para-
metric derivatives are of the type (u, ux , uxx , . . .). Note that the system must be
in passive orthonomic form; this also means that there will be no nontrivial inte-
grability conditions between parametric derivatives. (Lines beginning with % are
comments for REDUCE.) The input is formed as follows (Burger’s equation).
Systems of PDEs are input in the same way: of course, the above two lists must
have the same length. See 16.12.16 for an example.
24
This terminology dates back to Riquier, see [19]
403
cde({indep_var,dep_var,{},total_order},
{principal_der,de,{},{}})$
Here the three empty lists are placeholders; they are important for computations
with odd variables. The function cde computes principal and parametric deriva-
tives of even and odd variables, they are stored in the lists all_parametric_der,
all_principal_der, all_parametric_odd, all_principal_odd.
The function cde also defines total derivatives truncated at the order total_order
and restricted on the (even and odd) equation; this means that total derivatives are
tangent to the equation manifold. Their coordinate expressions are of the form
∂ X
i ∂ X ∂
Dλ = + u σλ + piσλ i , (16.48)
∂xλ i
∂u i
σ i
∂p σ
uσ parametric pσ parametric
where σ is a multiindex. It can happen that uiσλ (or piσλ ) is principal and must be
replaced with differential consequences of the equation. Such differential conse-
quences are called primary differential consequences, and are computed; in general
they will depend on other, possibly new, differential consequences, and so on. Such
newly appearing differential consequences are called secondary differential conse-
quences. If the equation is in passive orthonomic form, the system of all differential
consequences (up to the maximal order total_order) must be solvable in terms
of parametric derivatives only. The function cde automatically computes all neces-
sary and sufficient differential consequences which are needed to solve the system.
The solved system is available in the form of REDUCE let-rules in the variables
repprincparam_der and repprincparam_odd.
The syntax and properties (expansion and letop) of total derivatives remain the
same. For exmaple:
td(u,t);
returns
u_2x+2*u*u_x;
It is possible to deal with mixed systems on eve and odd variables. For example,
in the case of Burgers equation we can input the linearized equation as a PDE on
a new odd variable as follows (of course, in addition to what has been defined
before):
odd_var:={q}$
principal_odd:={q_t}$
de_odd:={q_2x + 2*u_x*q + 2*u*q_x}$
404 CHAPTER 16. USER CONTRIBUTED PACKAGES
cde({indep_var,dep_var,odd_var,total_order},
{principal_der,de,principal_odd,de_odd})$
pvar_df(0,lagrangian_dens,ui);
pvar_df(1,lagrangian_dens,pi);
where
• the first argument can be 0 or 1 and is the parity of the variable ui or pi;
• lagrangian_dens is L;
• ui or pi are the given dependent variables.
The Euler operator computes variational derivatives with respect to all even and
odd variables in the jet space, and arranges them in a list of two lists, the list of even
variational derivatives and the list of odd variational derivatives. The command is
euler_df(lagrangian_dens);
All the above is used in the definition of Schouten brackets, as we will see in
Subsection 16.12.6.
Linearizing (or taking the Fréchet derivative) of a vector function that defines a dif-
ferential equation yields a differential operator in total derivatives. This operator
can be restricted to the differential equation, which may be regarded as a differen-
tial constraint; the kernel of the restricted operator is the space of all symmetries
(including higher or generalized symmetries) [2, 25].
The formal adjoint of the linearization operator yields by restriction to the cor-
responding differential equation a differential operator whose kernel contains all
characteristic vectors or generating functions of conservation laws [2, 25].
405
C-differential operators
P = {ϕ : J r (n, m) → Rk }, Q = {ψ : J r (n, m) → Rs }.
where aσj r
i are differentiable functions on J (n, m), 1 ≤ i ≤ k, 1 ≤ j ≤ s. The
order of δ is the highest length of σ in the above formula.
We may consider a generalization to k-C-differential operators of the type
∆ : P1 × · · · × Ph → Q
aσi11···i
,...,σh , j
X
∆(ϕ1 , . . . , ϕh ) = ( h
Dσ1 ϕi11 · · · Dσh ϕihh ), (16.51)
σ1 ,...,σh ,i1 ,...,ih
where the enclosing parentheses mean that the value of the operator is a vector
function in Q.
A C-differential operator in CDE must be declared as follows:
mk_cdiffop(opname,num_arg,length_arg,length_target)
where
opname(j,i1,...,ih,phi1,...,phih)
There are several operations which involve differential operators. Obviously they
can be summed and multiplied by scalars.
An important example of C-differential operator is that of linearization, or Fréchet
derivative, of a vector function
F : J r (n, m) → Rk .
X ∂aσi11···i
,...,σk , j
`∆ (p1 , . . . , pk , ϕ) = ( k
Dσ ϕi Dσ1 pi11 · · · Dσk pikk )
∂uiσ
σ,σ1 ,...,σk ,i,i1 ,...,ik
Note that the matrix of coefficients is transposed. Again, the coefficients of the
adjoint operator can be found by computing ∆∗ (xσ ej ) for every basis vector ej and
every count xσ , where |σ| ≤ r, and r is the order of the operator. This operation
can be generalized to C-differential operators with h arguments.
At the moment, CDE can compute the adjoint of an operator with one argument
(Section 16.12.8).
407
then X X σj
∇ ◦ ∆(p) = ( bτj k Dτ ( ai Dσ pi ))
τ,j σ,i
In the papers [11, 12] (and independently in [10]) a scheme for dealing with (skew-
adjoint) variational multivectors was devised. The idea was that operators of the
type (16.51) could be represented by homogeneous vector superfunctions on a
supermanifold, where odd coordinates qσi would correspond to total derivatives
D σ ϕi .
The isomorphism between the two languages is given by
aσi11···i
,...,σh , j
X ih
i1
h
D σ1 ϕ 1 · · · D σ h
ϕh
σ1 ,...,σh ,i1 ,...,ih
(16.54)
aσi11···i
,...,σh , j i1
X
−→ h
qσ1 · · · qσihh
σ1 ,...,σh ,i1 ,...,ih
where qσi is the derivative of an odd dependent variable (and an odd variable itself).
A superfunction in CDE must be declared as follows:
mk_superfun(sfname,num_arg,length_arg,length_target)
where
The above parameters of the operator opname are stored in the property list25
of the identifier opname. This means that if one would like to know how many
arguments has the operator opname the answer will be the output of the command
get(’cdnarg,cdiff_op);
sfname(j)
CDE is able to deal with C-differential operators in both formalisms, and provides
conversion utilities:
• conv_cdiff2superfun(cdop,superfun)
• conv_superfun2cdiff(superfun,cdop)
where in the first case a C-differential operator cdop is converted into a vector
superfunction superfun with the same properties, and conversely.
∆: κ × · · · × κ →
{J r (n, m) → λn T ∗ Rn }/d({J
¯ r (n, m) → λn−1 T ∗ Rn }) (16.55)
It is known [10, 12] that the Schouten bracket between two variational multivec-
tors A1 , A2 can be computed in terms of their corresponding superfunction by the
formula h δA δA
1 2 δA2 δA1 i
[A1 , A2 ] = + (16.56)
δuj δpj δuj δpj
where δ/δui , δ/δpj are the variational derivatives and the square brackets at the
right-hand side should be understood as the equivalence class up to total divergen-
cies.
25
The property list is a lisp concept, see [21] for details.
409
schouten_bracket(biv1,biv2,tv12),
where biv1 and biv2 are bivectors, or C-differential operators with 2 arguments,
and tv12 is the result of the computation, which is a three-vector (it is automat-
ically declared to be a superfunction). Examples of this computation are given in
Section 16.12.18.
where σ is a constant. Then a jet space with independent variables x,t, dependent
variables u,v and odd variables in the same number as dependent variables p,q
must be created:
indep_var:={x,t}$
dep_var:={u,v}$
odd_var:={p,q}$
total_order:=8$
cde({indep_var,dep_var,odd_var,total_order},{})$
410 CHAPTER 16. USER CONTRIBUTED PACKAGES
The linearization of the above system and its adjoint are, respectively
Dt − vDx − vx −ux − uDx − σDxxx
`Bou = ,
−Dx Dt − vx − vDx
∗ −Dt + vDx Dx
`Bou =
uDx + σDxxx −Dt + vDx
Let us introduces the vector function whose zeros are the Boussinesq equation:
ell_function(f_bou,lbou);
2: lbou_sf(1);
3: lbou_sf(2);
shows the vector superfunction corresponding to `Bou . To compute the value of the
(1, 1) component of the matrix `Bou applied to an argument psi do
lbou(1,1,psi);
In order to check that the result is correct one could define the linearization as a
C-differential operator and then check that the corresponding superfunctions are
the same:
mk_cdiffop(lbou2,1,{2},2);
for all phi let lbou2(1,1,phi)
= td(phi,t) - v*td(phi,x) - v_x*phi;
for all phi let lbou2(1,2,phi)
= - u_x*phi - u*td(phi,x) - sig*td(phi,x,3);
for all phi let lbou2(2,1,phi)
= - td(phi,x);
for all phi let lbou2(2,2,phi)
411
conv_cdiff2superfun(lbou2,lbou2_sf);
lbou2_sf(1) - lbou_sf(1);
lbou2_sf(2) - lbou_sf(2);
adjoint_cdiffop(lbou,lbou_star);
4: lbou_star_sf(1);
5: lbou_star_sf(2);
1. compute linearization of a PDE of the form F = 0 and its adjoint, and save
them in the form of a vector superfunction;
2. start a new computation with the given even PDE as a constraint on the (even)
jet space;
Only the last step needs to be explained. If we are considering, eg the Boussinesq
equation, then ut and its differential consequences (ie the principal derivatives) are
not automatically expanded to the right-hand side of the equation and its differen-
tial consequences. At the moment this step is not fully automatic. More precisely,
only principal derivatives which appear as coefficients in total derivatives can be
replaced by their expression. The lists of such derivatives with the corresponding
412 CHAPTER 16. USER CONTRIBUTED PACKAGES
In this section we show the computation of (some) higher [2] (or generalized, [25])
symmetries of Burgers’equation B = ut − uxx + 2uux = 0.
We provide two ways to solve the equations for higher symmetries. The first pos-
sibility is to use dimensional analysis. The idea is that one can use the scale sym-
metries of Burgers’equation to assign “gradings” to each variable appearing in the
equation (in other words, one can use dimensional analisys). As a consequence,
one could try different ansatz for symmetries with polynomial generating funct-
ions. For example, it is possible to require that they are sum of monomials of given
degrees. This ansatz yields a simplification of the equations for symmetries, be-
cause it is possible to solve them in a “graded” way, i.e., it is possible to split them
into several equations made by the homogeneous components of the equation for
symmetries with respect to gradings.
In particular, Burgers’equation translates into the following dimensional equation:
By the rules [uz ] = [u] − [z] and [uv] = [u] + [v], and choosing [x] = −1, we
have [u] = 1 and [t] = −2. This will be used to generate the list of homogeneous
monomials of given grading to be used in the ansatz about the structure of the
generating function of the symmetries.
The file for the above computation is bur_hsy1.red and the results of the com-
putation are in results/bur_hsy1_res.red.
Another possibility to solve the equation for higher symmetries is to use a PDE
solver that is especially devoted to overdetermined systems, which is the distin-
guishing feature of systems coming from the symmetry analysis of PDEs. This ap-
proach is described below. The file for the above computation is bur_hsy2.red
and the results of the computation are in results/bur_hsy2_res.red.
413
indep_var:={x,t}$
dep_var:={u}$
deg_indep_var:={-1,-2}$
deg_dep_var:={1}$
total_order:=10$
principal_der:={u_t}$
de:={u_2x+2*u*u_x}$
cde({indep_var,dep_var,{},total_order},
{principal_der,de,{},{}})$
Higher symmetries of the given equation are functions sym depending on paramet-
ric coordinates up to some jet space order. We assume that they are graded poly-
nomials of all parametric derivatives. In practice, we generate a linear combination
of graded monomials with arbitrary coefficients, then we plug it in the equation of
the problem and find conditions on the coefficients that fulfill the equation. To con-
struct a good ansatz, it is required to make several attempts with different gradings,
possibly including independent variables, etc.. For this reason, ansatz-constructing
functions are especially verbose. In order to use such functions they must be ini-
tialized with the following command:
cde_grading(deg_indep_var,deg_dep_var,{})$
Note the empty list at the end; it playe a role only for computations involving odd
variables.
We need one operator equ whose components will be the equation of higher sym-
metries and its consequences. Moreover, we need an operator c which will play
the role of a vector of constants, indexed by a counter ctel:
ctel:=0;
414 CHAPTER 16. USER CONTRIBUTED PACKAGES
operator c,equ;
l_grad_var:=der_deg_ordering(0,all_parametric_der)$
gradmon:=graded_mon(1,5,l_grad_var)$
gradmon:={1} . gradmon$
ansatz:=for each el in gradmon join el$
Next, we define the equation `B (sym) = 0. Here, `B stands for the linearization
(Section 16.12.8). A function sym that fulfills the above equation, on account of
B = 0, is an higher symmetry.
We cannot define the linearization as a C-differential operator in this way:
bur:={u_t - (2*u*u_x+u_2x)};
ell_function(bur,lbur);
mk_cdiffop(lbur,1,{1},1);
for all phi let lbur(1,1,phi)
415
= td(phi,t)-td(phi,x,2)-2*u*td(phi,x)-2*u_x*phi;
Note that for evolutionary equations the restriction of the linearization to the equat-
ion is equivalent to just restricting total derivatives, which is automatic in CDE.
The equation becomes
equ 1:=lbur(1,1,sym);
At this point we initialize the equation solver. This is a part of the CDIFF pack-
age called integrator.red (see the original documentation inside the folder
packages/cdiff in REDUCE’s source code). In our case the above package
will solve a large sparse linear system of algebraic equations on the coefficients of
sym.
The list of variables, to be passed to the equation solver:
vars:=append(indep_var,all_parametric_der);
tel:=1;
• the equation vector equ togeher with its length tel (i.e., the total number
of equations);
• the list of variables with respect to which the system must not split the equat-
ions, i.e., variables with respect to which the unknowns are not polynomial.
In this case this list is just {};
• the constants’vector c, its length ctel, and the number of negative indexes
if any; just 0 in our example;
• the vector of free functions f that may appear in computations. Note that in
{f,0,0 } the second 0 stands for the length of the vector of free functions.
In this example there are no free functions, but the command needs the pres-
ence of at least a dummy argument, f in this case. There is also a last zero
which is the negative length of the vector f , just as for constants.
initialize_equations(equ,tel,{},{c,ctel,0},{f,0,0});
tel:=splitvars_opequ(equ,1,1,vars);
Note that splitvars_opequ needs to know the indices of the first and the last
equation in equ, and here we have only one equation as equ(1). The output
tel is the final number of splitted equations, starting just after the initial equation
equ(1).
Next command tells the solver the total number of equations obtained after running
splitvars.
put_equations_used tel;
This command solves the equations for the coefficients. Note that we have to skip
the initial equations!
off echo$
off nat$
out <<resname>>;
sym:=sym;
write ";end;";
shut <<resname>>;
on nat$
on echo$
The command off nat turns off writing in natural notation; results in this form
are better only for visualization, not for writing or for input into another computa-
tion. The command «resname» forces the evaluation of the variable resname
to its string value. The commands out and shut are for file opening and closing.
The command sym:=sym is evaluated only on the right-hand side.
One more example file is available; it concerns higher symmetries of the KdV
equation. In order to deal with symmetries explicitely depending on x and t
it is possible to use REDUCE and CDE commands in order to have sym =
x*(something of degree 3) + t*(something of degree 5) + (something of degree
2); this yields scale symmetries. Or we could use sym = x*(something of degree
1) + t*(something of degree 3) + (something of degree 0); this yields Galilean
boosts.
417
total_eq:=lbur(1,1,ansatz)$
The above command will issue an error if the list {total_eq} depends on the
flag variable letop. In this case the computation has to be redone within a jet
space of higher order.
The equation ell_b(ansatz)=0 is polynomial with respect to the variables of
order higher than those appearing in ansatz. For this reason, its coefficients can
be put to zero independently. This is the reason why the PDEs that determine
symmetries are overdetermined. To tell this to CRACK, we issue the command
split_vars:=diffset(all_parametric_der,even_vars)$
418 CHAPTER 16. USER CONTRIBUTED PACKAGES
The list split_vars contains variables which are in the current CDE jet space
but not in even_vars.
Then, we load the package CRACK and get results.
load_package crack;
crack_results:=crack(total_eq,{},{ansatz},split_vars);
{{{},
{ansatz=(2*c_12*u_x + 2*c_13*u*u_x + c_13*u_2x
+ 6*c_8*u**2*u_x + 6*c_8*u*u_2x + 2*c_8*u_3x
+ 6*c_8*u_x**2)/2},{c_8,c_13,c_12},
{}}}$
In this section we will find (some) local conservation laws for the KdV equation
F = ut − uxxx + uux = 0. Concretely, we have to find non-trivial 1-forms
f = fx dx+ft dt on F = 0 such that df ¯ = 0 on F = 0. “Triviality” of conservation
laws is a delicate matter, for which we invite the reader to have a look in [2].
The files containing this example are kdv_lcl1,kdv_lcl2 and the correspond-
ing results and debug files.
We suppose that the conservation law has the form ω = fx dx + ft dt. Using the
same ansatz as in the previous example we assume
¯
Next we define the equation d(ω) = 0, where d¯ is the total exterior derivative
restricted to the equation.
equ 1:=td(fx,t)-td(ft,x)$
equ 1:=fx-td(f0,x);
equ 2:=ft-td(f0,t);
after having loaded the values fx and ft found by the previous program. In order
to do that we have to introduce two new counters:
operator cc,equ;
cctel:=0;
fxnontriv := fx-td(f0,x);
ftnontriv := ft-td(f0,t);
we obtain
fxnontriv := c(2)*u$
ftnontriv := (c(2)*(u**2 + 2*u_2x))/2$
In this section we will show how to compute local Hamiltonian operators for
Korteweg–de Vries, Boussinesq and Kadomtsev–Petviashvili equations. It is inter-
esting to note that we will adopt the same computational scheme for all equations,
even if the latter is not in evolutionary form and it has more than two independent
variables. This comes from a new mathematical theory which started in [12] for
evolution equations and was later extended to general differential equations in [14].
420 CHAPTER 16. USER CONTRIBUTED PACKAGES
Here we will find local Hamiltonian operators for the KdV equation ut = uxxx +
uux . A necessary condition for an operator to be Hamiltonian is that it sends
generating functions (or characteristics, according with [25]) of conservation laws
to higher (or generalized) symmetries. As it is proved in [12], this amounts at
solving `¯KdV (phi) = 0 over the equation
ut = uxxx + uux
pt = pxxx + upx
or, in geometric terminology, find the shadows of symmetries on the `∗ -covering
of the KdV equation, with the further condition that the shadows must be linear in
the p-variables. Note that the second equation (in odd variables!) is just the adjoint
of the linearization of the KdV equation applied to an odd variable.
The file containing this example is kdv_lho1.
We stress that the linearization `¯KdV (phi) = 0 is the equation
td(phi,t)-u*td(phi,x)-u_x*phi-td(phi,x,3)=0
but the total derivatives are lifted to the `∗ covering, hence they contain also deriva-
tives with respect to p’s. We can define a linearization operator lkdv as usual.
In order to produce an ansatz which is a superfunction of one odd variable (or a
linear function in odd variables) we produce two lists: the list l_grad_var of all
even variables collected by their gradings and a similar list l_grad_odd for odd
variables:
l_grad_var:=der_deg_ordering(0,all_parametric_der)$
l_grad_odd:={1} . der_deg_ordering(1,all_parametric_odd)$
gradmon:=graded_mon(1,10,l_grad_var)$
gradmon:={1} . gradmon$
We need a list of graded monomials which are linear in odd variables. The func-
tion mkalllinodd produces all monomials which are linear with respect to the
variables from l_grad_odd, have (monomial) coefficients from the variables in
l_grad_var, and have total scale degrees from 1 to 6. Such monomials are then
converted to the internal representation of odd variables.
linodd:=mkalllinodd(gradmon,l_grad_odd,1,6)$
Note that all odd variables have positive scale degrees thanks to our initial choice
deg_odd_var:=1;. Finally, the ansatz for local Hamiltonian operators:
equ 1:=lkdv(1,1,sym);
tel:=splitext_opequ(equ,1,1);
in order to split the polynomial equation with respect to the ext variables, then
splitvars
tel2:=splitvars_opequ(equ,2,tel,vars);
put_equations_used tel;
for i:=2:tel do integrate_equation i;
end;
p x → Dx ,
1 1
(3p3x + 2upx + ux p) → (3Dxxx + 2uDx + ux )
3 3
Note that each operator is multiplied by one arbitrary real constant, c(5) and
c(2).
The same problem can be approached using CRACK, as follows (file kdv_lho2.red).
An ansatz is constructed by the following instructions:
ctemp:=0$
ansatz:=for each el in ext_vars sum
mkid(s,ctemp:=ctemp+1)*el$
operator ell_f$
for all sym let ell_f(sym)=
td(sym,t) - u*td(sym,x) - u_x*sym - td(sym,x,3)$
and the equation to be solved, together with the usual test that checks for the nedd
to enlarge the jet space:
total_eq:=ell_f(ansatz)$
Finally, we split the above equation by collecting all coefficients of odd variables:
system_eq:=splitext_list({total_eq})$
and we feed CRACK with the equations that consist in asking to the above coeffi-
cients to be zero:
load_package crack;
crack_results:=crack(system_eq,{},unk,
diffset(all_parametric_der,even_vars));
crack_results := {{{},
{s4=(3*c_17)/2,s3=0,s2=c_16 + c_17*u,s1=(c_17*u_x)/2},
{c_17,c_16},
{}}}$
423
There is no conceptual difference when computing for systems of PDEs with re-
spect to the previous computations for scalar equations. We will look for Hamilto-
nian structures for the dispersionless Boussinesq equation (16.58).
We will proceed by dimensional analysis. Gradings can be taken as
where p, q are the two odd coordinates. We have the `∗Bou covering equation
−pt + vpx + qx = 0
upx + σpxxx − qt + vqx = 0
u − ux v − uvx − σvxxx = 0
t
vt − ux − vvx = 0
indep_var:={x,t}$
dep_var:={u,v}$
odd_var:={p,q}$
deg_indep_var:={-1,-2}$
deg_dep_var:={2,1}$
deg_odd_var:={1,2}$
total_order:=8$
principal_der:={u_t,v_t}$
de:={u_x*v+u*v_x+sig*v_3x,u_x+v*v_x}$
principal_odd:={p_t,q_t}$
de_odd:={v*p_x+q_x,u*p_x+sig*p_3x+v*q_x}$
The ansatz for the components of the Hamiltonian operator, of scale degree be-
tween 1 and 6, is
linodd:=mkalllinodd(gradmon,l_grad_odd,1,6)$
phi1:=(for each el in linodd sum (c(ctel:=ctel+1)*el))$
phi2:=(for each el in linodd sum (c(ctel:=ctel+1)*el))$
and the equation for shadows of symmetries is (lbou2 is taken from Sec-
tion 16.12.8)
After the usual procedures for decomposing polynomials we obtain three local
Hamiltonian operators:
indep_var:={t,x,y}$
dep_var:={u}$
odd_var:={p}$
deg_indep_var:={-3,-2,-1}$
deg_dep_var:={2}$
deg_odd_var:={1}$
total_order:=6$
principal_der:={u_2y}$
de:={u_tx-u_x**2-u*u_2x-(1/12)*u_4x}$
principal_odd:={p_2y}$
de_odd:={p_tx-u*p_2x-(1/12)*p_4x}$
linodd:=mkalllinodd(gradmon,l_grad_odd,1,5)$
425
After solving the equation for shadows of symmetries in the cotangent covering
phi := c(13)*p_2x$
H : P̂ → κ (16.60)
As the operators are mainly used to define a bracket operation and a Lie alge-
bra structure on conservation laws, two properties are required: skew-adjointness
H ∗ = −H (corresponding with skew-symmetry of the bracket) and [H, H] = 0
(corresponding with the Jacobi property of the bracket).
In order to compute the two properties we proceed as follows. Skew-adjointness
is checked by computing the adjoint and verifying that the sum with the initial
operator is zero.
426 CHAPTER 16. USER CONTRIBUTED PACKAGES
Ĥ : κ̂ × κ̂ → ∧n T ∗ Rn (16.61)
H = aik σ pk σ → Ĥ = aik σ pk σ pi .
Note that the product pk σ pi is anticommutative since p’s are odd variables.
After that a C-differential operator of the type of H has been converted into a
bivector it is possible to apply the formulae (16.56) and (16.57) in order to compute
the Schouten bracket. This is what we will see in next section.
We can do the above computations using KdV equation as a test case (see the file
kdv_lho3.red).
Let us load the above operators:
operator ham1;
for all psi1 let ham1(psi1)=td(psi1,x);
operator ham2;
for all psi2 let ham2(psi2)=
(1/3)*u_x*psi2 + td(psi2,x,3) + (2/3)*u*td(psi2,x);
conv_cdiff2superfun(ham1,sym1);
conv_cdiff2superfun(ham2,sym2);
sym1(1) := {p_x};
sym2(2) := {(1/3)*p*u_x + p_3x + (2/3)*p_x*u};
adjoint_cdiffop(ham1,ham1_star);
adjoint_cdiffop(ham2,ham2_star);
427
ham1_star_sf(1)+sym1(1);
ham2_star_sf(1)+sym2(1);
conv_genfun2biv(sym1_odd,biv1);
conv_genfun2biv(sym2_odd,biv2);
biv1(1) := - ext(p,p_x);
biv2(1) := - (1/3)*( - 3*ext(p,p_3x) - 2*ext(p,p_x)*u);
Finally, the three Schouten brackets [Ĥi , Ĥj ] are computed, with i, j = 1, 2:
schouten_bracket(biv1,biv1,sb11);
schouten_bracket(biv1,biv2,sb12);
schouten_bracket(biv2,biv2,sb22);
This subsection refers to the the example file wdvv_biham1.red. The simplest
nontrivial case of the WDVV equations is the third-order Monge–Ampère equat-
2 −f
ion, fttt = fxxt xxx fxtt [4]. This PDE can be transformed into hydrodynamic
form,
at = bx , bt = cx , ct = (b2 − ac)x ,
via the change of variables a = fxxx , b = fxxt , c = fxtt . This system possesses
two Hamiltonian formulations [7]:
a δHi /δa
b = Ai δHi /δb , i = 1, 2
c t δHi /δc
R
with the Hamiltonian H1 = c dx, and the homogeneous third-order Hamiltonian
operator
0 0 Dx
A2 = D x 0 Dx −Dx a Dx ,
Dx −aDx Dx b + bDx + aDx a
with the nonlocal Hamiltonian
Z
1 −1 2
−1 −1
H2 = − a Dx b + Dx bDx c dx.
2
Both operators are of Dubrovin–Novikov type [5, 6]. This means that the operators
are homogeneous with respect to the grading |Dx | = 1. It follows that the operators
are form-invariant under point transformations of the dependent variables, ui =
ui (ũj ). Here and in what follows we will use the letters ui to denote the dependent
variables (a, b, c). Under such transformations, the coefficients of the operators
transform as differential-geometric objects.
The operator A1 has the general structure
A1 = g1ij Dx + Γij k
k ux
operator a1;
We could also use one specialized Reduce package for the computation of
the Christoffel symbols, like RedTen or GRG. Assuming that the operators
gamma_hi(i,j,k) have been defined equal to Γij k and computed in the sys-
tem using the inverse matrix gij of the leading coefficient contravariant metric26
3 1
−2 2a b
g ij = 12 a b 3
2c
3 2
b 2 c 2(b − ac)
then, provided we defined a list dep_var of the dependent variables, we could set
operator gamma_hi_con;
for all i,j let gamma_hi_con(i,j) =
(
for k:=1:3 sum gamma_hi(i,j,k)*mkid(part(dep_var,k),!_x)
)$
and
operator a1$
for all i,j,psi let a1(i,j,psi) =
gu1(i,j)*td(psi,x)+(for k:=1:3 sum gamma_hi_con(i,j)*psi
)$
The third order operator can be reconstructed as follows. Observe that the leading
contravariant metric is
0 0 1
g ij = 0 1 −a
1 −a 2b + a2
gu3:=gl3**(-1)$
operator c_lo$
for i:=1:3 do
for j:=1:3 do
for k:=1:3 do
<<
c_lo(i,j,k):=
26
Indeed in the example file wdvv_biham1.red there are procedures for computing all those
quantities.
430 CHAPTER 16. USER CONTRIBUTED PACKAGES
(1/3)*(df(gl3(k,i),part(dep_var,j))
- df(gl3(j,i),part(dep_var,k)))$
>>$
templist:={}$
operator c_hi$
for i:=1:ncomp do
for j:=1:ncomp do
for k:=1:ncomp do
c_hi(i,j,k):=
<<
templist:=
for m:=1:ncomp join
for n:=1:ncomp collect
gu3(n,i)*gu3(m,j)*c_lo(m,n,k)$
templist:=part(templist,0):=plus
>>$
operator c_hi_con$
for i:=1:ncomp do
for j:=1:ncomp do
c_hi_con(i,j):=
<<
templist:=for k:=1:ncomp collect
c_hi(i,j,k)*mkid(part(dep_var,k),!_x)$
templist:=part(templist,0):=plus
>>$
operator aa2$
for all i,j,psi let aa2(i,j,psi) =
td(
gu3(i,j)*td(psi,x,2)+c_hi_con(i,j)*td(psi,x)
,x)$
conv_cdiff2genfun(aa1,sym1)$
conv_cdiff2genfun(aa2,sym2)$
431
conv_genfun2biv(sym1,biv1)$
conv_genfun2biv(sym2,biv2)$
schouten_bracket(biv1,biv1,sb11);
schouten_bracket(biv1,biv2,sb12);
schouten_bracket(biv2,biv2,sb22);
Needless to say, the result of the last three command is a list of zeroes.
We observe that the same software can be used to prove the bi-Hamiltonianity of a
6-component WDVV system [26].
The formulae (16.56), (16.57) hold also in the case of multidimensional operators,
ie operators with total derivatives in more than one independent variables. Here
we give one Hamiltonian operator H and we give two more variational bivectors
P1 , P2 ; all operators are of Dubrovin–Novikov type (homogeneous). We check the
compatibility by computing [H, P1 ] and [H, P2 ]. Such computations are standard
for the problem of computing the Hamiltonian cohomology of H.
This example has been provided by M. Casati. The file of the computation is
dn2d_sb1.red. The dependent variables are p1 , p2 .
Let us set
Dx 0
H= (16.65)
0 Dy
11
P1 P112
P1 = (16.66)
P121 P122
where
∂g 2 ∂g ∂g ∂g
P111 =2 1
py Dx + 1 p2xy + 1 2 p2x p2y + 2 1 p1x p2y
∂p ∂p ∂p ∂p ∂ p
∂g ∂f ∂f
P121 = − f Dx2 + gDy2 + 2 p2y Dy − ( 1 p1x + 2 2 p2x )Dx
∂p ∂p ∂p
∂f ∂f ∂f
− 2 2 p2x p2x − 1 2 p1x p2x − 2 p22 x;
∂ p ∂p ∂p ∂p
∂f ∂g ∂g 1
P112 =f Dx2 − gDy2 + 1 p1x Dx − p2
y + 2 p Dy
∂p ∂p2 ∂p1 y
∂g ∂g ∂g
− 2 1 p1y p1y − 1 2 p1y p2y − 1 p12y ;
∂ p ∂p ∂p ∂p
∂f 1 ∂f 1 ∂f ∂f
P122 =2 2 px Dy + 2 px y + 1 2 p1x p1y + 2 2 p1x p2y ;
∂p ∂p ∂p ∂p ∂ p
432 CHAPTER 16. USER CONTRIBUTED PACKAGES
mk_cdiffop(aa2,1,{2},2)$
for all psi let aa2(1,1,psi) =
2*df(g,p1)*p2_y*td(psi,x) + df(g,p1)*p2_xy*psi
+ df(g,p1,p2)*p2_x*p2_y*psi + df(g,p1,2)*p1_x*p2_y*psi;
mk_cdiffop(aa3,1,{2},2)$
for all psi let aa3(1,1,psi) = aa2(1,1,psi);
for all psi let aa3(1,2,psi) = aa2(2,1,psi);
for all psi let aa3(2,1,psi) = aa2(1,2,psi);
for all psi let aa3(2,2,psi) = aa2(2,2,psi);
conv_cdiff2superfun(aa1,sym1)$
conv_cdiff2superfun(aa2,sym2)$
conv_cdiff2superfun(aa3,sym3)$
adjoint_cdiffop(aa1,aa1_star);
adjoint_cdiffop(aa2,aa2_star);
adjoint_cdiffop(aa3,aa3_star);
conv_cdiff2superfun(aa1,sym1)$
conv_cdiff2superfun(aa2,sym2)$
conv_cdiff2superfun(aa3,sym3)$
conv_genfun2biv(sym1,biv1)$
conv_genfun2biv(sym2,biv2)$
conv_genfun2biv(sym3,biv3)$
schouten_bracket(biv1,biv1,sb11);
schouten_bracket(biv1,biv2,sb12);
schouten_bracket(biv1,biv3,sb13);
More formulae are currently being implemented in the system, like symplecticity
and Nijenhuis condition for recursion operators [13]. Interested readers are warmly
invited to contact R. Vitolo for questions/feature requests.
In this section we will show an experimental way to find nonlocal operators. The
word ‘experimental’ comes from the lack of a comprehensive mathematical theory
of nonlocal operators; in particular, it is still missing a theoretical framework for
Schouten brackets of nonlocal opeartors in the odd variable language.
In any case we will achieve the results by means of a covering of the cotangent
covering. Indeed, it can be proved that there is a 1 − 1 correspondence between
(higher) symmetries of the initial equation and conservation laws on the cotangent
covering. Such conservation laws provide new potential variables, hence a cover-
ing (see [2] for theoretical details on coverings).
In Section 16.12.25 we will also discuss a procedure for finding conservation laws
from their generating functions that is of independent interest.
Here we will compute some nonlocal Hamiltonian operators for the KdV equation.
The result of the computation (without the details below) has been published in
434 CHAPTER 16. USER CONTRIBUTED PACKAGES
[12].
We have to solve equations of the type ddx(ct)-ddt(cx) as in 16.12.13. The
main difference is that we will attempt a solution on the `∗ -covering (see Subsec-
tion 16.12.14). For this reason, first of all we have to determine covering variables
with the usual mechanism of introducing them through conservation laws, this time
on the `∗ -covering.
As a first step, let us compute conservation laws on the `∗ -covering whose compo-
nents are linear in the p’s. This computation can be found in the file kdv_nlcl1
and related results and debug files.
The conservation laws that we are looking for are in 1 − 1 correspondence with
symmetries of the initial equation [12]. We will look for conservatoin laws which
correspond to Galilean boost, x-translation, t-translation at the same time. In the
case of 2 independent variables and 1 dependent variable, one could prove that one
component of such conservation laws can always be written as sym*p as follows:
c1x:=(t*u_x+1)*p$ % degree 1
c2x:=u_x*p$ % degree 4
c3x:=(u*u_x+u_3x)*p$ % degree 6
c1t:=f1*p+f2*p_x+f3*p_2x$
% degree 6
c2t:=(for each el in linodd6 sum (c(ctel:=ctel+1)*el))$
% degree 8
c3t:=(for each el in linodd8 sum (c(ctel:=ctel+1)*el))$
where we already introduced the sets linodd6 and linodd8 of 6-th and 8-th
degree monomials which are linear in odd variables (see the source code). For the
first conservation law solutions of the equation
f3:=t*u_x+1$
f2:=-td(f3,x)$
f1:=u*f3+td(f3,x,2)$
equ 2:=td(c2t,x)-td(c2x,t);
435
equ 3:=td(c3t,x)-td(c3x,t);
They are solved in the usual way (see the source code of the example and the results
file kdv_nlcl1_res).
Now, we solve the equation for shadows of nonlocal symmetries in a covering of
the `∗ -covering (source file kdv_nlho1). We can produce such a covering by
introducing three new nonlocal (potential) variables ra,rb,rc. We are going to
look for non-local Hamiltonian operators depending linearly on one of these vari-
ables. To this aim we modify the odd part of the equation to include the components
of the above conservation laws as the derivatives of the new non-local variables r1,
r2, r3:
principal_odd:={p_t,r1_x,r1_t,r2_x,r2_t,r3_x,r3_t}$
de_odd:={u*p_x+p_3x,
p*(t*u_x + 1),
p*t*u*u_x + p*t*u_3x + p*u + p_2x*t*u_x + p_2x
- p_x*t*u_2x,
p*u_x,
p*u*u_x + p*u_3x + p_2x*u_x - p_x*u_2x,
p*(u*u_x + u_3x),
p*u**2*u_x + 2*p*u*u_3x + 3*p*u_2x*u_x + p*u_5x
+ p_2x*u*u_x + p_2x*u_3x - p_x*u*u_2x
- p_x*u_4x - p_x*u_x**2}$
The scale degree analysis of the local Hamiltonian operators of the KdV equation
leads to the formulation of the ansatz
where linext is the list of graded mononials which are linear in odd variables
and have degree 7 (see the source file). The equation for shadows of nonlocal
symmetries in `∗ -covering
equ 1:=td(phi,t)-u*td(phi,x)-u_x*phi-td(phi,x,3);
Higher non-local Hamiltonian operators could also be found [12]. The CRACK
approach also holds for non-local computations.
436 CHAPTER 16. USER CONTRIBUTED PACKAGES
Following the ideas in [12], a differential operator that sends symmetries into sym-
metries can be found as a shadow of symmetry on the `-covering of the KdV equat-
ion, with the further condition that the shadows must be linear in the covering
q-variables. The tangent covering of the KdV equation is
ut = uxxx + uux
qt = ux q + uqx + qxxx
and we have to solve the equation `¯KdV (phi) = 0, where `¯KdV means that the
linearization of the KdV equation is lifted over the tangent covering.
The file containing this example is kdv_ro1.red. The example closely follows
the computational scheme presented in [16].
Usually, recursion operators are non-local: operators of the form Dx−1 appear in
their expression. Geometrically we interpret this kind of operator as follows. We
introduce a conservation law on the cotangent covering of the form
ω = rt dx + rx dt
The operator q stands for the identity operator, which is (and must be!) always a
solution; the other solution corresponds to the Lenard–Magri operator
3Dxx + 2u + ux Dx−1 .
`F (p) = pxz + pty − 2utx ptx + u2x p2t + u2t p2x = 0. (16.68)
It is not difficult to realize that the above equation can be written in explicit con-
servative form as
This is a new nonlocal variable for the (co)tangent covering of the Plebanski equat-
ion. We can load the Plebanski equation together with its nonlocal variable r as
follows:
indep_var:={t,x,y,z}$
dep_var:={u}$
odd_var:={p,r}$
deg_indep_var:={-1,-1,-4,-4}$
deg_dep_var:={1}$
deg_odd_var:={1,4}$
total_order:=6$
principal_der:={u_xz}$
de:={-u_ty+u_tx**2-u_2t*u_2x}$
% rhs of the equations that define the nonlocal variable
rt:= - p_z - u_2t*p_x + u_tx*p_t$
rx:= p_y + u_2x*p_t - u_tx*p_x$
% We add conservation laws as new nonlocal odd variables;
principal_odd:={p_xz,r_x,r_t}$
%
de_odd:={-p_ty+2*u_tx*p_tx-u_2x*p_2t-u_2t*p_2x,rx,rt}$
We can easily verify that the integrability condition for the new nonlocal variable
holds:
td(r,t,x) - td(r,x,t);
438 CHAPTER 16. USER CONTRIBUTED PACKAGES
the result is 0.
Now, we look for nonlocal recursion operators in the tangent covering using the
new nonlocal odd variable r. We can load the equation exactly as before. We look
for recursion operators which depend on r (which has scale degree 4); we produce
the following ansatz for phi:
linodd:=mkalllinodd(gradmon,l_grad_odd,1,4)$
phi:=(for each el in linodd sum (c(ctel:=ctel+1)*el))$
equ 1:=td(phi,x,z)+td(phi,t,y)-2*u_tx*td(phi,t,x)
+u_2x*td(phi,t,2)+u_2t*td(phi,x,2)$
The solution is
hence we obtain the identity operator p and the new nonlocal operator r. It can be
proved that changing coordinates to the evolutionary presentation yields the local
operator (which has a much more complex expression than the identity operator)
and one of the nonlocal operators of [?]. More details on this computation can be
found in [?].
CDE 1.0 This version was published in October 2014. It was programmed in
REDUCE’s algebraic mode, so its capabilities were limited, and its speed was
severely affected by the systematic use of the package assist for manipulating
algebraic lists. Its features were:
CDE 1.0 has never ben included in the official REDUCE distribution, and it is still
available at [1].
Bibliography
[9] E.V. F ERAPONTOV, M.V. PAVLOV, R.F. V ITOLO, Towards the classifica-
tion of homogeneous third-order Hamiltonian operators, http://arxiv.
org/abs/1508.02752
[10] E. Getzler, A Darboux theorem for Hamiltonian operators in the formal cal-
culus of variations, Duke J. Math. 111 (2002), 535-560.
[21] A.C. N ORMAN , R. V ITOLO, Inside Reduce, part of the official REDUCE
documentation included in the source code, see below.
[22] M.C. N UCCI, Interactive REDUCE programs for calculating classical, non-
classical, and approximate symmetries of differential equations, in Compu-
tational and Applied Mathematics II. Differential Equations, W.F. Ames, and
P.J. Van der Houwen, Eds., Elsevier, Amsterdam (1992) pp. 345–350.
441
[23] M.C. N UCCI, Interactive REDUCE programs for calculating Lie point, non-
classical, Lie-Bäcklund, and approximate symmetries of differential equat-
ions: manual and floppy disk, in CRC Handbook of Lie Group Analysis of
Differential Equations. Vol. 3 N.H. Ibragimov, Ed., CRC Press, Boca Raton
(1996) pp. 415–481.
[26] M.V. PAVLOV, R.F. V ITOLO: On the bi-Hamiltonian geometry of the WDVV
equations, http://arxiv.org/abs/1409.7647
[30] T. W OLF, A. B RAND, Investigating DEs with CRACK and Related Pro-
grams, SIGSAM Bulletin, Special Issue, (June 1995), p 1-8.
16.13.1 Introduction
This brief guide refers to using CDIFF, a set of symbolic computation programs
devoted to computations in geometry of DEs and developed by P. Gragert, P.H.M.
Kersten, G. Post and G. Roelofs at the University of Twente, The Netherlands.
Initially, the development of the CDIFF packages was started by Gragert and Ker-
sten for symmetry computations in DEs, then they have been partly rewritten and
extended by Roelofs and Post. The CDIFF packages consist of 3 program files plus
a utility file; only the main three files are documented [7, 8, 9]. The CDIFF pack-
ages, as well as a copy of the documentation (including this manual) and several
example programs, can be found both at Sourceforge in the sources of REDUCE
[1] and in the Geometry of Differential Equations (GDEQ for short) web site [2].
The name of the packages, CDIFF, comes from the fact that the package is aimed
at defining differential operators in total derivatives and do computations involving
them. Such operators are called C-differential operators (see [11]).
The main motivation for writing this manual was that REDUCE 3.8 recently be-
443
came free software, and can be downloaded here [1]. For this reason, we are able
to make our computations accessible to a wider public, also thanks to the inclusion
of CDIFF in the official REDUCE distribution. The readers are warmly invited
to send questions, comments, etc., both on the computations and on the technical
aspects of installation and configuration of REDUCE, to the author of the present
manual.
Acknowledgements. My warmest thanks are for Paul H.M. Kersten, who ex-
plained to me how to use the CDIFF packages for several computations of in-
terest in the Geometry of Differential Equations. I also would like to thank I.S.
Krasil’shchik and A.M. Verbovetsky for constant support and stimulating discus-
sions which led me to write this text.
load_package(cdiff);
All programs that we will discuss in this manual can be found inside the subfolder
examples in the folder which contains this manual. In order to run them just do
in "filename.red";
• Program files have the extension .red. This will load automatically the
reduce-ide mode in emacs (provided you made the installation steps de-
scribed in the reduce-ide guides).
equationname_typeofcomputation_version.red
where equationname stands for the shortened name of the equation (e.g.
Korteweg–de Vries is always indicated by KdV), typeofcomputation
stands for the type of geometric object which is computed with the given file,
for example symmetries, Hamiltonian operators, etc., version is a version
number.
• More specific information, like the date and more details on the computation
done in each version, are included as comment lines at the very beginning of
each file.
444 CHAPTER 16. USER CONTRIBUTED PACKAGES
Now we describe some examples of computations with CDIFF. The parts of exam-
ples which are shared between all examples are described only once. We stress that
all computations presented in this document are included in the official REDUCE
distribution and can be also downloaded at the GDEQ website [2]. The examples
can be run with REDUCE by typing in "program.red"; at the REDUCE
prompt, as explained above.
Remark. The mathematical theories on which the computations are based can be
found in [11, 12].
Higher symmetries
By the rules [uz ] = [u] − [z] and [uv] = [u] + [v], and choosing [x] = −1, we
have [u] = 1 and [t] = −2. This will be used to generate the list of homogeneous
monomials of given grading to be used in the ansatz about the structure of the
generating function of the symmetries.
The following instructions initialize the total derivatives. The first string is the
name of the vector field, the second item is the list of even variables (note that
u1, u2, ... are ux , uxx , . . . ), the third item is the list of odd (non-commuting)
variables (‘ext’ stands for ‘external’ like in external (wedge) product). Note that in
this example odd variables are not strictly needed, but it is better to insert some of
them for syntax reasons.
super_vectorfield(ddx,{x,t,u,u1,u2,u3,u4,u5,u6,u7,
u8,u9,u10,u11,u12,u13,u14,u15,u16,u17},
{ext 1,ext 2,ext 3,ext 4,ext 5,ext 6,ext 7,ext 8,ext 9,
ext 10,ext 11,ext 12,ext 13,ext 14,ext 15,ext 16,ext 17,
ext 18,ext 19,ext 20,ext 21,ext 22,ext 23,ext 24,ext 25,
445
super_vectorfield(ddt,{x,t,u,u1,u2,u3,u4,u5,u6,u7,
u8,u9,u10,u11,u12,u13,u14,u15,u16,u17},
{ext 1,ext 2,ext 3,ext 4,ext 5,ext 6,ext 7,ext 8,ext 9,
ext 10,ext 11,ext 12,ext 13,ext 14,ext 15,ext 16,ext 17,
ext 18,ext 19,ext 20,ext 21,ext 22,ext 23,ext 24,ext 25,
ext 26,ext 27,ext 28,ext 29,ext 30,ext 31,ext 32,ext 33,
ext 34,ext 35,ext 36,ext 37,ext 38,ext 39,ext 40,ext 41,
ext 42,ext 43,ext 44,ext 45,ext 46,ext 47,ext 48,ext 49,
ext 50,ext 51,ext 52,ext 53,ext 54,ext 55,ext 56,ext 57,
ext 58,ext 59,ext 60,ext 61,ext 62,ext 63,ext 64,ext 65,
ext 66,ext 67,ext 68,ext 69,ext 70,ext 71,ext 72,ext 73,
ext 74,ext 75,ext 76,ext 77,ext 78,ext 79,ext 80
});
Specification of the vectorfield ddx. The meaning of the first index is the par-
ity of variables. In particular here we have just even variables. The second in-
dex parametrizes the second item (list) in the super_vectorfield declara-
tion. More precisely, ddx(0,1) stands for ∂/∂x, ddx(0,2) stands for ∂/∂t,
ddx(0,3) stands for ∂/∂u, ddx(0,4) stands for ∂/∂ux , . . . , and all coordi-
nates x, t, ux , . . . , are treated as even coordinates. Note that ‘$’ suppresses the
output.
ddx(0,1):=1$
ddx(0,2):=0$
ddx(0,3):=u1$
ddx(0,4):=u2$
ddx(0,5):=u3$
ddx(0,6):=u4$
ddx(0,7):=u5$
ddx(0,8):=u6$
ddx(0,9):=u7$
ddx(0,10):=u8$
ddx(0,11):=u9$
ddx(0,12):=u10$
446 CHAPTER 16. USER CONTRIBUTED PACKAGES
ddx(0,13):=u11$
ddx(0,14):=u12$
ddx(0,15):=u13$
ddx(0,16):=u14$
ddx(0,17):=u15$
ddx(0,18):=u16$
ddx(0,19):=u17$
ddx(0,20):=letop$
ddt(0,1):=0$
ddt(0,2):=1$
ddt(0,3):=ut$
ddt(0,4):=ut1$
ddt(0,5):=ut2$
ddt(0,6):=ut3$
ddt(0,7):=ut4$
ddt(0,8):=ut5$
ddt(0,9):=ut6$
ddt(0,10):=ut7$
ddt(0,11):=ut8$
ddt(0,12):=ut9$
ddt(0,13):=ut10$
ddt(0,14):=ut11$
ddt(0,15):=ut12$
ddt(0,16):=ut13$
ddt(0,17):=ut14$
ddt(0,18):=letop$
ddt(0,19):=letop$
sddt(0,20):=letop$
We now give the equation in the form one of the derivatives equated to a right-hand
side expression. The left-hand side derivative is called principal, and the remaining
derivatives are called parametric27 . For scalar evolutionary equations with two
independent variables internal variables are of the type (t, x, u, ux , uxx , . . .).
27
This terminology dates back to Riquier, see [13]
447
ut:=u2+2*u*u1;
ut1:=ddx ut;
ut2:=ddx ut1;
ut3:=ddx ut2;
ut4:=ddx ut3;
ut5:=ddx ut4;
ut6:=ddx ut5;
ut7:=ddx ut6;
ut8:=ddx ut7;
ut9:=ddx ut8;
ut10:=ddx ut9;
ut11:=ddx ut10;
ut12:=ddx ut11;
ut13:=ddx ut12;
ut14:=ddx ut13;
Test for verifying the commutation of total derivatives. Highest order defined terms
may yield some letop.
operator ev;
This is the list of variables with respect to their grading, starting from degree one.
all_graded_der:={{u},{u1},{u2},{u3},{u4},{u5},
{u6},{u7},{u8},{u9},{u10},{u11},{u12},{u13},{u14},{u15},
{u16},{u17}};
This is the list of all monomials of degree 0, 1, 2, . . . which can be constructed from
the above list of elementary variables with their grading.
grd0:={1};
grd1:= mkvarlist1(1,1)$
grd2:= mkvarlist1(2,2)$
grd3:= mkvarlist1(3,3)$
grd4:= mkvarlist1(4,4)$
grd5:= mkvarlist1(5,5)$
grd6:= mkvarlist1(6,6)$
grd7:= mkvarlist1(7,7)$
grd8:= mkvarlist1(8,8)$
grd9:= mkvarlist1(9,9)$
grd10:= mkvarlist1(10,10)$
448 CHAPTER 16. USER CONTRIBUTED PACKAGES
grd11:= mkvarlist1(11,11)$
grd12:= mkvarlist1(12,12)$
grd13:= mkvarlist1(13,13)$
grd14:= mkvarlist1(14,14)$
grd15:= mkvarlist1(15,15)$
grd16:= mkvarlist1(16,16)$
operator c,equ;
ctel:=0;
sym:=
(for each el in grd0 sum (c(ctel:=ctel+1)*el))+
(for each el in grd1 sum (c(ctel:=ctel+1)*el))+
(for each el in grd2 sum (c(ctel:=ctel+1)*el))+
(for each el in grd3 sum (c(ctel:=ctel+1)*el))+
(for each el in grd4 sum (c(ctel:=ctel+1)*el))+
(for each el in grd5 sum (c(ctel:=ctel+1)*el))$
This is the equation `¯B (sym) = 0, where B = 0 is Burgers’ equation and sym is
the generating function. From now on all equations are arranged in a single vector
whose name is equ.
equ 1:=ddt(sym)-ddx(ddx(sym))-2*u*ddx(sym)-2*u1*sym ;
vars:={x,t,u,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,
u12,u13,u14,u15,u16,u17};
tel:=1;
The following procedure uses multi_coeff (from the package tools). It gets
all coefficients of monomials appearing in the initial equation(s). The coefficients
are put into the vector equ after the initial equations.
procedure splitvars i;
begin;
449
ll:=multi_coeff(equ i,vars);
equ(tel:=tel+1):=first ll;
ll:=rest ll;
for each el in ll do equ(tel:=tel+1):=second el;
end;
• the equation vector equ togeher with its length tel (i.e., the total number
of equations);
• the list of variables with respect to which the system must not split the equat-
ions, i.e., variables with respect to which the unknowns are not polynomial.
In this case this list is just {};
• the constants’vector c, its length ctel, and the number of negative indexes
if any; just 0 in our example;
• the vector of free functions f that may appear in computations. Note that in
{f,0,0 } the second 0 stands for the length of the vector of free functions.
In this example there are no free functions, but the command needs the pres-
ence of at least a dummy argument, f in this case. There is also a last zero
which is the negative length of the vector f , just as for constants.
initialize_equations(equ,tel,{},{c,ctel,0},{f,0,0});
splitvars 1;
Next command tells the solver the total number of equations obtained after running
splitvars.
put_equations_used tel;
This command solves the equations for the coefficients. Note that we have to skip
the initial equations!
In this section we will find (some) local conservation laws for the KdV equation
F = ut − uxxx + uux = 0. Concretely, we have to find non-trivial 1-forms
f = fx dx+ft dt on F = 0 such that df ¯ = 0 on F = 0. “Triviality” of conservation
laws is a delicate matter, for which we invite the reader to have a look in [11].
The files containing this example is KdV_loc-cl_1.red, KdV_loc-cl_2.red
and the corresponding results files.
We make use of ddx and ddt, which in the even part are the same as in the previ-
ous example (subsection 16.13.2). After defining the total derivatives we prepare
the list of graded variables (recall that in KdV u is of degree 2):
all_graded_der:={{},{u},{u1},{u2},{u3},{u4},{u5},
{u6},{u7},{u8},{u9},{u10},{u11},{u12},{u13},{u14},
{u15},{u16},{u17}};
fx:=
(for each el in grd0 sum (c(ctel:=ctel+1)*el))+
(for each el in grd1 sum (c(ctel:=ctel+1)*el))+
(for each el in grd2 sum (c(ctel:=ctel+1)*el))+
(for each el in grd3 sum (c(ctel:=ctel+1)*el))$
451
ft:=
(for each el in grd2 sum (c(ctel:=ctel+1)*el))+
(for each el in grd3 sum (c(ctel:=ctel+1)*el))+
(for each el in grd4 sum (c(ctel:=ctel+1)*el))+
(for each el in grd5 sum (c(ctel:=ctel+1)*el))$
for the components of the conservation law. We have to solve the equation
equ 1:=ddt(fx)-ddx(ft);
the fact that ddx and ddt are expressed in internal coordinates on the equation
means that the objects that we consider are already restricted to the equation.
We shall split the equation in its graded summands with the procedure splitvars,
then solve it
initialize_equations(equ,tel,{},{c,ctel,0},{f,0,0});
splitvars 1;
pte tel;
for i:=2:tel do es i;
end;
As a result we get
equ 1:=fx-ddx(f0);
equ 2:=ft-ddt(f0);
after having loaded the values fx and ft found by the previous program. We make
the following ansatz on f0:
f0:=
(for each el in grd0 sum (cc(cctel:=cctel+1)*el))+
(for each el in grd1 sum (cc(cctel:=cctel+1)*el))+
(for each el in grd2 sum (cc(cctel:=cctel+1)*el))+
(for each el in grd3 sum (cc(cctel:=cctel+1)*el))$
452 CHAPTER 16. USER CONTRIBUTED PACKAGES
Note that this gives a grading which is compatible with the gradings of fx and ft.
After solving the system
initialize_equations(equ,tel,{},{cc,cctel,0},{f,0,0});
for i:=1:2 do begin splitvars i;end;
pte tel;
for i:=3:tel do es i;
end;
fxnontriv := fx-ddx(f0);
ftnontriv := ft-ddt(f0);
we obtain
In this section we will find local Hamiltonian operators for the KdV equation ut =
uxxx + uux . Concretely, we have to solve `¯KdV (phi) = 0 over the equation
ut = uxxx + uux
pt = pxxx + upx
or, in geometric terminology, find the shadows of symmetries on the `∗ -covering
of the KdV equation. The reference paper for this type of computations is [12].
The file containing this example is KdV_Ham_1.red.
We make use of ddx and ddt, which in the even part are the same as in the previ-
ous example (subsection 16.13.2). We stress that the linearization `¯KdV (phi) = 0
is the equation
ddt(phi)-u*ddx(phi)-u1*phi-ddx(ddx(ddx(phi)))=0
but the total derivatives are lifted to the `∗ covering, hence they must contain also
derivatives with respect to p’s. This will be achieved by treating p variables as odd
and introducing the odd parts of ddx and ddt,
ddx(1,1):=0$
453
ddx(1,2):=0$
ddx(1,3):=ext 4$
ddx(1,4):=ext 5$
ddx(1,5):=ext 6$
ddx(1,6):=ext 7$
ddx(1,7):=ext 8$
ddx(1,8):=ext 9$
ddx(1,9):=ext 10$
ddx(1,10):=ext 11$
ddx(1,11):=ext 12$
ddx(1,12):=ext 13$
ddx(1,13):=ext 14$
ddx(1,14):=ext 15$
ddx(1,15):=ext 16$
ddx(1,16):=ext 17$
ddx(1,17):=ext 18$
ddx(1,18):=ext 19$
ddx(1,19):=ext 20$
ddx(1,20):=letop$
In the above definition the first index ‘1’ says that we are dealing with odd vari-
ables, ext indicates anticommuting variables. Here, ext 3 is p0 , ext 4 is px ,
ext 5 is pxx , . . . so ddx(1,3):=ext 4 indicates px ∂/∂p, etc..
Now, remembering that the additional equation is again evolutionary, we can get
rid of pt by letting it be equal to ext 6 + u*ext 4, as follows:
ddt(1,1):=0$
ddt(1,2):=0$
ddt(1,3):=ext 6 + u*ext 4$
ddt(1,4):=ddx(ddt(1,3))$
ddt(1,5):=ddx(ddt(1,4))$
ddt(1,6):=ddx(ddt(1,5))$
ddt(1,7):=ddx(ddt(1,6))$
ddt(1,8):=ddx(ddt(1,7))$
ddt(1,9):=ddx(ddt(1,8))$
ddt(1,10):=ddx(ddt(1,9))$
ddt(1,11):=ddx(ddt(1,10))$
ddt(1,12):=ddx(ddt(1,11))$
ddt(1,13):=ddx(ddt(1,12))$
ddt(1,14):=ddx(ddt(1,13))$
ddt(1,15):=ddx(ddt(1,14))$
ddt(1,16):=ddx(ddt(1,15))$
ddt(1,17):=ddx(ddt(1,16))$
454 CHAPTER 16. USER CONTRIBUTED PACKAGES
ddt(1,18):=letop$
ddt(1,19):=letop$
ddt(1,20):=letop$
phi:=
(for each el in grd0 sum (c(ctel:=ctel+1)*el))*ext 3+
(for each el in grd1 sum (c(ctel:=ctel+1)*el))*ext 3+
(for each el in grd2 sum (c(ctel:=ctel+1)*el))*ext 3+
(for each el in grd3 sum (c(ctel:=ctel+1)*el))*ext 3+
Note that we are looking for generating functions of shadows which are linear
with respect to p’s. Moreover, having set [p] = −2 we will look for solutions of
maximal possible degree +1.
After having set
equ 1:=ddt(phi)-u*ddx(phi)-u1*phi-ddx(ddx(ddx(phi)));
vars:={x,t,u,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,
u13,u14,u15,u16,u17};
tel:=1;
procedure splitext i;
begin;
ll:=operator_coeff(equ i,ext);
equ(tel:=tel+1):=first ll;
ll:=rest ll;
for each el in ll do equ(tel:=tel+1):=second el;
end;
455
initialize_equations(equ,tel,{},{c,ctel,0},{f,0,0});
do splitext
splitext 1;
then splitvars
tel1:=tel;
for i:=2:tel1 do begin splitvars i;equ i:=0;end;
put_equations_used tel;
for i:=2:tel do write equ i:=equ i;
pause;
for i:=2:tel do integrate_equation i;
end;
ext(4) → Dx ,
3*c(3)*ext(6) + 2*c(3)*ext(4)*u + c(3)*ext(3)*u1 →
3Dxxx + 2uDx + ux
Note that each operator is multiplied by one arbitrary real constant, c(4) and
c(3).
main difference is that we will attempt a solution on the `∗ -covering (see Subsec-
tion 16.13.2). For this reason, first of all we have to determine covering variables
with the usual mechanism of introducing them through conservation laws, this time
on the `∗ -covering.
As a first step, let us compute conservation laws on the `∗ -covering whose
components are linear in the p’s. This computation can be found in the file
KdV_nloc-cl_1.red and related results file. When specifying odd variables
in ddx and ddt, we have something like
ddx(1,1):=0$
ddx(1,2):=0$
ddx(1,3):=ext 4$
ddx(1,4):=ext 5$
ddx(1,5):=ext 6$
ddx(1,6):=ext 7$
ddx(1,7):=ext 8$
ddx(1,8):=ext 9$
ddx(1,9):=ext 10$
ddx(1,10):=ext 11$
ddx(1,11):=ext 12$
ddx(1,12):=ext 13$
ddx(1,13):=ext 14$
ddx(1,14):=ext 15$
ddx(1,15):=ext 16$
ddx(1,16):=ext 17$
ddx(1,17):=ext 18$
ddx(1,18):=ext 19$
ddx(1,19):=ext 20$
ddx(1,20):=letop$
ddx(1,50):=(t*u1+1)*ext 3$ % degree -2
ddx(1,51):=u1*ext 3$ % degree +1
ddx(1,52):=(u*u1+u3)*ext 3$ % degree +3
and
ddt(1,1):=0$
ddt(1,2):=0$
ddt(1,3):=ext 6 + u*ext 4$
ddt(1,4):=ddx(ddt(1,3))$
ddt(1,5):=ddx(ddt(1,4))$
ddt(1,6):=ddx(ddt(1,5))$
ddt(1,7):=ddx(ddt(1,6))$
ddt(1,8):=ddx(ddt(1,7))$
457
ddt(1,9):=ddx(ddt(1,8))$
ddt(1,10):=ddx(ddt(1,9))$
ddt(1,11):=ddx(ddt(1,10))$
ddt(1,12):=ddx(ddt(1,11))$
ddt(1,13):=ddx(ddt(1,12))$
ddt(1,14):=ddx(ddt(1,13))$
ddt(1,15):=ddx(ddt(1,14))$
ddt(1,16):=ddx(ddt(1,15))$
ddt(1,17):=ddx(ddt(1,16))$
ddt(1,18):=letop$
ddt(1,19):=letop$
ddt(1,20):=letop$
ddt(1,50):=f1*ext 3+f2*ext 4+f3*ext 5$
ddt(1,51):=f4*ext 3+f5*ext 4+f6*ext 5$
ddt(1,52):=f7*ext 3+f8*ext 4+f9*ext 5$
The variables corresponding to the numbers 50,51,52 here play a dummy role,
the coefficients of the corresponding vector are the unknown generating functions
of conservation laws on the `∗ -covering. More precisely, we look for conservation
laws of the form
fx= phi*ext 3
ft= f1*ext3+f2*ext4+f3*ext5
The ansatz is chosen because, first of all, ext 4 and ext 5 can be removed from
fx by adding a suitable total divergence (trivial conservation law); moreover it can
be proved that phi is a symmetry of KdV. We can write down the equations
equ 1:=ddx(ddt(1,50))-ddt(ddx(1,50));
equ 2:=ddx(ddt(1,51))-ddt(ddx(1,51));
equ 3:=ddx(ddt(1,52))-ddt(ddx(1,52));
However, the above choices make use of a symmetry which contains ‘t’ in the
generator. This would make automatic computations more tricky, but still possible.
In this case the solution of equ 1 has been found by hand and passed to the
program:
f3:=t*u1+1$
f1:=u*f3+ddx(ddx(f3))$
f2:=-ddx(f3)$
together with the ansatz on the coefficients for the other equations
The previous ansatz keep into account the grading of the starting symmetry in
phi*ext 3. The resulting equations are solved in the usual way (see the example
file).
Now, we solve the equation for shadows of nonlocal symmetries in a covering of
the `∗ -covering. We can choose between three new nonlocal variables ra,rb,rc.
We are going to look for non-local Hamiltonian operators depending linearly on
one of these variables. Higher non-local Hamiltonian operators could be found by
introducing total derivatives of the r’s. As usual, the new variables are specified
through the components of the previously found conservation laws according with
the rule
ra_x=fx, ra_t=ft,
ddx(1,50):=(t*u1+1)*ext 3$ % degree -2
ddx(1,51):=u1*ext 3$ % degree +1
ddx(1,52):=(u*u1+u3)*ext 3$ % degree +3
and
as it results from the computation of the conservation laws. The following ansatz
for the nonlocal Hamiltonian operator comes from the fact that local Hamiltonian
operators have gradings −1 and +1 when written in terms of p’s. So we are looking
for a nonlocal Hamiltonian operator of degree 3.
phi:=
(for each el in grd6 sum (c(ctel:=ctel+1)*el))*ext 50+
(for each el in grd3 sum (c(ctel:=ctel+1)*el))*ext 51+
459
As a solution, we obtain
rb_x:=u1*ext 3$
rb_t:=ext(5)*u1 - ext(4)*u2 + ext(3)*u*u1 + ext(3)*u3$
where σ is a constant. This example also shows how to deal with jet spaces with
more than one dependent variable. Here gradings can be taken as
∂ ∂
[t] = −2, [x] = −1, [v] = 1, [u] = 2, [p] = [ ] = −2, [q] = [ ] = −1
∂u ∂v
where p, q are the two coordinates in the space of generating functions of conser-
vation laws.
The linearization of the above system and its adjoint are, respectively
Dt − vDx − vx −ux − uDx − σDxxx ∗ −Dt + vDx Dx
`Bou = , `Bou =
−Dx Dt − vx − vDx uDx + σDxxx −Dt + vDx
460 CHAPTER 16. USER CONTRIBUTED PACKAGES
super_vectorfield(ddx,{x,t,u,v,u1,v1,u2,v2,u3,v3,u4,v4,
u5,v5,u6,v6,u7,v7,u8,v8,u9,v9,u10,v10,u11,v11,u12,v12,
u13,v13,u14,v14,u15,v15,u16,v16,u17,v17},
{ext 1,ext 2,ext 3,ext 4,ext 5,ext 6,ext 7,ext 8,ext 9,
ext 10,ext 11,ext 12,ext 13,ext 14,ext 15,ext 16,ext 17,
ext 18,ext 19,ext 20,ext 21,ext 22,ext 23,ext 24,ext 25,
ext 26,ext 27,ext 28,ext 29,ext 30,ext 31,ext 32,ext 33,
ext 34,ext 35,ext 36,ext 37,ext 38,ext 39,ext 40,ext 41,
ext 42,ext 43,ext 44,ext 45,ext 46,ext 47,ext 48,ext 49,
ext 50,ext 51,ext 52,ext 53,ext 54,ext 55,ext 56,ext 57,
ext 58,ext 59,ext 60,ext 61,ext 62,ext 63,ext 64,ext 65,
ext 66,ext 67,ext 68,ext 69,ext 70,ext 71,ext 72,ext 73,
ext 74,ext 75,ext 76,ext 77,ext 78,ext 79,ext 80
});
super_vectorfield(ddt,{x,t,u,v,u1,v1,u2,v2,u3,v3,u4,v4,
u5,v5,u6,v6,u7,v7,u8,v8,u9,v9,u10,v10,u11,v11,u12,v12,
u13,v13,u14,v14,u15,v15,u16,v16,u17,v17},
{ext 1,ext 2,ext 3,ext 4,ext 5,ext 6,ext 7,ext 8,ext 9,
ext 10,ext 11,ext 12,ext 13,ext 14,ext 15,ext 16,ext 17,
ext 18,ext 19,ext 20,ext 21,ext 22,ext 23,ext 24,ext 25,
ext 26,ext 27,ext 28,ext 29,ext 30,ext 31,ext 32,ext 33,
ext 34,ext 35,ext 36,ext 37,ext 38,ext 39,ext 40,ext 41,
ext 42,ext 43,ext 44,ext 45,ext 46,ext 47,ext 48,ext 49,
ext 50,ext 51,ext 52,ext 53,ext 54,ext 55,ext 56,ext 57,
ext 58,ext 59,ext 60,ext 61,ext 62,ext 63,ext 64,ext 65,
ext 66,ext 67,ext 68,ext 69,ext 70,ext 71,ext 72,ext 73,
ext 74,ext 75,ext 76,ext 77,ext 78,ext 79,ext 80
});
ddx(0,1):=1$
ddx(0,2):=0$
461
ddx(0,3):=u1$
ddx(0,4):=v1$
ddx(0,5):=u2$
ddx(0,6):=v2$
...
ut:=u1*v+u*v1+sig*v3;
vt:=u1+v*v1;
ut1:=ddx ut;
ut2:=ddx ut1;
ut3:=ddx ut2;
...
vt1:=ddx vt;
vt2:=ddx vt1;
vt3:=ddx vt2;
...
up to the required order (here the order can be stopped at 15). Odd variables p and q
must be specified with an appropriate length (here it is OK to stop at ddx(1,36)).
Recall to replace pt , qt with the internal coordinates of the covering:
ddt(1,1):=0$
ddt(1,2):=0$
ddt(1,3):=+v*ext 5+ext 6$
ddt(1,4):=u*ext 5+sig*ext 9+v*ext 6$
ddt(1,5):=ddx(ddt(1,3))$
...
all_graded_der:={{v},{u,v1},{u1,v2},{u2,v3},{u3,v4},{u4,v5},
{u5,v6},{u6,v7},{u7,v8},{u8,v9},{u9,v10},{u10,v11},
{u11,v12},{u12,v13},{u13,v14},{u14,v15},{u15,v16},
{u16,v17},{u17}};
phi1:=
(for each el in grd2 sum (c(ctel:=ctel+1)*el))*ext 3+
462 CHAPTER 16. USER CONTRIBUTED PACKAGES
phi2:=
(for each el in grd1 sum (c(ctel:=ctel+1)*el))*ext 3+
(for each el in grd0 sum (c(ctel:=ctel+1)*el))*ext 5+
(for each el in grd0 sum (c(ctel:=ctel+1)*el))*ext 4
$
equ 1:=ddt(phi1)-v*ddx(phi1)-v1*phi1-u1*phi2-u*ddx(phi2)
-sig*ddx(ddx(ddx(phi2)));
equ 2:=-ddx(phi1)-v*ddx(phi2)-v1*phi2+ddt(phi2);
After the usual procedures for decomposing polynomials we obtain the following
result:
phi1 := c(6)*ext(6)$
phi2 := c(6)*ext(5)$
phi1:=
(for each el in grd3 sum (c(ctel:=ctel+1)*el))*ext 3+
(for each el in grd2 sum (c(ctel:=ctel+1)*el))*ext 5+
(for each el in grd1 sum (c(ctel:=ctel+1)*el))*ext 7+
(for each el in grd0 sum (c(ctel:=ctel+1)*el))*ext 9+
(for each el in grd2 sum (c(ctel:=ctel+1)*el))*ext 4+
(for each el in grd1 sum (c(ctel:=ctel+1)*el))*ext 6+
(for each el in grd0 sum (c(ctel:=ctel+1)*el))*ext 8
$
phi2:=
(for each el in grd2 sum (c(ctel:=ctel+1)*el))*ext 3+
(for each el in grd1 sum (c(ctel:=ctel+1)*el))*ext 5+
(for each el in grd0 sum (c(ctel:=ctel+1)*el))*ext 7+
(for each el in grd1 sum (c(ctel:=ctel+1)*el))*ext 4+
(for each el in grd0 sum (c(ctel:=ctel+1)*el))*ext 6
$
There is one more higher local Hamiltonian operator, and a whole hierarchy of
nonlocal Hamiltonian operators [12].
phi:=1/(u3+u*u1)$
for i:=1:100 do begin
phi:=ddx(phi)$
write i;
end;
The program shows the iteration number. At the 18th iteration the program uses
about 600MB of RAM, as shown by top run from another shell, and 100% of one
processor.
There is a simple way to avoid denominator explosion. The file is KdV_denom_2.red.
After having defined total derivatives with respect to x (on the KdV equation, for
example) consider in the same ddx a component with a sufficently high index
immediately after ‘letop’ (otherwise super_vectorfield does not work!),
say ddx(0,21), and think of it as being the coefficient to a vector of the type
aa21:=1/(u3+u*u1);
ddx(0,21):=-aa21**2*(u4+u1**2+u*u2)$
ddx(0,1):=1$
ddx(0,2):=0$
ddx(0,3):=u1$
ddx(0,4):=u2$
464 CHAPTER 16. USER CONTRIBUTED PACKAGES
ddx(0,5):=u3$
ddx(0,6):=u4$
ddx(0,7):=u5$
ddx(0,8):=u6$
ddx(0,9):=u7$
ddx(0,10):=u8$
ddx(0,11):=u9$
ddx(0,12):=u10$
ddx(0,13):=u11$
ddx(0,14):=u12$
ddx(0,15):=u13$
ddx(0,16):=u14$
ddx(0,17):=u15$
ddx(0,18):=u16$
ddx(0,19):=u17$
ddx(0,20):=letop$
ddx(0,21):=-aa21**2*(u4+u1**2+u*u2)$
Now, suppose that we want to compute the 5th total derivative of phi. Write the
following code:
phi:=aa30;
for i:=1:5 do begin
phi:=ddx(phi)$
write i;
end;
+ 720*aa21**3*u**2*u1**2*u2**2*u5 + 1440*aa21**3*u**2*u1**2*u2*u3*u4
+ 2160*aa21**3*u**2*u1*u2**3*u4 + 720*aa21**3*u**2*u2**2*u4*u5
+ 720*aa21**3*u**2*u2*u3*u4**2 + 240*aa21**3*u*u1**6*u3
+ 2160*aa21**3*u*u1**5*u2**2 + 720*aa21**3*u*u1**4*u2*u5
+ 720*aa21**3*u*u1**4*u3*u4 + 4320*aa21**3*u*u1**3*u2**2*u4
+ 1440*aa21**3*u*u1**2*u2*u4*u5 + 720*aa21**3*u*u1**2*u3*u4**2
+ 2160*aa21**3*u*u1*u2**2*u4**2 + 720*aa21**3*u*u2*u4**2*u5
+ 240*aa21**3*u*u3*u4**3 + 720*aa21**3*u1**7*u2
+ 240*aa21**3*u1**6*u5
+ 2160*aa21**3*u1**5*u2*u4 + 720*aa21**3*u1**4*u4*u5
+ 2160*aa21**3*u1**3*u2*u4**2 + 720*aa21**3*u1**2*u4**2*u5
+ 720*aa21**3*u1*u2*u4**3 + 240*aa21**3*u4**3*u5
- 60*aa21**2*u**3*u2**2*u4 - 90*aa21**2*u**3*u2*u3**2
- 120*aa21**2*u**2*u1**2*u2*u4 - 90*aa21**2*u**2*u1**2*u3**2
- 780*aa21**2*u**2*u1*u2**2*u3 - 180*aa21**2*u**2*u2**4
- 60*aa21**2*u**2*u2**2*u6 - 180*aa21**2*u**2*u2*u3*u5
- 120*aa21**2*u**2*u2*u4**2 - 90*aa21**2*u**2*u3**2*u4
- 60*aa21**2*u*u1**4*u4 - 1020*aa21**2*u*u1**3*u2*u3
- 1170*aa21**2*u*u1**2*u2**3 - 120*aa21**2*u*u1**2*u2*u6
- 180*aa21**2*u*u1**2*u3*u5 - 120*aa21**2*u*u1**2*u4**2
- 540*aa21**2*u*u1*u2**2*u5 - 1020*aa21**2*u*u1*u2*u3*u4
- 360*aa21**2*u*u2**3*u4 - 120*aa21**2*u*u2*u4*u6
- 90*aa21**2*u*u2*u5**2 - 180*aa21**2*u*u3*u4*u5
- 60*aa21**2*u*u4**3 - 240*aa21**2*u1**5*u3
- 990*aa21**2*u1**4*u2**2 - 60*aa21**2*u1**4*u6
- 540*aa21**2*u1**3*u2*u5 - 480*aa21**2*u1**3*u3*u4
- 1170*aa21**2*u1**2*u2**2*u4 - 120*aa21**2*u1**2*u4*u6
- 90*aa21**2*u1**2*u5**2 - 540*aa21**2*u1*u2*u4*u5
- 240*aa21**2*u1*u3*u4**2 - 180*aa21**2*u2**2*u4**2
- 60*aa21**2*u4**2*u6 - 90*aa21**2*u4*u5**2
+ 10*aa21*u**2*u2*u5 + 20*aa21*u**2*u3*u4 + 10*aa21*u*u1**2*u5
+ 110*aa21*u*u1*u2*u4 + 80*aa21*u*u1*u3**2 + 160*aa21*u*u2**2*u3
+ 10*aa21*u*u2*u7 + 20*aa21*u*u3*u6 + 30*aa21*u*u4*u5
+ 50*aa21*u1**3*u4 + 340*aa21*u1**2*u2*u3 + 10*aa21*u1**2*u7
+ 180*aa21*u1*u2**3 + 60*aa21*u1*u2*u6 + 80*aa21*u1*u3*u5
+ 50*aa21*u1*u4**2 + 60*aa21*u2**2*u5 + 100*aa21*u2*u3*u4
+ 10*aa21*u4*u7 + 20*aa21*u5*u6 - u*u6 - 6*u1*u5 - 15*u2*u4
- 10*u3**2 - u8)$
Bibliography
16.14.1 Introduction
Consider the ideal basis F = {ax, x + y}. Treating a as a parameter, the calling
sequence
torder({x,y},lex)$
groebner{a*x,x+y};
{x,y}
yields {x, y} as reduced Gröbner basis. This is, however, not correct under the spe-
cialization a = 0. The reduced Gröbner basis would then be {x + y}. Taking these
results together, we obtain C = {x + y, ax, ay}, which is correct wrt. all special-
izations for a including zero specializations. We call this set C a comprehensive
Gröbner basis (CGB).
The notion of a CGB and a corresponding algorithm has been introduced bei
Weispfenning [Wei92]. This algorithm works by performing case distinctions
wrt. parametric coefficient polynomials in order to find out what the head monomi-
als are under all possible specializations. It does thus not only determine a CGB, but
even classifies the contained polynomials wrt. the specializations they are relevant
for. If we keep the Gröbner bases for all cases separate and associate information
on the respective specializations with them, we obtain a Gröbner system. For our
example, the Gröbner system is the following;
a 6= 0 {x + y, ax, ay}
.
a=0 {x + y}
A CGB is obtained as the union of the single Gröbner bases in a Gröbner system.
It has also been shown that, on the other hand, a Gröbner system can easily be
reconstructed from a given CGB [Wei92].
The CGB package provides functions for computing both CGB’s and Gröbner sys-
tems, and for turning Gröbner systems into CGB’s.
For managing the conditions occurring with the CGB computations, the CGB
package uses the package REDLOG implementing first-order formulas, [DS97a,
DS99], which is also part of the REDUCE distribution.
468 CHAPTER 16. USER CONTRIBUTED PACKAGES
The CGB package uses the settings made with the function torder of the
GROEBNER package. This includes in particular the choice of the main vari-
ables. All variables not mentioned in the variable list argument of torder are
parameters. The only term ordering modes recognized by CGB are lex and
revgradlex.
The function cgb expects a list F of expressions. It returns a CGB of F wrt. the
current torder setting.
Example
torder({x,y},lex)$
cgb{a*x+y,x+b*y};
ws;
{b*y + x,
a*x + y,
y*(a*b - 1)}
Note that the basis returned by the cgb call has not undergone the standard eval-
uation process: The returned polynomials are ordered wrt. the chosen term order.
Reevaluation changes this as can be seen with the output of ws.
The function gsys follows the same calling conventions as cgb. It returns the
complete Gröbner system represented as a nested list
c1 , {g11 , . . . , g1n1 } , . . . , cm , {gm1 , . . . , g1nm } .
Example
torder({x,y},lex)$
gsys {a*x+y,x+b*y};
If the switch cgbgen is turned on, both gsys and cgb will assume all parametric
coefficients to be non-zero ignoring the other cases. For cgb this means that the re-
sult equals—up to auto-reduction—that of groebner. A call to gsys will return
this result as a single case including the assumptions made during the computation:
Example
torder({x,y},lex)$
on cgbgen;
gsys{a*x+y,x+b*y};
off cgbgen;
470 CHAPTER 16. USER CONTRIBUTED PACKAGES
The call gsys2cgb turns a given Gröbner system into a CGB by constructing the
union of the Gröbner bases of the single cases.
Example
torder({x,y},lex)$
gsys{a*x+y,x+b*y}$
gsys2cgb ws;
All computations considered so far have taken place over the complex numbers,
more precisely, over algebraically closed fields. Over the real numbers, certain
branches of the CGB computation can become inconsitent though they are not in-
consistent over the complex numbers. Consider, e.g., a condition a2 + 1 = 0.
When turning on the switch cgbreal, all simplifications of conditions are per-
formed over the real numbers. The methods used for this are described in [DS97b].
Example
torder({x,y},lex)$
off cgbreal;
gsys {a*x+y,x-a*y};
2
{{a + 1 <> 0 and a <> 0,
2
{a*x + y,x - a*y,(a + 1)*y}},
2
{a <> 0 and a + 1 = 0,{a*x + y,x - a*y}},
on cgbreal;
gsys({a*x+y,x-a*y});
471
{{a <> 0,
2
{a*x + y,x - a*y,(a + 1)*y}},
16.14.8 Switches
cgbreal Compute over the real numbers. See Section 16.14.7 for details.
cgbgs Gröbner simplification of the condition. The switch cgbgs can be turned
on for applying advanced algebraic simplification techniques to the condi-
tions. This will, in general, slow down the computation, but lead to a simpler
Gröbner system.
cgbstat Statistics of the CGB run. The switch cgbstat toggles the creation and
output of statistical information on the CGB run. The statistical information
is printed at the end of the run.
cgbfullred Full reduction. By default, the CGB functions perform full reductions
in contrast to pure top reductions. By turning off the switch cgbfullred,
reduction can be restricted to top reductions.
Bibliography
[DS99] Andreas Dolzmann and Thomas Sturm. Redlog User Manual. FMI,
Universität Passau, D-94030 Passau, Germany, April 1999. Edition 2.0
for Version 2.0.
2 2
SIN(X) *C + COS(X) *S + 1 .
This package provides an alternative method for computing traces of Dirac gamma
matrices, based on an algorithm by Cvitanovich that treats gamma matrices as 3-j
symbols.
Authors: V.Ilyin, A.Kryukov, A.Rodionov, A.Taranov.
Abstract
In modern high energy physics the calculation of Feynman diagrams are still very
important. One of the difficulties of these calculations are trace calculations. So
the calculation of traces of Dirac’s γ-matrices were one of first task of computer al-
gebra systems. All available algorithms are based on the fact that gamma-matrices
constitute a basis of a Clifford algebra:
{Gm,Gn} = 2gmn.
Module RED_TO_CVIT_INTERFACE
Author: A.P.Kryukov
Purpose:interface REDUCE and CVIT package
476 CHAPTER 16. USER CONTRIBUTED PACKAGES
Module CVITMAPPING
Author: A.Ya.Rodionov
Purpose: graphs reduction
There are also some functions for printing several internal structures: PRINT_ATLAS,
PRINT_VERTEX, PRINT_EDGE, PRINT_COEFF, PRINT_DENOM. This func-
tions can be used for debugging.
If an error occur in module CVITMAPPING the error message “ERROR IN
MAP CREATING ROUTINES” is displayed. Error has number 55. The switch
CVITERROR allows to give full information about error: name of function where
error occurs and names and values of function’s arguments. If CVITERROR switch
is on and backtracking fails message about error in SORT_ATLAS function is
printed. The result of computation however will be correct because in this case
factorized structure is not used. This happens extremely seldom.
Data structure
WORLD ::= (EDGELIST,VARIANTS,WORLD1)
WORLD1 ::= (MAP2,COEFF,DENOM)
MAP2 ::= (MAPS,VARIANTS,PLAN)
MAPS ::= (EDGEPAIR . GSTRAND)
MAP1 ::= (EDGEPAIR . MAP)
MAP ::= list of VERTICES (unordered)
EDGEPAIR ::= (OLDEDGELIST . NEWEDGELIST)
COEFF ::= list of WORLDS (unordered)
ATLAS ::= (MAP,COEFF,DENOM)
GSTRAND ::= (STRAND*,MAP,TADPOLES,DELTAS)
VERTEX ::= list of EDGEs (with cyclic order)
EDGE ::= (NAME,PROPERTY,TYPE)
479
Author: A.Taranov
Purpose: evaluate single Map
LIST OF MESSAGES
• THREE INDICES HAVE NAME <name> There are three indices with
equal names in evaluated expression.
List of switches
------------------------------------------------------------
switch default comment
------------------------------------------------------------
CVIT ON If it is on then use Kennedy-
Cvitanovic algorithm else use
standard facilities.
CVITOP OFF Fierz optimization switch
CVITBTR ON Bubbles and triangles
factorisation switch
CVITRACE OFF Backtracking tracing switch
------------------------------------------------------------
CALC_SPUR
481
|
+-->SIMP!* (REDUCE)
|
+-->CALC_SPUR0
|
|--->TRANSFORM_MAP_
| |
| |--->MK_SIMPLE_VERTEX
| +--->MK_SIMPLE_MAP_
| |
| +--->MK_SIMPLE_MAP_1
| |
| +--->MK_FIERS_OP
|
|--->WORLD_FROM_ATLAS
| |
| +--->CONSTR_WORLDS
| |
| +---->MK_WORLD1
| |
| +--->MAP_2_FROM_MAP_1
| |
| |--->MARK_EDGES
| +--->MAP_1_TO_STRAND
| |
| +-->PRE!-CALC!-MAP_
| (INTERFIRZ)
|
|--->CALC_WORLD
| |
| |--->CALC!-MAP_TAR (INTERFIRZ)
| |--->CALC!-DENTAR (INTERFIRZ)
| +--->REVAL (REDUCE)
|
+--->FIND_BUBLTR
|
+--->FIND_BUBLTR0
|
|--->SORT_ATLAS
+--->FIND_BUBLTR1
|
|--->FIND_BUBLES1
+--->FIND_TRIANGLES1
*Unmarked functions are from CVITMPPING module.
482 CHAPTER 16. USER CONTRIBUTED PACKAGES
References
• 1. Ilyin V.A., Kryukov A.P., Rodionov A.Ya., Taranov A.Yu. Fast algorithm
for calculation of Diracs gamma-matrices traces. SIGSAM Bull., 1989, v.23,
no.4, pp.15-24.
Keywords
16.18.1 Introduction
! ! !
Z ∞ (c ) (a ) (g )
u p k
x α−1
Gst
uv σx Gmn
pq ωx l/k
dx = kGij
kl ξ
(dv ) (bq ) (hl )
0
(16.72)
The resulting Meijer G-function is then retransformed, either directly or via a
hypergeometric function simplification, to give the answer. A more detailed ac-
count of this theory can be found in [2].
then initially the correct Meijer G-functions are found, via a pattern matching pro-
cess, and are substituted into eq. 16.72 to give
! !
∞
√ x2
Z . ..
π x−1 G10 x G10 dx
01 02 1
0 0 4 20
484 CHAPTER 16. USER CONTRIBUTED PACKAGES
The cases for validity of the integral are then checked. If these are found to be
satisfactory then the formula is calculated and we obtain the following Meijer G-
function
!
1
1
G12 1 2
22 1
2 0
π
4
The above formula (1) is also true for the integration of a single Meijer G-function
by replacing the second Meijer G-function with a trivial Meijer G-function.
A list of numerous particular Meijer G-functions is available in [1].
Although the description so far has been limited to the computation of definite inte-
grals between 0 and infinity, it can also be extended to calculate integrals between
0 and some specific upper bound, and by further extension, integrals between any
two bounds. One approach is to use the Heaviside function, i.e.
Z ∞ Z 1
2 −x
x e H(1 − x) dx = x2 e−x dx
0 0
Another approach, again not involving the normal indefinite integration process,
again uses Meijer G-functions, this time by means of the following formula
! !
Z y (a ) (a ..a , 1 − α, a
u 1 n n+1 ..ap )
xα−1 Gmn
pq σx dx = y α Gm n+1
p+1 q+1 σy
0 (bv ) (b1 ..bm , −α, bm+1 ..bq )
(16.73)
For a more detailed look at the theory behind this see [2].
For example, if one wishes to calculate the following integral
Z y √
sin(2 x) dx
0
485
then initially the correct Meijer G-function is found, by a pattern matching process,
and is substituted into eq. 16.73 to give
!
Z y ..
G10 x 1 dx
02
0 20
load_package defint;
Definite integration is then possible using the int command with the syntax:
INT(EXPRN:algebraic,VAR:kernel,LOW:algebraic,UP:algebraic)
:algebraic.
where LOW and UP are the lower and upper bounds respectively for the definite
integration of EXPRN with respect to VAR.
Examples
Z ∞
e−x dx
0
int(e^(-x),x,0,infinity);
Z ∞
xsin(1/x) dx
0
486 CHAPTER 16. USER CONTRIBUTED PACKAGES
int(x*sin(1/x),x,0,infinity);
1
INT(X*SIN(---),X,0,INFINITY)
X
Z ∞
x2 cos(x) e−2x dx
0
int(x^2*cos(x)*e^(-2*x),x,0,infinity);
4
-----
125
Z ∞ Z 1
−1/2x
xe H(1 − x) dx = xe−1/2x dx
0 0
int(x*e^(-1/2x)*Heaviside(1-x),x,0,infinity);
2*(2*SQRT(E) - 3)
-------------------
SQRT(E)
Z 1
x log(1 + x) dx
0
int(x*log(1+x),x,0,1);
1
---
4
Z y
cos(2x) dx
0
int(cos(2x),x,y,2y);
SIN(4*Y) - SIN(2*Y)
---------------------
2
487
• Laplace transform
• Hankel transform
• Y-transform
• K-transform
• StruveH transform
Laplace transform
For example
L {e−at }
is entered as
laplace_transform(e^(-a*x),x);
1
s+a
488 CHAPTER 16. USER CONTRIBUTED PACKAGES
Hankel transform
hankel_transform(f(x),x);
Y-transform
The Y-transform
Z ∞ √
f (ω) = F (t) Yν (2 ωt) dt
0
Y_transform(f(x),x);
K-transform
The K-transform
Z ∞ √
f (ω) = F (t) Kν (2 ωt) dt
0
K_transform(f(x),x);
StruveH transform
Z ∞ √
f (ω) = F (t) StruveH(ν, 2 ωt) dt
0
struveh_transform(f(x),x);
fourier_sin(f(x),x);
fourier_cos(f(x),x);
symbolic putv(mellin!-transforms!*,n,’
(() (m n p q) (ai) (bj) (C) (var)));
where f(x) is the new function, i = 1..p, j=1..q, C = a constant, var = variable, n =
an indexing number.
For example when considering cos(x) we have
Meijer G representation -
!
√ x2 ..
π G10 1 dx
02
4 02
symbolic putv(mellin!-transforms!*,3,’
(() (1 0 0 2) () (nil (quotient 1 2))
(sqrt pi) (quotient (expt x 2) 4)));
symbolic putv(mellin!-transforms!*,50,’
((n) (1 0 0 2) () ((quotient n 2)
(minus quotient n 2)) 1
(quotient (expt x 2) 4)));
The required conditions for the validity of the transform integrals can be viewed
using the following command:
491
print_conditions().
laplace_transform(x^k,x);
or mod(arg(eta))=pi*delta
or ( - min(repart(bj))<repart(s))<1 - max(repart(ai))
or mod(arg(eta))<pi*delta
where
delta = s + t − u−v 2
eta = 1 − α(v − u) − µ − ρ
µ = qj=1 bj − pi=1 ai + p−q
P P
Pv Pu 2 +1
ρ = j=1 dj − i=1 ci + u−v 2 +1
s, t, u, v, p, q, α as in (1)
16.18.8 Tracing
16.18.9 Acknowledgements
I would like to thank Victor Adamchik whose implementation of the definite inte-
gration package for REDUCE is vital to this interface.
Bibliography
[1] A.P. Prudnikov, Yu.A. Brychkov and O.I. Marichev, Integrals and Series, Vol-
ume 3: More Special Functions Gordon and Breach Science Publishers (1990)
492 CHAPTER 16. USER CONTRIBUTED PACKAGES
[2] V.S. Adamchik and O.I. Marichev, The Algorithm for Calculating Integrals
of Hypergeometric Type Functions and its Realization in Reduce System from
ISSAC 90:Symbolic and Algebraic Computation Addison-Wesley Publishing
Company (1990)
[3] Yudell L. Luke, The Special Functions and their Approximations, Volume 1
Academic Press (1969).
493
This package enables the basis of formal solutions to be computed for an ordinary
homogeneous differential equation with polynomial coefficients over Q of any or-
der, in the neighborhood of zero (regular or irregular singular point, or ordinary
point).
Authors: C. Dicrescenzo, F. Richard-Jung, E. Tournier.
E-mail: [email protected]
16.19.1 INTRODUCTION
This software enables the basis of formal solutions to be computed for an ordinary
homogeneous differential equation with polynomial coefficients over Q of any or-
der, in the neighbourhood of zero ( regular or irregular singular point, or ordinary
point ).
Tools have been added to deal with equations with a polynomial right-hand side,
parameters and a singular point not to be found at zero.
This software can be used in two ways :
The basic procedure is the DELIRE procedure which enables the solutions of a
494 CHAPTER 16. USER CONTRIBUTED PACKAGES
We have tried to represent solutions in the simplest form possible. For that, we
have had to choose different forms according to the complexity of the equation
(parameters) and the later use we shall have of these solutions.
"general solution" = {......, { split_sol , cond },....}
The variable in the differential operator being x, solutions are expressed in respect
to a new variable xt, which is a fractional power of x, in the following way :
495
x : variable
k : "number of desired terms".
For each formal series in xt appearing in polysol,
a0 + a1 xt + a2 xt2 + ... + an xtn + . . ., we compute the k + 1 first
coefficients a0 , a1 , . . . , ak .
grille : the coefficients of the differential operator are polynomial in xgrille (in
general grille = 1)
lcoef f : list of coefficients of the differential operator (in increasing order of
differentiation)
param : list of parameters
procedure lectabcoef( );
This procedure is called by DESIR to read the coefficients of an equation, in in-
creasing order of differentiation, but can be used independently.
reading of n : order of the equation.
reading of parameters (only if a variable other than x appears in the coefficients)
this procedure returns the list { lcoef f, param } made up of the list of coefficients
and the list of parameters (which can be empty).
Verification of results
On the other hand, this procedure carries over the solution in the equation and
DISPLAYS the significative term of the result. This is of the form :
Finally this procedure RETURNS the complete result of the carry over of the solu-
tion in the equation.
This procedure cannot be used if the solution number solk is linked to a condition.
procedure standsol(solutions);
This procedure enables the simplified form of each solution to be obtained from
the list "solutions", {lcoef f ,{...,{general_solution},....}} which is one of the el-
ements of the list returned by DESIR, or {lcoef f, sol} where sol is the list returned
by DELIRE.
This procedure RETURNS a list of 3 elements : { lcoef f, solstand, solcond }
lcoef = list of differential equation coefficients
solstand = list of solutions written in standard form
solcond = list of conditional solutions that have not been written in
standard form. This solutions remain in general form.
This procedure has no meaning for "conditional" solutions. In case, a value has
to be given to the parameters, that can be done either by calling the procedure
SORPARAM that displays and returns these solutions in the standard form, either
by calling the procedure SOLPARAM which returns these solutions in general
form.
procedure sorsol(sol);
This procedure is called by DESIR to write the solution sol, given in general form,
in standard form with enumeration of different conditions (if there are any).
It can be used independently.
Transformations
switch trdesir : when it is ON, at each step of the Newton algorithm, a description
of the Newton polygon is displayed (it is possible to follow the break of slopes), and
at each call of the FROBENIUS procedure ( case of a null slope ) the corresponding
indicial equation is displayed.
By default, this switch is OFF.
16.19.6 LIMITATIONS
This package supports computations with total and partial derivatives of formal
function objects. Such computations can be useful in the context of differential
equations or power series expansions.
Author: Herbert Melenk.
The package DFPART supports computations with total and partial derivatives of
formal function objects. Such computations can be useful in the context of differ-
ential equations or power series expansions.
where f name is the (new) name of a function and argi are symbols for its for-
mal arguments. In the following f name is referred to as “generic function",
arg1 , arg2 · · · argn as “generic arguments" and f name(arg1 , arg2 · · · argn ) as
“generic form". Examples:
generic_function f(x,y);
generic_function g(z);
• expressions of the type f (), g() are abbreviations for f (x, y), g(z),
where expr is a function expression and df argi are the differentiation variables.
Examples:
dfp(f(),{x,y});
∂2f
means ∂x∂y and
dfp(f(u,v),{x,y});
∂ f2
stands for ∂x∂y (u, v). For compatibility with the DF operator the differentiation
variables need not be entered in list form; instead the syntax of DF can be used,
where the function expression is followed by the differentiation variables, eventu-
ally with repetition numbers. Such forms are interenally converted to the above
form with a list as second parameter.
The expression expr can be a generic function with or without arguments, or an
arithmetic expression built from generic functions and other algebraic parts. In the
second case the standard differentiation rules are applied in order to reduce each
derivative expressions to a minimal form.
When the switch NAT is on partial derivatives of generic functions are printed in
∂2f ∂2f
standard index notation, that is fxy for ∂x∂y and fxy (u, v) for ∂x∂y (u, v). There-
fore single characters should be used for the arguments whenever possible. Exam-
ples:
generic_function f(x,y);
generic_function g(y);
dfp(f(),x,2);
F
XX
dfp(f()*g(),x,2);
F *G()
XX
dfp(f()*g(),x,y);
502 CHAPTER 16. USER CONTRIBUTED PACKAGES
F *G() + F *G
XY X Y
The difference between partial and total derivatives is illustrated by the following
example:
generic_function h(x);
dfp(f(x,h(x))*g(h(x)),x);
F (X,H(X))*G(H(X))
X
df(f(x,h(x))*g(h(x)),x);
+ G (H(X))*H (X)*F(X,H(X))
Y X
Cooperation of partial derivatives and Taylor series under a differential side relation
dq
dx = f (x, q):
load_package taylor;
operator q;
let df(q(~x),x) => f(x,q(x));
taylor(q(x0+h),h,0,3);
F (X0,Q(X0)) + F (X0,Q(X0))*F(X0,Q(X0))
X Y 2
Q(X0) + F(X0,Q(X0))*H + -----------------------------------------*H
2
+ (F (X0,Q(X0)) + F (X0,Q(X0))*F(X0,Q(X0))
XX XY
2 2 3
+ F (X0,Q(X0))*F(X0,Q(X0)) + F (X0,Q(X0)) *F(X0,Q(X0)))/6*H
503
YY Y
4
+ O(H )
dfp(f(),x,y)-dfp(f(),y,x);
F - F
XY YX
generic_function q(x,y);
dfp_commute q(x,y);
dfp(q(),{x,y,y}) + dfp(q(),{y,x,y}) + dfp(q(),{y,y,x});
3*Q
XYY
If only a part of the derivatives commute, this has to be declared using the standard
REDUCE rule mechanism. Please note that then the derivative variables must be
written as list.
16.20.3 Substitutions
When a generic form or a DFP expression takes part in a substitution the following
steps are performed:
1. The substitutions are performed for the arguments. If the argument list is
empty the substitution is applied to the generic arguments of the function; if
these change, the resulting forms are used as new actual arguments. If the
generic function itself is not affected by the substitution, the process stops
here.
2. If the function name or the generic function form occurs as a left hand side
in the substitution list, it is replaced by the corresponding right hand side.
504 CHAPTER 16. USER CONTRIBUTED PACKAGES
3. The new form is partially differentiated according to the list of partial deriva-
tive variables.
4. The (eventually modified) actual parameters are substituted into the form for
their corresponding generic variables. This substitution is done by name.
Examples:
generic_function f(x,y);
sub(y=10,f());
F(X,10)
sub(y=10,dfp(f(),x,2));
F (X,10)
XX
sub(y=10,dfp(f(y,y),x,2));
F (10,10)
XX
sub(f=x**3*y**3,dfp(f(),x,2));
3
6*X*Y
generic_function ff(y,z);
sub(f=ff,f(a,b));
FF(B,Z)
This package allows a user to find the canonical form of expressions involving
dummy variables. In that way, the simplification of polynomial expressions can be
fully done. The indeterminates are general operator objects endowed with as few
properties as possible. In that way the package may be used in a large spectrum of
applications.
Author: Alain Dresse.
16.21.1 Introduction
A dummy variable (let us name it dv) is an identifier which runs from the integer
i1 to another integer i2 . To the extent that no definite space is defined, i1 and i2 are
assumed to be some integers which are the same for all dummy variables.
If f is any REDUCE operator, then the simplest dummy summation associated to
dv is the sum
Xi2
f (dv)
dv=i1
and the computer algebra system should be able to find that the expression
f (dv) − f (dum);
is equal to 0. A very special case which is allowed is when f is the identity operator.
So, a generic dummy polynomial will be a sum of dummy monomials of the kind
Y
ci ∗ fi (dv1 , . . . , dvki , f r1 , . . . , f rli )
i
where dv1 , . . . , are dummy variables while f r1 , . . . , are ordinary or free variables.
To declare dummy variables, two commands are available:
• i.
dummy_base <idp>;
• ii.
The first one declares idp1 , . . . , idpn as dummy variables i.e. all variables of
the form idpxxx where xxx is a number will be dummy variables, such as
idp1 , idp2 , . . . , idp23 . The second one gives special names for dummy variables.
All other identifiers which may appear are assumed to be free. However, there is a
restriction: named and base dummy variables cannot be declared simultaneously.
The above declarations are mutually exclusive. Here is an example showing that:
op(dv1)*sin(dv2)*abs(i)*op(dv2)$
means a sum over dv1 , dv2 . To clear the dummy base, and to create the dummy
names i, j, k one is to do
clear_dummy_base; ==> t
op(dv1)*sin(dv2)*abs(x)*op(i)^3*op(dv2)$
means a sum over i. One should keep in mind that every application of the above
commands erases the previous ones. It is also possible to display the declared
dummy names using SHOW_DUMMY_NAMES:
clear_dummy_names; clear_dummy_base;
508 CHAPTER 16. USER CONTRIBUTED PACKAGES
All dummy variables should appear at first level as arguments of operators. For
instance, if i and j are dummy variables, the expression
rr:= op(i,j)-op(j,j)
op(i,op(j)) - op(j,op(j))
is not allowed. This is because dummy variables are not detected if they appear
at a level larger than 1. Apart from that there is no restrictions. Operators may
be commutative, noncommutative or even anticommutative. Therefore they may
be elements of an algebra, they may be tensors, spinors, grassman variables, etc.
. . . By default they are assumed to be commutative and without symmetry proper-
ties. The REDUCE command NONCOM is taken into account and, in addition, the
command
The first one makes the operator (fully) symmetric. The second one declares it
antisymmetric with respect to the three last indices. The symbols !*, !+ and !- at
the beginning of each list mean that the operator has no symmetry, is symmetric or
is antisymmetric with respect to the indices inside the list. Notice that the indices
are not denoted by their names but merely by their natural order of appearance. 1
means the first written argument of r, 2 its second argument etc. The first command
is equivalent to the declaration symmetric except that the number of indices of
r is restricted to 4 i.e. to the number declared in SYMTREE. In the second example
r is stated to have no symmetry with respect to the first index and is declared to
be antisymmetric with respect to the three last indices. In the third example, r is
made symmetric with respect to the interchange of the pairs of indices 1,2 and 3,4
respectively and is made antisymmetric separately within the pairs (1, 2) and (3, 4).
It is the symmetry of the Riemann tensor. The anticommutation property and the
509
However, notice that the number of indices remains fixed and equal to 4 while with
REMSYM it becomes again arbitrary.
aa:=r(x3,x4,x2,x1)$
If it contains dummy indices, CANONICAL takes also into account the various
dummy summations, makes the relevant simplifications, eventually rename the
dummy indices and returns the resulting normal form. Here is a simple example:
operator at1,at2;
anticom at1,at2;
rr:=at1(i)*at2(k) -at2(k)*at1(i)$
operator op;
dummy_names i,j;
rr:=op(i,op(j))-op(j,op(j))$
aa:=df(op(x,i),x) -df(op(x,j),x)$
instead of zero. A second limitation is that CANONICAL does not add anything
to the problem of simplifications when side relations (like Bianchi identities) are
present.
16.21.5 Bibliography
- Butler, G. and Lam, C. W. H., “A general backtrack algorithm for the
isomorphism problem of combinatorial objects", J. Symb. Comput. vol.1,
(1985) p.363-381.
- Butler, G. and Cannon, J. J., “Computing in Permutation and Matrix
Groups I: Normal Closure, Commutator Subgroups, Series", Math. Comp.
vol.39, number 60, (1982), p. 663-670.
- Butler, G., “Computing in Permutation and Matrix Groups II: Backtrack
Algorithm", Math. Comp. vol.39, number 160, (1982), p.671-680.
- Leon, J.S., “On an Algorithm for Finding a Base and a Strong Generating
Setfor a Group Given by Generating Permutations”, Math. Comp. vol.35,
(1980), p941-974.
- Leon, J. S., “Computing Automorphism Groups of Combinatorial Objects”,
Proc. LMS Symp. on Computational Group Theory, Durham, England,
editor: Atkinson, M. D., Academic Press, London, (1984).
511
EXCALC is designed for easy use by all who are familiar with the calculus of Mod-
ern Differential Geometry. The program is currently able to handle scalar-valued
exterior forms, vectors and operations between them, as well as non-scalar valued
forms (indexed forms). It is thus an ideal tool for studying differential equations,
doing calculations in general relativity and field theories, or doing simple things
such as calculating the Laplacian of a tensor field for an arbitrary given frame.
Author: Eberhard Schrüfer.
Acknowledgments
This program was developed over several years. I would like to express my deep
gratitude to Dr. Anthony Hearn for his continuous interest in this work, and es-
pecially for his hospitality and support during a visit in 1984/85 at the RAND
Corporation, where substantial progress on this package could be achieved. The
Heinrich Hertz-Stiftung supported this visit. Many thanks are also due to Drs.
F.W. Hehl, University of Cologne, and J.D. McCrea, University College Dublin,
for their suggestions and work on testing this program.
16.22.1 Introduction
EXCALC is designed for easy use by all who are familiar with the calculus of
Modern Differential Geometry. Its syntax is kept as close as possible to standard
textbook notations. Therefore, no great experience in writing computer algebra
programs is required. It is almost possible to input to the computer the same as what
would have been written down for a hand-calculation. For example, the statement
f*x^y + u _| (y^z^x)
the program.
This is the last release of version 2. A much extended differential geometry pack-
age (which includes complete symbolic index simplification, tensors, mappings,
bundles and others) is under development.
Complaints and comments are appreciated and should be send to the author. If the
use of this program leads to a publication, this document should be cited, and a
copy of the article to the above address would be welcome.
16.22.2 Declarations
Geometrical objects like exterior forms or vectors are introduced to the system by
declaration commands. The declarations can appear anywhere in a program, but
must, of course, be made prior to the use of the object. Everything that has no
declaration is treated as a constant; therefore zero-forms must also be declared.
An exterior form is introduced by
PFORM < declaration1 >, < declaration2 >, . . . ;
where
< declaration > ::= < name > | < list of names >=< number > | < identifier > |
< expression >
< name > ::= < identifier > | < identifier >(< arguments >)
For example
pform u=k,v=4,f=0,w=dim-1;
pform curv(a,b)=2,chris(a,b)=1;
pform {x,y,z}=0,{rho(k,l),u,v(k)}=1;
For example, to declare X as a vector and COMM as a vector with two indices, one
would say
tvector x,comm(a,b);
exdegree(u + 3*chris(k,-k));
Exterior multiplication between exterior forms is carried out with the nary infix op-
erator ˆ (wedge). Factors are ordered according to the usual ordering in REDUCE
using the commutation rule for exterior products.
Example 10
pform u=1,v=1,w=k;
u^v;
U^V
v^u;
- U^V
u^u;
w^u^v;
K
( - 1) *U^V^W
515
(3*u-a*w)^(w+5*v)^u;
A*(5*U^V^W - U^W^W)
spacedim 4;
pform u=2,v=3;
u^v;
Partial differentiation is denoted by the operator @. Its capability is the same as the
REDUCE DF operator.
Example 11
@(sin x,x);
COS(X)
@(f,x);
fdomain f=f(x,y),h=h(x);
@(x*f,x);
516 CHAPTER 16. USER CONTRIBUTED PACKAGES
F + X*@ F
X
@(h,y);
The partial derivative symbol can also be an operator with a single argument. It
then represents a natural base element of a tangent vector.
Example 12
a*@ x + b*@ y;
A*@ + B*@
X Y
pform x=0,y=k,z=m;
d(x * y);
X*d Y + d X^Y
d(r*y);
R*d Y
d(x*y^z);
K
( - 1) *X*Y^d Z + X*d Y^Z + d X^Y^Z
noxpnd d;
d(y^z);
517
d(Y^Z)
To obtain a canonical form for an exterior product when the expansion is switched
off, the operator D is shifted to the right if it appears in the leftmost place.
d y ^ z;
K
- ( - 1) *Y^d Z + d(Y^Z)
pform x=0,y=0,z=0,f=0;
fdomain f=f(x,y);
d f;
@ F*d X + @ F*d Y
X Y
fdomain y=y(z);
d f;
d d x;
518 CHAPTER 16. USER CONTRIBUTED PACKAGES
pform u=k;
spacedim k;
d u;
The inner product between a vector and an exterior form is represented by the
diphthong _| (underscore or-bar), which is the notation of many textbooks. If the
exterior form is an exterior product, the inner product is carried through any factor.
Example 13
pform x=0,y=k,z=m;
tvector u,v;
u _| (x*y^z);
K
X*(( - 1) *Y^U _| Z + U _| Y^Z)
In repeated applications of the inner product to the same exterior form the vector
arguments are ordered e.g.
(u+x*v) _| (u _| (3*z));
- 3*U _| V _| Z
The duality of natural base elements is also known by the system, i.e.
pform {x,y}=0;
3*A - B
519
The Lie derivative can be taken between a vector and an exterior form or between
two vectors. It is represented by the infix operator |_ . In the case of Lie differen-
tiating, an exterior form by a vector, the Lie derivative is expressed through inner
products and exterior differentiations, i.e.
pform z=k;
tvector u;
u |_ z;
U _| d Z + d(U _| Z)
If the arguments of the Lie derivative are vectors, the vectors are ordered using the
anticommutivity property, and functions (zero forms) are differentiated out.
Example 14
tvector u,v;
v |_ u;
- U |_ V
pform x=0,y=0;
(x*u) |_ (y*v);
The Hodge-* duality operator maps an exterior form of degree K to an exterior form
of degree N-K, where N is the dimension of the space. The double application
of the operator must lead back to the original exterior form up to a factor. The
following example shows how the factor is chosen here
spacedim n;
pform x=k;
# # x;
520 CHAPTER 16. USER CONTRIBUTED PACKAGES
2
(K + K*N)
( - 1) *X*SGN
The indeterminate SGN in the above example denotes the sign of the determinant
of the metric. It can be assigned a value or will be automatically set if more of
the metric structure is specified (via COFRAME), i.e. it is then set to g/|g|, where
g is the determinant of the metric. If the Hodge-* operator appears in an exterior
product of maximal degree as the leftmost factor, the Hodge-* is shifted to the right
according to
pform {x,y}=k;
# x ^ y;
2
(K + K*N)
( - 1) *X^# Y
The function VARDF returns as its value the variation of a given Lagrangian n-form
with respect to a specified exterior form (a field of the Lagrangian). In the shared
variable BNDEQ!*, the expression is stored that has to yield zero if integrated over
the boundary.
Syntax:
VARDF(< Lagrangian n-form >,< exterior form >)
Example 15
spacedim 4;
pform l=4,a=1,j=3;
vardf(l,a);
- (# J + d # d A) %Maxwell’s equations
521
bndeq!*;
Restrictions:
In the current implementation, the Lagrangian must be built up by the fields and
the operations d, #, and @. Variation with respect to indexed quantities is currently
not allowed.
For the calculation of the conserved currents induced by symmetry operators (vec-
tor fields), the function NOETHER is provided. It has the syntax:
NOETHER(< Lagrangian n-form >,< field >,< symmetry generator >)
Example 16
pform l=4,a=1,f=2;
spacedim 4;
noether(l,a,x);
The above expression would be the canonical energy momentum 3-forms of the
Maxwell field, if X is interpreted as a translation;
Exterior forms and vectors may have indices. On input, the indices are given as
arguments of the object. A positive argument denotes a superscript and a negative
argument a subscript. On output, the indexed quantity is displayed two dimension-
ally if NAT is on. Indices may be identifiers or numbers.
Example 17
522 CHAPTER 16. USER CONTRIBUTED PACKAGES
pform om(k,l)=m,e(k)=1;
e(k)^e(-l);
K
E ^E
L
om(4,-2);
4
OM
2
indexrange t,r,ph,z;
pform e(k)=1,s(k,l)=2;
w := e(k)*e(-k);
T R PH Z
W := E *E + E *E + E *E + E *E
T R PH Z
s(k,l):=e(k)^e(l);
T T
S := 0
R T T R
S := - E ^E
PH T T PH
S := - E ^E
.
523
.
.
e(k)^e(l);
T T
NS := 0
R T T R
NS := - E ^E
.
.
.
It should be noted, however, that the index positions on the variable NS can some-
times not be uniquely determined by the system (because of possible reorderings in
the expression). Generally it is advisable to use assignments to display complicated
expressions.
A range can also be assigned to individual index-names. For example, the declara-
tion
indexrange {k,l}={x,y,z},{u,v,w}={1,2};
would assign to the index identifiers k,l the range values x,y,z and to the index
identifiers u,v,w the range values 1,2. The use of an index identifier not listed in
previous indexrange statements has the range of the union of all given index ranges.
With the above example of an indexrange statement, the following index evalua-
tions would take place
pform w n=0;
w(k)*w(-k);
X Y Z
W *W + W *W + W *W
X Y Z
524 CHAPTER 16. USER CONTRIBUTED PACKAGES
w(u)*w(-u);
1 2
W *W + W *W
1 2
w(r)*w(-r);
1 2 X Y Z
W *W + W *W + W *W + W *W + W *W
1 2 X Y Z
In certain cases, one would like to inhibit the summation over specified index
names, or at all. For this the command
NOSUM < indexname1 >, . . . ;
and the switch NOSUM are available. The command NOSUM has the effect that
summation is not performed over those indices which had been listed. The com-
mand RENOSUM enables summation again. The switch NOSUM, if on, inhibits any
summation.
It is possible to declare symmetry properties for an indexed quantity by the com-
mand INDEX_SYMMETRIES. A prototypical example is as follows
It declares the object u symmetric in the first two and last two indices and anti-
symmetric with respect to commutation of the given index pairs. If an object is
completely symmetric or antisymmetric, the indices need not to be given after the
corresponding keyword as shown above for g and h.
If applicable, this command should be issued, since great savings in memory and
execution time result. Only strict components are printed.
The commands symmetric and antisymmetric of earlier releases have no effect.
Syntax:
This statement automatically sets the dimension of the space and the index range.
The clause WITH METRIC can be omitted if the metric is Euclidean and the short-
hand WITH SIGNATURE < diagonal elements > can be used in the case
of a pseudo-Euclidean metric. The splitting of a metric structure in its metric ten-
sor coefficients and basis one-forms is completely arbitrary including the extremes
of an orthonormal frame and a coordinate frame.
Example 19
Individual elements of the metric can be accessed just by calling them with the
desired indices. The value of the determinant of the covariant metric is stored in
the variable DETM!*. The metric is not needed for lowering or raising of indices
as the system performs this automatically, i.e. no matter in what index position
values were assigned to an indexed quantity, the values can be retrieved for any
index position just by writing the indexed quantity with the desired indices.
Example 20
526 CHAPTER 16. USER CONTRIBUTED PACKAGES
pform f(k,l)=0;
f(k,l) := 0$
f(-t,-x):=ex$ f(-x,-y):=b$
on nero;
f(k,-l);
X
NS := - EX
T
T
NS := - EX
X
Y
NS := - B
X
X
NS := B
Y
d r^d th;
R TH
(E ^E )/R
d(e(th));
527
R TH
(E ^E )/R
pform f=0;
fdomain f=f(r,th,ph);
factor e;
on rat;
R TH PH
E *@ F + (E *@ F)/R + (E *@ F)/(R*SIN(TH))
R TH PH
The frame dual to the frame defined by the COFRAME command can be introduced
by FRAME command.
FRAME < identifier >;
This command causes the dual property to be recognized, and the tangent vectors
of the coordinate functions are replaced by the frame basis vectors.
Example 22
frame x;
on nero;
x(-k) _| b(l);
R
NS := 1
R
PH
NS := 1
PH
Z
528 CHAPTER 16. USER CONTRIBUTED PACKAGES
NS := 1
Z
NS := X /R
PH R PH
riemannconx om;
TH
NS := 0
TH
PH PH
529
NS := (E *COS(TH))/(SIN(TH)*R)
TH
TH PH
NS := ( - E *COS(TH))/(SIN(TH)*R)
PH
PH
NS := 0
PH
pform curv(k,l)=2;
TH
CURV := 0
TH
PH TH PH 2
CURV := ( - E ^E )/R
TH %Of course it was a sphere with
%radius R.
TH TH PH 2
CURV := (E ^E )/R
PH
PH
CURV := 0
PH
killing_vector u;
ph th
{@ * u + @ *u ,
ph th
th
{@ (u ),
th
ph 2 th
@ (u )*sin(th) + @ (u ),
th ph
th ph
cos(th)*u + @ (u )*sin(th)}}
ph
pform x=0,y=0,z=0,f=0,j=3;
531
j;
d j;
j^d x;
fdomain f=f(x);
d f^d y^d z;
@ F*J
X
The capabilities of KEEP are currently very limited. Only exterior products should
occur as righthand sides in KEEP.
532 CHAPTER 16. USER CONTRIBUTED PACKAGES
Table 16.1 summarizes EXCALC commands and the page number they are defined
on.
16.22.16 Examples
The following examples should illustrate the use of EXCALC. It is not intended
to show the most efficient or most elegant way of stating the problems; rather the
variety of syntactic constructs are exemplified. The examples are on a test file
distributed with EXCALC.
% Problem: Calculate the PDE’s for the isovector of the heat equation.
% --------
% (c.f. B.K. Harrison, f.B. Estabrook, "Geometric Approach...",
% J. Math. Phys. 12, 653, 1971)
pform {psi,u,x,y,t}=0,a=1,{da,b}=2;
da := - d u^d t - d y^d x;
tvector v;
pform {vpsi,vt,vu,vx,vy}=0;
fdomain vpsi=vpsi(psi,t,u,x,y),vt=vt(psi,t,u,x,y),vu=vu(psi,t,u,x,y),
vx=vx(psi,t,u,x,y),vy=vy(psi,t,u,x,y);
factor d;
on rat;
i1 := v |_ a - l*a;
pform o=1;
fdomain f=f(psi,t,u,x,y);
i11 := v _| d a - l*a + d f;
let vx=-@(f,y),vt=-@(f,u),vu=@(f,t)+u*@(f,psi),vy=@(f,x)+y*@(f,psi),
vpsi=f-u*@(f,u)-y*@(f,y);
factor ^;
let ou=0,oy=@(f,u,psi),ox=-u*@(f,u,psi),
ot=@(f,x,psi)+u*@(f,y,psi)+y*@(f,psi,psi);
i2;
let zeta=-@(f,u,x)-@(f,u,y)*u-@(f,u,psi)*y;
i2;
let xi=-@(f,t,u)-u*@(f,u,psi)+@(f,x,y)+u*@(f,y,y)+y*@(f,y,psi)+@(f,psi);
i2;
let @(f,u,u)=0;
clear a,da,b,v,i1,i11,o,i2,xi,t;
remfdomain f,vpsi,vt,vu,vx,vy;
clear @(f,u,u);
% Problem:
% --------
% Calculate the integrability conditions for the system of PDE’s:
% (c.f. B.F. Schutz, "Geometrical Methods of Mathematical Physics"
% Cambridge University Press, 1984, p. 156)
% @ z /@ x + a1*z + b1*z = c1
% 1 1 2
% @ z /@ y + a2*z + b2*z = c2
% 1 1 2
% @ z /@ x + f1*z + g1*z = h1
% 2 1 2
535
% @ z /@ y + f2*z + g2*z = h2
% 2 1 2 ;
pform w(k)=1,integ(k)=4,{z(k),x,y}=0,{a,b,c,f,g,h}=1,
{a1,a2,b1,b2,c1,c2,f1,f2,g1,g2,h1,h2}=0;
fdomain a1=a1(x,y),a2=a2(x,y),b1=b1(x,y),b2=b2(x,y),
c1=c1(x,y),c2=c2(x,y),f1=f1(x,y),f2=f2(x,y),
g1=g1(x,y),g2=g2(x,y),h1=h1(x,y),h2=h2(x,y);
a:=a1*d x+a2*d y$
b:=b1*d x+b2*d y$
c:=c1*d x+c2*d y$
f:=f1*d x+f2*d y$
g:=g1*d x+g2*d y$
h:=h1*d x+h2*d y$
clear a,b,c,f,g,h,x,y,w(k),integ(k),z(k);
remfdomain a1,a2,b1,c1,c2,f1,f2,g1,g2,h1,h2;
% Problem:
% --------
% Calculate the PDE’s for the generators of the d-theta symmetries of
% the Lagrangian system of the planar Kepler problem.
% c.f. W.Sarlet, F.Cantrijn, Siam Review 23, 467, 1981
% Verify that time translation is a d-theta symmetry and calculate the
% corresponding integral.
pform {t,q(k),v(k),lam(k),tau,xi(k),eta(k)}=0,theta=1,f=0,
{l,glq(k),glv(k),glt}=0;
tvector gam,y;
indexrange 1,2;
fdomain tau=tau(t,q(k),v(k)),xi=xi(t,q(k),v(k)),f=f(t,q(k),v(k));
536 CHAPTER 16. USER CONTRIBUTED PACKAGES
pform r=0;
fdomain r=r(q(k));
let @(r,q 1)=q(1)/r,@(r,q 2)=q(2)/r,q(1)**2+q(2)**2=r**2;
factor @;
s := y |_ theta - d f$
glq(k) := @(q k) _| s;
glv(k) := @(v k) _| s;
glt := @(t) _| s;
glq k := glq k;
glv k := glv k;
glt;
% Problem:
% --------
% Calculate the "gradient" and "Laplacian" of a function and the "curl"
% and "divergence" of a one-form in elliptic coordinates.
pform f=0;
fdomain f=f(u,v,phi);
factor e,^;
on rat,gcd;
order cosh v, sin u;
% The gradient:
d f;
factor @;
% The Laplacian:
# d # d f;
remfac @;
pform w=1,a(k)=0;
fdomain a=a(u,v,phi);
w := a(-k)*e k;
% The curl:
x := # d w;
factor @;
% The divergence:
y := # d # w;
remfac @;
clear x,y,w,u,v,phi,e k,a k;
remfdomain a,f;
% Problem:
% --------
% Calculate in a spherical coordinate system the Navier Stokes equations.
fdomain v=v(t,r,theta,phi),p=p(r,theta,phi);
538 CHAPTER 16. USER CONTRIBUTED PACKAGES
pform v(k)=0,p=0,w=1;
w := v(-k)*e(k)$
factor e; on rat;
% Finally we add the pressure term and print the components of the
% whole equation.
pform nasteq=1,nast(k)=0;
factor @;
remfac @,e;
% Problem:
% --------
% Calculate from the Lagrangian of a vibrating rod the equation of
% motion and show that the invariance under time translation leads
% to a conserved current.
pform {y,x,t,q,j}=0,lagr=2;
fdomain y=y(x,t),q=q(x),j=j(x);
factor ^;
vardf(lagr,y);
pform c=1;
factor d;
c := noether(lagr,y,@ t);
remfac d;
d c;
clear lagr,c,j,y,q;
remfdomain y,q,j;
% Problem:
% --------
% Show that the metric structure given by Eguchi and Hanson induces a
% self-dual curvature.
% c.f. T. Eguchi, P.B. Gilkey, A.J. Hanson, "Gravitation, Gauge Theories
% and Differential Geometry", Physics Reports 66, 213, 1980
pform f=0,g=0;
fdomain f=f(r), g=g(r);
frame e;
pform gamma(a,b)=1,curv2(a,b)=2;
index_symmetries gamma(a,b),curv2(a,b): antisymmetric;
factor o;
let f=1/g,g=sqrt(1-(a/r)**4);
pform chck(k,l)=2;
index_symmetries chck(k,l): antisymmetric;
clear gamma(a,b),curv2(a,b),f,g,chck(a,b),o(k),e(k),r,phi,psi;
remfdomain f,g;
pform {r,s}=0;
fdomain r=r(t),s=s(t);
coframe o(t) = d t,
o(1) = r*d u/(1 + k*(u**2)/4),
o(2) = r*u*d theta/(1 + k*(u**2)/4),
o(3) = r*u*sin(theta)*d phi/(1 + k*(u**2)/4),
o(4) = s*d v1,
o(5) = s*sin(v1)*d v2
with metric g =-o(t)*o(t)+o(1)*o(1)+o(2)*o(2)+o(3)*o(3)
+o(4)*o(4)+o(5)*o(5);
frame e;
riemannconx om;
pform curv(k,l)=2,{riemann(a,b,c,d),ricci(a,b),riccisc}=0;
ricci(-a,-b) := riemann(c,-a,-d,-b)*g(-c,d);
riccisc := ricci(-a,-b)*g(a,b);
pform {laglanc,inv1,inv2} = 0;
index_symmetries riemc3(k,l),riemri(k,l),
hlang(k,l),einst(k,l): symmetric;
pform {riemc3(i,j),riemri(i,j)}=0;
riemc3(-i,-j) := riemann(-i,-k,-l,-m)*riemann(-j,k,l,m)$
inv1 := riemc3(-i,-j)*g(i,j);
riemri(-i,-j) := 2*riemann(-i,-k,-j,-l)*ricci(k,l)$
inv2 := ricci(-a,-b)*ricci(a,b);
laglanc := (1/2)*(inv1 - 4*inv2 + riccisc**2);
pform {einst(a,b),hlang(a,b)}=0;
alp1 := 1$
factor alp2;
einst(-i,-j) := einst(-i,-j);
clear o(k),e(k),riemc3(i,j),riemri(i,j),curv(k,l),riemann(a,b,c,d),
ricci(a,b),riccisc,t,u,v1,v2,theta,phi,r,om(k,l),einst(a,b),
hlang(a,b);
remfdomain r,s;
% Problem:
% --------
% Calculate for a given coframe and given torsion the Riemannian part and
% the torsion induced part of the connection. Calculate the curvature.
% For a more elaborate example see E.Schruefer, F.W. Hehl, J.D. McCrea,
% "Application of the REDUCE package EXCALC to the Poincare gauge field
542 CHAPTER 16. USER CONTRIBUTED PACKAGES
frame e;
pform {tor(a),gwt(a)}=2,gamma(a,b)=1,
{u1,u3,u5}=0;
fdomain u1=u1(r),u3=u3(r),u5=u5(r);
tor(4) := 0$
pform curv(a,b)=2;
index_symmetries curv(a,b): antisymmetric;
factor ^;
clear o(k),e(k),curv(a,b),gamma(a,b),theta,phi,x,y,z,r,s,t,u,v,p,q,c,cs;
remfdomain u1,u3,u5,ff,gg;
showtime;
543
end;
544 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.23.1 Abstract
The FIDE package performs automation of the process of numerical solving par-
tial differential equations systems (PDES) by means of computer algebra. For
PDES solving finite difference method is applied. The computer algebra system
REDUCE and the numerical programming language FORTRAN are used in the
presented methodology. The main aim of this methodology is to speed up the
process of preparing numerical programs for solving PDES. This process is quite
often, especially for complicated systems, a tedious and time consuming task. In
the process one can find several stages in which computer algebra can be used
for performing routine analytical calculations, namely: transforming differential
equations into different coordinate systems, discretization of differential equations,
analysis of difference schemes and generation of numerical programs. The FIDE
package consists of the following modules:
HURWP for polynomial roots locating necessary in verifying the von Neumann
stability condition.
LINBAND for generating the block of FORTRAN code, which solves a system
of linear algebraic equations with band matrix appearing quite often in dif-
ference schemes.
545
Version 1.1 of the FIDE package is the result of porting FIDE package to RE-
DUCE 3.4. In comparison with Version 1.0 some features has been changed in the
LINBAND module (possibility to interface several numerical libraries).
References ———-
[1] R. Liska, L. Drska: FIDE: A REDUCE package for automation of FInite dif-
ference method for solving pDE. In ISSAC ’90, Proceedings of the International
Symposium on Symbolic and Algebraic Computation, Ed. S. Watanabe, M. Na-
gata. p. 169-176, ACM Press, Addison Wesley, New York 1990.
16.23.2 EXPRES
All evaluated quantities are transformed into the coordinate system set by the last
SCALEFACTORS statement. By default, if this statement is not applied, the three-
dimensional Cartesian coordinate system is employed. During the evaluation of
SCALEFACTORS statement the metric coefficients, i.e. scale factors SF(i), of a
defined coordinate system are computed and printed. If the WRCHRI switch is
ON, then the nonzero Christoffel symbols of the coordinate system are printed too.
By default the WRCHRI switch is OFF.
546 CHAPTER 16. USER CONTRIBUTED PACKAGES
For four different products between the tensor quantities, new infix operators have
been introduced (in the explaining examples, a two-dimensional coordinate system,
vectors U, V, and dyads T, W are considered):
The other usual arithmetic infix operators +, -, *, ** can be used in all situations
that have sense (e.g. vector addition, a multiplication of a tensor by a scalar, etc.).
New prefix operators have been introduced to express tensor quantities in its com-
ponents and the differential operators over the tensor quantities:
The results of the differential operators are written using the DIFF operator.
DIFF(<scalar>,<cor i>) expresses the derivative of <scalar> with respect to the
coordinate <cor i>. This operator is not further simplified. If the user wants to
make it simpler as common derivatives, he performs the following declaration:
Then, however, we must realize that if the scalars or tensor quantities do not di-
rectly explicitly depend on the coordinates, their dependencies have to be declared
using the DEPEND statements, otherwise the derivative will be evaluated to zero.
The dependence of all vector or dyadic components (as dependence of the name of
vector or dyad) has to appear before VECTORS or DYADS declarations, otherwise
after these declarations one has to declare the dependencies of all components. For
formulating the explicit derivatives of tensor expressions, the differentiation oper-
ator DF can be used (e.g. the differentiation of a vector in its components).
Tensor expressions
Tensor expressions are the input into the EXPRES module and can have a variety
of forms. The output is then the formulation of the given tensor expression in
the specified coordinate system. The most general form of a tensor expression
<tensor> is described as follows (the conditions (d=i) represent the limitation on
the dimension of the coordinate system equalling i):
Assigning statement
The assigning statement for tensor variables has a usual syntax, namely:
The assigning statement assigns the tensor variable the value of the given tensor
expression, formulated in the given coordinate system. After a change of the coor-
dinate system, the tensor variables have to be redefined.
References ———-
[1] M. C. Wirth, On the Automation of Computational Physics. PhDr Thesis. Re-
port UCRL-52996, Lawrence Livermore National Laboratory, Livermore, 1980.
16.23.3 IIMET
This statement specifies that the <coordinate i> will correspond to the <index i>.
A new COORDINATES statement cancels the definitions given by the preceding
COORDINATES statement. If the part [ INTO ... ] is not included in the statement,
the statement assigns the coordinates the indices I, J, K, L, M, N, respectively. If
it is included, the number of coordinates and the number of indices should be the
same.
ON CENTERGRID
I-1/2 I I+1/2 I+1 I+3/2
---|--------|--------|--------------|--------------|----
I I+1/2 I+1 I+3/2 I+2
OFF CENTERGRID
In the case of ON CENTERGRID, the indices i,i+1,i-1... thus designate the centers
of the cells of the integer grid and the boundary points of the cells of the half-integer
grid, and, similarly, in the case of OFF CENTERGRID, the boundaries of the cells
of the integer grid and the central points of the half-integer grid. The meaning
of the integer and half-integer grids depends on the CENTERGRID switch in the
550 CHAPTER 16. USER CONTRIBUTED PACKAGES
described way. After the package is loaded, the CENTERGRID is ON. Obviously,
this switch is significant only for non-uniform grids with a variable size of each
cell. The grids can be uniform, i.e. with a constant cell size - the step of the grid.
The following statement:
GRID UNIFORM,<coordinate>{,<coordinate>};
defines uniform grids in all coordinates occurring in it. Those coordinates that do
not occur in the GRID UNIFORM statement are supposed to have non-uniform
grids. In the outputs, the grid step is designated by the identifier that is made by
putting the character H before the name of the coordinate. For a uniform grid,
this identifier (e.g. for the coordinate X the grid step HX) has the meaning of a
step of an integer or half-integer grids that are identical. For a non-uniform grid,
this identifier is an operator and has the meaning of a step of an integer grid, i.e.
the length of a cell whose center (in the case of ON CENTERGRID) or beginning
(in the case of OFF CENTERGRID) is designated by a single argument of this
operator. For each coordinate s designated by the identifier i, this step of the integer
non-uniform grid is defined as follows:
for all integers j (s(k) designates the value of the coordinate s in the cellular bound-
ary point subscripted with the index k). The steps of the half-integer non-uniform
grid are not applied in outputs.
DEPENDENCE <dependence>{,<dependence>};
<dependence> ::= <function>([<order>],<coordinate>{,
<coordinate>})
<function> ::= "identifier" - the name of the function
<order> ::= 1|2 tensor order of the function (the value of
the function is 1 - vector, 2 - dyad (two-
551
dimensional tensor))
GIVEN <function>{,<function>};
declares all functions included in it as given functions whose values are known to
the user or can be computed. The CLEARGIVEN statement:
CLEARGIVEN;
cancels all preceding GIVEN declarations. If the TWOGRID switch is ON, the
given functions can be differentiated both on the integer and the half-integer grids.
If the TWOGRID switch is OFF, any given function can be differentiated only on
one grid. After the package is loaded, the TWOGRID is ON.
SAME <function>{,<function>};
552 CHAPTER 16. USER CONTRIBUTED PACKAGES
all functions given in one of these declarations will be discretized on the same
grids in all coordinates. In each SAME statement, at least one of these functions
in one SAME statement must be the sought one. If the given function occurs in
the SAME statement, it will be discretized only on one grid, regardless of the state
of the TWOGRID switch. If a vector or a dyadic function occurs in the SAME
statement, what has been said above relates to all its scalar components. There
are several SAME statements that can be presented. All SAME statements can be
canceled by the following statement:
CLEARSAME;
The SAME statement can be successfully used, for example, when the given func-
tion depends on the function sought in a complicated manner that cannot be in-
cluded either in the differential equation or in the difference scheme explicitly, and
when both the functions are desired to be discretized in the same points so that
the user will not be forced to execute the interpolation during the evaluation of the
given function. In some cases, it is convenient too to specify directly which vari-
able on which grid is to be discretized, for which case the ISGRID statement is
applied:
ISGRID <s-function>{,<s-function>};
<s-function> ::= <function>([<component>,]<s-grid>{,<s-grid>})
<s-grid> ::= <coordinate> .. <grid>,
<grid> ::= ONE | HALF designation of the integer
(ONE) and half-integer (HALF)
grids
<component> ::= <i-dim> | for the vector <function>
<i-dim>,<i-dim> for the dyadic <function>
it is not presented for the
scalar <function>
<i-dim> ::= *| "natural number from 1 to the space dimension
the space dimension is specified in the EXPRES
module by the SCALEFACTORS statement, * means all
components
The statement defines that the given functions or their components will be dis-
cretized in the specified coordinates on the specified grids, so that, for example,
the statement ISGRID U (X..ONE,Y..HALF), V(1,Z..ONE), T(*,1,X..HALF); de-
fines that scalar U will be discretized on the integer grid in the coordinate X, and
on the half-integer one in the coordinate Y, the first component of vector V will
be on the integer grid in the coordinate Z, and the first column of tensor T will be
on the half-integer grid in the coordinate X. The ISGRID statement can be applied
more times. The functions used in this statement have to be declared before by the
DEPENDENCE statement.
553
GRIDEQ <g-function>{,<g-function>};
<g-function> ::= <function>(<s-grid>{,<s-grid>})
Every equation can be discretized in any coordinate either on the integer or half-
integer grid. This statement determines the discretization of the equations given by
the functions included in it in given coordinates, on given grids. The meaning of
the fact that an equation is discretized on a certain grid is as follows: index I used
in the DIFMATCH statements (discussed in the following section), specifying the
discretization of the basic terms, will be located in the center of the cell of this
grid, and indices I+1/2, I-1/2 from the DIFMATCH statement on the boundaries
of the cell of this grid. The actual name of the index in the given coordinate is
determined using the COORDINATES statement, and its location on the grid is set
by the CENTERGRID switch.
1. D(a+b) = D(a)+D(b)
2. D(-a) = -D(a)
3. D(p.a) = p.D(a) (p does not depend on the coordinate x)
4. D(a/p) = D(a)/p
The linearization lasts as long as some of these rules can be applied. The basic
terms that must be discretized after the linearization have then the forms of the
following quantities:
The way of discretizing these basic terms, while the functions are on integer and
half-integer grids, is determined using the DIFMATCH statement:
The first parameter of the DIFMATCH statement determines the coordinate for
which the discretization defined in it is valid. If ALL is used, the discretization
will be valid for all coordinates, and this discretization is accepted when it has
been checked whether there has been no other discretization defined for the given
coordinate and the given pattern term. Each pattern sought function, occurring in
the pattern term, must be included in the specification of the grids. The pattern
given functions from the pattern term can occur in the grid specification, but in
some cases (see below) need not. In the grid specification the maximum number
of 3 pattern functions may occur. The discretization of each pattern term has to
be specified in all combinations of the pattern functions occurring in the grid spec-
ification, on the integer and half-integer grids, that is 2**n variants for the grid
specification with n pattern functions (n=0,1,2,3). The discretized term is the dis-
cretization of the pattern term in the pattern coordinate X in the point X(I) on the
pattern grid (see Fig. 2.2), and the pattern functions occurring in the grid specifi-
cation are in the discretized term on the respective grids from this specification (to
the discretized term corresponds the grid specification preceding it).
integer grid
X(I-1) X(I) X(I+1)
| DIM1 | DIP1 |
---|------|------|-------------|-------------|-----|-----|---
| DIM2 | DI | DIP2 |
X(I-3/2) X(I-1/2) X(I+1/2) X(I+3/2)
half-integer grid
can occur in the discretized term. In the integro-interpolation method, the dis-
556 CHAPTER 16. USER CONTRIBUTED PACKAGES
<discretized term>=1/(X(I+1/2)-X(I-1/2))*DINT(X(I-1/2),X(I+1/2),
<pattern term>,X),
DIFMATCH R,DIFF(U,X),U=ONE,2,(U(I+1)-U(I-1))/(2*DI);
U=HALF,0,(U(I+1/2)-U(I-1/2))/DI;
DIFMATCH R,DIFF(U,X,2),U=ONE,0,(U(I+1)-2*U(I)+U(I-1))/DI**2,
U=HALF,2,(U(I+3/2)-U(I+1/2)-U(I-1/2)+U(I-3/2))/(2*DI**2);
CLEARDIFMATCH;
After this statement user has to supply its own DIFMATCH statements. But now
back to the discretizing of the basic terms obtained by the linearization of the par-
tial differential equation, as mentioned at the beginning of this section. Using the
method of pattern matching, for each basic term a term representing its pattern is
found in the base of pattern terms (specified by the DIFMATCH statements). The
pattern matching obeys the following rules:
1. The pattern for the coordinate in which the discretization is executed is the
pattern coordinate X.
2. The pattern for the sought function is some pattern sought function, and this
557
3. The pattern for the given function is some pattern given function, or, in case
the EQFU switch is ON, some pattern sought function, and, again, the cor-
respondence of the pattern with the given function is mutually unambiguous
(after loading the EQFU switch is ON).
4. The pattern for the products of quantities is the product of the patterns of
these quantities, irrespective of their sequence.
5. The pattern for the quotient of quantities is the quotient of the patterns of
these quantities.
6. The pattern for the natural power of a quantity is the same power of the
pattern of this quantity or the power of this quantity with the pattern exponent
N.
7. The pattern for the derivative of a quantity with respect to the coordinate in
which the discretization is executed is the derivative of the pattern of this
quantity with respect to the pattern coordinate X of the same order of differ-
entiation.
8. The pattern for the sum of the quantities that have the same pattern with the
identical correspondence of functions and pattern functions is this common
pattern (so that it will not be necessary to multiply the parentheses during
discretizing the products in the second and further coordinates).
When matching the pattern of one basic term, the program finds the pattern term
and the functions corresponding to the pattern functions, maybe also the exponent
corresponding to the pattern exponent N. After determining on which grids the in-
dividual functions and the individual equations will be discretized, which will be
discussed in the next section, the program finds in the pattern term base the dis-
cretized term either with pattern functions on the same grids as are the functions
from the basic term corresponding to them in case that the given equation is differ-
entiated on the integer grid, or with pattern functions on inverse grids (an inverse
integer grid is a half-integer grid, and vice versa) compared with those used for
the functions from the basic term corresponding to them in case the given equation
is differentiated on the half-integer grid (the discretized term in the DIFMATCH
statement is expressed in the point X(I), i.e. on the integer grid, and holds for the
discretizing of the equation on the integer grid; with regard to the substitutions for
the pattern index I mentioned later, it is possible to proceed in this way and not nec-
essary to define the discretization in the points X(I+1/2) too, i.e. on the half-integer
grid). The program replaces in the thus obtained discretized term:
1. The pattern coordinate X with the particular coordinate s in which the dis-
cretization is actually performed.
558 CHAPTER 16. USER CONTRIBUTED PACKAGES
2. The pattern index I and the grid steps DIM2, DIM1, DI, DIP1, DIP2 with
the expression given in table 2.1 according to the state of the CENTERGRID
switch and to the fact whether the given equation is discretized on the integer
or half-integer grid (i is the index corresponding to the coordinate s according
to the COORDINATES statement, the grid steps were defined in section 2.2)
3. The pattern functions with the corresponding functions from the basic term
and, possibly, the pattern exponent with the corresponding exponent from
the basic term.
--------------------------------------------------------------------
| the equation discretized on |
| the integer grid | the half-integer grid |
| CENTERGRID |CENTERGRID|CENTERGRID| CENTERGRID |
| OFF | ON | OFF | ON |
|------------------------------------------------------------------|
| I | i | i+1/2 |
|----|-------------------------------------------------------------|
|DIM2|(Hs(i-2)+Hs(i-1))/2| Hs(i-1) |(Hs(i-1)+Hs(i))/2 |
|DIM1| Hs(i-1) | (Hs(i-1)+Hs(i))/2 | Hs(i) |
|DI |(Hs(i-1)+Hs(i))/2 | Hs(i) |(Hs(i)+Hs(i+1))/2 |
|DIP1| Hs(i) | (Hs(i)+Hs(i+1))/2 | Hs(i+1) |
|DIP2|(Hs(i)+Hs(i+1))/2 | Hs(i+1) |(Hs(i+1)+Hs(i+2))/2|
--------------------------------------------------------------------
More details will be given now to the discretization of the given functions and its
specification. The given function may occur in the SAME statement, which makes
it bound with some sought function, in other words it can be discretized only on one
grid. This means that all basic terms, in which this function occurs, must have their
pattern terms in whose discretization definitions by the DIFMATCH statement the
pattern function corresponding to the mentioned given function has to occur in the
grid specification. If the given function does not occur in the SAME statement and
the TWOGRID switch is OFF, i.e. it can be discretized only on one grid again,
the same holds true. If, however, the given function does not occur in the SAME
statement and the TWOGRID switch is ON, i.e. it can be discretized simultane-
ously on the integer and the half-integer grids, then the basic terms of the equations
including this function have their pattern terms in whose discretization definitions
the pattern function corresponding to the mentioned given function need not occur
in the grid specification. If, however, in spite of all, this pattern function in the dis-
cretization definition does occur in the grid specification, it is the alternative with
a smaller number of interpolations occurring in the DIFMATCH statement that
559
is selected for each particular basic term with a corresponding pattern (the given
function can be on the integer or half-integer grid). Before the discretization is exe-
cuted, it is necessary to define using the DIFMATCH statements the discretization
of all pattern terms that are the patterns of all basic terms of all equations appearing
in the discretized system in all coordinates. The fact that the pattern terms of the
basic terms of partial equations occur repeatedly in individual systems has made
it possible to create a library of the discretizations of the basic types of pattern
terms using the integro-interpolation method. This library is a component part of
the IIMET module (in its end) and makes work easier for those users who find
the pattern matching mechanism described here too difficult. New DIFMATCH
statements have to be created by those whose equations will contain a basic term
having no pattern in this library, or those who need another method to perform
the discretization. The described implemented algorithm of discretizing the basic
terms is sufficiently general to enable the use of a nearly arbitrary discretization on
orthogonal grids.
All statements influencing the run of the discretization that one want use in this
run have to be executed before the discretization is initiated. The COORDI-
NATES, DEPENDENCE, and DIFMATCH statements have to occur in all appli-
cations. Further, if necessary, the GRID UNIFORM, GIVEN, ISGRID, GRIDEQ,
SAME, and DIFCONST statements can be used, or some of the CENTREGRID,
TWOGRID, EQFU, and FULLEQ switches can be set. Only then the discretization
of a system of partial differential equations can be started using the IIM statement:
Hence, in the IIM statement the name of the array in which the resulting difference
schemes will be stored, and the pair sought function - equation, which describes
this function, are specified. The meaning of the relation between the sought func-
tion and its equation during the discretization lies in the fact that the sought function
is preferred in its equation so that the interpolation is not, if possible, used in dis-
cretizing the terms of this equation that contain it. In the equations, the functions
560 CHAPTER 16. USER CONTRIBUTED PACKAGES
and the coordinates appear as identifiers. The identifiers that have not been de-
clared as functions by the DEPENDENCE statement or as coordinates by the CO-
ORDINATES statement are considered constants independent of the coordinates.
The partial derivatives are expressed by the DIFF operator that has the same syntax
as the standard differentiation operator DF. The functions and the equations can
also have the vector or tensor character. If these non-scalar quantities are applied,
the EXPRES module has to be used together with the IIMET module, and also
non-scalar differential operators such as GRAD, DIV, etc. can be employed. The
sequence performed by the program in the discretization can be briefly summed up
in the following items:
2. In each equation, the terms containing derivatives are transferred to the left
side, and the other terms to the right side of the equation.
3. For each coordinate, with respect to the sequence in which they occur in the
COORDINATES statement, the following is executed:
a) It is determined on which grids all functions and all equations in the actual
coordinate will be discretized, and simultaneously the limits are kept result-
ing from the ISGRID, GRIDEQ, and SAME statements if they were used.
Such a distribution of functions and equations on the grids is selected among
all possible variants that ensures the minimum sum of all numbers of the
interpolations of the basic terms (specified by the DIFMATCH statement) of
all equations if the FULLEQ switch is ON, or of all left sides of the equat-
ions if the FULLEQ switch is OFF (after the loading the FULLEQ switch is
ON).
b) The discretization itself is executed, as specified by the DIFMATCH state-
ments.
4. If the array name is A, then if there is only one scalar equation in the IIM
statement, the discretized left side of this equation is stored in A(0) and the
discretized right side in A(1) (after the transfer mentioned in item 2), if there
are more scalar equations than one in the IIM statement, the discretization of
the left side of the i-th scalar equation is stored in A(i,0) and the discretiza-
tion of the right side in A(i,1).
The IIM statement can be used more times during one program run, and between its
calls, the discretizing process can be altered using other statements of this module.
561
Error messages
The IIMET module provides error messages in the case of the user’s errors. Sim-
ilarly as in the REDUCE system, the error reporting is marked with five stars :
"*****" on the line start. Some error messages are identical with those of the
REDUCE system. Here are given some other error messages that require a more
detailed explanation:
16.23.4 APPROX
In the determining of the approximation order, all discrete values of the functions
are expanded into the Taylor series in all coordinates. In order to determine the
Taylor expansion, the program needs to know the point in which it performs this
expansion, and the number of terms in the Taylor series in individual coordinates.
The center of the Taylor expansion is specified by the CENTER statement and the
number of terms in the Taylor series in individual coordinates by the MAXORDER
statement:
CENTER <center>{,<center>};
<center> ::= <coordinate> = <increment>
<increment> ::= "rational number"
MAXORDER <order>{,<order>};
<order> ::= <coordinate> = <number of terms>
<number of terms> ::= "natural number"
The increment in the CENTER statement determines that the center of the Taylor
expansion in the given coordinate will be in the point specified by the index I +
<increment>, where I is the index corresponding to this coordinate, defined using
the COORDINATES statement, e.g. the following example
specifies that the center of the Taylor expansion will be in the point (t(n+1/2),x(j+1))
and that until the second derivatives with respect to t (second powers of ht) and un-
til the third derivatives with respect to x (third powers of hx) the expansion will
be performed. The CENTER and MAXORDER statements can be placed only
after the COORDINATES statement. If the center of the Taylor expansion is not
defined in some coordinate, it is supposed to be in the point given by the index
of this coordinate (i.e. zero increment). If the number of the terms of the Taylor
expansion is not defined in some coordinate, the expansion is performed until the
third derivatives with respect to this coordinate.
Function declaration
All functions whose discrete values are to be expanded into the Taylor series must
be declared using the FUNCTIONS statement:
In the specification of the difference scheme, the functions are used as operators
with one or more arguments, designating the discrete values of the functions. Each
argument is the sum of the coordinate index (from the COORDINATES statement)
and a rational number. If some index is omitted in the arguments of a function, this
functional value is supposed to lie in the point in which the Taylor expansion is
performed, as specified by the CENTER statement. In other words, if the COOR-
DINATES and CENTER statements, shown in the example in the previous section,
are valid, then it holds that U(N+1) = U(N+1,J+1) and U(J-1) = U(N+1/2,J-1). The
FUNCTIONS statement can declare both the sought and the known functions for
the expansion.
In the difference scheme occur the functions in the form described in the preceding
section, the coordinate indices and the grid steps described in section 3.1, and the
other symbolic parameters of the difference scheme. The APPROX statement ex-
pands all discrete values of the functions declared in the FUNCTIONS statement
into the Taylor series in all coordinates (the point in which the Taylor expansion
is performed is specified by the CENTER statement, and the number of the ex-
pansion terms by the MAXORDER statement), substitutes the expansions into the
difference scheme, which gives a modified differential equation. The modified dif-
ferential equation, containing the grid steps too, is an equation that is really solved
by the difference scheme (into the given orders in the grid steps). The partial
differential equation, whose solution is approximated by the difference scheme, is
determined by replacing the grid steps by zeros and is displayed after the following
message:
"Difference scheme approximates differential equation"
Then the following message is displayed:
"with orders of approximation:"
and the lowest powers (except for zero) of the grid steps in all coordinates, occur-
ring in the modified differential equation are written. If the PRAPPROX switch
is ON, then the rest of the modified differential equation is printed. If this rest is
added to the left hand side of the approximated differential equation, one obtain
modified equation. By default the PRAPPROX switch is OFF. If the grid steps are
564 CHAPTER 16. USER CONTRIBUTED PACKAGES
found in some denominator in the modified equation, i.e. with a negative exponent,
the following message is written, preceding the approximated differential equation:
"Reformulate difference scheme, grid steps remain in denominator"
and the approximated differential equation is not correctly determined (one of its
sides is zero). Generally, this message means that there is a term in the difference
scheme that is not a difference replacement of the derivative, i.e. the ratio of the
differences of the discrete function values and the discrete values of the coordinates
(the steps of the difference grid). The user, however, must realize that in some cases
such a term occurs purposefully in the difference scheme (e.g. on the grid boundary
to keep the scheme conservative).
16.23.5 CHARPOL
A Module for Calculating the Amplification Matrix and the Characteristic Polyno-
mial of the Difference Scheme
This program module is used for the first step of the stability analysis of the differ-
ence scheme using the Fourier method. It substitutes the Fourier components into
the difference scheme, calculates the amplification matrix of the scheme for tran-
sition from one time layer to another, and computes the characteristic polynomial
of this matrix.
Function declaration
The UNFUNC statement declares the names of the sought functions used in the
difference scheme:
UNFUNC <function>{,<function>}
<function> ::= "identifier" - the name of the sought function
The functions are used in the difference schemes as operators with one or more
arguments for designating the discrete function values. Each argument is the sum
565
of the index (from the COORDINATES statement) and a rational number. If some
index is omitted in the function arguments, this function value is supposed to lie in
the point specified only by this index, which means that, with the indices N and J
and the function U, it holds that U(N+1) = U(N+1,J) and U(J-1) = U(N,J-1). As
two-step (in time) difference schemes may be used only, the time index may occur
either completely alone in the arguments, or in the sum with a one.
Amplification matrix
Characteristic polynomial
Automatic denotation
Several statements and procedures are designed for automatic denotation of some
parts of algebraic expressions by identifiers. This denotation is namely useful when
we obtain very large expressions, which cannot fit into the available memory. We
can denote subparts of an expression from the previous step of calculation by iden-
tifiers, replace these subparts by these identifiers and continue the analytic calcu-
lation only with these identifiers. Every time we use this technique we have to
explicitly survive in processed expressions those algebraic quantities which will be
necessary in the following steps of calculation. The process of denotation and re-
placement is performed automatically and the algebraic values which are denoted
by these new identifiers can be written out at any time. We describe how this au-
tomatic denotation can be used. The statement DENOTID defines the beginning
letters of newly created identifiers. Its syntax is
DENOTID <id>;
<id> ::= "identifier"
After this statement the new identifiers created by the operators DENOTEPOL and
DENOTEMAT will begin with the letters of the identifier <id> used in this state-
ment. Without using any DENOTID statement all new identifiers will begin with
one letter A. We suggest to use this statement every time before using operators
DENOTEPOL or DENOTEMAT with some new identifier and to choose identi-
fiers used in this statement in such a way that the newly created identifiers are not
equal to any identifiers used in the expressions you are working with. The operator
DENOTEPOL has one argument, a polynomial in LAM, and denotes the real and
imaginary part of its coefficients by new identifiers. The real part of the j-th LAM
power coefficient is denoted by the identifier <id>R0j and the imaginary part by
<id>I0j, where <id> is the identifier used in the last DENOTID statement. The
denotation is done only for non-numeric coefficients. The value of this operator
is the polynomial in LAM with coefficients constructed from the new identifiers.
The algebraic expressions which are denoted by these identifiers are stored as LISP
data structure standard quotient in the LISP variable DENOTATION!* (assoc. list).
The operator DENOTEMAT has one argument, a matrix, and denotes the real and
imaginary parts of its elements. The real part of the (j,k) matrix element is denoted
by the identifier <id>Rjk and the imaginary part by <id>Ijk. The returned value of
567
the operator is the original matrix with non-numeric elements replaced by <id>Rjk
+ I*<id>Ijk. Other matters are the same as for the DENOTEPOL operator. The
statement PRDENOT has the syntax
PRDENOT;
and writes from the variable DENOTATION!* the definitions of all new identifiers
introduced by the DENOTEPOL and DENOTEMAT operators since the last call of
CLEARDENOT statement (or program start) in the format defined by the present
setting of output control declarations and switches. The definitions are written in
the same order as they have been entered, so that the definitions of the first DE-
NOTEPOL or DENOTEMAT operators are written first. This order guarantees
that this statement can be utilized directly to generate a semantically correct nu-
merical program (the identifiers from the first denotation can appear in the second
one, etc.). The statement CLEARDENOT with the syntax
CLEARDENOT;
clears the variable DENOTATION!*, so that all denotations saved earlier by the
DENOTEPOL and DENOTEMAT operators in this variable are lost. The PRDE-
NOT statement succeeding this statement writes nothing.
16.23.6 HURWP
Conformal mapping
special values of those parameters, the polynomial may have a unit root. During
the evaluation of the TROOT1 operator, the condition concerning the polynomial
parameters is displayed, and if it is fulfilled, the resulting polynomial has a unit
root.
16.23.7 LINBAND
A Module for Generating the Numeric Program for Solving a System of Linear
Algebraic Equations with Band Matrix
The LINBAND module generates the numeric program in the FORTRAN lan-
guage, which solves a system of linear algebraic equations with band matrix us-
ing the routine from the LINPACK, NAG ,IMSL or ESSL program library. As
input data only the system of equations is given to the program. Automatically, the
statements of the FORTRAN language are generated that fill the band matrix of
the system in the corresponding memory mode of chosen library, call the solving
routine, and assign the chosen variables to the solution of the system. The module
can be used for solving linear difference schemes often having the band matrix.
Program generation
not have the usual meaning of the possibility of repetition, they designate REDUCE
lists):
GENLINBANDSOL (<n-lower>,<n-upper>,{<system>});
<n-lower> ::= "natural number"
<n-upper> ::= "natural number"
<system> ::= <part of system> | <part of system>,<system>
<part of system>::= {<variable>,<equation>} | <loop>
<variable> ::= "kernel"
<equation> ::= <left side> = <right side>
<left side> ::= "algebraic expression"
<right side> ::= "algebraic expression"
<loop> ::= {DO,{<parameter>,<from>,<to>,<step>},<c-system>}
<parameter> ::= "identifier"
<from> ::= <i-expression>
<to> ::= <i-expression>
<step> ::= <i-expression>
<i-expression> ::= "algebraic expression" with natural value
(evaluated in FORTRAN)
<c-system> ::= <part of c-system> | <part of c-system>,<c-
system>
<part of c-system> ::= {<variable>,<equation>}
The first and second argument of the GENLINBANDSOL statement specifies the
number of the lower (below the main diagonal) and the upper diagonals of the
band matrix of the system. The system of linear algebraic equations is specified
by means of lists expressed by braces in the REDUCE system. The variables of
the equation system can be identifiers, but most probably they are operators with an
argument or with arguments that are analogous to array in FORTRAN. The left side
of each equation has to be a linear combination of the system variables, the right
side, on the contrary, is not allowed to contain any variables of the system. The
sequence of the band matrix lines is given by the sequence of the equations, and
the sequence of the columns by the sequence of the variables in the list describing
the equation system. The meaning of the loop in the system list is similar to that of
the DO loop of the FORTRAN language. The individual variables and equations
described by the loop are obtained as follows:
1. <parameter> = <from>. 2. The <parameter> value is substituted into the vari-
ables and equations of the <c-system> loop, by which further variables and equat-
ions of the system are obtained. 3. <parameter> is increased by <step>. 4. If
<parameter> is less or equal <to>, then go to step 2, else all variables and equat-
ions described by the loop have already been obtained.
The variables and equations of the system included in the loop usually contain the
loop parameter, which mostly occur in the operator arguments in the REDUCE
570 CHAPTER 16. USER CONTRIBUTED PACKAGES
where UP represents the rounding-off to a higher natural number, and DOWN the
rounding-off to a lower natural number. With regard to the fact that, for example,
the last variable before the loop is not required to equal the last variable from the
loop system, into which the loop parameter equal to F-S is substituted, when the
band matrix is being constructed, from the FORTRAN loop that corresponds to the
loop from the specification of the equation system, at least the first NL variables-
equations have to be moved to precede the FORTRAN loop, and at least the last
NU variables-equations have to be moved to follow this loop in order that the cor-
respondence of the system variables in this loop with the system variables before
and after this loop will be secured. And this move requires the above mentioned
condition to be fulfilled. As, in most cases, NL/N and NU/N are small with respect
to (T-F)/S, this condition does not represent any considerable constrain. The loop
parameters <from>, <to>, and <step> can be natural numbers or expressions that
must have natural values in the run of the FORTRAN program.
The user can choose the routines of which numerical library will be used in the
generated FORTRAN code. The supported numerical libraries are: LINPACK,
NAG, IMSL and ESSL (IBM Engineering and Scientific Subroutine Library) .
The routines DGBFA, DGBSL (band solver) and DGTSL (tridiagonal solver) are
used from the LINPACK library, the routines F01LBF, F04LDF (band solver) and
F01LEF, F04LEF (tridiagonal solver) are used from the NAG library, the routine
LEQT1B is used from the IMSL library and the routines DGBF, DGBS (band
solver) and DGTF, DGTS (tridiagonal solver) are used from the ESSL library. By
default the LINPACK library routines are used. The using of other libraries is con-
trolled by the switches NAG,IMSL and ESSL. All these switches are by default
OFF. If the switch IMSL is ON then the IMSL library routine is used. If the switch
IMSL is OFF and the switch NAG is ON then NAG library routines are used. If
the switches IMSL and NAG are OFF and the switch ESSL is ON then the ESSL
library is used. During generating the code using LINPACK, NAG or ESSL li-
braries the special routines are use for systems with tridiagonal matrices, because
tridiagonal solvers are faster than the band matrix solvers.
571
2. The assigning the values to the integer variables describing the real dimen-
sions of used arrays (again as described in generated FORTRAN comments)
3. The filling of the variables that can occur in the loop parameters.
4. The filling or declaration of all variables and arrays occurring in the system
equations, except for the variables of the system of linear equations.
The mentioned envelope for the generated block can be created manually, or di-
rectly using the GENTRAN program package for generating numeric programs.
The LINBAND module itself uses the GENTRAN package, and the GENLIN-
BANDSOL statement can be applied directly in the input files of the GENTRAN
package (template processing). The GENTRAN package has to be loaded prior to
loading of the LINBAND module. The generated block of FORTRAN code has to
be linked with the routines from chosen numerical library.
References ———-
[1] R. Liska: Numerical Code Generation for Finite Difference Schemes Solving.
In IMACS World Congress on Computation and Applied Mathematics. Dublin,
July 22-26, 1991, Dublin,(In press).
572 CHAPTER 16. USER CONTRIBUTED PACKAGES
This package can expand a specific class of functions into their corresponding
Laurent-Puiseux series.
Authors: Wolfram Koepf and Winfried Neun.
16.24.1 Introduction
This package can expand functions of certain type into their corresponding
Laurent-Puiseux series as a sum of terms of the form
∞
X
ak (x − x0 )mk/n+s
k=0
The FPS package is an implementation of the method presented in [2]. The imple-
mentations of this package for M APLE (by D. Gruntz) and M ATHEMATICA (by W.
Koepf) served as guidelines for this one.
Numerous examples can be found in [3]–[4], most of which are contained in the test
file fps.tst. Many more examples can be found in the extensive bibliography
of Hansen [1].
FPS(f,x,x0) tries to find a formal power series expansion for f with respect
to the variable x at the point of development x0. It also works for formal Lau-
rent (negative exponents) and Puiseux series (fractional exponents). If the third
argument is omitted, then x0:=0 is assumed.
Examples: FPS(asin(x)^2,x) results in
573
2*k 2*k 2 2
x * 2 * factorial(k) *x
infsum(----------------------------,k,0,infinity)
factorial(2*k + 1)*(k + 1)
2*k k
( - pi + x) *( - 1) *( - pi + x)
infsum(------------------------------------,k,0,infinity)
factorial(2*k + 1)
2*k
- x *sqrt(2)*factorial(2*k)
infsum(--------------------------------,k,0,infinity)
k 2
8 *factorial(k) *(2*k - 1)
Note: The result contains one or more infsum terms such that it does not interfere
with the REDUCE operatorP sum. In graphical oriented REDUCE interfaces this
operator results in the usual notation.
If possible, the output is given using factorials. In some cases, the use of the
Pochhammer symbol pochhammer(a,k):= a(a+1) · · · (a+k−1) is necessary.
The operator FPS uses the operator SimpleDE of the next section.
If an error message of type
occurs, you can set the corresponding limit yourself and try a recalculation. In the
computation of FPS(atan(cot(x)),x,0), REDUCE is not able to find the
value for the limit limit(atan(cot(x)),x,0) since the atan function is
multi-valued. One can choose the branch of atan such that this limit equals π/2
so that we may set
let limit(atan(cot(~x)),x,0)=>pi/2;
2
df(y,x,3)*(x - 1) + 3*df(y,x,2)*x + df(y,x)
SimpleDE(exp(x^(1/3)),x) gives
2
27*df(y,x,3)*x + 54*df(y,x,2)*x + 6*df(y,x) - y
2
df(y,x)*(x - 2) - x*y
The depth for the search of a differential equation for f is controlled by the vari-
able fps_search_depth; higher values for fps_search_depth will in-
crease the chance to find the solution, but increases the complexity as well. The
default value for fps_search_depth is 5. For FPS(sin(x^(1/3)),x), or
SimpleDE(sin(x^(1/3)),x) e. g., a setting fps_search_depth:=6 is
necessary.
The output of the FPS package can be influenced by the switch tracefps. Set-
ting on tracefps causes various prints of intermediate results.
Bibliography
[3] Wolfram Koepf, Examples for the Algorithmic Calculation of Formal Puiseux,
Laurent and Power series, SIGSAM Bulletin 27, 1993, 20-32.
[4] Wolfram Koepf, Algorithmic development of power series. In: Artificial in-
telligence and symbolic mathematical computing, ed. by J. Calmet and J. A.
Campbell, International Conference AISMC-1, Karlsruhe, Germany, August
1992, Proceedings, Lecture Notes in Computer Science 737, Springer-Verlag,
Berlin–Heidelberg, 1993, 195–213.
[5] Wolfram Koepf, Algorithmic work with orthogonal polynomials and special
functions. Konrad-Zuse-Zentrum Berlin (ZIB), Preprint SC 94-5, 1994.
576 CHAPTER 16. USER CONTRIBUTED PACKAGES
This package reuses the code of the RCREF package to create a graph displaying
the interdependency of procedures in a Reduce source code file.
Authors: A. Dolzmann, T. Sturm.
load_package gcref;
on gcref;
in "<filename>.red";
off gcref;
At off gcref; the graph is printed to the screen in TGF format. To redirect this
output to a file, use the following:
load_package gcref;
on gcref;
in "<filename>.red";
out "<filename>.tgf";
off gcref;
shut "<filename>.tgf";
./gcref filename.red
"gcref" is configured to use CSL Reduce. To use PSL Reduce instead, set $RE-
DUCE in the environment. To use PSL by default, define
REDUCE=redpsl
in line 3 of "gcref".
The obtained TGF file can be viewed with a graph editor. I recommend using the
free software yED, which is written in Java and available for many platforms.
577
http://www.yworks.com/en/products_yed_about.html
Note that TGF is not suitable for storing rendering information. After opening the
TGF file with yED, the graph has to be rendered explicitly as follows:
* From menu "Layout" choose "Hierarchical Layout".
To resize the nodes to the procedure names
* from menu "Tools" choose "Fit Node to Label".
Feel free to experiment with yED and use other layout and layout options, which
might be suitable for your particular software.
For saving your particular layout at the end, use the GRAPHML format instead of
TGF.
578 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.27.1 Introduction
The G NU P LOT system provides easy to use graphics output for curves or surfaces
which are defined by formulas and/or data sets. G NU P LOT supports a variety of
output devices such as VGA screen, postscript, picTEX, MS Windows.
The REDUCE G NU P LOT package lets one use the G NU P LOT graphical output
directly from inside REDUCE, either for the interactive display of curves/surfaces
or for the production of pictures on paper.
Under REDUCE G NU P LOT is used as graphical output server, invoked by the com-
mand plot(...). This command can have a variable number of parameters:
Please note that a blank has to be inserted between a number and a dot, otherwise
the REDUCE translator will be misled.
If a function is given as an equation the left-hand side is mainly used as a label for
the axis of the dependent variable.
In two dimensions, plot can be called with more than one explicit function; all
curves are drawn in one picture. However, all these must use the same independent
variable name. One of the functions can be a point set or a point set list. Normally
all functions and point sets are plotted by lines. A point set is drawn by points only
if functions and the point set are drawn in one picture.
The same applies to three dimensions with explicit functions. However, an implic-
itly given curve must be the sole object for one picture.
The functional expressions are evaluated in rounded mode. This is done auto-
matically, it is not necessary to turn on rounded mode explicitly.
581
Examples:
plot(cos x);
plot(s=sin phi, phi=(-3 .. 3));
plot(sin phi, cos phi, phi=(-3 .. 3));
plot (cos sqrt(x^2 + y^2), x=(-3 .. 3), y=(-3 .. 3), hidden3d);
plot {{0,0},{0,1},{1,1},{0,0},{1,0},{0,1},{0.5,1.5},{1,1},{1,0}};
% parametric: screw
on rounded;
w := for j := 1:200 collect {1/j*sin j, 1/j*cos j, j/200}$
plot w;
% parametric: globe
dd := pi/15$
w := for u := dd step dd until pi-dd collect
for v := 0 step dd until 2pi collect
{sin(u)*cos(v), sin(u)*sin(v), cos(u)}$
plot w;
Piecewise-defined functions
A composed graph can be defined by a rule-based operator. In that case each rule
must contain a clause which restricts the rule application to numeric arguments,
e.g.
operator my_step1;
let {my_step1(~x) => -1 when numberp x and x<-pi/2,
my_step1(~x) => 1 when numberp x and x>pi/2,
my_step1(~x) => sin x
when numberp x and -pi/2<=x and x<=pi/2};
plot(my_step2(x));
procedure my_step3(x);
if x<-1 then -1 else if x>1 then 1 else x;
operator my_step2;
let my_step2(~x) => my_step3(x) when numberp x;
582 CHAPTER 16. USER CONTRIBUTED PACKAGES
plot(my_step2(x));
Plot options
Additional options
The following additional G NU P LOT options are supported in the plot command:
The following example works for a PostScript printer. If your printer uses a differ-
ent communication, please find the correct setting for the terminal variable in
the G NU P LOT documentation.
For a PostScript printer, add the options terminal=postscript and output="filename"
to your plot command, e.g.
The basic mesh for finding an implicitly-given curve, the x, y plane is subdivided
into an initial set of triangles. Those triangles which have an explicit zero point or
which have two points with different signs are refined by subdivision. A further re-
finement is performed for triangles which do not have exactly two zero neighbours
because such places may represent crossings, bifurcations, turning points or other
difficulties. The initial subdivision and the refinements are controlled by the option
points which is initially set to 20: the initial grid is refined unconditionally until
approximately points * points equally-distributed points in the x, y plane
have been generated.
The final mesh can be visualized in the picture by setting
on show_grid;
584 CHAPTER 16. USER CONTRIBUTED PACKAGES
By default the functions are computed at predefined mesh points: the ranges are
divided by the number associated with the option points in both directions.
For two dimensions the given mesh is adaptively smoothed when the curves are
too coarse, especially if singularities are present. On the other hand refinement can
be rather time-consuming if used with complicated expressions. You can control it
with the option refine. At singularities the graph is interrupted.
In three dimensions no refinement is possible as G NU P LOT supports surfaces only
with a fixed regular grid. In the case of a singularity the near neighborhood is
tested; if a point there allows a function evaluation, its clipped value is used instead,
otherwise a zero is inserted.
When plotting surfaces in three dimensions you have the option of hidden line
removal. Because of an error in Gnuplot 3.2 the axes cannot be labeled correctly
when hidden3d is used ; therefore they aren’t labelled at all. Hidden line removal
is not available with point lists.
The command plotreset; deletes the current G NU P LOT output window. The
next call to plot will then open a new one.
If G NU P LOT is invoked directly by an output pipe (UNIX and Windows), an even-
tual error in the G NU P LOT data transmission might cause G NU P LOT to quit. As
REDUCE is unable to detect the broken pipe, you have to reset the plot system by
calling the command plotreset; explicitly. Afterwards new graphics output
can be produced.
Under Windows 3.1 and Windows NT, G NU P LOT has a text and a graph window.
If you don’t want to see the text window, iconify it and activate the option update
wgnuplot.ini from the graph window system menu - then the present screen
layout (including the graph window size) will be saved and the text windows will
come up iconified in future. You can also select some more features there and so
tailor the graphic output. Before you terminate REDUCE you should terminate
the graphic window by calling plotreset;. If you terminate REDUCE without
deleting the G NU P LOT windows, use the command button from the G NU P LOT text
window - it offers an exit function.
GNUPLOT If you want to use the internal G NU P LOT command sequence more
than once (e.g. for producing a picture for a publication), you may set
585
on trplot, plotkeep;
G NU P LOT has a lot of facilities which are not accessed by the operators and pa-
rameters described above. Therefore genuine G NU P LOT commands can be sent by
REDUCE. Please consult the G NU P LOT manual for the available commands and
parameters. The general syntax for a G NU P LOT call inside REDUCE is
gnuplot(<cmd>,<p_1>,<p_2> ...)
where cmd is a command name and p1 , p2 , . . . are the parameters, inside REDUCE
separated by commas. The parameters are evaluated by REDUCE and then trans-
mitted to G NU P LOT in G NU P LOT syntax. Usually a drawing is built by a sequence
of commands which are buffered by REDUCE or the operating system. For termi-
nating and activating them use the REDUCE command plotshow. Example:
gnuplot(set,polar);
gnuplot(set,noparametric);
gnuplot(plot, x*sin x);
plotshow;
16.27.9 Examples
The following are taken from a collection of sample plots (gnuplot.tst) and
a set of tests for plotting special functions. The pictures are made using the qt
G NU P LOT device and using the menu of the graphics window to export to PDF or
PNG.
586 CHAPTER 16. USER CONTRIBUTED PACKAGES
0.8
0.6
0.4
0.2
0
y
-0.2
-0.4
-0.6
-0.8
-1
-1 -0.5 0 0.5 1
x
1.5
0.5
0
x
-0.5
-1
-1.5
-2
-2.5
-6 -4 -2 0 2 4 6
y
587
1
0.8
0.6
0.4
0.2
z 0
-0.2
-0.4
-0.6
-0.8
-1
3
2
1
-3 0
-2
-1 -1 x
0
1 -2
y 2
3-3
plot(sinh(x*y)/sinh(2*x*y), hidden3d);
REDUCE Plot
0.5
0.45
0.4
0.35
0.3
z 0.25
0.2
0.15
0.1
0.05
0
10
5
-10 0
-5 x
0 -5
y 5
-10
10
588 CHAPTER 16. USER CONTRIBUTED PACKAGES
on rounded;
w:= {for j:=1 step 0.1 until 20 collect {1/j*sin j, 1/j*cos j, j},
for j:=1 step 0.1 until 20 collect
{(0.1+1/j)*sin j, (0.1+1/j)*cos j, j} }$
plot w;
REDUCE Plot
20
18
16
14
12
z 10
8
6
4
2
0
0.6
0.4
0.2
-0.4 0
-0.2
0 -0.2 y
0.2
0.4 -0.4
0.6
x 0.8
1-0.6
An example taken from: Cox, Little, O’Shea, Ideals, Varieties and Algorithms:
300
200
100
z 0
-100
-200
-300
2500
2000
1500
1000
-2500-2000 500
0
-1500-1000 -500 y
-500 0 -1000
500 1000 -1500
x 15002000 -2000
-2500
2500
589
The following examples use the specfn package to draw a collection of Cheby-
shev T polynomials and Bessel Y functions. The special function package has to
be loaded explicitely to make the operator ChebyshevT and BesselY available.
load_package specfn;
plot(chebyshevt(1,x), chebyshevt(2,x), chebyshevt(3,x),
chebyshevt(4,x), chebyshevt(5,x),
x=(-1 .. 1), title="Chebyshev t Polynomials");
Chebyshev t Polynomials
1
0.5
0
y
-0.5
-1
-1 -0.5 0 0.5 1
x
0.4
0.2
-0.2
y
-0.4
-0.6
-0.8
-1
0 1 2 3 4 5 6 7 8 9 10
x
590 CHAPTER 16. USER CONTRIBUTED PACKAGES
GROEBNER is a package for the computation of Gröbner Bases using the Buch-
berger algorithm and related methods for polynomial ideals and modules. It can be
used over a variety of different coefficient domains, and for different variable and
term orderings.
Gröbner Bases can be used for various purposes in commutative algebra, e.g. for
elimination of variables, converting surd expressions to implicit polynomial form,
computation of dimensions, solution of polynomial equation systems etc. The
package is also used internally by the SOLVE operator.
Authors: Herbert Melenk, H.M. Möller and Winfried Neun.
Gröbner bases are a valuable tool for solving problems in connection with multi-
variate polynomials, such as solving systems of algebraic equations and analyzing
polynomial ideals. For a definition of Gröbner bases, a survey of possible applica-
tions and further references, see [6]. Examples are given in [5], in [7] and also in
the test file for this package.
The groebner package calculates Gröbner bases using the Buchberger algorithm.
It can be used over a variety of different coefficient domains, and for different
variable and term orderings.
The current version of the package uses parts of a previous version, written by R.
Gebauer, A.C. Hearn, H. Kredel and H. M. Möller. The algorithms implemented
in the current version are documented in [10], [11], [15] and [12]. The operator
saturation has been implemented in July 2000 (Herbert Melenk).
16.28.1 Background
The various functions of the groebner package manipulate equations and/or poly-
nomials; equations are internally transformed into polynomials by forming the dif-
ference of left-hand side and right-hand side, if equations are given.
All manipulations take place in a ring of polynomials in some variables x1, . . . , xn
over a coefficient domain d:
d[x1, . . . , xn],
where d is a field or at least a ring without zero divisors. The set of variables
x1, . . . , xn can be given explicitly by the user or it is extracted automatically from
the input expressions.
All REDUCE kernels can play the role of “variables” in this context; examples are
591
The domain d is the current REDUCE domain with those kernels adjoined that are
not members of the list of variables. So the elements of d may be complicated
polynomials themselves over kernels not in the list of variables; if, however, the
variables are extracted automatically from the input expressions, d is identical with
the current REDUCE domain. It is useful to regard kernels not being members of
the list of variables as “parameters”, e.g.
Term Ordering
In the theory of Gröbner bases, the terms of polynomials are considered as or-
dered. Several order modes are available in the current package, including the
basic modes:
All orderings are based on an ordering among the variables. For each pair of vari-
ables (a, b) an order relation must be defined, e.g. “a b”. The greater sign
does not represent a numerical relation among the variables; it can be interpreted
only in terms of formula representation: “a” will be placed in front of “b” or “a” is
more complicated than “b”.
592 CHAPTER 16. USER CONTRIBUTED PACKAGES
x1 x2 x3
lex:
x ∗ y ∗ ∗3 y ∗ ∗48 (heavier variable)
x ∗ ∗4 ∗ y ∗ ∗2 x ∗ ∗3 ∗ y ∗ ∗10 (higher degree in 1st variable)
gradlex:
y ∗ ∗3 ∗ z ∗ ∗4 x ∗ ∗3 ∗ y ∗ ∗3 (higher total degree)
x ∗ z y ∗ ∗2 (equal total degree)
revgradlex:
y ∗ ∗3 ∗ z ∗ ∗4 x ∗ ∗3 ∗ y ∗ ∗3 (higher total degree)
x ∗ z y ∗ ∗2 (equal total degree,
so reverse order of lex)
The formal description of the term order modes is similar to [14]; this description
regards only the exponents of a term, which are written as vectors of integers with
0 for exponents of a variable which does not occur:
lex:
(e) > lex > (0) =⇒ ek > 0 and ej = 0 for j = 1, . . . , k − 1
gradlex:
(e) > gl > (0) =⇒ deg(e) > 0 or (e) > lex > (0)
revgradlex:
(e) > rgl > (0) =⇒ deg(e) > 0 or (e) < lex < (0)
593
Note that the lex ordering is identical to the standard REDUCE kernel ordering,
when korder is set explicitly to the sequence of variables.
lex is the default term order mode in the groebner package.
It is beyond the scope of this manual to discuss the functionality of the term order
modes. See [7].
The list of variables is declared as an optional parameter of the torder statement
(see below). If this declaration is missing or if the empty list has been used, the
variables are extracted from the expressions automatically and the REDUCE sys-
tem order defines their sequence; this can be influenced by setting an explicit order
via the korder statement.
The result of a Gröbner calculation is algebraically correct only with respect to the
term order mode and the variable sequence which was in effect during the calcu-
lation. This is important if several calls to the groebner package are done with
the result of the first being the input of the second call. Therefore we recommend
that you declare the variable list and the order mode explicitly. Once declared it re-
mains valid until you enter a new torder statement. The operator gvars helps you
extract the variables from a given set of polynomials, if an automatic reordering
has been selected.
The following command loads the package into REDUCE (this syntax may vary
according to the implementation):
load_package groebner;
The package contains various operators, and switches for control over the reduction
process. These are discussed in the following.
where vl is a variable list (or the empty list if no variables are declared ex-
plicitly), m is the name of a term ordering mode lex, gradlex, revgradlex
(or another implemented mode) and [p1 , p2 , . . .] are additional parameters
for the term ordering mode (not needed for the basic modes).
torder sets variable set and the term ordering mode. The default mode is lex.
The previous description is returned as a list with corresponding elements.
Such a list can alternatively be passed as sole argument to torder.
If the variable list is empty or if the torder declaration is omitted, the auto-
matic variable extraction is activated.
gvarslast.
Example 27
torder({},lex)$
groebner{3*x**2*y + 2*x*y + y + 9*x**2 + 5*x - 3,
2*x**3*y - x*y - y + 6*x**3 - 2*x**2 - 3*x + 3,
595
2
{8*x - 2*y + 5*y + 3,
3 2
2*y - 3*y - 16*y + 21}
This example used the default system variable ordering, which was {x, y}. With
the other variable ordering, a different basis results:
torder({y,x},lex)$
groebner{3*x**2*y + 2*x*y + y + 9*x**2 + 5*x - 3,
2*x**3*y - x*y - y + 6*x**3 - 2*x**2 - 3*x + 3,
x**3*y + x**2*y + 3*x**3 + 2*x**2 };
2
{2*y + 2*x - 3*x - 6,
3 2
2*x - 5*x - 5*x}
torder({x,y},revgradlex)$
groebner{3*x**2*y + 2*x*y + y + 9*x**2 + 5*x - 3,
2*x**3*y - x*y - y + 6*x**3 - 2*x**2 - 3*x + 3,
x**3*y + x**2*y + 3*x**3 + 2*x**2 };
2
{2*y - 5*y - 8*x - 3,
y*x - y + x + 3,
2
2*x + 2*y - 3*x - 6}
groebopt – If set on, the sequence of variables is optimized with respect to execu-
tion speed; the algorithm involved is described in [5]; note that the final list
of variables is available in gvarslast.
An explicitly declared dependency supersedes the variable optimization. For
596 CHAPTER 16. USER CONTRIBUTED PACKAGES
example
depend a, x, y;
gltbasis – If set on, the leading terms of the result basis are extracted. They are
collected in a basis of monomials, which is available as value of the global
variable with the name gltb.
glterms – If {exp1 , . . . , expm } contain parameters (symbols which are not mem-
ber of the variable list), the share variable glterms contains a list of expres-
sion which during the calculation were assumed to be nonzero. A Gröbner
basis is valid only under the assumption that all these expressions do not
vanish.
The following switches control the print output of groebner; by default all these
switches are set of f and nothing is printed.
gzerodim!? bas
where bas is a Gröbner basis in the current setting. The result is nil, if bas is
the basis of an ideal of polynomials with more than finitely many common
zeros. If the ideal is zero dimensional, i. e. the polynomials of the ideal have
only finitely many zeros in common, the result is an integer k which is the
number of these common zeros (counted with multiplicities).
597
The following operators can be used to compute the dimension and the independent
variable sets of an ideal which has the Gröbner basis bas with arbitrary term order:
gdimension bas
The switch groebopt plays no role in the algorithms gdimension and gindependent_sets.
It is set of f during the processing even if it is set on before. Its state is saved during
the processing.
The “Kredel-Weispfenning" algorithm is used (see [15], extended to general order-
ing in [4].
torder({{w,p,z,t,s,b},gradlex)
200*s - 500*b - 9,
2
10000*b + 6600*b + 2673}
glexconvert(g,{w,p,z,t,s,b},maxdeg=5,newvars={w});
2
100000000*w + 2780000*w + 416421
glexconvert(g,{w,p,z,t,s,b},maxdeg=5,newvars={p});
2
6000*p - 2360*p + 3051
graduated basis of the given variable sequence to a lex one of the same sequence.
The job is done by computing a sequence of Gröbner bases of correspondig mono-
mial ideals, lifting the original system each time. The algorithm has been described
(more generally) by [2],[3],[1] and [8]. groebner_walk should be only called, if
the direct calculation of a lex Gröbner base does not work. The computation of
groebner_walk includes some overhead (e. g. the computation divides poly-
nomials). Normally torder must be called before to define the variables and the
variable sorting. The reordering of variables makes no sense with groebner_walk;
so do not call groebner_walk with groebopt on!
groebner_walk g
where g is a polynomial ideal basis computed under gradlex or under
weighted with a one–element, non zero weight vector with only one ele-
ment, repeated for each variable. The result is a corresponding lex basis (if
that is computable), independet of the degree of the ideal (even for non zero
degree ideals). The variabe gvarslast is not set.
the trivial basis {1}, the result has only one basis; nevertheless it is a list of lists
of polynomials. If no solution is found, the result will be {{1}}. Multiplicities
(one factor with a higher power, the same partial basis twice) are deleted as early
as possible in order to speed up the calculation. The factorizing is controlled by
some switches.
As a side effect, the sequence of variables is stored as a REDUCE list in the shared
variable
gvarslast .
If gltbasis is on, a corresponding list of leading term bases is also produced and is
available in the variable gltb.
The third parameter of groebnerf allows one to declare some polynomials
nonzero. If any of these is found in a branch of the calculation the branch is can-
celled. This can be used to save a substantial amount of computing time. The
second parameter must be included as an empty list if the third parameter is to be
used.
torder({x,y},lex)$
groebnerf { 3*x**2*y + 2*x*y + y + 9*x**2 + 5*x = 3,
2*x**3*y - x*y - y + 6*x**3 - 2*x**2 - 3*x = -3,
x**3*y + x**2*y + 3*x**3 + 2*x**2 \};
{{y - 3,x},
2
{2*y + 2*x - 1,2*x - 5*x - 5}}
It is obvious here that the solutions of the equations can be read off immediately.
All switches from groebner are valid for groebnerf as well:
groebopt
gltbasis
groebf ullreduction
groebstat
trgroeb
trgroebs
rgroeb1
groebmonf ac
groebmonf ac := 0
groebresmax
controls the number of partial results. Its default value is 300. If groebresmax
partial results are calculated, the calculation is terminated. groebresmax counts
all branches, including those which are terminated (have been computed already),
give no contribution to the result (partial basis 1), or which are unified in the result
with other (partial) bases. So the resulting number may be much smaller. When
the limit of groeresmax is reached, a warning
GROEBRESMAX limit reached
is issued; this warning in any case has to be taken as a serious one. For "nor-
mal" calculations the groebresmax limit is not reached. groebresmax is a shared
variable (with an integer value); it can be set in the algebraic mode to a different
(positive integer) value.
values or positive definite values for the variables. A significant amount of com-
puting time can be saved if nonrelevant computation branches can be terminated
early.
Positivity: If a polynomial has no (strictly) positive zero, then every system con-
taining it has no nonnegative or strictly positive solution. Therefore, the Buch-
berger algorithm tests the coefficients of the polynomials for equal sign if re-
quested. For example, in 13 ∗ x + 15 ∗ y ∗ z can be zero with real nonnegative
values for x, y and z only if x = 0 and y = 0 or z = 0; this is a sort of “factoriza-
tion by restriction”. A polynomial 13 ∗ x + 15 ∗ y ∗ z + 20 never can vanish with
nonnegative real variable values.
Zero point: If any polynomial in an ideal has an absolute term, the ideal cannot
have the origin point as a common solution.
By setting the shared variable
groebrestriction
groebnerf is informed of the type of restriction the user wants to impose on the
solutions:
groebrestiction:=nonnegative;
only nonnegative real solutions are of interest
groebrestriction:=positive;
only nonnegative and nonzero solutions are of interest
groebrestriction:=zeropoint;
only solution sets which contain the point {0, 0, . . . , 0} are or interest.
If the coefficients are taken from a ring without zero divisors we cannot divide by
each possible number like in the field case. But using that in the field case, c ∗ p is
reduced to c ∗ q, if p is reduced to q, for arbitrary numbers c, the reduction for the
ring case uses the least c which makes the (field) reduction for c ∗ p integer. The
result of this reduction is returned as (ring) reduction of p eventually after removing
the content, i.e. the greatest common divisor of the coefficients. The result of this
type of reduction is also called a pseudo reduction of p.
where exp is an expression, and {exp1, exp2, . . . , expm} is a list of any number
of expressions or equations.
greduce first converts the list of expressions {exp1, . . . , expn} to a Gröbner basis,
and then reduces the given expression modulo that basis. An error results if the list
of expressions is inconsistent. The returned value is an expression representing the
reduced polynomial. As a side effect, greduce sets the variable gvarslast in the
same manner as groebner does.
where expm is an expression, and {exp1, exp2, . . . , expm} is a list of any number
of expressions or equations.
preduce reduces the given expression modulo the set {exp1, . . . , expm}. If this
set is a Gröbner basis, the obtained reduced expression is uniquely determined.
If not, then it depends on the subsequence of the single reduction steps (see 27).
preduce does not check whether {exp1, exp2, . . . , expm} is a Gröbner basis in
the actual order. Therefore, if the expressions are a Gröbner basis calculated earlier
604 CHAPTER 16. USER CONTRIBUTED PACKAGES
torder({x,y},lex);
gb:=groebner{3*x**2*y + 2*x*y + y + 9*x**2 + 5*x - 3,
2*x**3*y - x*y - y + 6*x**3 - 2*x**2 - 3*x + 3,
x**3*y + x**2*y + 3*x**3 + 2*x**2}$
preduce (5*y**2 + 2*x**2*y + 5/2*x*y + 3/2*y
+ 8*x**2 + 3/2*x - 9/2, gb);
2
y
The expression exp is reduced by greduce with the orders in the shared variable
gorders, which must be a list of term orders (if set). By default it is set to
The shortest polynomial is the result. The order with the shortest polynomial is
set to the shared variable gorder. A Gröbner basis of the system {exp1, exp2, . . . ,
expm} is computed for each element of orders. With the default setting gorder in
most cases will be set to revgradlex. If the variable set is given, these variables are
taken; otherwise all variables of the system {exp1, exp2, . . . , expm} are extracted.
The Gröbner basis computations can take some time; if interrupted, the interme-
diate result of the reduction is set to the shared variable greduce_result, if one is
done already. However, this is not nesessarily the minimal form.
If the variable gorders should be set to orders with a parameter, the term oder has
to be replaced by a list; the first element is the term oder selected, followed by its
parameter(s), e.g.
Reduction Tree In some case not only are the results produced by greduce and
preduce of interest, but the reduction process is of some value too. If the switch
groebprot
is set on, groebner, greduce and preduce produce as a side effect a trace of their
work as a REDUCE list of equations in the shared variable
groebprotf ile.
Its value is a list of equations with a variable “candidate” playing the role of the
object to be reduced. The polynomials are cited as “poly1”, “poly2”, . . . . If read as
assignments, these equations form a program which leads from the reduction input
to its result. Note that, due to the pseudo reduction with a ring as the coefficient
domain, the input coefficients may be changed by global factors.
606 CHAPTER 16. USER CONTRIBUTED PACKAGES
Example 29
on groebprot $
preduce (5 ∗ y ∗ ∗2 + 2 ∗ x ∗ ∗2 ∗ y + 5/2 ∗ x ∗ y + 3/2 ∗ y + 8 ∗ x ∗ ∗2
+3/2 ∗ x − 9/2, gb);
2
y
groebprotfile;
2 2 2
{candidate=4*x *y + 16*x + 5*x*y + 3*x + 10*y + 3*y - 9,
2
poly1=8*x - 2*y + 5*y + 3,
3 2
poly2=2*y - 3*y - 16*y + 21,
candidate=2*candidate,
candidate= - x*y*poly1 + candidate,
candidate= - 4*x*poly1 + candidate,
candidate=4*candidate,
3
candidate= - y *poly1 + candidate,
candidate=2*candidate,
2
candidate= - 3*y *poly1 + candidate,
candidate=13*y*poly1 + candidate,
candidate=candidate + 6*poly1,
2
candidate= - 2*y *poly2 + candidate,
candidate= - y*poly2 + candidate,
candidate=candidate + 6*poly2}
607
This means
5 3 3 9
16(5y 2 + 2x2 y + xy + y + 8x2 + x − ) =
2 2 2 2
(−8xy − 32x − 2y 3 − 3y 2 + 13y + 6)poly1
+(−2y 2 − 2y + 6)poly2 + y 2 .
and these relations are needed explicitly sometimes. In B UCHBERGER [6], such
cases are described in the context of linear polynomial equations. The standard
technique for computing the above formulae is to perform Gröbner reductions,
keeping track of the computation in terms of the input data. In the current package
such calculations are performed with (an internally hidden) cofactor technique:
the user has to assign unique names to the input expressions and the arithmetic
combinations are done with the expressions and with their names simultaneously.
So the result is accompanied by an expression which relates it algebraically to the
input values.
There are two complementary operators with this feature: groebnert and preducet;
functionally they correspond to groebner and preduce. However, the sets of ex-
pressions here must be equations with unique single identifiers on their left side
and the lhs are interpreted as names of the expressions. Their results are sets of
equations (groebnert) or equations (preducet), where a lhs is the computed value,
while the rhs is its equivalent in terms of the input names.
Example 30
We calculate the Gröbner basis for an ellipse (named “p1” ) and a line (named
“p2” ); p2 is member of the basis immediately and so the corresponding first result
element is of a very simple form; the second member is a combination of p1 and
p2 as shown on the rhs of this equation:
gb1:=groebnert {p1=2*x**2+4*y**2-100,p2=2*x-y+1};
Example 31
608 CHAPTER 16. USER CONTRIBUTED PACKAGES
We want to reduce the polynomial x**2 wrt the above Gröbner basis and need
knowledge about the reduction formula. We therefore extract the basis polynomials
from gb1, assign unique names to them (here g1, g2) and call preducet. The
polynomial to be reduced here is introduced with the name Q, which then appears
on the rhs of the result. If the name for the polynomial is omitted, its formal value
is used on the right side too.
Example 32
If we reduce a polynomial which is member of the ideal, we consequently get a
result with lhs zero:
preducet(q=2*x**2+4*y**2-100,gb2);
This means
1 1 1
q = (x + y − )g1 + g2.
2 2 2
With these operators the matrices Cij and Dji are available implicitly, Dji as side
effect of groebnertT, cij by calls of preducet of fi wrt {gj }. The latter by defini-
tion will have the lhs zero and a rhs with linear fi .
If {1} is the Gröbner basis, the groebnert calculation gives a “proof”, showing,
how 1 can be computed as combination of the input polynomials.
Given a polynomial ring, e.g. r = z[x1 · · · xk ] and an integer n > 1: the vectors
with n elements of r form a module under vector addition (= componentwise
609
gmodule := {v1,v2,v3};
After this declaration all monomials built from these variables are considered as an
algebraically independent basis of a vector space. However, you had best use them
only linearly. Once gmodule has been set, the auxiliary variables automatically
will be added to the end of each variable list (if they are not yet member there).
Example:
torder({x,y,v1,v2,v3},lex)$
gmodule := {v1,v2,v3}$
g:=groebner{x^2*v1 + y*v2,x*y*v1 - v3,2y*v1 + y*v3};
2
g := {x *v1 + y*v2,
2
x*v3 + y *v2,
3
y *v2 - 2*v3,
2*y*v1 + y*v3}
preduce((x+y)^3*v1,g);
1 3 2
- x*y*v2 - ---*y *v3 - 3*y *v2 + 3*y*v3
2
In many cases a total degree oriented term order will be adequate for computations
in modules, e.g. for all cases where the submodule membership is investigated.
However, arranging the auxiliary variables in an elimination oriented term order
can give interesting results. E.g.
610 CHAPTER 16. USER CONTRIBUTED PACKAGES
p1:=(x-1)*(x^2-x+3)$ p2:=(x-1)*(x^2+x-5)$
gmodule := {v1,v2,v3};
torder({v1,x,v2,v3},lex)$
gb:=groebner {p1*v1+v2,p2*v1+v3};
2 2
x *v2 - x *v3 + x*v2 + x*v3 - 5*v2 - 3*v3}
g:=coeffn(first gb,v1,1);
g := 30*(x - 1)
c1:=coeffn(first gb,v2,1);
c1 := x + 5
c2:=coeffn(first gb,v3,1);
c2 := - x - 3
c1*p1 + c2*p2;
30*(x - 1)
Here two polynomials are entered as vectors [p1 , 1, 0] and [p2 , 0, 1]. Using a term
ordering such that the first dimension ranges highest and the other components low-
est, a classical cofactor computation is executed just as in the extended Euclidean
algorithm. Consequently the leading polynomial in the resulting basis shows the
greatest common divisor of p1 and p2 , found as a coefficient of v1 while the coef-
ficients of v2 and v3 are the cofactors c1 and c2 of the polynomials p1 and p2 with
the relation gcd(p1 , p2 ) = c1 p1 + c2 p2 .
Additional Orderings
Besides the basic orderings, there are ordering options that are used for special
purposes.
Gröbner basis. That however may be hard to compute as it does more separation
than necessary. The following orderings group the variables into two (or more)
sets, where inside each set a classical ordering acts, while the sets are handled via
their total degrees, which are compared in elimination style. So the Gröbner basis
will eliminate the members of the first set, if algebraically possible. torder here
gets an additional parameter which describe the grouping
torder (vl,gradlexgradlex, n)
torder (vl,gradlexrevgradlex,n)
torder (vl,lexgradlex, n)
torder (vl,lexrevgradlex, n)
Here the integer n is the number of variables in the first group and the names
combine the local ordering for the first and second group, e.g.
Note that in the second place there is no lex ordering available; that would not make
sense.
establishes a graduated ordering, where the exponents are first multiplied by the
given weights. If there are less weight values than variables, the weight 1 is added
automatically. If the weighted degree calculation is not decidable, a lex compari-
son follows.
establishes a graduated ordering, where the exponents are first multiplied by the
given weights. If there are less weight values than variables, the weight 1 is added
automatically. If the weighted degree calculation is not decidable, the term order
order2 specified in the following argument(s) is used. The ordering graded is
designed primarily for use with the operator dd_groebner.
612 CHAPTER 16. USER CONTRIBUTED PACKAGES
torder (vl,matrix, m) ;
where m is a matrix with integer elements and row length which corresponds to the
variable number. The exponents of each monomial form a vector; two monomials
are compared by multiplying their exponent vectors first with m and comparing
the resulting vector lexicographically. E.g. the unit matrix establishes the classical
lex term order mode, a matrix with a first row of ones followed by the rows of a
unit matrix corresponds to the gradlex ordering.
The matrix m must have at least as many rows as columns; a non–square matrix
contains redundant rows. The matrix must have full rank, and the top non–zero
element of each column must be positive.
The generality of the matrix based term order has its price: the computing time
spent in the term sorting is significantly higher than with the specialized term or-
ders. To overcome this problem, you can compile a matrix term order ; the com-
pilation reduces the computing time overhead significantly. If you set the switch
comp on, any new order matrix is compiled when any operator of the groebner
package accesses it for the first time. Alternatively you can compile a matrix ex-
plicitly
torder_compile(<n>,<m>);
where < n > is a name (an identifier) and < m > is a term order matrix.
torder_compile transforms the matrix into a LISP program, which is compiled
by the LISP compiler when comp is on or when you generate a fast loadable mod-
ule. Later you can activate the new term order by using the name < n > in a
torder statement as term ordering mode.
Based on the elementary Gröbner operations, the groebner package offers ad-
ditional operators, which allow the decomposition of an ideal or of a system of
equations down to the individual solutions.
2 2 2 2 2
{{x=(sqrt( - a*p + a*q + s )*q - p*s)/(p - q ),
2 2 2 2 2
y= - (sqrt( - a*p + a*q + s )*p - q*s)/(p - q )},
2 2 2 2 2
{x= - (sqrt( - a*p + a*q + s )*q + p*s)/(p - q ),
2 2 2 2 2
y=(sqrt( - a*p + a*q + s )*p + q*s)/(p - q )}}
mixed leading term. Hillebrand has written the article and Möller was the tutor of
this job.
The reordering of the groesolve variables is controlled by the REDUCE switch
varopt. If varopt is on (which is the default of varopt), the variable sequence
is optimized (the variables are reordered). If varopt is of f , the given variable
sequence is taken (if no variables are given, the order of the REDUCE system
is taken instead). In general, the reordering of the variables makes the Gröbner
basis computation significantly faster. A variable dependency, declare by one (or
several) depend statements, is regarded (if varopt is on). The switch groebopt has
no meaning for groesolve; it is stored during its processing.
groepostproc({x3**2 + x3 + x2 - 1,
x2*x3 + x1*x3 + x3 + x1*x2 + x1 + 2,
x2**2 + 2*x2 - 1,
x1**2 - 2},{x3,x2,x1});
{{x3= - sqrt(2),
x2=sqrt(2) - 1,
x1=sqrt(2)},
{x3=sqrt(2),
x1= - sqrt(2)},
sqrt(4*sqrt(2) + 9) - 1
{x3=-------------------------,
615
x1=sqrt(2)},
- (sqrt(4*sqrt(2) + 9) + 1)
{x3=------------------------------,
2
x1=sqrt(2)},
sqrt( - 4*sqrt(2) + 9) - 1
{x3=----------------------------,
2
x2=sqrt(2) - 1,
x1= - sqrt(2)},
- (sqrt( - 4*sqrt(2) + 9) + 1)
{x3=---------------------------------,
2
x2=sqrt(2) - 1,
x1= - sqrt(2)}}
In some cases where no Gröbner basis with lexical ordering can be calculated, a
calculation with a total degree ordering is still possible. Then the Hilbert polyno-
mial gives information about the dimension of the solutions space and for finite sets
of solutions univariate polynomials can be calculated. The solutions of the equat-
ion system then is contained in the cross product of all solutions of all univariate
polynomials.
hilbertpolynomial({exp1, . . . , expm}) ;
where {exp1, . . . , expm} is a list of any number of expressions or equations.
hilertpolynomial calculates the Hilbert polynomial of the ideal with basis
{exp1, . . . , expm} with respect to the variables given or extracted provided
the given term ordering is compatible with the degree, such as the gradlex-
or revgradlex-ordering. The term ordering of the basis must be active and
{exp1, . . ., expm} should be a Gröbner basis with respect to this ordering. The
Hilbert polynomial gives information about the cardinality of solutions of the sys-
tem {exp1, . . . , expm}: if the Hilbert polynomial is an integer, the system has
617
only a discrete set of solutions and the polynomial is identical with the number
of solutions counted with their multiplicities. Otherwise the degree of the Hilbert
polynomial is the dimension of the solution space.
If the Hilbert polynomial is not a constant, it is constructed with the variable “x”
regardless of whether x is member of {var1, . . . , varn} or not. The value of this
polynomial at sufficiently large numbers “x” is the difference of the dimension of
the linear vector space of all polynomials of degree ≤ x minus the dimension of
the subspace of all polynomials of degree ≤ x which belong also to the ideal.
x must be an undefined variable or the value of x must be an undefined variable;
otherwise a warning is given and a new (generated) variable is taken instead.
Remark: The number of zeros in an ideal and the Hilbert polynomial depend
only on the leading terms of the Gröbner basis. So if a subsequent Hilbert calcu-
lation is planned, the Gröbner calculation should be performed with on gltbasis
and the value of gltb (or its elements in a groebnerf context) should be given to
hilbertpolynomial. In this manner, a lot of computing time can be saved in the
case of long calculations.
gsortp;
where p is a polynomial or a list of polynomials.
If p is a single polynomial, the result is a reordered version of p in the distributive
representation according to the variables and the current term order mode; if p
is a list, its members are converted into distributive representation and the result
is the list sorted by the term ordering of the leading terms; zero polynomials are
eliminated from the result.
torder({alpha,beta,gamma},lex);
dip := gsort(gamma*(alpha-1)**2*(beta+1)**2);
618 CHAPTER 16. USER CONTRIBUTED PACKAGES
2 2 2
dip := alpha *beta *gamma + 2*alpha *beta*gamma
2 2
+ alpha *gamma - 2*alpha*beta *gamma - 4*alpha*beta*gamma
2
- 2*alpha*gamma + beta *gamma + 2*beta*gamma + gamma
gsplitp;
where p is a polynomial.
gsplit converts the polynomial p into distributive representation and splits it into
leading monomial and reductum. The result is a list with two elements, the leading
monomial and the reductum.
gslit dip;
2 2
{alpha *beta *gamma,
2 2 2
2*alpha *beta*gamma + alpha *gamma - 2*alpha*beta *gamma
2
- 4*alpha*beta*gamma - 2*alpha*gamma + beta *gamma
+ 2*beta*gamma + gamma}
gspoly(p1, p2);
where p1 and p2 are polynomials.
gspoly calculates the s-polynomial from p1 and p2;
619
torder({x,y,z},lex)$
g1 := x**3*y*z - x*z**2;
g2 := x*y**2*z - x*y*z;
g3 := x**2*y**2 - z;$
% first S-polynomial
g4 := gspoly(g2,g3);$
2 2
g4 := x *y*z - z
% next S-polynomial
p := gspoly(g2,g4); $
2 2
p := x *y*z - y*z
g5 := preduce(p,{g4});
2 2
g5 := - y*z + z
% last S-polynomial}
g6 := gspoly(g4,g5);
2 2 3
g6 := x *z - z
gsort{g2,g3,g4,g5,g6};
2 2
{x *y - z,
2 2
x *y*z - z ,
620 CHAPTER 16. USER CONTRIBUTED PACKAGES
2 2 3
x *z - z ,
2
x*y *z - x*y*z,
2 2
- y*z + z }
Bibliography
[1] Beatrice Amrhein and Oliver Gloor. The fractal walk. In Bruno Buchberger
an Franz Winkler, editor, Gröbner Bases and Applications, volume 251 of
LMS, pages 305 –322. Cambridge University Press, February 1998.
[2] Beatrice Amrhein, Oliver Gloor, and Wolfgang Kuechlin. How fast does
the walk run? In Alain Carriere and Louis Remy Oudin, editors, 5th Rhine
Workshop on Computer Algebra, volume PR 801/96, pages 8.1 – 8.9. Institut
Franco–Allemand de Recherches de Saint–Louis, January 1996.
[3] Beatrice Amrhein, Oliver Gloor, and Wolfgang Kuechlin. Walking faster. In
J. Calmet and C. Limongelli, editors, Design and Implementation of Symbolic
Computation Systems, volume 1128 of Lecture Notes in Computer Science,
pages 150 –161. Springer, 1996.
[4] Thomas Becker and Volker Weispfenning. Gröbner Bases. Springer, 1993.
[5] W. Boege, R. Gebauer, and H. Kredel. Some examples for solving systems of
algebraic equations by calculating Gröbner bases. J. Symbolic Computation,
2(1):83–98, March 1986.
[8] S. Collart, M. Kalkbrener, and D. Mall. Converting bases with the Gröbner
walk. J. Symbolic Computation, 24:465 – 469, 1997.
[9] James H. Davenport, Yves Siret, and Evelyne Tournier. Computer Algebra,
Systems and Algorithms for Algebraic Computation. Academic Press, 1989.
621
[12] A. Giovini, T. Mora, G. Niesi, L. Robbiano, and C. Traverso. One sugar cube,
please or selection strategies in the Buchberger algorithm. In Proc. of ISSAC
’91, pages 49–55, 1991.
[15] Heinz Kredel and Volker Weispfenning. Computing dimension and inde-
pendent sets for polynomial ideals. J. Symbolic Computation, 6(1):231–247,
November 1988.
[16] Herbert Melenk, H. Michael Möller, and Winfried Neun. On Gröbner bases
computation on a supercomputer using REDUCE. Preprint SC 88-2, Konrad-
Zuse-Zentrum für Informationstechnik Berlin, January 1988.
622 CHAPTER 16. USER CONTRIBUTED PACKAGES
Computer algebra systems typically drop some degenerate cases when evaluating
expressions, e.g., x/x becomes 1 dropping the case x = 0. We claim that it is feasi-
ble in practice to compute also the degenerate cases yielding guarded expressions.
We work over real closed fields but our ideas about handling guarded expression
can be easily transferred to other situations. Using formulas as guards provides
a powerful tool for heuristically reducing the combinatorial explosion of cases:
equivalent, redundant, tautological, and contradictive cases can be detected by sim-
plification and quantifier elimination. Our approach allows to simplify the expres-
sions on the basis of simplification knowledge on the logical side. The method
described in this paper is implemented in the REDUCE package GUARDIAN.
Authors: Andreas Dolzmann and Thomas Sturm.
16.29.1 Introduction
It is meanwhile a well-known fact that evaluations obtained with the interactive use
of computer algebra systems (CAS) are not entirely correct in general. Typically,
some degenerate cases are dropped. Consider for instance the evaluation
x2
= x,
x
which is correct only if x 6= 0. The problem here is that CAS consider variables
to be transcendental elements. The user, in contrast, has in mind variables in the
sense of logic. In other words: The user does not think of rational functions but of
terms.
Next consider the valid expression
√ √
x + −x
.
x
It is meaningless over the reals. C AS often offer no choice than to interprete surds
over the complex numbers even if they distinguish between a real and a complex
mode.
Corless and Jeffrey [4] have examined the behavior of a number of CAS with such
input data. They come to the conclusion that simultaneous computation of all
cases is exemplary but not feasible due to the combinatorial explosion of cases
to be considered. Therefore, they suggest to ignore the degenerate cases but to
provide the assumptions to the user on request. We claim, in contrast, that it is in
fact feasible to compute all possible cases.
Our setting is as follows: Expressions are evaluated to guarded expressions con-
sisting of possibly several conventional expressions guarded by quantifier-free for-
623
Guarded expressions
Here the non-generic cases already cover the whole domain. The generic case is
in some way redundant. It is just present for keeping track of the system’s default
behavior. Formally we have
n
_
γi ←→ γ0 . (16.75)
i=1
As an example for a non-redundant, i.e., necessary generic case we have the eval-
uation of the reciprocal x1 :
x 6= 0 x1 .
In every guarded expression, the generic case is explicitly marked as either neces-
sary or redundant. The corresponding tag is inherited during the evaluation process.
Unfortunately it can happen that guarded expressions satisfy (16.75) without being
tagged redundant, e.g., specialization of
T sin x
x=0 0
to x = 0 if the system cannot evaluate sin(0). This does not happen if one claims
for necessary generic cases to have, as the reciprocal above, no alternative cases at
all. Else, in the sequel “redundant generic case” has to be read as “tagged redun-
dant.”
With guarded expressions, the evaluation splits into two independent parts: Al-
gebraic evaluation and a subsequent simplification of the guarded expression ob-
tained.
625
Guarding schemes
In the introduction we have seen that certain operators introduce case distinctions.
For this, with each operator f there is a guarding scheme associated providing
information on how to map f (t1 , . . . , tm ) to a guarded expression provided that
one does not have to care for the argument expressions t1 , . . . , tm . In the easiest
case, this is a rewrite rule
f (a1 , . . . , am ) → G(a1 , . . . , am ).
The actual terms t1 , . . . , tm are simply substituted for the formal symbols a1 ,
. . . , am into the generic guarded expression G(a1 , . . . , am ). We give some ex-
amples:
a1 h i
→ a2 6= 0 aa12
a2
√ √
a1 → a1 ≥ 0 a1
T sign(a1 )
a1 > 0 1
sign(a1 ) → a1 = 0
0
a1 < 0 −1
T |a1 |
|a1 | → a1 ≥ 0 a1 (16.76)
a1 < 0 −a1
For functions of arbitrary arity, e.g., min or max, we formally assume infinitely
many operators of the same name. Technically, we associate a procedure parame-
terized with the number of arguments m that generates the corresponding rewrite
rule. As min_scheme(2) we obtain, e.g.,
T min(a1 , a2 )
min(a1 , a2 ) → a1 ≤ a2 a1 , (16.77)
a2 ≤ a1 a2
while for higher arities there are more case distinctions necessary.
For later complexity analysis, we state the concept of a guarding scheme formally:
a guarding scheme for an m-ary operator f is a map
gschemef : Em → GE
where E is the set of expressions, and GE is the set of guarded expressions. This al-
lows to split f (t1 , . . . , tm ) in dependence on the form of the parameter expressions
t1 , . . . , tm .
626 CHAPTER 16. USER CONTRIBUTED PACKAGES
Algebraic evaluation
Then the operator f is “moved inside” the e0i by combining all cases, technically a
simultaneous Cartesian product computation of both the sets of guards and the sets
of terms:
m
Y m
Y
Γ= {γi0 , . . . , γini }, T = {ti0 , . . . , tini }. (16.79)
i=1 i=1
This leads to the intermediate result
γ10 ∧ · · · ∧ γm0 f (t10 , . . . , tm0 )
.. ..
. .
γ1n1 ∧ · · · ∧ γm0 f (t1n1 , . . . , tm0 )
. (16.80)
.. ..
. .
γ1n1 ∧ · · · ∧ γmnm f (t1n1 , . . . , tmnm )
The new generic case is exactly the combination of the generic cases of the e0i . It
is redundant if at least one of these combined cases is redundant.
Next, all non-generic cases containing at least one redundant generic constituent
γi0 in their guard are deleted. The reason for this is that generic cases are only
used to keep track of the system default behavior. All other cases get the status of a
non-generic case even if they contain necessary generic constituents in their guard.
At this point, we apply the guarding scheme of f to all remaining expressions
f (t1i1 , . . . , tmim ) in the form (16.80) yielding a nested guarded expression
δ00 u00
.. ..
Γ0
. .
δ0k0 u0k0
.. ..
, (16.81)
. .
δN 0 uN 0
.. .
.
ΓN .
.
δN kN uN kN
627
Evaluating guarded expressions The previous section was concerned with the
evaluation of pure conventional expressions into guarded expressions. Our system
currently combines both conventional and guarded expressions. We are thus faced
with the problem of treating guarded subexpressions during evaluation.
When there is a guarded subexpression ei detected during evaluation, all contained
expressions are recursively evaluated to guarded expressions yielding a nested
guarded expression of the form (16.81). This is resolved as described above yield-
ing the evaluation subresult e0i .
As a special case, this explains how guarded expressions are (re)evaluated to
guarded expressions.
Example
We describe the evaluation of the expression min(x, |x|). The first argument e1 =
x evaluates recursively to
e01 = T x
(16.82)
with a necessary generic case. The nested x inside e2 = |x| evaluates to the same
form (16.82). For obtaining e02 , we apply the guarding scheme (16.76) of the abso-
lute value to the only term of (16.82) yielding
T |x|
T x ≥ 0 x ,
x < 0 −x
628 CHAPTER 16. USER CONTRIBUTED PACKAGES
Worst-case complexity
Our measure of complexity |G| for guarded expressions G is the number of con-
tained cases:
γ0 t0
γ1 t1
.. = n + 1.
..
. .
γn tn
In the important special case that the guarding scheme of f is a rewrite rule
f (a1 , . . . , am ) → G, the above complexity estimation simplifies to
m
Y m
|f (e01 , . . . , e0m )| ≤ |G| · |e0j | ≤ |G| · max |e0j | .
1≤j≤m
j=1
In other words: |G| plays the role of a factor, which, however, depends on f , and
|f (e01 , . . . , e0m )| is polynomial in the size of the ei but exponential in the arity of f .
Simplification
In view of the increasing size of the guarded expressions coming into existence
with subsequent computations, it is indispensable to apply simplification strate-
gies. There are two different algorithms involved in the simplification of guarded
expressions:
2. Effective quantifier elimination for real closed fields over the language of
ordered rings.
630 CHAPTER 16. USER CONTRIBUTED PACKAGES
It is not relevant, which simplifier and which quantifier elimination procedure is ac-
tually used. We use the formula simplifier described in [6]. Our quantifier elimina-
tion uses test point methods developed by Weispfenning [18, 15, 21]. It is restricted
to formulas obeying certain degree restrictions wrt. the quantified variables. As an
alternative, REDLOG provides an interface to Hong’s QEPCAD quantifier elimina-
tion package [14]. Compared to the simplification, the quantifier elimination is
more time consuming. It can be turned off by a switch.
The following simplification steps are applied in the given order:
Keep one tautological case If the guard of some non-generic case becomes “T,”
we delete all other non-generic cases. Else, if quantifier elimination is turned on,
we try to detect a tautology by eliminating the universal closures ∀γ of the guards
γ. This quantifier elimination is also applied to the guards of generic cases. These
are, in case of success, simply replaced by “T” without deleting the case.
Remove contradictive cases A non-generic case is deleted if its guard has be-
come “F.” If quantifier elimination is turned on, we try to detect further contradic-
tive cases by eliminating the existential closure ∃γ for each guard γ. This quantifier
elimination is also applied to generic cases. In case of success they are not deleted
but their guards are replaced by “F.” Our assumption (16.74) allows then to delete
all non-generic cases.
631
Example revisited
We turn back to the form (16.83) of our example min(x, |x|). Contraction of cases
with subsequent simplification automatically yields
T min(x, |x|)
T x
,
|x| − x ≤ 0 |x|
F −x
Output modes
An output mode determines which part of the information contained in the guarded
expressions is provided to the user. G UARDIAN knows the following output modes:
Matrix Output matrices in the style used throughout this paper. We have already
seen that these can become very large in general.
Generic term Output only the generic term. Thus the output is exactly the same
as without the guardian package. If the condition of the generic case becomes “F,”
a warning “contradictive situation” is given. The computation can,
however, be continued.
Note that output modes are restrictions concerning only the output; internally the
system still computes with the complete guarded expressions.
A smart mode
Consider the evaluation result (16.84) of min(x, |x|). The generic term output
mode would output min(x, |x|), although more precise information could be given,
namely x. The problem is caused by the fact that generic cases are used to keep
track of the system’s default behavior. In this section we will describe an optional
smart mode with a different notion of generic case. To begin with, we show why
the problem can not be overcome by a “smart output mode.”
632 CHAPTER 16. USER CONTRIBUTED PACKAGES
Assume that there is an output mode which outputs x for (16.84). As the next
computation involving (16.84) consider division by y. This would result in
" #
y 6= 0 min(x,|x|)
y
x .
y 6= 0 y
Again, there are identic conditions for the generic case and some non-generic case,
and, again, the term belonging to the latter is simpler. Our mode would output xy .
Next, we apply the absolute value once more yielding
| min(x,|x|)|
y 6= 0 |y|
x
xy ≥ 0 ∧ y 6= 0 .
y
−x
xy < 0 ∧ y 6= 0 y
Here, the condition of the generic case differs from all other conditions. We thus
have to output the generic term. For the user, the evaluation of | xy | results in
| min(x,|x|)|
|y| .
The smart mode can turn a non-generic case into a necessary generic one dropping
the original generic case and all other non-generic cases. Consider, e.g., (16.84),
where the conditions are equal, and the non-generic term is “simpler.”
In fact, the relevant relationship between the conditions is that the generic condition
implies the non-generic one. In other words: Some non-generic condition is not
more restrictive than the generic condition, and thus covers the whole domain of the
guarded expression. Note that from the implication and (16.74) we may conclude
that the cases are even equivalent.
Implication is heuristically checked by simplification. If this fails, quantifier elim-
ination provides a decision procedure. Note that our test point methods are in-
complete in this regard due to the degree restrictions. Also it cannot be applied
straightforwardly to guards containing operators that do not belong to the language
of ordered rings.
Whenever we happen to detect a relevant implication, we actually turn the cor-
responding non-generic case into the generic one. From our motivation of non-
generic cases, we may expect that non-generic expressions are generally more con-
venient than generic ones.
16.29.3 Examples
We give the results for the following computations as they are printed in the output
mode matrix providing the full information on the computation result. The reader
can derive himself what the output in the mode generic case or generic term would
be.
633
The evaluation time for the last example is 119 ms on a SUN SPARC -4. This illus-
trates that efficiency is no problem with such interactive examples.
634 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.29.4 Outlook
This section describes possible extensions of the GUARDIAN. The extensions pro-
posed in Section 16.29.4 on simplification of terms and Section 16.29.4 on a back-
ground theory are clear from a theoretical point of view but not yet implemented.
Section 16.29.4 collects some ideas on the application of our ideas to the REDUCE
integrator. In this field, there is some more theoretical work necessary.
Simplification of terms
In smart mode second case would then become the only generic case.
Generally, one would proceed as follows: If the guard is a conjunction containing
as toplevel equations
t1 = 0, . . . , tk = 0,
reduce the corresponding expression modulo the set of univariate linear polynom-
ials among t1 , . . . , tk .
A more general approach would reduce the expression modulo a Gröbner basis of
all the t1 , . . . , tk . This leads, however, to larger expressions in general.
One can also imagine to make use of non-conjunctive guards in the following way:
2. Split the case into several cases corresponding to the conjunctions in the
DNF .
Background theory
In practice one often computes with quantities guaranteed to lie in a certain range.
For instance, when computing an electrical resistance, one knows in advance that it
will not be negative. For such cases one would like to have some facility to provide
external information to the system. This can then be used to reduce the complexity
of the guarded expressions.
One would provide a function assert(ϕ), which asserts the formula ϕ to hold.
Successive applications of assert establish a background theory, which is a set of
formulas considered conjunctively. The information contained in the background
theory can be used with the guarded expression computation. The user must, how-
ever, not rely on all the background information to be actually used.
Technically, denote by Φ the (conjunctive) background theory. For the simplifica-
tion of the guards, we can make use of the fact that our simplifier is designed to
simplify wrt. a theory, cf. [6]. For proving that some guard γ is tautological, we
try to prove
∀(Φ −→ γ)
instead of ∀γ. Similarly, for proving that γ is contradictive, we try to disprove
∃(Φ ∧ γ).
Independently, one can imagine to use a background theory for reducing the output
with the matrix output mode. For this, one simplifies each guard wrt. the theory
at the output stage treating contradictions and tautologies appropriately. Using the
theory for replacing all cases by one at output stage in a smart mode manner leads
once more to the problem of expressions or even guarded expressions “mysteri-
ously” getting more complicated. Applying the theory only at the output stage
makes it possible to implement a procedure unassert(ϕ) in a reasonable way.
Integration
This problem can also be solved by using guarded expressions for integration re-
sults.
Within the framework of this paper, we would have to associate a guarding scheme
to the integrator int. It is not hard to see that this cannot be done in a reasonable
way without putting as much knowledge into the scheme as into the integrator
itself. Thus for treating integration, one has to modify the integrator to provide
guarded expressions.
Next, we have to clarify what the guarded expression for the above integral would
look like. Since we know that the integral is defined for all interpretations of the
variables, our assumption (16.74) implies that the generic condition be “T.” We
obtain the guarded expression
R a
T x dx
a 6= −1 1 a+1
a+1 x .
a = −1 ln x
Note that the redundant generic case does not model the system’s current behavior.
Our method, in the described form, uses an already implemented algebraic evalu-
ator. In the previous section, we have seen that this point of view is not sufficient
for treating integration appropriately.
Also our approach runs into trouble with built-in knowledge such as
√
x2 = |x|, (16.85)
sign(|x|) = 1. (16.86)
16.29.5 Conclusions
Bibliography
[2] Broadberry, P., Gómez-Díaz, T., and Watt, S. On the implementation of dy-
namic evaluation. In Proceedings of the International Symposium on Symb-
olic and Algebraic Manipulation (ISSAC 95) (New York, N.Y., 1995), A. Lev-
elt, Ed., ACM Press, pp. 77–89.
[3] Collins, G. E. Quantifier elimination for the elementary theory of real closed
fields by cylindrical algebraic decomposition. In Automata Theory and For-
mal Languages. 2nd GI Conference (Berlin, Heidelberg, New York, May
1975), H. Brakhage, Ed., vol. 33 of Lecture Notes in Computer Science,
Gesellschaft für Informatik, Springer-Verlag, pp. 134–183.
[4] Corless, R. M., and Jeffrey, D. J. Well . . . it isn’t quite that simple. ACM
SIGSAM Bulletin 26, 3 (Aug. 1992), 2–6. Feature.
[5] Davenport, J. H., and Faure, C. The “unknown” in computer algebra. Pro-
grammirovanie 1, 1 (1994).
[8] Dolzmann, A., and Sturm, T. Redlog user manual. Technical Report MIP-
9616, FMI, Universität Passau, D-94030 Passau, Germany, Oct. 1996. Edi-
tion 1.0 for Version 1.0.
[9] Duval, D., and Gonzáles-Vega, L. Dynamic evaluation and real closure. In
Proceedings of the IMACS Symposium on Symbolic Computation (1993).
[10] Duval, D., and Reynaud, J.-C. Sketches and computation I: Basic definitions
and static evaluation. Mathematical Structures in Computer Science 4, 2
(1994), 185–238.
[11] Duval, D., and Reynaud, J.-C. Sketches and computation II: Dynamic eval-
uation and applications. Mathematical Structures in Computer Science 4, 2
(1994), 239–271.
[13] Hearn, A. C., and Fitch, J. P. Reduce User’s Manual for Version 3.6. RAND,
Santa Monica, CA 90407-2138, July 1995. RAND Publication CP78.
[14] Hong, H., Collins, G. E., Johnson, J. R., and Encarnacion, M. J. QEPCAD
interactive version 12. Kindly communicated to us by Hoon Hong, Sept.
1993.
[15] Loos, R., and Weispfenning, V. Applying linear quantifier elimination. The
Computer Journal 36, 5 (1993), 450–462. Special issue on computational
quantifier elimination.
[16] Melenk, H. Reduce symbolic mode primer. In REDUCE 3.6 User’s Guide
for UNIX. Konrad-Zuse-Institut, Berlin, 1995.
[17] Tarski, A. A decision method for elementary algebra and geometry. Tech.
rep., University of California, 1948. Second edn., rev. 1951.
This package implements the basic arithmetic for polynomial ideals by exploiting
the Gröbner bases package of REDUCE. In order to save computing time all inter-
mediate Gröbner bases are stored internally such that time consuming repetitions
are inhibited.
Author: Herbert Melenk.
16.30.1 Introduction
This package implements the basic arithmetic for polynomial ideals by exploiting
the Gröbner bases package of REDUCE. In order to save computing time all inter-
mediate Gröbner bases are stored internally such that time consuming repetitions
are inhibited. A uniform setting facilitates the access.
16.30.2 Initialization
Prior to any computation the set of variables has to be declared by calling the
operator I_setting . E.g. in order to initiate computations in the polynomial ring
Q[x, y, z] call
I_setting(x,y,z);
A subsequent call to I_setting allows one to select another set of variables; at the
same time the internal data structures are cleared in order to free memory resources.
16.30.3 Bases
u := I(x*z-y**2, x**3-y*z);
Alternatively a list of polynomials can be used as input basis; however, all arith-
metic results will be presented in the above form. The operator ideal2list allows
one to convert an ideal basis into a conventional REDUCE list.
Operators
Example:
I(x+y,x^2) .* I(x-z);
2 2 2
I(X + X*Y - X*Z - Y*Z,X*Y - Y *Z)
The test operators return the values 1 (=true) or 0 (=false) such that they can be
used in REDUCE if − then − else statements directly.
The results of sum, product, quotient, intersction are ideals represented by their
Gröbner basis in the current setting and term order. The term order can be modified
using the operator torder from the Gröbner package. Note that ideal equality
cannot be tested with the REDUCE equal sign:
16.30.4 Algorithms
16.30.5 Examples
This package supports the operator ineq_solve that tries to solves single in-
equalities and sets of coupled inequalities.
Author: Herbert Melenk.
The following types of systems are supported :
• a linear system of mixed equations and <= – >= inequalities, applying the
method of Fourier and Motzkin 28 ,
• a univariate inequality with <=, >=, > or < operator and polynomial or
rational left–hand and right–hand sides, or a system of such inequalities with
only one variable.
For linear optimization problems please use the operator simplex of the L INALG
package (cf. section 16.37).
Syntax:
INEQ_SOLVE(hexpri [,hvli])
reg:=
{a + b - c>=0, a - b + c>=0, - a + b + c>=0, 0>=0, 2>=0,
2*c - 2>=0, a - b + c>=0, a + b - c>=0, - a + b + c - 2>=0,
2>=0, 0>=0, 2*b - 2>=0, k + 1>=0, - a - b - c + k>=0,
- a - b - c + k + 2>=0, - 2*b + k>=0,
- 2*c + k>=0, a + b + c - k>=0,
2*b + 2*c - k - 2>=0, a + b + c - k>=0}$
ineq_solve (reg,{k,a,b,c});
{c=(1 .. infinity),
b=(1 .. infinity),
k=a + b + c}
644 CHAPTER 16. USER CONTRIBUTED PACKAGES
Involutive bases are a new tool for solving problems in connection with multivari-
ate polynomials, such as solving systems of polynomial equations and analyzing
polynomial ideals. An involutive basis of polynomial ideal is nothing but a special
form of a redundant Gröbner basis. The construction of involutive bases reduces
the problem of solving polynomial systems to simple linear algebra.
Authors: A.Yu. Zharkov and Yu.A. Blinkov.
16.32.1 Introduction
Involutive bases are a new tool for solving problems in connection with multivari-
ate polynomials, such as solving systems of polynomial equations and analyzing
polynomial ideals, see [1]. An involutive basis of polynomial ideal is nothing but
a special form of a redundant Gröbner basis. The construction of involutive bases
reduces the problem of solving polynomial systems to simple linear algebra.
The INVBASE package 29 calculates involutive bases of polynomial ideals using
an algorithm described in [1] which may be considered as an alternative to the
well-known Buchberger algorithm [2]. The package can be used over a variety of
different coefficient domains, and for different variable and term orderings.
The algorithm implemented in the INVBASE package is proved to be valid for
any zero-dimensional ideal (finite number of solutions) as well as for positive-
dimensional ideals in generic form. However, the algorithm does not terminate
for “sparse” positive-dimensional systems. In order to stop the process we use
the maximum degree bound for the Gröbner bases of generic ideals in the total-
degree term ordering established in [3]. In this case, it is reasonable to call the
GROEBNER package with the answer of INVBASE as input information in order
to compute the reduced Gröbner basis under the same variable and term ordering.
Though the INVBASE package supports computing involutive bases in any admis-
sible term ordering, it is reasonable to compute them only for the total-degree term
orderings. The package includes a special algorithm for conversion of total-degree
involutive bases into the triangular bases in the lexicographical term ordering that is
desirable for finding solutions. Normally the sum of timings for these two compu-
tations is much less than the timing for direct computation of the lexicographical
involutive bases. As a rule, the result of the conversion algorithm is a reduced
Gröbner basis in the lexicographical term ordering. However, because of some
gaps in the current version of the algorithm, there may be rare situations when
the resulting triangular set does not possess the formal property of Gröbner bases.
Anyway, we recommend using the GROEBNER package with the result of the
29
The REDUCE implementation has been supported by the Konrad-Zuse-Zentrum Berlin
645
conversion algorithm as input in order either to check the Gröbner bases property
or to transform the result into a lexicographical Gröbner basis.
Term Ordering
These modes have the same meaning as for the GROEBNER package.
All orderings are based on an ordering among the variables. For each pair of vari-
ables an order relation > must be defined, e.g. x > y. The term ordering mode as
well as the order of variables are set by the operator
where < mode > is one of the term order modes listed above. The notion of
{x1 , ..., xn } as a list of variables at the same time means x1 > ... > xn .
Example 1.
IN V T ORDER REV GRADLEX, {x, y, z}
sets the reverse graduated term ordering based on the variable order x > y > z.
The operator IN V T ORDER may be omitted. The default term order mode is
REV GRADLEX and the default decreasing variable order is alphabetical (or,
more generally, the default REDUCE kernel order). Furthermore, the list of vari-
ables in the IN V T ORDER may be omitted. In this case the default variable
order is used.
accordingly, polynomials and rational functions in the parametric case). The com-
putations modulo prime numbers are also available. For this purpose one should
type the REDUCE commands
g := { 8 ∗ x ∗ y ∗ z3 − 2 ∗ x ∗ y ∗ z2 + 4 ∗ y3 −
4 ∗ y ∗ z 2 + 16 ∗ x ∗ y + 17 ∗ y ∗ z − 4 ∗ y,
8 ∗ y 4 − 8 ∗ x ∗ z 2 − 256 ∗ y 2 + 2 ∗ x ∗ z + 64 ∗ z 2 − 96 ∗ x + 20 ∗ z − 9,
2 ∗ y 3 ∗ z + 4 ∗ x ∗ y + y,
8 ∗ x ∗ z 3 − 2 ∗ x ∗ z 2 + 4 ∗ y 2 − 4 ∗ z 2 + 16 ∗ x + 17 ∗ z − 4,
−4 ∗ y ∗ z 3 − 8 ∗ y 3 + 6 ∗ x ∗ y ∗ z + y ∗ z 2 − 36 ∗ x ∗ y − 8 ∗ y,
4 ∗ x ∗ y 2 + 32 ∗ y 2 − 8 ∗ z 2 + 12 ∗ x − 2 ∗ z + 1,
2 ∗ y 2 ∗ z + 4 ∗ x + 1,
−4 ∗ z 3 − 8 ∗ y 2 + 6 ∗ x ∗ z + z 2 − 36 ∗ x − 8,
8 ∗ x2 − 16 ∗ y 2 + 4 ∗ z 2 − 6 ∗ x − z }
h := IN V LEX g;
The result is
The resulting list of polynomials which is not an involutive basis is stored in the
share variable INVTEMPBASIS. In this case it is reasonable to call the GROEB-
NER package with the value of INVTEMPBASIS as input under the same variable
and term ordering.
Bibliography
The various lines specify different options for what the left hand side (non-terminal
symbol) might correspond to, while the items within the braces are sematic actions
that get obeyed or evaluated when the production ruls is used.
Each LHS is treated as a non-terminal symbol and is specified as a simple name.
Note that by default the Reduce parser will be folding characters within names
to lower case and so it will be best to choose names for non-terminals that are
unambiguous even when case-folded, but I would like to establish a convention
that in source code they are written in capitals.
649
The RHS items may be either non-terminals (identified because they are present
in the left hand side of some production) or terminals. Terminal symbols can be
specified in two different ways.
The lexer has built-in recipes that decode certain sequences of characters and return
the special markers for !:symbol, !:number, !:string, !:list for commonly used cases.
In these cases the variable yylval gets left set to associated data, so for instance in
the case of !:symbol it gets set to the particular symbol concerned. The token type
:list is used for Lisp or rlisp-like notation where the input contains ’expression or
‘expression so for instance the input ‘(a b c) leads to the lexer returning !:list and
yylvel being set to (backquote (a b c)). This treatment is specialised for handling
rlisp-like syntax.
Other terminals are indicated by writing a string. That may either consist of char-
acters that would otherwise form a symbol (ie a letter followed by letters, digits
and underscores) or a sequence of non-alphanumeric characters. In the latter case
if a sequence of three or more punctuation marks make up a terminal then all the
shorter prefixes of it will also be grouped to form single entities. So if "<–>" is a
terminal then ’<’, ’<-’ and ’<–’ will each by parsed as single tokens, and any of
them that are not used as terminals will be classified as !:symbol.
As well as terminals and non-terminals (which are writtent as symbols or strings)
it is possible to write one of
(OPT s1 s2 . . . ) 0 or 1 instances of the sequence s1, . . .
(STAR s1 s2 . . . ) 0, 1, 2, . . . instances.
(PLUS s1 s2 . . . ) 1, 2, 3, . . . instances.
(LIST sep s1 s2 . . . ) like (STAR s1 s2 . . . ) but with the single item
sep between each instance.
(LISTPLUS sep s1 . . . ) like (PLUS s2 . . . ) but with sep interleaved.
(OR s1 s2 . . . ) one or other of the tokens shown.
When the lexer processes input it will return a numeric code that identifies the type
of the item seen, so in a production one might write (!:symbol ":=" EXPRESSION)
and as it recognises the first two tokens the lexer will return a numeric code for
!:symbol (and set yylval to the actual symbol as seen) and then a numeric code
that it allocates for ":=". In the latter case it will also set yylval to the symbol
!:!= in case that is useful. Precedence can be set using lalr_precedence. See
examples below.
16.33.1 Limitations
1. Grammar rules and semantic actions are specified in fairly raw Lisp.
2. The lexer is hand-written and can not readily be reconfigured for use with
languages other than rlisp. For instance it has use of "!" as a character escape
built into it.
650 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.33.2 An example
<< lex_init();
yyparse() >>;
c c c d c d ;
651
This package can calculate ordinary and inverse Laplace transforms of expressions.
Documentation is in plain text.
Authors: C. Kazasov, M. Spiridonova, V. Tomov.
Syntax:
where < exp > is the expression to be transformed, < var − s > is the source
variable (in most cases < exp > depends explicitly of this variable) and < var −
t > is the target variable. If < var − t > is omitted, the package uses an internal
variable lp!& or il!&, respectively.
lmon: If on, sin, cos, sinh and cosh are converted by LAPLACE into
exponentials,
lhyp: If on, expressions e˜x are converted by INVLAP into hyperbolic
functions sinh and cosh,
ltrig: If on, expressions e˜x are converted by INVLAP into trigonometric
functions sin and cos.
The system can be extended by adding Laplace transformation rules for single
functions by rules or rule sets. In such a rule the source variable MUST be free,
the target variable MUST be il!& for LAPLACE and lp!& for INVLAP and the
third parameter should be omitted. Also rules for transforming derivatives are en-
tered in such a form.
652 CHAPTER 16. USER CONTRIBUTED PACKAGES
Examples:
operator f;
let{
when fixp n,
laplace(f(~x),x) = f(il!&)
};
which means "Integral of < expr > wrt. < var > taken from 0 to < obj.var >",
e.g. intl(2∗y 2 , y, 0, x) which is formally a function in x.
We recommend reading the file LAPLACE.TST for a further introduction.
653
LIE is a package of functions for the classification of real n-dimensional Lie al-
gebras. It consists of two modules: liendmc1 and lie1234. With the help of the
functions in the liendmcl module, real n-dimensional Lie algebras L with a derived
algebra L(1) of dimension 1 can be classified.
Authors: Carsten and Franziska Schöbel.
LIE is a package of functions for the classification of real n-dimensional Lie alge-
bras. It consists of two modules: liendmc1 and lie1234.
liendmc1
With the help of the functions in this module real n-dimensional Lie algebras L
with a derived algebra L(1) of dimension 1 can be classified. L has to be defined
by its structure constants ckij in the basis {X1 , . . . , Xn } with [Xi , Xj ] = ckij Xk .
The user must define an ARRAY LIENSTRUCIN(n, n, n) with n being the dimen-
sion of the Lie algebra L. The structure constants LIENSTRUCIN(i, j, k):=ckij for
i < j should be given. Then the procedure LIENDIMCOM1 can be called. Its
syntax is:
LIENDIMCOM1(<number>).
(i) {LIE_ALGEBRA(2),COMMUTATIVE(n-2)} or
(ii) {HEISENBERG(k),COMMUTATIVE(n-k)}
with 3 ≤ k ≤ n, k odd.
The concepts correspond to the following theorem (LIE_ALGEBRA(2) → L2 ,
HEISENBERG(k) → Hk and COMMUTATIVE(n-k) → Cn−k ):
Theorem. Every real n-dimensional Lie algebra L with a 1-dimensional derived
algebra can be decomposed into one of the following forms:
(i) C(L) ∩ L(1) = {0} : L2 ⊕ Cn−2 or
(ii) C(L) ∩ L(1) = L(1) : Hk ⊕ Cn−k (k = 2r − 1, r ≥ 2), with
654 CHAPTER 16. USER CONTRIBUTED PACKAGES
ON TR_LIE;
lie1234
This part of the package classifies real low-dimensional Lie algebras L of the di-
mension n :=dim L = 1, 2, 3, 4. L is also given by its structure constants ckij in
the basis {X1 , . . . , Xn } with [Xi , Xj ] = ckij Xk . An ARRAY LIESTRIN(n, n, n)
has to be defined and LIESTRIN(i, j, k):=ckij for i < j should be given. Then the
procedure LIECLASS can be performed whose syntax is:
LIECLASS(<number>).
<number> should be the dimension of the Lie algebra L. The procedure stepwise
simplifies the commutator relations of L using properties of invariance like the
dimension of the centre, of the derived algebra, unimodularity etc. The returned
value has the form:
{LIEALG(n),COMTAB(m)},
{LIEALG(n),COMTAB(m),p1,p2}.
This returned value is also stored as LIE_CLASS. The linear transformation from
the basis {X1 , . . . , Xn } into the basis of the standard form {Y1 , . . . , Yn } is given
by the matrix LIEMAT: Yj = (LIEMAT)kj Xk .
655
ON TR_LIE;
before the procedure LIECLASS is called the output contains not only the list
LIE_CLASS but also the non-vanishing commutator relations in the standard form.
By the value m and the parameters further examinations of the Lie algebra are pos-
sible, especially if in a data bank mathematical relevant properties of the enumer-
ated standard forms are stored.
Bibliography
[1] M.A.H. MacCallum. On the classification of the real four-dimensional lie al-
gebras. 1979.
This is the standard way of calling limit, applying all of the methods. The result is
the limit of EXPRN as VAR approaches LIMPOINT.
If the limit depends upon the direction of approach to the LIMPOINT, the functions
LIMIT!+ and LIMIT!- may be used. They are defined by:
This package provides a selection of functions that are useful in the world of linear
algebra.
Author: Matt Rebbeck.
16.37.1 Introduction
This package provides a selection of functions that are useful in the world of linear
algebra. These functions are described alphabetically in subsection 16.37.3 and are
labelled 16.37.3.1 to 16.37.3.53. They can be classified into four sections(n.b: the
numbers after the dots signify the function label in section 16.37.3).
Contributions to this package have been made by Walter Tietze (ZIB).
16.37.1.2 Constructors
16.37.1.4 Predicates
Note on examples:
Notation
Throughout I is used to indicate the identity matrix and AT to indicate the trans-
pose of the matrix A.
If you have not used matrices within REDUCE before then the following may be
helpful.
660 CHAPTER 16. USER CONTRIBUTED PACKAGES
Creating matrices
Syntax:
add_columns(A,c1,c2,expr);
A :- a matrix.
c1, c2 :- positive integers.
expr :- a scalar expression.
Synopsis:
add_columns replaces column c2 of A by
expr ∗ column(A,c1) + column(A,c2).
add_rows performs the equivalent task on the rows of A.
661
Examples:
1 x+2 3
add_columns(A, 1, 2, x) = 4 4 ∗ x + 5 6
7 7∗x+8 9
1 2 3
add_rows(A, 2, 3, 5) = 4 5 6
27 33 39
Related functions:
add_to_columns, add_to_rows, mult_columns, mult_rows.
16.37.3.2 add_rows
See: add_columns.
Syntax:
add_to_columns(A,column_list,expr);
A :- a matrix.
column_list :- a positive integer or a list of positive integers.
expr :- a scalar expression.
Synopsis:
add_to_columns adds expr to each column specified in column_list of
A.
add_to_rows performs the equivalent task on the rows of A.
Examples:
11 12 3
add_to_columns(A, {1, 2}, 10) = 14 15 6
17 18 9
1 2 3
add_to_rows(A, 2, −x) = −x + 4 −x + 5 −x + 6
7 8 9
Related functions:
add_columns, add_rows, mult_rows, mult_columns.
662 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.37.3.4 add_to_rows
See: add_to_columns.
Syntax:
augment_columns(A,column_list);
A :- a matrix.
column_list :- either a positive integer or a list of positive integers.
Synopsis:
augment_columns gets hold of the columns of A specified in col-
umn_list and sticks them together.
stack_rows performs the same task on rows of A.
Examples:
cc1 2
augment_columns(A, {1, 2}) = 4 5
7 8
1 2 3
stack_rows(A, {1, 3}) =
7 8 9
Related functions:
get_columns, get_rows, sub_matrix.
16.37.3.6 band_matrix
Syntax:
band_matrix(expr_list,square_size);
expr_list :- either a single scalar expression or a list of an odd num-
ber of scalar expressions.
square_size :- a positive integer.
Synopsis:
band_matrix creates a square matrix of dimension square_size. The
diagonal consists of the middle expr of the expr_list. The expressions to
the left of this fill the required number of sub-diagonals and the expressions
to the right the super-diagonals.
663
y z 0 0 0 0
x y z 0 0 0
0 x y z 0 0
Examples: band_matrix({x, y, z}, 6) =
0
0 x y z 0
0 0 0 x y z
0 0 0 0 x y
Related functions:
diagonal.
16.37.3.7 block_matrix
Syntax:
block_matrix(r,c,matrix_list);
r, c :- positive integers.
matrix_list :- a list of matrices.
Synopsis:
block_matrix creates a matrix that consists of r × c matrices filled from
the matrix_list row-wise.
Examples:
1 0 5 22 33
B= , C= , D=
0 1 5 44 55
1 0 5 22 33
0 1 5 44 55
block_matrix(2, 3, {B, C, D, D, C, B}) =
22 33 5 1 0
44 55 5 0 1
16.37.3.8 char_matrix
Syntax:
char_matrix(A, λ);
A :- a square matrix.
λ :- a symbol or algebraic expression.
Synopsis:
char_matrix creates the characteristic matrix C of A. This is C = λI −
A.
x − 1 −2 −3
Examples: char_matrix(A, x) = −4 x − 5 −6
−7 −8 x − 9
664 CHAPTER 16. USER CONTRIBUTED PACKAGES
Related functions:
char_poly.
16.37.3.9 char_poly
Syntax:
char_poly(A, λ);
A :- a square matrix.
λ :- a symbol or algebraic expression.
Synopsis:
char_poly finds the characteristic polynomial of A.
This is the determinant of λI − A.
Examples:
char_poly(A, x) = x3 − 15 ∗ x2 − 18 ∗ x
Related functions:
char_matrix.
16.37.3.10 cholesky
Syntax:
cholesky(A);
A :- a positive definite matrix containing numeric entries.
Synopsis:
cholesky computes the cholesky decomposition of A.
It returns {L, U} where L is a lower matrix, U is an upper matrix,
A = LU, and U = LT .
Examples:
1 1 0
F = 1 3 1
0 1 1
1 √0
0 1 √1 0
cholesky(F) = 1 2 0 , 0
2 √1
2
0 √1
√1 0 0 √1
2 2 2
Related functions:
lu_decom.
665
16.37.3.11 coeff_matrix
Syntax:
coeff_matrix({lin_eqn1 ,lin_eqn2 , ...,lin_eqnn }); 30
lin_eqn1 ,lin_eqn2 , . . . ,lin_eqnn :- linear equations. Can be of the
form equation = number or just
equation which is equivalent to
equation = 0.
Synopsis:
coeff_matrix creates the coefficient matrix C of the linear equations. It
returns {C, X , B} such that CX = B.
Examples:
Syntax:
column_dim(A);
A :- a matrix.
Synopsis:
column_dim finds the column dimension of A.
row_dim finds the row dimension of A.
Examples:
column_dim(A) = 3
16.37.3.13 companion
Syntax:
companion(poly,x);
poly :- a monic univariate polynomial in x.
x :- the variable.
30
If you’re feeling lazy then the {}’s can be omitted.
666 CHAPTER 16. USER CONTRIBUTED PACKAGES
Synopsis:
companion creates the companion matrix C of poly.
This is the square matrix of dimension n, where n is the degree of poly
w.r.t. x. The entries of C are: C(i, n) = −coeffn(poly, x, i − 1) for
i = 1, . . . , n, C(i, i − 1) = 1 for i = 2, . . . , n and the rest are 0.
0 0 0 −11
1 0 0 0
Examples: companion(x4 + 17 ∗ x3 − 9 ∗ x2 + 11, x) = 0 1 0
9
0 0 1 −17
Related functions:
find_companion.
16.37.3.14 copy_into
Syntax:
copy_into(A, B,r,c);
A, B :- matrices.
r, c :- positive integers.
Synopsis:
copy_into copies matrix A into B with A(1, 1) at B(r, c).
Examples:
0 0 0 0
0 0 0 0
G= 0
0 0 0
0 0 0 0
0 1 2 3
0 4 5 6
copy_into(A, G, 1, 2) =
0
7 8 9
0 0 0 0
Related functions:
augment_columns, extend, matrix_augment, matrix_stack,
stack_rows, sub_matrix.
16.37.3.15 diagonal
Syntax:
diagonal({mat1 ,mat2 , ...,matn });31
31
If you’re feeling lazy then the {}’s can be omitted.
667
Examples:
66 77
H=
88 99
1 2 3 0 0 0
4 5 6 0 0 0
7 8 9 0 0 0
diagonal({A, x, H}) =
0
0 0 x 0 0
0 0 0 0 66 77
0 0 0 0 88 99
Related functions:
jordan_block.
16.37.3.16 extend
Syntax:
extend(A,r,c,expr);
A :- a matrix.
r, c :- positive integers.
expr :- algebraic expression or symbol.
Synopsis:
extend returns a copy of A that has been extended by r rows and c
columns. The new entries are made equal to expr.
1 2 3 x x
4 5 6 x x
Examples: extend(A, 1, 2, x) = 7 8 9 x x
x x x x x
Related functions:
copy_into, matrix_augment, matrix_stack, remove_columns,
remove_rows.
16.37.3.17 find_companion
Syntax:
find_companion(A,x);
668 CHAPTER 16. USER CONTRIBUTED PACKAGES
A :- a matrix.
x :- the variable.
Synopsis:
Given a companion matrix, find_companion finds the polynomial from
which it was made.
Examples:
0 0 0 −11
1 0 0 0
C= 0
1 0 9
0 0 1 −17
find_companion(C, x) = x4 + 17 ∗ x3 − 9 ∗ x2 + 11
Related functions:
companion.
Syntax:
get_columns(A,column_list);
A :- a matrix.
c :- either a positive integer or a list of positive integers.
Synopsis:
get_columns removes the columns of A specified in column_list and
returns them as a list of column matrices.
get_rows performs the same task on the rows of A.
Examples:
1 3
get_columns(A, {1, 3}) = 4 , 6
7 9
get_rows(A, 2) = 4 5 6
Related functions:
augment_columns, stack_rows, sub_matrix.
16.37.3.19 get_rows
See: get_columns.
669
16.37.3.20 gram_schmidt
Syntax:
gram_schmidt({vec1 ,vec2 , ...,vecn }); 32
vec1 ,vec2 , . . . ,vecn :- linearly-independent vectors. Each vector must
be written as a list, eg:{1,0,0}.
Synopsis:
gram_schmidt performs the Gram-Schmidt orthonormalisation on the in-
put vectors. It returns a list of orthogonal normalised vectors.
Examples:
gram_schmidt({{1,0,0},{1,1,0},{1,1,1}}) = {{1,0,0},{0,1,0},{0,0,1}}
√ √
1 2 2∗ 5 − 5
gram_schmidt({{1,2},{3,4}}) = {{ √ , √ }, { , }}
5 5 5 5
16.37.3.21 hermitian_tp
Syntax:
hermitian_tp(A);
A :- a matrix.
Synopsis:
hermitian_tp computes the hermitian transpose of A.
This is a matrix in which the (i, j)th entry is the conjugate of the (j, i)th
entry of A.
Examples:
i+1 i+2 i+3
J = 4 5 2
1 i 0
−i + 1 4 1
hermitian_tp(J ) = −i + 2 5 −i
−i + 3 2 0
Related functions:
tp33 .
32
If you’re feeling lazy then the {}’s can be omitted.
33
standard reduce call for the transpose of a matrix - see section 14.4.
670 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.37.3.22 hessian
Syntax:
hessian(expr,variable_list);
expr :- a scalar expression.
variable_list :- either a single variable or a list of variables.
Synopsis:
hessian computes the hessian matrix of expr w.r.t. the varibles in
variable_list.
This is an n × n matrix where n is the number of variables and the (i, j)th
entry is df(expr,variable_list(i),variable_list(j)).
0 0 0 0
0 2 z y
Examples: hessian(x ∗ y ∗ z + x2 , {w, x, y, z}) =
0 z 0 x
0 y x 0
Related functions:
df34 .
16.37.3.23 hilbert
Syntax:
hilbert(square_size,expr);
square_size :- a positive integer.
expr :- an algebraic expression.
Synopsis:
hilbert computes the square hilbert matrix of dimension square_size.
This is the symmetric matrix in which the (i, j)th entry is 1/(i + j − expr).
−1 −1 −1
x+y−2 x+y−3 x+y−4
−1 −1 −1
Examples: hilbert(3, y + x) = x+y−3 x+y−4 x+y−5
−1 −1 −1
x+y−4 x+y−5 x+y−6
16.37.3.24 jacobian
Syntax:
mat_jacobian(expr_list,variable_list);
34
standard reduce call for differentiation - see section 7.8.
671
0 4 ∗ x3
0 0
0 y2 2∗x∗y 0
0 y∗z 3 x∗z 3 3∗x∗y∗z 2
Related functions:
hessian, df35 .
NOTE: The function mat_jacobian used to be called just "jacobian"
however us of that name was in conflict with another Reduce package.
16.37.3.25 jordan_block
Syntax:
jordan_block(expr,square_size);
expr :- an algebraic expression or symbol.
square_size :- a positive integer.
Synopsis:
jordan_block computes the square jordan block matrix J of dimension
square_size.
The entries of J are: J (i, i) = expr for i = 1, . . . , n, J (i, i + 1) = 1 for
i = 1, . . . , n − 1, and all other entries are 0.
x 1 0 0 0
0 x 1 0 0
Examples: jordan_block(x,5) = 0 0 x 1 0
0 0 0 x 1
0 0 0 0 x
Related functions:
diagonal, companion.
35
standard reduce call for differentiation - see REDUCE User’s Manual[2].
672 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.37.3.26 lu_decom
Syntax:
lu_decom(A);
A :- a matrix containing either numeric entries or imaginary entries
with numeric coefficients.
Synopsis:
lu_decom performs LU decomposition on A, ie: it returns {L, U} where
L is a lower diagonal matrix, U an upper diagonal matrix and A = LU.
Caution: The algorithm used can swap the rows of A during the calculation.
This means that LU does not equal A but a row equivalent of it. Due to this,
lu_decom returns {L, U,vec}. The call convert(A,vec) will return
the matrix that has been decomposed, ie: LU = convert(A,vec).
1 3 5
Examples: K = −4 3 7
8 6 4
8 0 0 1 0.75 0.5
lu := lu_decom(K) = −4 6 0 , 0 1 1.5 , [ 3 2 3 ]
1 2.25 1.1251 0 0 1
8 6 4
first lu * second lu = −4 3 7
1 3 5
8 6 4
convert(K,third lu) = −4
3 7
1 3 5
i+1 i+2 i+3
P= 4 5 2
1 i 0
1 0 0
lu := lu_decom(P) = 4 −4 ∗ i + 5 0 ,
i+1 3 0.41463 ∗ i + 2.26829
1 i 0
0 1 0.19512 ∗ i + 0.24390 , [ 3 2 3 ]
0 0 1
673
1 i 0
first lu * second lu = 4 5 2
i+1 i+2 i+3
1 i 0
convert(P, thirdlu) = 4 5 2
i+1 i+2 i+3
Related functions:
cholesky.
16.37.3.27 make_identity
Syntax:
make_identity(square_size);
square_size :- a positive integer.
Synopsis:
make_identity creates the identity matrix of dimension square_size.
1 0 0 0
0 1 0 0
Examples: make_identity(4) = 0 0 1 0
0 0 0 1
Related functions:
diagonal.
Syntax:
matrix_augment({mat1 ,mat2 , ...,matn });36
mat1 ,mat2 , . . . ,matn :- matrices.
Synopsis:
matrix_augment sticks the matrices in matrix_list together hori-
zontally.
matrix_stack sticks the matrices in matrix_list together vertically.
36
If you’re feeling lazy then the {}’s can be omitted.
674 CHAPTER 16. USER CONTRIBUTED PACKAGES
Examples:
1 2 3 1 2 3
matrix_augment({A, A}) = 4
4 6 4 5 6
7 8 9 7 8 9
1 2 3
4 5 6
7 8 9
matrix_stack({A, A}) =
1 2
3
4 5 6
7 8 9
Related functions:
augment_columns, stack_rows, sub_matrix.
16.37.3.29 matrixp
Syntax:
matrixp(test_input);
test_input :- anything you like.
Synopsis:
matrixp is a boolean function that returns t if the input is a matrix and nil
otherwise.
Examples:
matrixp(A) = t
matrixp(doodlesackbanana) = nil
Related functions:
squarep, symmetricp.
16.37.3.30 matrix_stack
See: matrix_augment.
16.37.3.31 minor
Syntax:
minor(A,r,c);
A :- a matrix.
r, c :- positive integers.
675
Synopsis:
minor computes the (r, c)th minor of A.
This is created by removing the rth row and the cth column from A.
4 5
Examples: minor(A, 1, 3) =
7 8
Related functions:
remove_columns, remove_rows.
Syntax:
mult_columns(A,column_list,expr);
A :- a matrix.
column_list :- a positive integer or a list of positive integers.
expr :- an algebraic expression.
Synopsis:
mult_columns returns a copy of A in which the columns specified in
column_list have been multiplied by expr.
mult_rows performs the same task on the rows of A.
Examples:
x 2 3∗x
mult_columns(A, {1, 3}, x) = 4 ∗ x 5 6 ∗ x
7∗x 8 9∗x
1 2 3
mult_rows(A, 2, 10) = 40 50 60
7 8 9
Related functions:
add_to_columns, add_to_rows.
16.37.3.33 mult_rows
See: mult_columns.
16.37.3.34 pivot
Syntax:
pivot(A,r,c);
676 CHAPTER 16. USER CONTRIBUTED PACKAGES
A :- a matrix.
r, c :- positive integers such that A(r, c) 6= 0.
Synopsis:
pivot pivots A about its (r, c)th entry.
To do this, multiples of the r’th row are added to every other row in the
matrix.
This means that the c’th column will be 0 except for the (r,c)’th entry.
−1 −0.5 0
Examples: pivot(A, 2, 3) = 4 5 6
1 0.5 0
Related functions:
rows_pivot.
16.37.3.35 pseudo_inverse
Syntax:
pseudo_inverse(A);
A :- a matrix containing only real numeric entries.
Synopsis:
pseudo_inverse, also known as the Moore-Penrose inverse, computes
the pseudo inverse of A.
Given the singular value decomposition of A, i.e: A = UΣV T , then the
pseudo inverse A† is defined by A† = VΣ† U T . For the diagonal matrix
Σ, the pseudoinverse Σ† is computed by taking the reciprocal of only the
nonzero diagonal elements.
If A is square and non-singular, then A† = A. In general, however,
AA† A = A, and A† AA† = A† .
Perhaps more importantly, A† solves the following least-squares problem:
given a rectangular matrix A and a vector b, find the x minimizing kAx−bk2 ,
and which, in addition, has minimum `2 (euclidean) Norm, kxk2 . This x is
A† b.
Examples:
−0.2 0.1
1 2 3 4 −0.05 0.05
R= , pseudo_inverse(R) =
9 8 7 6 0.1 0
0.25 −0.05
Related functions:
svd.
677
16.37.3.36 random_matrix
Syntax:
random_matrix(r,c,limit);
r, c, limit :- positive integers.
Synopsis:
random_matrix creates an r × c matrix with random entries in the range
−limit < entry < limit.
Switches:
imaginary :- if on, then matrix entries are x + iy where −limit <
x, y < limit.
not_negative :- if on then 0 < entry < limit. In the imaginary case
we have 0 < x, y < limit.
only_integer :- if on then each entry is an integer. In the imaginary
case x, y are integers.
symmetric :- if on then the matrix is symmetric.
upper_matrix :- if on then the matrix is upper triangular.
lower_matrix :- if on then the matrix is lower triangular.
Examples:
−4.729721 6.987047 7.521383
random_matrix(3, 3, 10) = −5.224177 5.797709 −4.321952
−9.418455 −9.94318 −0.730980
Syntax:
remove_columns(A,column_list);
A :- a matrix.
column_list :- either a positive integer or a list of positive integers.
Synopsis:
remove_columns removes the columns specified in column_list from A.
remove_rows performs the same task on the rows of A.
678 CHAPTER 16. USER CONTRIBUTED PACKAGES
Examples:
1 3
remove_columns(A, 2) = 4 6
7 9
remove_rows(A, {1, 3}) = 4 5 6
Related functions:
minor.
16.37.3.38 remove_rows
See: remove_columns.
16.37.3.39 row_dim
See: column_dim.
16.37.3.40 rows_pivot
Syntax:
rows_pivot(A,r,c,{row_list});
A :- a matrix.
r,c :- positive integers such that A(r,c) neq 0.
row_list :- positive integer or a list of positive integers.
Synopsis:
rows_pivot performs the same task as pivot but applies the pivot only
to the rows specified in row_list.
Examples:
1 2 3
4 5 6
N =
7 8 9
1 2 3
4 5 6
1 2 3
4 5 6
rows_pivot(N , 2, 3, {4, 5}) 7
= 8 9
−0.75 0 0.75
−0.375 0 0.375
679
Related functions:
pivot.
16.37.3.41 simplex
Syntax:
simplex(max/min,objective function,{linear inequalities},[{bounds}]);
max/min :- either max or min (signifying maximise and
minimise).
objective function :- the function you are maximising or minimising.
linear inequalities :- the constraint inequalities. Each one must be of
the form sum of variables (<=, =, >=) num-
ber.
bounds :- bounds on the variables as specified for the LP
file format. Each bound is of one of the forms
l ≤ v, v ≤ u, or l ≤ v ≤ u, where v is a
variable and l, u are numbers or infinity or
-infinity
Synopsis:
simplex applies the revised simplex algorithm to find the optimal(either
maximum or minimum) value of the objective function under the linear in-
equality constraints.
It returns {optimal value,{ values of variables at this optimal}}.
The {bounds} argument is optional and admissible only when the switch
fastsimplex is on, which is the default.
Without a {bounds} argument, the algorithm implies that all the variables
are non-negative.
Examples: simplex(max,x+y,{x>=10,y>=20,x+y<=25});
simplex(max,10x+5y+5.5z,{5x+3z<=200,x+0.1y+0.5z<=12,
0.1x+0.2y+0.3z<=9, 30x+10y+50z<=1500});
{525.0,{x=40.0,y=25.0,z=0}}
16.37.3.42 squarep
Syntax:
squarep(A);
680 CHAPTER 16. USER CONTRIBUTED PACKAGES
A :- a matrix.
Synopsis:
squarep is a boolean function that returns t if the matrix is square and nil
otherwise.
Examples:
L= 1 3 5
squarep(A) = t
squarep(L) = nil
Related functions:
matrixp, symmetricp.
16.37.3.43 stack_rows
See: augment_columns.
16.37.3.44 sub_matrix
Syntax:
sub_matrix(A,row_list,column_list);
A :- a matrix.
row_list, column_list :- either a positive integer or a list of positive in-
tegers.
Synopsis:
sub_matrix produces the matrix consisting of the intersection of the rows
specified in row_list and the columns specified in column_list.
2 3
Examples: sub_matrix(A, {1, 3}, {2, 3}) =
8 9
Related functions:
augment_columns, stack_rows.
Syntax:
svd(A);
A :- a matrix containing only real numeric entries.
681
Synopsis:
svd computes the singular value decomposition of A. If A is an m × n real
matrix of (column) rank r, svd returns the 3-element list {U, Σ, V} where
A = UΣV T .
Let k = min(m, n). Then U is m × k, V is n × k, and and Σ =
diag(σ1 , . . . , σk ), where σi ≥ 0 are the singular values of A; only r of
these are non-zero. The singular values are the non-negative square roots of
the eigenvalues of AT A.
U and V are such that UU T = VV T = V T V = Ik .
Note: there are a number of different definitions of SVD in the literature, in
some of which Σ is square and U and V rectangular, as here, but in others U
and V are square, and Σ is rectangular.
Examples:
1 3
Q = −4 3
3 6
0.0236042 0.419897
4.83288 0
svd(Q) = −0.969049 0.232684 ,
,
0 7.52618
0.245739 0.877237
0.959473 0.281799
−0.281799 0.959473
0.959473 0.281799 4.83288 0
svd(TP(Q)) = , ,
−0.281799 0.959473 0 7.52618
0.0236042 0.419897
−0.969049 0.232684
0.245739 0.877237
Syntax:
swap_columns(A,c1,c2);
A :- a matrix.
c1,c1 :- positive integers.
Synopsis:
swap_columns swaps column c1 of A with column c2.
swap_rows performs the same task on 2 rows of A.
682 CHAPTER 16. USER CONTRIBUTED PACKAGES
1 3 2
Examples: swap_columns(A, 2, 3) = 4 6 5
7 9 8
Related functions:
swap_entries.
16.37.3.47 swap_entries
Syntax:
swap_entries(A,{r1,c1},{r2,c2});
A :- a matrix.
r1,c1,r2,c2 :- positive integers.
Synopsis:
swap_entries swaps A(r1,c1) with A(r2,c2).
9 2 3
Examples: swap_entries(A, {1, 1}, {3, 3}) = 4 5 6
7 8 1
Related functions:
swap_columns, swap_rows.
16.37.3.48 swap_rows
See: swap_columns.
16.37.3.49 symmetricp
Syntax:
symmetricp(A);
A :- a matrix.
Synopsis:
symmetricp is a boolean function that returns t if the matrix is symmetric
and nil otherwise.
Examples:
1 2
M=
2 1
symmetricp(A) = nil
symmetricp(M) = t
683
Related functions:
matrixp, squarep.
16.37.3.50 toeplitz
Syntax:
toeplitz({expr1 ,expr2 , ...,exprn }); 37
expr1 ,expr2 , . . . ,exprn :- algebraic expressions.
Synopsis:
toeplitz creates the toeplitz matrix from the expression list.
This is a square symmetric matrix in which the first expression is placed on
the diagonal and the i’th expression is placed on the (i-1)’th sub and super
diagonals.
It has dimension n where n is the number of expressions.
w x y z
x w x y
Examples: toeplitz({w, x, y, z}) = y x w x
z y x w
16.37.3.51 triang_adjoint
Syntax:
triang_adjoint(A);
A :- a matrix.
Examples:
1 0 0
triang_adjoint(A) = −4 1 0
−3 6 −3
1 2 3
F ∗ A = 0 −3 −6
0 0 0
37
If you’re feeling lazy then the {}’s can be omitted.
684 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.37.3.52 Vandermonde
Syntax:
vandermonde({expr1 ,expr2 , . . . ,exprn }); 38
expr1 ,expr2 , . . . ,exprn :- algebraic expressions.
Synopsis:
Vandermonde creates the Vandermonde matrix from the expression list.
(j−1)
This is the square matrix in which the (i, j)th entry is expri . It has
dimension n, where n is the number of expressions.
x2
1 x
Examples: vandermonde({x, 2 ∗ y, 3 ∗ z}) = 1 2 ∗ y 4 ∗ y 2
1 3 ∗ z 9 ∗ z2
16.37.3.53 kronecker_product
Syntax:
kronecker_product(M1 , M2 )
M1 , M2 :- Matrices
Synopsis:
kronecker_product creates a matrix containing the Kronecker product
(also called direct product or tensor product) of its arguments.
Examples: a1 := mat((1,2),(3,4),(5,6))$
a2 := mat((1,1,1),(2,z,2),(3,3,3))$
kronecker_product(a1,a2);
1 1 1 2 2 2
2
z 2 4 2∗z 4
3 3 3 6 6 6
3 3 3 4 4 4
6 3∗z 6 8 4∗z 8
9 9 9 12 12 12
5 5 5 6 6 6
10 5 ∗ z 10 12 6 ∗ z 12
15 15 15 18 18 18
By turning the fast_la switch on, the speed of the following functions will be
increased:
38
If you’re feeling lazy then the {}’s can be omitted.
685
16.37.5 Acknowledgments
Many of the ideas for this package came from the Maple[3] Linalg package [4].
The algorithms for cholesky, lu_decom, and svd are taken from the book
Linear Algebra - J.H. Wilkinson & C. Reinsch[5].
The gram_schmidt code comes from Karin Gatermann’s Symmetry package[6]
for REDUCE.
Bibliography
[3] Bruce W. Char. . . [et al.]: Maple (Computer Program). Springer-Verlag (1991)
A := {a1,a2,a3,a4};
B := {b1,b2,b3,b4};
c1*A + c2*B;
{a1*c1 + b1*c2,
a2*c1 + b2*c2,
a3*c1 + b3*c2,
a4*c1 + b4*c2}
{a,b,c}/{3,g,5};
a b c
{---,---,---}
3 g 5
ws^3;
3 3 3
a b c
{----,----,-----}
27 3 125
g
{a,b,c,d} *. {5,7,9,11/d};
For accessing list elements, the new operator _ (lnth) can be used instead of the
PART operator:
l := {1,{2,3},4}$
lnth(l,3);
l _2*3;
{6,9}
l _2 _2;
It can also be used to modify a list (unlike PART, which returns a modified list):
part(l,2,2):=three;
{1,{2,three},4}
l;
{1,{2,3},4}
l _ 2 _2 :=three;
three
l;
{1,{2,three},4}
a *. log b;
{ - sin(x), - 6*sin(y)*x}
688 CHAPTER 16. USER CONTRIBUTED PACKAGES
{ - cos(x),sin(x)}
listproc spat3(u,v,w);
begin scalar x,y;
x := u *. w;
y := u *. v;
return v*x - w*y
end;
689
16.39.1 Introduction
Consider now the set F [∂x1 , . . . , ∂xn ], where the derivations are used as variables.
This set forms a non-commutative linear partial differential operator ring with
pointwise addition, and multiplication defined as follows: For f ∈ F and ∂xi ,
∂xj ∈ ∆ we have for any g ∈ F that
Here “ · ” denotes the multiplication in F . From (16.90) and (16.88) it follows that
∂xi ∂xj = ∂xj ∂xi , and using (16.89) and (16.87) the following commutator can be
proved:
D = D1 · · · Dr ∈ F [∂x1 , . . . , ∂xn ]
into multiplicative factors, each of which is an LPDO Di of order greater than 0 and
less than k. If such a factorization exists, then D is called reducible or factorable,
else irreducible.
690 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.39.2 Operators
16.39.2.1 partial
16.39.2.2 ***
input: a()***partial(y)***b()***partial(x);
Here the F-elements are polynomials, where the unknowns are of the type constant-
operator denoting functions from F :
hconstant-operatori → hidi ( )
We do not admit division of such constant operators since we cannot exclude that
such a constant operator denotes 0.
691
The operator notation on the one hand emphasizes the fact that the denoted el-
ements are functions. On the other hand it distinguishes a() from the variable
a of a rational function, which specifically denotes the corresponding projection.
Consider e.g.
input: (x+y)***partial(y)***(x-y)***partial(x);
2 2
(x - y ) *** partial(x) *** partial(y) + ( - x - y) *** partial(x)
16.39.2.3 diff
In our example with constant operators, the transformation into normal form in-
troduces a formal derivative operation diff(·,·,·), which cannot be evaluated.
Notice that we do not use the Reduce operator df(·,·,·) here, which for technical
reasons cannot smoothly handle our constant operators.
In our second example with rational functions as F-elements, derivative occurring
with commutation can be computed such that diff does not occur in the output.
16.39.3.1 lpdoset
We give an example for a shape that fixes all constant operators to denote generic
bivariate affine linear functions:
input: d := (a()+b())***partial(x1)***partial(x2)**2;
2
d := (a() + b()) *** partial(x1) *** partial(x2)
{-1}
input: d;
2
692 CHAPTER 16. USER CONTRIBUTED PACKAGES
(a00 + a01*x2 + a10*x1 + b00 + b01*x2 + b10*x1) *** partial(x1) *** partial(x2)
Notice that the placeholder # must be escaped with !, which is a general conven-
tion for Rlisp/Reduce. Notice that lpdoset returns the old shape and that {-1}
denotes the default state that there is no shape selected.
16.39.3.2 lpdoweyl
input: lpdoweyl(2,x1,x2);
2 2
{#_00_ + #_01_*x2 + #_02_*x2 + #_10_*x1 + #_11_*x1*x2 + #_20_*x1 ,x1,x2}
input: d;
2 2
(a_00_ + a_01_*x2 + a_02_*x2 + a_10_*x1 + a_11_*x1*x2 + a_20_*x1 + b_00_
2 2
+ b_01_*x2 + b_02_*x2 + b_10_*x1 + b_11_*x1*x2 + b_20_*x1 ) *** partial(x1)
2
*** partial(x2)
16.39.4 Commands
16.39.4.1 General
input: lpdoord((a()+b())***partial(x1)***partial(x2)**2+3***partial(x1));
input: lpdoptl(a()***partial(x1)***partial(x2)+partial(x4)+diff(a(),x3,1));
{partial(x1),partial(x2),partial(x4)}
693
input: lpdogp(a,{x1,x2},2);
2 2
a_00_ + a_01_*x2 + a_02_*x2 + a_10_*x1 + a_11_*x1*x2 + a_20_*x1
input: lpdogdp(a,{x1,x2},2);
2 2
a_20_ *** partial(x1) + a_02_ *** partial(x2)
16.39.4.2 Symbols
input: lpdosym((a()+b())***partial(x1)***partial(x2)**2+3***partial(x1));
2
y_x1_*y_x2_ *(a() + b())
More generally, one can use a second optional arguments to specify a the order of
a different differential monomial to form the symbol of:
input: lpdosym((a()+b())***partial(x1)***partial(x2)**2+3***partial(x1),1);
3*y_x1_
Finally, a third optional argument can be used to specify an alternative starting sym-
bol for the commutative variable, which is y by default. Altogether, the optional
arguments default like lpdosym(·)=lpdosym(·,lpdoord(·),y).
694 CHAPTER 16. USER CONTRIBUTED PACKAGES
input: d := a()***partial(x1)***partial(x2)+partial(x3)$
input: s := lpdosym d;
s := a()*y_x1_*y_x2_
input: lpdosym2dp s;
input: p := a()***partial(x1)+b()$
input: q := c()***partial(x1)+d()***partial(x2)$
input: lpdos(p,q,1);
+ b()*d()*y_x2_
16.39.4.3 Factorization
2 2
bk := partial(x) - partial(y) + a10 *** partial(x) + a01 *** partial(y)
695
2 2
- a01 + a10
+ ----------------
4
{{true,
a01 - a10
{ - partial(x) - partial(y) + -----------,
2
- a01 - a10
- partial(x) + partial(y) + --------------}}}
2
If the result is the empty list, then this guarantees that there is no approximate fac-
torization possible. In general it is possible to obtain several sample factorizations.
Note, however, that the result does not provide a complete list of possible factor-
izations with a left factor of order 1 but only at least one such sample factorization
in case of reducibility.
Furthermore, the procedure might fail due to polynomial degrees exceeding cer-
tain bounds for the extended quantifier elimination by virtual substitution used in-
ternally. In this case there is the identifier failed returned. This must not be
confused with the empty list indicating irreducibility as described above.
Besides
1. the LPDO d,
2. An LPDO of order 1, which serves as a template for the left (linear) factor.
The default is a generic linear LPDO with generic coefficient functions ac-
cording from the ground field specified via lpdoset. The principle idea is
to support the factorization by guessing that certain differential monomials
are not present.
3. An LPDO of order ord(d)−1, which serves as a template for the right factor.
Similarly to the previous argument the default is fully generic.
696 CHAPTER 16. USER CONTRIBUTED PACKAGES
{{true,
a01 - a10
{p_00_00_ = -----------,
2
- a01 - a10
q_00_00_ = --------------,
2
The result of the extended quantifier elimination provides coefficient values for
generic factor polynomials p and q. These are automatically interpreted and con-
verted into differential polynomials by lpdofactorize.
input: f2 := partial(x1)***partial(x2) + 1$
If the result is the empty list, then this guarantees that there is no approximate
factorization possible. In our example we happen to obtain two possible factor-
izations. Note, however, that the result in general does not provide a complete
list of factorizations with a left factor of order 1 but only at least one such sample
factorization.
Furthermore, the procedure might fail due to polynomial degrees exceeding certain
bounds for the extended quantifier elimination by virtual substitution used inter-
nally. If this happens, the corresponding Ai will contain existential quantifiers ex,
and Li will be meaningless.
Da sollte besser ein failed kommen ...
The first of the two subresults above has the semantics that ∂x1 ∂x2 is an approxi-
mate factorization of f2 for all ε ≥ 1. Formally, ||f2 − ∂x1 ∂x2 || ≤ ε for all ε ≥ 1,
which is equivalent to ||f2 − ∂x1 ∂x2 || ≤ 1. That is, 1 is an upper bound for the ap-
proximation error over R2 . Where there are two possible choices for the seminorm
|| · ||:
1. ...
2. ...
1. the LPDO d,
3., 4. An LPDO of order 1, which serves as a template for the left (linear) factor,
and an LPDO of order ord(d) − 1, which serves as a template for the right
factor. See the documentation of lpdofactorize for defaults and details.
input: lpdofactorizex(f3,psi1,a()***partial(x1),b()***partial(x2));
lpdohrect
lpdohcirc
699
This package supports solve (M_SOLVE) and roots (M_ROOTS) operators for
modular polynomials and modular polynomial systems. The moduli need not be
primes. M_SOLVE requires a modulus to be set. M_ROOTS takes the modulus as
a second argument. For example:
on modular; setmod 8;
m_solve(2x=4); -> {{X=2},{X=6}}
m_solve({x^2-y^3=3});
-> {{X=0,Y=5}, {X=2,Y=1}, {X=4,Y=5}, {X=6,Y=1}}
m_solve({x=2,x^2-y^3=3}); -> {{X=2,Y=1}}
off modular;
m_roots(x^2-1,8); -> {1,3,5,7}
m_roots(x^3-x,7); -> {0,1,6}
which, by its very definition can only have one of the values {−1, 0, 1}.
There is no further documentation for this package.
Author: Herbert Melenk.
700 CHAPTER 16. USER CONTRIBUTED PACKAGES
This package arises from the PhD thesis of Dominik Gruntz, of the ETH Zürich.
He developed a new algorithm to compute limits of "exp-log" functions. Many of
the examples he gave were unable to be computed by the present limits package in
REDUCE, the simplest example being the following, whose limit is obviously 0:
load limits;
limit(x^7/e^x,x,infinity);
7
x
limit(----,x,infinity)
x
e
This particular problem arises, because L’Hopital’s rule for the computation of
∞
indefinite forms (such as 0/0, or ∞ ) can only be applied in a CAS a finite num-
ber of times, and in REDUCE, this number is 3. Applied 7 times to the above
problem would have yielded the correct answer 0. The new algorithm solves this
particular problem, and enables the computation of many more limit calculations
in REDUCE. We first define the domain in which we work, and then give a state-
ment of the main algorithm that is used in this package.
Definition:
Let <[x] be the ring of polynomials in x with real coefficients, and let f be an
element in this ring. The field which is obtained from <[x] by closing it under the
operations f → exp(f ) and f → log |f | is called the L- field (or logarithmico-
exponential field, or field of exp-log functions for short).
with:
f (x) = ex ∗ log(log(x))
log(log(x + e−x ))
f (x) =
ex2 + log(log(x))
f (x) = log(x)log(x)
f (x) = ex∗log(x)
• Let f (ω) be the function obtained from f (x) by replacing all elements of Ω
by their representation in terms of ω. Consider all expressions independent
of ω as constants and compute the leading term of the power series of f(ω)
around ω = 0+
• If the leading exponent e0 > 0, then the limit is 0, and we stop. If the leading
exponent e0 < 0 then the limit is ±∞. The sign is defined by the sign of the
leading coefficient c0 . If the leading exponent e0 = 0 then the limit is the
limit of the leading coeficient c0 . If c0 6∈ C, where C = Const(L), the set of
exp-log constants, we apply the same algorithm recursively on c0 .
The algorithm to compute the most rapidly varying subset (the mrv set) of a func-
tion f is given below:
procedure mrv(f)
if (not (depend(f,x))) → return ({})
else if f = x → return({x})
else if f = gh → return(max(mrv(g),mrv(h)))
else if f = g + h → return(max(mrv(g),mrv(h)))
else if f = g c and c ∈ C → return(mrv(g))
702 CHAPTER 16. USER CONTRIBUTED PACKAGES
The function max() computes the maximum of the two sets of expressions. Max()
compares two elements of its argument sets and returns the set which is in the
higher comparability class or the union of both if they have the same order of vari-
ation.
For further details, proofs and explanations of the algorithm, please consult [Grn96].
For example, we have
mrv(ex ) = {ex }
mrv(log(log(log(x + x2 + x3 )))) = {x}
mrv(x) = {x}
mrv(ex + e−x + x2 + x log(x)) = {ex , e−x }
−x
mrv(ee ) = {e−x }
mrv_limit(e^x,x,infinity);
infinity
mrv_limit(1/log(x),x,infinity);
b:=e^x*(e^(1/x-e^-x)-e^(1/x));
-1 - x
x + x - e
b := e * (e - 1)
mrv_limit(b,x,infinity);
703
-1
-1
ex:= - log(log(log(log(x))) + log(x)) *log(x)
off mcd;
mrv_limit(ex,x,infinity);
(log(x+e^-x)+log(1/x))/(log(x)*e^x);
- x -1 -1 - x
e * log(x) * (log(x ) + log(e + x));
mrv_limit(ws,x,infinity);
mrv_limit((log(x)*e^-x)/e^(log(x)+e^(x^2)),x,infinity);
The package provides a means of tracing the mrv_limit function at its main steps,
and is intended to help the user if he encounters problems. Messages are displayed
informing the user which Taylor expansion is being computed, all recursive calls
are listed, and the value returned by the mrv function is given. This information
is displayed when a switch tracelimit is on. This is off by default, but can be
704 CHAPTER 16. USER CONTRIBUTED PACKAGES
on tracelimit;
For a more complete examination of the workings of the algorithm, the user could
also try the command
tr mrv_limit;
This is not recommended, as the amount of information returned is often huge and
difficult to wade through. Here is a simple example in REDUCE:
1: load mrvlimit;
2: on tracelimit;
3: mrv_limit(e^x,x,infinity);
mrv_f is {x}
x
After move_up, f is e
-1
performing taylor on: ww
-1
series expansion is ww
-1
series is ww
x
mrv_f is {e }
h is x
705
mrv_f is {x}
x
After move_up, f is e
-1
performing taylor on: ww
-1
series expansion is ww
-1
series is ww
- x
small has been changed to e
-1
After substitution to ww, f is ww
-1
performing taylor on: ww
-1
series expansion is ww
-1
series is ww
infinity
Note that, due to the recursiveness of the functions mrv and mrv_limit, many
706 CHAPTER 16. USER CONTRIBUTED PACKAGES
calls to each function are made, and information is given on all calls when the
tracelimit switch is on.
Bibliography
[Red36] Hearn, Anthony C. and Fitch, John F. REDUCE User’s Manual 3.6,
RAND Corporation, 1995
This package allows the user to set up automatically a consistent environment for
computing in an algebra where the non–commutativity is defined by Lie-bracket
commutators. The package uses the REDUCE noncom mechanism for elementary
polynomial arithmetic; the commutator rules are automatically computed from the
Lie brackets.
Authors: Herbert Melenk and Joachim Apel.
16.42.1 Introduction
REDUCE supports a very general mechanism for computing with objects under a
non–commutative multiplication, where commutator relations must be introduced
explicitly by rule sets when needed. The package NCPOLY allows you to set
up automatically a consistent environment for computing in an algebra where the
non–commutativity is defined by Lie-bracket commutators. The package uses the
REDUCE noncom mechanism for elementary polynomial arithmetic; the commu-
tator rules are automatically computed from the Lie brackets. You can perform
polynomial arithmetic directly, including division and factorization. Additionally
NCPOLY supports computations in a one sided ideal (left or right), especially one
sided Gröbner bases and polynomial reduction.
Before the computations can start the environment for a non–commutative compu-
tation must be defined by a call to nc_setup:
nc_setup(<vars>[,<comms>][,<dir>]);
707
where
< vars > is a list of variables; these must include the non–commutative quantities.
< comms > is a list of equations <u>*<v> - <v>*<u>=<rh> where < u >
and < v > are members of < vars >, and < rh > is a polynomial.
< dir > is either lef t or right selecting a left or a right one sided ideal. The initial
direction is lef t.
nc_setup generates from < comms > the necessary rules to support an algebra
where all monomials are ordered corresponding to the given variable sequence.
All pairs of variables which are not explicitly covered in the commutator set are
considered as commutative and the corresponding rules are also activated.
The second parameter in nc_setup may be omitted if the operator is called for
the second time, e.g. with a reordered variable sequence. In such a case the last
commutator set is used again.
Remarks:
• The variables need not be declared noncom - nc_setup performs all neces-
sary declarations.
• The commands order and korder should be avoided because nc_setup sets
these such that the computation results are printed in the correct term order.
Example:
nc_setup({KK,NN,k,n},
{NN*n-n*NN= NN, KK*k-k*KK= KK});
• in a total degree ordering the total degree of < rh > may be not higher than
1,
• in an elimination degree order (e.g. lex) all variables in < rh > must be
below the minimum of < u > and < v >.
• If < rh > does not contain any variables or has at most < u > or < v >,
any term order can be selected.
nc_cleanup;
without parameters. It removes all internal rules and definitions which nc_setup
had introduced. To reactive non–commutative call nc_setup again.
nc_groebner(<plist>);
Note that the variable set and variable sequence must be defined before in the
nc_setup call. The term order for the Gröbner calculation can be set by using the
torder declaration. The internal steps of the Gröbner calculation can be watched
709
by setting the switches trgroeb (=list all internal basis polynomials) or trgroebs
(=list additionally the S-polynomials) 39 .
For details about torder, trgroeb and trgroebs see the REDUCE GROEBNER
manual.
2: nc_setup({k,n,NN,KK},{NN*n-n*NN=NN,KK*k-k*KK=KK},left);
3: p1 := (n-k+1)*NN - (n+1);
p1 := - k*nn + n*nn - n + nn - 1
4: p2 := (k+1)*KK -(n-k);
p2 := k*kk + k - n + kk
5: nc_groebner ({p1,p2});
{k*nn - n*nn + n - nn + 1,
k*kk + k - n + kk,
Important: Do not use the operators of the GROEBNER package directly as they
would not consider the non–commutative multiplication.
The operator nc_divide computes the one sided quotient and remainder of two
polynomials:
nc_divide(<p1>,<p2>);
The result is a list with quotient and remainder. The division is performed as a
pseudo–division, multiplying < p1 > by coefficients if necessary. The result {<
q >, < r >} is defined by the relation
< c > ∗ < p1 >=< q > ∗ < p2 > + < r > for direction lef t and
< c > ∗ < p1 >=< p2 > ∗ < q > + < r > for direction right,
39
The command lisp(!*trgroebfull:=t); causes additionally all elementary polynomial
operations to be printed.
710 CHAPTER 16. USER CONTRIBUTED PACKAGES
where < c > is an expression that does not contain any of the ideal variables, and
the leading term of < r > is lower than the leading term of < p2 > according to
the actual term order.
For the computation of the one sided remainder of a polynomial modulo a given
set of other polynomials the operator nc_preduce may be used:
nc_preduce(<polynomial>,<plist>);
The result of the reduction is unique (canonical) if and only if < plist > is a one
sided Gröbner basis. Then the computation is at the same time an ideal membership
test: if the result is zero, the polynomial is member of the ideal, otherwise not.
16.42.7 Factorization
16.42.7.1 Technique
nc_factorize(<polynomial>);
The result is a list of factors of < polynomial >. A list with the input expression
is returned if it is irreducible.
As non–commutative factorization is not unique, there is an additional operator
which computes all possible factorizations
nc_factorize_all(<polynomial>);
The result is a list of factor decompositions of < polynomial >. If there are no
factors at all the result list has only one member which is a list containing the input
polynomial.
tors in special context, e.g. factors with a limited degree or factors which contain
only explicitly specified variables:
left_factor(<polynomial>[,<deg>[,<vars>]])
right_factor(<polynomial>[,<deg>[,<vars>]])
left_factors(<polynomial>[,<deg>[,<vars>]])
right_factors(<polynomial>[,<deg>[,<vars>]])
where < polynomial > is the form under investigation, < vars > is an optional
list of variables which must appear in the factor, and < deg > is an optional
integer degree bound for the total degree of the factor, a zero for an unbounded
search, or a monomial (product of powers of the variables) where each exponent is
an individual degree bound for its base variable; unmentioned variables are allowed
in arbitrary degree. The operators ∗_f actor stop when they have found one factor,
while the operators ∗_f actors select all one–sided factors within the given range.
If there is no factor of the desired type, an empty list is returned by ∗_f actors
while the routines ∗_f actor return the input polynomial.
The share variable nc_f actor_time sets an upper limit for the time to be spent
for a call to the non–commutative factorizer. If the value is a positive integer,
a factorization is terminated with an error message as soon as the time limit is
reached. The time units are milliseconds.
The factorizer internally uses solve, which is controlled by the REDUCE switch
varopt. This switch (which per default is set on) allows, to reorder the variable
sequence, which is favourable for the normal system. It should be avoided to set
varopt of f , when using the non–commutative factorizer, unless very small poly-
nomials are used.
nc_compact(<polynomial>)
collects the coefficients to the powers of the lowest possible non-commutative vari-
able.
712 CHAPTER 16. USER CONTRIBUTED PACKAGES
load ncpoly;
nc_setup({n,NN},{NN*n-n*NN=NN})$
p1 := n**4 + n**2*nn + 4*n**2 + 4*n*nn + 4*nn + 4;
4 2 2
p1 := n + n *nn + 4*n + 4*n*nn + 4*nn + 4
nc_compact p1;
2 2 2
(n + 2) + (n + 2) *nn
713
This package contains routines for computing the following normal forms of ma-
trices:
• smithex_int
• smithex
• frobenius
• ratjordan
• jordansymbolic
• jordan.
16.43.1 Introduction
When are two given matrices similar? Similar matrices have the same trace, deter-
minant, characteristic polynomial, and eigenvalues, but the matrices
0 1 0 0
U= and V =
0 0 0 0
are the same in all four of the above but are not similar. Otherwise there could exist
a nonsingular N ∈M2 (the set of all 2 × 2 matrices) such that U = N VN −1 =
N 0 N −1 = 0 , which is a contradiction since U 6= 0 .
Two matrices can look very different but still be similar. One approach to deter-
mining whether two given matrices are similar is to compute the normal form of
them. If both matrices reduce to the same normal form they must be similar.
NORMFORM is a package for computing the following normal forms of matrices:
- smithex
- smithex_int
- frobenius
- ratjordan
- jordansymbolic
- jordan
By default all calculations are carried out in Q (the rational numbers). For
smithex, frobenius, ratjordan, jordansymbolic, and jordan, this
field can be extended. Details are given in the respective sections.
The frobenius, ratjordan, and jordansymbolic normal forms can also
be computed in a modular base. Again, details are given in the respective sections.
The algorithms for each routine are contained in the source code.
NORMFORM has been converted from the normform and Normform packages
written by T.M.L. Mulders and A.H.M. Levelt. These have been implemented
in Maple [4].
Function
smithex(A, x) computes the Smith normal form S of the matrix A.
It returns {S, P, P −1 } where S, P, and P −1 are such that PSP −1 = A.
A is a rectangular matrix of univariate polynomials in x.
x is the variable name.
Field extensions
Calculations are performed in Q. To extend this field the ARNUM package
can be used. For details see subsection 16.43.8.
• The Smith normal form is obtained by doing elementary row and col-
umn operations. This includes interchanging rows (columns), multi-
plying through a row (column) by −1, and adding integral multiples of
one row (column) to another.
715
• Although the rank and determinant can be easily obtained from S, this
is not an efficient method for computing these quantities except that this
may yield a partial factorization of det(A) without doing any explicit
factorizations.
Example:
load_package normform;
x x+1
A=
0 3 ∗ x2
1 0 1 0 x x+1
smithex(A, x) = , ,
0 x3 3 ∗ x2 1 −3 −3
16.43.3 smithex_int
Function
Given an n by m rectangular matrix A that contains only integer entries,
smithex_int(A) computes the Smith normal form S of A.
It returns {S, P, P −1 } where S, P, and P −1 are such that PSP −1 = A.
• The Smith normal form is obtained by doing elementary row and col-
umn operations. This includes interchanging rows (columns), multi-
plying through a row (column) by −1, and adding integral multiples of
one row (column) to another.
Example
716 CHAPTER 16. USER CONTRIBUTED PACKAGES
load_package normform;
9 −36 30
A = −36 192 −180
30 −180 180
3 0 0 −17 −5 −4 1 −24 30
smithex_int(A) = 0 12 0 , 64 19 15 , −1 25 −30
0 0 60 −50 −15 −12 0 −1 1
16.43.4 frobenius
Function
frobenius(A) computes the Frobenius normal form F of the matrix A.
It returns {F, P, P −1 } where F, P, and P −1 are such that PF P −1 = A.
A is a square matrix.
Field extensions
Calculations are performed in Q. To extend this field the ARNUM package
can be used. For details see subsection 16.43.8
Modular arithmetic
frobenius can be calculated in a modular base. For details see subsection
16.43.9.
where the C(pi )’s are companion matrices associated with polynomials
p1 , p2 , . . . , pk , with the property that pi divides pi+1 for i = 1 . . . k −1.
All unmarked entries are zero.
• The Frobenius normal form defined in this way is unique (ie: if we
require that pi divides pi+1 as above).
Example
717
load_package normform;
−x2 +y 2 +y −x2 +x+y 2 −y
!
y y
A= −x2 −x+y 2 +y −x2 +x+y 2 −y
y y
frobenius(A) =
x∗(x2 −x−y 2 +y) −x2 +y 2 +y −x2 +y 2 +y
( ! ! !)
0 y 1 y 1 x2 +x−y 2 −y
−2∗x2 +x+2∗y 2
, −x2 −x+y 2 +y
, −y
1 y 0 y
0 x2 +x−y 2 −y
16.43.5 ratjordan
Function
ratjordan(A) computes the rational Jordan normal form R of the matrix
A.
It returns {R, P, P −1 } where R, P, and P −1 are such that PRP −1 = A.
A is a square matrix.
Field extensions
Calculations are performed in Q. To extend this field the ARNUM package
can be used. For details see subsection 16.43.8.
Modular arithmetic
ratjordan can be calculated in a modular base. For details see subsection
16.43.9.
where there are eij times C(p) blocks along the diagonal and C(p) is
the companion matrix associated with the irreducible polynomial p. All
unmarked entries are zero.
Example
load_package normform;
x+y 5
A=
y x2
ratjordan(A) =
−(x+y)
( ! ! !)
0 −x3 − x2 ∗ y + 5 ∗ y 1 x+y 1 y
, , 1
1 x2 + x + y 0 y 0 y
16.43.6 jordansymbolic
Function
jordansymbolic(A) computes the Jordan normal form J of the matrix
A.
It returns {J , L, P, P −1 }, where J , P, and P −1 are such that PJ P −1 =
A. L = {ll, ξ}, where ξ is a name and ll is a list of irreducible factors of
p(ξ).
A is a square matrix.
Field extensions
Calculations are performed in Q. To extend this field the ARNUM package
can be used. For details see subsection 16.43.8.
Modular arithmetic
jordansymbolic can be calculated in a modular base. For details see
subsection 16.43.9.
Extras
If using xr, the X interface for REDUCE, the appearance of the output can
be improved by setting the switch looking_good to on. This converts
all lambda to ξ and improves the indexing, e.g., lambda12 ⇒ ξ12 . The
example below shows the output when this switch is on.
Synopsis • A Jordan block k (λ) is a k by k upper triangular matrix of the
form:
λ 1
λ 1
k (λ) =
.. ..
. .
λ 1
λ
719
jordansymbolic(A) =
ξ11 0
, −y 3 + ξ 2 − 4 ∗ ξ + 3 , ξ ,
0 ξ12
ξ11 −2 ξ11 +y 3 −1
! !)
ξ11 − 3 ξ12 − 3 2∗(y 3 −1) 2∗y 2 ∗(y 3 +1)
, ξ12 −2 ξ12 +y 3 −1
y2 y2 2∗(y 3 −1) 2∗y 2 ∗(y 3 +1)
solve(-yˆ3+xiˆ2-4*xi+3,xi);
p p
{ξ = y 3 + 1 + 2, ξ = − y 3 + 1 + 2}
J = sub({xi(1,1)=sqrt(yˆ3+1)+2, xi(1,2)=-sqrt(yˆ3+1)+2},
first jordansymbolic (A))
p !
y3 + 1 + 2 0
J = p
0 − y3 + 1 + 2
For a similar example ot this in standard REDUCE (ie: not using xr), see
the normform.rlg file.
720 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.43.7 jordan
Function
jordan(A) computes the Jordan normal form J of the matrix A.
It returns {J , P, P −1 }, where J , P, and P −1 are such that PJ P −1 = A.
A is a square matrix.
Field extensions
Calculations are performed in Q. To extend this field the ARNUM package
can be used. For details see subsection 16.43.8.
Note
In certain polynomial cases the switch fullroots is turned on to compute
the zeroes. This can lead to the calculation taking a long time, as well as the
output being very large. In this case a message
***** WARNING: fullroots turned on. May take a while.
will be printed. It may be better to kill the calculation and compute
jordansymbolic instead.
Synopsis • The Jordan normal form J with entries in an algebraic extension
of Q is computed.
• A Jordan block k (λ) is a k by k upper triangular matrix of the form:
λ 1
λ 1
k (λ) =
.. ..
. .
λ 1
λ
There are k − 1 terms “+1” in the superdiagonal; the scalar λ appears
k times on the main diagonal. All other matrix entries are zero, and
1 (λ) = (λ).
• A Jordan matrix J ∈ Mn (the set of all n by n matrices) is a direct
sum of jordan blocks.
n1 (λ1 )
n2 (λ2 )
J = , n1 + n2 + · · · + nk = n
..
.
nk (λk )
in which the orders ni may not be distinct and the values λi need not
be distinct.
• Here λ is a zero of the characteristic polynomial p of A. The zeroes of
the characteristic polynomial are computed exactly, if possible. Other-
wise they are approximated by floating point numbers.
721
Example
load_package normform;
−9 −21 −15 4 2 0
−10 21 −14 4 2 0
−8 16 −11 4 2 0
A= −6
12 −9 3 3 0
−4 8 −6 0 5 0
−2 4 −3 0 1 3
J = first jordan(A);
3 0 0 0 0 0
0 3 0 0 0 0
0 0 1 1 0 0
J =
0
0 0 1 0 0
0 0 0 0 i+2 0
0 0 0 0 0 −i + 2
16.43.8.1 Example
load_package normform;
load_package arnum;
defpoly sqrt2**2-2;
722 CHAPTER 16. USER CONTRIBUTED PACKAGES
√
(sqrt2 now changed to 2 for looks!)
√ √ √
4 ∗ √2 − 6 −4 ∗ √2 + 7 −3 ∗ √2 + 6
A = 3 ∗ 2√− 6 −3 ∗ 2√ + 7 −3 ∗ 2√+ 6
3∗ 2 1−3∗ 2 −2 ∗ 2
√
2 √0 0
ratjordan(A) = 0 2 0
√
,
0 0 −3 ∗ 2 + 1
√ √ √
−21∗ 2+18
7 ∗ 2 − 6 2∗ 31 2−49
31
√ √ √
3 ∗ 2 − 6 21∗ 2−18 −21∗ 2+18 ,
31 √31
√ √
−3∗ 2+24 3∗ 2−24
3∗ 2+1 31 31
√
0 √2+1 1√
−1 4 ∗ 2 + 9 4 ∗ 2
√
−1 − 16 ∗ 2 + 1 1
16.43.9.1 Example
load_package normform;
on modular;
setmod 23;
10 18
A=
17 20
jordansymbolic(A) =
18 0 15 9 1 14
, {{λ + 5, λ + 11} , λ} , ,
0 12 22 1 1 15
723
on balanced_mod;
jordansymbolic(A) =
−5 0 −8 9 1 −9
, {{λ + 5, λ + 11} , λ} , ,
0 −11 −1 1 1 −8
Bibliography
[1] T.M.L.Mulders and A.H.M. Levelt: The Maple normform and Normform pack-
ages. (1993)
[3] Roger A. Horn and Charles A. Johnson: Matrix Analysis. Cambridge Univer-
sity Press (1990)
[4] Bruce W. Chat. . . [et al.]: Maple (Computer Program). Springer-Verlag (1991)
num_min(sin(x)+x/5, x);
• numerical quadrature
16.44.1 Syntax
Intervals are generally coded as lower bound and upper bound connected by the
operator ‘..’, usually associated to a variable in an equation. E.g.
x= (2.5 .. 3.5)
725
means that the variable x is taken in the range from 2.5 up to 3.5. Note, that the
bounds can be algebraic expressions, which, however, must evaluate to numeric
results. In cases where an interval is returned as the result, the lower and upper
bounds can be extracted by the PART operator as the first and second part respec-
tively. A starting point is specified by an equation with a numeric righthand side,
e.g.
x=3.0
16.44.1.3 tracing
Normally the algorithms produce only a minimum of printed output during their
operation. In cases of an unsuccessful or unexpected long operation a trace of the
iteration can be printed by setting
on trnumeric;
16.44.2 Minima
The Fletcher Reeves version of the steepest descent algorithms is used to find
the minimum of a function of one or more variables. The function must have
continuous partial derivatives with respect to all variables. The starting point of
the search can be specified; if not, random values are taken instead. The steepest
descent algorithms in general find only local minima.
Syntax:
Examples:
num_min(sin(x)+x/5, x);
{4.9489585606,{X=29.643767785}}
num_min(sin(x)+x/5, x=0);
{ - 1.3342267466,{X= - 1.7721582671}}
{0.00000021870228295,{X1=0.99953284494,X2=0.99906807238}}
Syntax:
Example:
{X= - 1.8561957251,Y=2.856195584}
jacobian;
[COS(X) SIN(Y)]
[ ]
[ 1 1 ]
16.44.4 Integrals
For the numerical evaluation of univariate integrals over a finite interval the fol-
lowing strategy is used:
For multivariate integrals only the adaptive quadrature is used. This algorithm tol-
erates isolated singularities. The value iterations here limits the number of local
interval intersection levels. Accuracy is a measure for the relative total discretiza-
tion error (comparison of order 1 and order 2 approximations).
Syntax:
Example:
2.0000010334
Example:
{{0.0,1.0},{0.2,1.2214},{0.4,1.49181796},{0.6,1.8221064563},
{0.8,2.2255208258},{1.0,2.7182511366}}
Remarks:
– If in exp the differential is not isolated on the lefthand side, please ensure
that the dependent variable is explicitly declared using a DEPEND statement,
e.g.
depend y,x;
– The REDUCE package SOLVE is used to convert the form into an explicit
ODE. If that process fails or has no unique result, the evaluation is stopped
with an error message.
730 CHAPTER 16. USER CONTRIBUTED PACKAGES
Upper and lower bounds of a real valued function over an interval or a rectangu-
lar multivariate domain are computed by the operator BOUNDS. The algorithmic
basis is the computation with inequalities: starting from the interval(s) of the vari-
ables, the bounds are propagated in the expression using the rules for inequality
computation. Some knowledge about the behavior of special functions like ABS,
SIN, COS, EXP, LOG, fractional exponentials etc. is integrated and can be eval-
uated if the operator BOUNDS is called with rounded mode on (otherwise only
algebraic evaluation rules are available).
If BOUNDS finds a singularity within an interval, the evaluation is stopped with
an error message indicating the problem part of the expression.
Syntax:
BOUNDS (exp, var1 = (l1 ..u1 )[, var2 = (l2 ..u2 ) . . .])
BOUNDS (exp, {var1 = (l1 ..u1 )[, var2 = (l2 ..u2 ) . . .]})
where exp is the function to be investigated,
var1 , var2 , . . . are the variables of exp,
l1 , l2 , . . . and u1 , u2 , . . . specify the area (intervals).
BOU N DS computes upper and lower bounds for the expression in the
given area. An interval is returned.
Example:
{-1,1}
on rounded;
bounds(sin x,x=(1 .. 2));
0.84147098481 .. 1
bounds(x**2+x,x=(-0.5 .. 0.5));
- 0.25 .. 0.75
731
Example:
on rounded;
3 2
w := {0.03824*x - 0.2398*x + 0.06514*x + 0.9778,
{0.8991,-0.4066,-0.005198,0.009464,-0.00009511}}
0.4111
The result is a list containing as first element the function which approximates the
given values, and as second element a list of coefficients which were used to build
this function from the basis.
Example:
num_fit(vals,{1,x,x**2},x=pts);
2
{14.571428571*X - 61.428571429*X + 54.6,{54.6,
- 61.428571429,14.571428571}}
num_fit(vals,{1,x,x**2,x**3,x**4},x=pts);
733
4 3
{2.2083333234*X - 20.249999879*X
2
+ 67.791666154*X - 93.749999133*X
+ 44.999999525,
{44.999999525, - 93.749999133,67.791666154,
- 20.249999879,2.2083333234}}
The following procedures compute sets of functions e.g. to be used for approxima-
tion. All procedures have two parameters, the expression to be used as variable
(an identifier in most cases) and the order of the desired system. The functions are
not scaled to a specific interval, but the variable can be accompanied by a scale
factor and/or a translation in order to map the generic interval of orthogonality to
another (e.g. (x − 1/2) ∗ 2pi). The result is a function list with ascending order,
such that the first element is the function of order zero and (for the polynomial
systems) the function of order n is the n + 1-th element.
monomial_base(x,n) {1,x,...,x**n}
trigonometric_base(x,n) {1,sin x,cos x,sin(2x),cos(2x)...}
Bernstein_base(x,n) Bernstein polynomials
Legendre_base(x,n) Legendre polynomials
Laguerre_base(x,n) Laguerre polynomials
Hermite_base(x,n) Hermite polynomials
Chebyshev_base_T(x,n) Chebyshev polynomials first kind
Chebyshev_base_U(x,n) Chebyshev polynomials second kind
Example:
Bernstein_base(x,5);
5 4 3 2
{ - X + 5*X - 10*X + 10*X - 5*X + 1,
734 CHAPTER 16. USER CONTRIBUTED PACKAGES
4 3 2
5*X*(X - 4*X + 6*X - 4*X + 1),
2 3 2
10*X *( - X + 3*X - 3*X + 1),
3 2
10*X *(X - 2*X + 1),
4
5*X *( - X + 1),
5
X }
735
16.45 ODESOLVE:
Ordinary differential equations solver
depend(y,x);
odesolve(df(y,x)=x**2+e**x,y,x);
X 3
3*E + 3*ARBCONST(1) + X
{Y=---------------------------}
3
16.45.1 Introduction
16.45.2 Installation
The file odesolve.in inputs the full set of source files that are required to im-
plement ODESolve 1+ assuming that the current directory is the ODESolve 1+
source directory. Hence, ODESolve 1+ can be run without compiling it in any im-
plementation of REDUCE 3.7 by starting REDUCE in the ODESolve 1+ source
directory and entering the statement
1: in "odesolve.in"$
1: faslout odesolve;
2: in "odesolve.in"$
3: faslend;
In CSL-REDUCE, this will work only if you have write access to the REDUCE
image file (reduce.img), so you may need to set up a private copy first. In
PSL-REDUCE, you may need to move the compiled image file odesolve.b to
a directory in your PSL load path, such as the main fasl directory. Please refer
to the documentation for your implementation of REDUCE for details. Once a
compiled version of ODESolve 1+ has been correctly installed, it can be loaded
by entering the REDUCE statement
1: load_package odesolve;
autoload. However, the ODESolve 1+ global switches are not declared, and the
symbolic mode interface provided for backward compatibility with the previous
version is not defined, until after the package has loaded. The former is not a huge
problem because all ODESolve switches can be accessed as optional arguments,
and the backward compatibility interface should probably not be used in new code
anyway.
The principal interface is via the operator odesolve. (It also has a synonym
called dsolve to make porting of examples from Maple easier, but it does not
accept general Maple syntax!) For purposes of description I will refer to the de-
pendent variable as “y” and the independent variable as “x”, but of course the
names are arbitrary. The general input syntax is
All arguments except the first are optional. This is possible because, if necessary,
ODESolve 1+ attempts to deduce the dependent and independent variables used
and to make any necessary DEPEND declarations. Messages are output to indicate
any assumptions or dependence declarations that are made. Here is an example of
what is probably the shortest possible valid input:
odesolve(df(y,x));
*** depend y , x
{y=arbconst(1)}
The first argument (ode) is required, and must be either an ODE or a variable (or
expression) that evaluates to an ODE. Automatic dependence declaration works
only when the ODE is input directly as an argument to the odesolve operator.
Here, “ODE” means an equation or expression containing one or more derivatives
of y with respect to x. Derivatives of y with respect to other variables are not
738 CHAPTER 16. USER CONTRIBUTED PACKAGES
allowed because ODESolve 1+ does not solve partial differential equations, and
symbolic derivatives of variables other than y are treated as symbolic constants.
An expression is implicitly equated to zero, as is usual in equation solvers.
The independent variable may be either an operator that explicitly depends on the
independent variable, e.g. y(x) (as required in Maple), or a simple variable that is
declared (by the user or automatically by ODESolve 1+) to depend on the inde-
pendent variable. If the independent variable is an operator then it may depend on
parameters as well as the independent variable. Variables may be simple identifiers
or, more generally, REDUCE “kernels”, e.g.
operator x, y;
odesolve(df(y(x(a),b),x(a)) = 0);
{y(x(a),b)=arbconst(1)}
The order in which arguments are given must be preserved, but arguments may
be omitted, except that if x is specified then y must also be specified, although an
empty list {} can be used as a “place-holder” to represent “no specified argument”.
Variables are distinguished from options by requiring that if a variable is specified
then it must appear in the ODE, otherwise it is assumed to be an option.
Generally in REDUCE it is not recommended to use the identifier t as a variable,
since it is reserved in Lisp. However, it is very common practice in applied mathe-
matics to use it as a variable to represent time, and for that reason ODESolve 1+
provides special support to allow it as either the independent or a dependent vari-
able. But, of course, its use may still cause trouble in other parts of REDUCE!
If specified, the “conditions” argument must take the form of an (unordered) list of
(unordered lists of) equations with either y, x, or a derivative of y on the left. A
single list of conditions need not be contained within an outer list. Combinations
of conditions are allowed. Conditions within one (inner) list all relate to the same
x value. For example:
Boundary conditions:
{{y=y0, x=x0}, {y=y1, x=x1}, ...}
Initial conditions:
{x=x0, y=y0, df(y,x)=dy0, ...}
739
Combined conditions:
{{y=y0, x=x0}, {df(y,x)=dy1, x=x1}, {df(y,x)=dy2, y=y2, x=x2}, ...}
2*x 2*x 2
- e *a + e *b*e + a*e - b*e
{y=-----------------------------------}
x 2 x
e *e - e
2*x 2*x
e * a + e *b + a - b
{y=-------------------------}
x
2*e
2*x 2*x 2
e *a + e *b*e + a*e - b*e
{y=--------------------------------}
x 2 x
e *e + e
y = y0, x = x0
or
For example
740 CHAPTER 16. USER CONTRIBUTED PACKAGES
odesolve(df(y,x) = y, y = A, x = 0);
x
{y=e *a}
2*x 2*x 2
- e *a + e *b*e + a*e - b*e
{y=-----------------------------------}
x 2 x
e *e - e
The final arguments may be one or more of the option identifiers listed in the table
below, which take precedence over the default settings. All options can also be
specified on the right of equations with the identifier “output” on the left, e.g. “out-
put = basis”. This facility if provided mainly for compatibility with other systems
such as Maple, although it also allows options to be distinguished from variables
in case of ambiguity. Some options can be specified on the left of equations that
assign special values to the option. Currently, only “trode” and its synonyms can
be assigned the value 1 to give an increased level of tracing.
The following switches set default options – they are all off by default. Options set
locally using option arguments override the defaults set by switches.
in demonstrations and possibly for debugging, and not really for general users.
The “basis” option causes ODESolve 1+ to output the general solutions of linear
ODEs in basis format (explained below). Special solutions (of ODEs with condi-
tions) and solutions of nonlinear ODEs are not affected.
The “trode” (or “trace” or “tracing”) option turns on tracing of the algorithms used
by ODESolve 1+. It reports its classification of the ODE and any intermediate
results that it computes, such as a chain of progressively simpler (in some sense)
ODEs that finally leads to a solution. Tracing can produce a lot of output, e.g. see
the test log file “zimmer.rlg”. The option “trode = 1” or the global assign-
ment “!*trode := 1” causes ODESolve 1+ to report every test that it tries
in its classification process, producing even more tracing output. This is probably
most useful for debugging, but it may give the curious user further insight into the
operation of ODESolve 1+.
The “fast” option disables all non-deterministic solution techniques (including
most of those for nonlinear ODEs of order > 1). It may be most useful if
ODESolve 1+ is used as a subroutine, including calling it recursively in a hook.
It makes ODESolve 1+ behave like the odesolve distributed with REDUCE
versions up to and including 3.7, and so does not affect the odesolve.tst file.
The “fast” option causes ODESolve 1+ to return no solution fast in cases where,
by default, if would return either a solution or no solution (perhaps much) more
slowly. Solution of sufficiently simple “deterministically-solvable” ODEs is unaf-
fected.
The “check” option turns on checking of the solution. This checking is performed
by code that is largely independent of the solver, so as to perform a genuinely
independent check. It is not turned on by default so as to avoid the computa-
tional overhead, which is currently of the order of 30%. A check is made that
each component solution satisfies the ODE and that a general solution contains
at least enough arbitrary constants, or equivalently that a basis solution contains
enough basis functions. Otherwise, warning messages are output. It is possible
that ODESolve 1+ may fail to verify a solution because the automatic simplifica-
tion fails, which indicates a failure in the checker rather than in the solver. This
option is not yet well tested; please report any checking failures to me (FJW).
In some cases, in particular when an implicit solution contains an unevaluated in-
tegral, the checker may need to differentiate an integral with respect to a variable
other than the integration variable. In order to do this, it turns on the differentiator
switch “allowdfint” globally. [I hope that this setting will eventually become the
default.] In some cases, in particular in symbolic solutions of Clairaut ODEs, the
checker may need to differentiate a composition of operators using the chain rule.
In order to do this, it turns on the differentiator switch “expanddf” locally only.
Although the code to support both these differentiator facilities has been in RE-
DUCE for a while, they both require patches that are currently only applied when
743
ODESolve 1+ is loaded. [I hope that these patches will eventually become part of
REDUCE itself.]
The ODESolve 1+ interface module pre-processes the problem and applies any
conditions to the solution. The other modules deal with the actual solution.
ODESolve 1+ first classifies the input ODE according to whether it is linear or
nonlinear and calls the appropriate solver. An ODE that consists of a product of
744 CHAPTER 16. USER CONTRIBUTED PACKAGES
ODESolve 1+ splits every linear ODE into a “reduced ODE” and a “driver” term.
The driver is the component of the ODE that is independent of y, the reduced ODE
is the component of the ODE that depends on y, and the sign convention is such
that the ODE can be written in the form “reduced ODE = driver”. The reduced
ODE is then split into a list of “ODE coefficients”.
The linear solver now determines the order of the ODE. If it is 1 then the ODE
is immediately solved using an integrating factor (if necessary). For a higher or-
der linear ODE, ODESolve 1+ considers a sequence of progressively more com-
plicated solution techniques. For most purposes, the ODE is made “monic” by
dividing through by the coefficient of the highest order derivative. This puts the
ODE into a standard form and effectively deals with arbitrary overall algebraic
factors that would otherwise confuse the solution process. (Hence, there is no need
to perform explicit algebraic factorization on linear ODEs.) The only situation in
which the original non-monic form of the ODE is considered is when checking for
exactness, which may depend critically on otherwise irrelevant overall factors.
If the ODE has constant coefficients then it can (in principle) be solved using ele-
mentary “D-operator” techniques in terms of exponentials via an auxiliary equat-
ion. However, this works only if the polynomial auxiliary equation can be solved.
Assuming that it can and there is a driver term, ODESolve 1+ tries to use a
method based on inverse “D-operator” techniques that involves repeated integra-
tion of products of the solutions of the reduced ODE with the driver. Experience
(by Malcolm MacCallum) suggests that this normally gives the most satisfactory
form of solution if the integrals can be evaluated. If any integral fails to evaluate,
the more general method of “variation of parameters”, based on the Wronskian of
the solution set of the reduced ODE, is used instead. This involves only a single
integral and so can never lead to nested unevaluated integrals.
If the ODE has non-constant coefficients then it may be of Euler (sometimes am-
biguously called “homogeneous”) type, which can be trivially reduced to an ODE
with constant coefficients. A shift in x is accommodated in this process. Next it
is tested for exactness, which leads to a first integral that is an ODE of order one
745
lower. After that it is tested for the explicit absence of y and low order derivatives,
which allows trivial order reduction. Then the monic ODE is tested for exactness,
and if that fails and the original ODE was non-monic then the original form is
tested for exactness.
Finally, pattern matching is used to seek a solution involving special functions,
such as Bessel functions. Currently, this is implemented only for second-order
ODEs satisfied by Bessel and Airy-integral functions. It could easily be extended
to other orders and other special functions. Shifts in x could also be accommodated
in the pattern matching. [Work to enhance this component of ODESolve 1+ is
currently in progress.]
If all linear techniques fail then ODESolve 1+ currently calls the variable inter-
change routine (described below), which takes it into the nonlinear solver. Occa-
sionally, this is successful in producing some, although not necessarily the best,
solution of a linear ODE.
In order to handle trivial nonlinearity, ODESolve 1+ first factorizes the ODE al-
gebraically, solves each factor that depends on y and then merges the resulting
solutions. Other factors are ignored, but a warning is output unless they are purely
numerical.
If all attempts at solution fail then ODESolve 1+ checks whether the original (un-
factored) ODE was exact, because factorization could destroy exactness. Currently,
ODESolve 1+ handles only first and second order nonlinear exact ODEs.
A version of the main solver applied to each algebraic factor branches depending
on whether the ODE factor is linear or nonlinear, and the nonlinear solver branches
depending on whether the order is 1 or higher and calls one of the solvers described
in the next two sections. If that solver fails, ODESolve 1+ checks for exactness (of
the factor). If that fails, it checks whether only a single order derivative is involved
and tries to solve algebraically for that. If successful, this decomposes the ODE
into components that are, in some sense, simpler and may be solvable. (However,
in some cases these components are algebraically very complicated examples of
simple types of ODE that the integrator cannot in practice handle, and it can take a
very long time before returning an unevaluated integral.)
If all else fails, ODESolve 1+ interchanges the dependent and independent vari-
ables and calls the top-level solver recursively. It keeps a list of all ODEs that have
entered the top-level solver in order to break infinite loops that could arise if the
solution of the variable-interchanged ODE fails.
746 CHAPTER 16. USER CONTRIBUTED PACKAGES
Separable The gradient has the form f (x)g(y), leading immediately to a solution
by quadrature, i.e. the solution can be immediately written in terms of indef-
inite integrals. (This is considered to be a solution of the ODE, regardless of
whether the integrals can be evaluated.) The solver recognises both explicit
and implicit dependence when detecting separable form.
Quasi-separable The gradient has the form f (y + kx), which is (trivially) sepa-
rable after a linear transformation. It arises as a special case of the “quasi-
homogeneous” case below, but is better treated earlier as a case in its own
right.
Homogeneous The gradient has the form f (y/x), which is algebraically homoge-
neous. A substitution of the form “y = vx” leads to a first-order linear ODE
that is (in principle) immediately solvable.
Quasi-homogeneous The gradient has the form f ( aa21 x+b
x+b1 y+c1
2 y+c2
), which is homo-
geneous after a linear transformation.
Bernoulli The gradient has the form P (x)y + Q(x)y n , in which case the ODE is
a first-order linear ODE for y 1−n .
Riccati The gradient has the form a(x)y 2 + b(x)y + c(x), in which case the ODE
can be transformed into a linear second-order ODE that may be solvable.
Currently, ODESolve 1+ recognises the above forms only if the ODE manifestly
has the specified form and does not try very hard to actually solve for x or y, which
perhaps it should!
Higher-order nonlinear solution techniques The techniques used here are all
special cases of Lie symmetry analysis, which is not yet applied in any general
way.
Higher-order nonlinear ODEs are passed through a number of “simplifier” filters
that are applied in succession, regardless of whether the previous filter simplifies
the ODE or not. Currently, the first filter tests for the explicit absence of y and
low order derivatives, which allows trivial order reduction. The second filter tests
whether the ODE manifestly depends on x + k for some constant k, in which case
it shifts x to remove k.
After that, ODESolve 1+ tests for each of the following special forms in sequence.
The sequence used here is important, because the classification is not unique, so it
is important to try the most useful classification first.
The recursive nature of ODESolve 1+, especially the thread described in this sec-
tion, can lead to complicated “arbitrary constant expressions”. Arbitrary constants
must be included at the point where an ODE is solved by quadrature. Further
processing of such a solution, as may happen when a recursive solution stack is
unwound, can lead to arbitrary constant expressions that should be re-written as
simple arbitrary constants. There is some simple code included to perform this
arbitrary constant simplification, but it is rudimentary and not entirely successful.
748 CHAPTER 16. USER CONTRIBUTED PACKAGES
The idea is that the ODESolve extension interface allows any user to add solution
techniques without needing to edit and recompile the main source code, and (in
principle) without needing to be intimately familiar with the internal operation of
ODESolve 1+.
The extension interface consists of a number of “hooks” at various critical places
within ODESolve 1+. These hooks are modelled in part on the hook mechanism
used to extend and customize the Emacs editor, which is a large Lisp-based system
with a structure similar to that of REDUCE . Each ODESolve 1+ hook is an
identifier which can be defined to be a function (i.e. a procedure), or have assigned
to it (in symbolic mode) a function name or a (symbolic mode) list of function
names. The function should be written to accept the arguments specified for the
particular hook, and it should return either a solution to the specified class of ODE
in the specified form or nil.
If a hook returns a non-nil value then that value is used by ODESolve 1+ as the
solution of the ODE at that stage of the solution process. [If the ODE being solved
was generated internally by ODESolve 1+ or conditions are imposed then the so-
lution will be re-processed before being finally returned by ODESolve 1+.] If a
hook returns nil then it is ignored and ODESolve 1+ proceeds as if the hook func-
tion had not been called at all. This is the same mechanism that it used internally by
ODESolve 1+ to run sub-solvers. If a hook evaluates to a list of function names
then they are applied in turn to the hook arguments until a non-nil value is returned
and this is the value of the hook; otherwise the hook returns nil. The same code
is used to run all hooks and it checks that an identifier is the name of a function
before it tries to apply it; otherwise the identifier is ignored. However, the hook
code does not perform any other checks, so errors within functions run by hooks
will probably terminate ODESolve 1+ and errors in the return value will probably
cause fatal errors later in ODESolve 1+. Such errors are user errors rather than
ODESolve 1+ errors!
Hooks are defined in pairs which are inserted before and after critical stages of the
solver, which currently means the general ODE solver, the nonlinear ODE solver,
and the solver for linear ODEs of order greater than one (on the grounds that solv-
ing first order linear ODEs is trivial and the standard ODESolve 1+ code should
always suffice). The precise interface definition is as follows.
A reference to an “algebraic expression” implies that the REDUCE representation
is a prefix or pseudo-prefix form. A reference to a “variable” means an identifier
(and never a more general kernel). The “order” of an ODE is always an explicit
positive integer. The return value of a hook function must always be either nil or
an algebraic-mode list (which must be represented as a prefix form). Since the
input and output of hook functions uses prefix forms (and never standard quotient
forms), hook functions can equally well be written in either algebraic or symbolic
749
Arguments: 3
Arguments: 4
Arguments: 6
1. A list of the coefficient functions of the “reduced ODE”, i.e. the co-
efficients of the different orders (including zero) of derivatives of the
dependent variable, each in the form of an algebraic expression, in low
to high derivative order. [In general the ODE will not be “monic” so
the leading (i.e. last) coefficient function will not be 1. Hence, the ODE
may contain an essentially irrelevant overall algebraic factor.]
2. The “driver” term, i.e. the term involving only the independent variable,
in the form of an algebraic expression. The sign convention is such that
“reduced ODE = driver”.
3. The dependent variable.
4. The independent variable.
5. The (maximum) order (> 1) of the ODE.
6. The minimum order derivative present.
Return value: A list consisting of a basis for the solution space of the reduced
ODE and optionally a particular integral of the full ODE. This list does not
contain any equations, and the dependent variable never appears in it. The
particular integral may be omitted if it is zero. The basis is itself a list of
algebraic expressions in the independent variable. (Hence the return value is
always a list and its first element is also always a list.)
Run before and after: The solver for first-order first-degree nonlinear (“gradi-
ent”) ODEs, which can be expressed in the form dy/dx = gradient(y, x).
Arguments: 3
The file extend.tst contains a very simple test and demonstration of the oper-
ation of the first three classes of hook.
This extension interface is experimental and subject to change. Please check the
version of this document (or the source code) for the version of ODESolve 1+
you are actually running.
21 September 2000 Version 1.063 added the “trace”, “check” and “algint” opt-
ions, the “Non1Grad” hooks, handling of implicit dependence in separable
ODEs, and handling of the general class of quasi-homogeneous ODEs.
28 September 2000 Version 1.064 added support for using ‘t’ as a variable and re-
placed the version identification output by the odesolve_version vari-
able.
14 August 2001 Version 1.065 fixed obscure bugs in the first-order nonlinear ODE
handler and the arbitrary constant simplifier, and revised some tracing mes-
sages slightly.
• Improve recognition of exact ODEs, and add some support for more general
use of integrating factors.
• Add a “classify” option, that turns on trode but avoids any actual solution, to
report all possible (?) top-level classifications.
• Add more standard elementary techniques and more general techniques such
as Lie symmetry, Prelle-Singer, etc.
752 CHAPTER 16. USER CONTRIBUTED PACKAGES
• Improve integration support, preferably to remove the need for the “noint”
option.
Bibliography
[2] A. C. Hearn and J. P. Fitch (ed.), REDUCE User’s Manual 3.6, RAND Pub-
lication CP78 (Rev. 7/95), RAND, Santa Monica, CA 90407-2138, USA
(1995).
[5] Y.-K. Man, Algorithmic Solution of ODEs and Symbolic Summation using
Computer Algebra, PhD Thesis, School of Mathematical Sciences, Queen
Mary and Westfield College, University of London (July 1994).
[9] T. Wolf and A. Brand, The Computer Algebra Package CRACK for Investi-
gating PDEs, LATEX file reduce/doc/crack.tex distributed with RE-
DUCE 3.6. A shorter document is included in the printed REDUCE User’s
Manual 3.6 [2], 241–244.
16.46.1 Introduction
The revised version of ORTHOVEC[2] is, like the original[1], a collection of RE-
DUCE procedures and operators designed to simplify the machine aided manip-
ulation of vectors and vector expansions frequently met in many areas of applied
mathematics. The revisions have been introduced for two reasons: firstly, to add
extra capabilities missing from the original and secondly, to tidy up input and out-
put to make the package easier to use.
The changes from Version 1 include:
The LISP vector primitives are again used to store vectors, although with the in-
troduction of LIST types in algebraic mode in REDUCE 3.4, the implementation
may have been more simply achieved using lists to store vector components.
The philosophy used in Version 2 follows that used in the original: namely, alge-
braic mode is used wherever possible. The view is taken that some computational
inefficiencies are acceptable if it allows coding to be intelligible to (and thence
adaptable by) users other than LISP experts familiar with the internal workings of
REDUCE.
Procedures and operators in ORTHOVEC fall into the five classes: initialisation,
input-output, algebraic operations, differential operations and integral operations.
755
Definitions are given in the following sections, and a summary of the procedure
names and their meanings are give in Table 1. The final section discusses test
examples.
16.46.2 Initialisation
5. others
which the user selects by number. Selecting options (1)-(4) automatically sets up
the coordinates and scale factors. Selection option (5) shows the user how to select
another coordinate system. If VSTART is not called, then the default cartesian co-
ordinates are used. ORTHOVEC may be re-initialised to a new coordinate system
at any time during a given REDUCE session by typing
VSTART $.
16.46.3 Input-Output
The standard REDUCE output for vectors when using the terminator “;” is to list
the three components inside square brackets [· · · ], with each component in prefix
form. A replacement for the standard REDUCE procedure MAPRIN is included in
the package to change the output of LISP vector components to algebraic notation.
The procedure VOUT (which returns the value of its argument) can be used to give
labelled output of components in algebraic form: e.g.,
The operator _ can be used to select a particular component (1, 2 or 3) for output
e.g.
b_1 ;
Six infix operators, sum, difference, quotient, times, exponentiation and cross prod-
uct, and four prefix operators, plus, minus, reciprocal and modulus are defined in
ORTHOVEC. These operators can take suitable combinations of scalar and vector
arguments, and in the case of scalar arguments reduce to the usual definitions of
+, −, ∗, /, etc.
The operators are represented by symbols
+, -, /, *, ^, ><
The composite >< is an attempt to represent the cross product symbol × in ASCII
characters. If we let v be a vector and s be a scalar, then valid combinations
of arguments of the procedures and operators and the type of the result are as
summarised below. The notation used is
result :=procedure(left argument, right argument) or
result :=(left operand) operator (right operand) .
757
Vector Addition
v := VECTORPLUS(v) or v := +v
s := VECTORPLUS(s) or s := +s
v := VECTORADD(v,v) or v := v+v
s := VECTORADD(s,s) or s := s+s
Vector Subtraction
v := VECTORMINUS(v) or v := -v
s := VECTORMINUS(s) or s := -s
v := VECTORDIFFERENCE(v,v) or v := v-v
s := VECTORDIFFERENCE(s,s) or s := s-s
Vector Division
v := VECTORRECIP(v) or v := /v
s := VECTORRECIP(s) or s := /s
v := VECTORQUOTIENT(v,v) or v := v/v
v := VECTORQUOTIENT(v, s ) or v := v/s
v := VECTORQUOTIENT( s ,v) or v := s/v
s := VECTORQUOTIENT(s,s) or s := s/s
Vector Multiplication
v := VECTORTIMES( s ,v) or v := s*v
v := VECTORTIMES(v, s ) or v := v*s
s := VECTORTIMES(v,v) or s := v*v
s := VECTORTIMES( s , s ) or s := s*s
Vector Cross Product
v := VECTORCROSS(v,v) or v := v×v
Vector Exponentiation
s := VECTOREXPT (v, s ) or s := vˆs
s := VECTOREXPT ( s , s ) or s := sˆs
Vector Modulus
s := VMOD (s)
s := VMOD (v)
All other combinations of operands for these operators lead to error messages being
issued. The first two instances of vector multiplication are scalar multiplication of
vectors, the third is the product of two scalars and the last is the inner (dot)
product. The unary operators +, -, / can take either scalar or vector arguments
and return results of the same type as their arguments. VMOD returns a scalar.
In compound expressions, parentheses may be used to specify the order of combi-
nation. If parentheses are omitted the ordering of the operators, in increasing order
of precedence is
+ | - | dotgrad | * | >< | ^ | _
758 CHAPTER 16. USER CONTRIBUTED PACKAGES
s := div (v)
v := grad(s)
v := curl(v)
v := delsq(v)
s := delsq(s)
v := v dotgrad v
s := v dotgrad s
and these are placed in the precedence list defined in REDUCE after <. The differ-
ential operator DOTGRAD is defined in the following section, and the component
selector _ was introduced in section 3.
Vector divisions are defined as follows: If a and b are vectors and c is a scalar, then
a·b
a/b =
| b |2
ca
c/a =
| a |2
Both scalar multiplication and dot products are given by the same symbol, braces
are advisable to ensure the correct precedences in expressions such as (a · b)(c · d).
Vector exponentiation is defined as the power of the modulus:
an ≡ VMOD(a)n =| a |n
Differential operators provided are div, grad, curl, delsq, and dotgrad. All
but the last of these are prefix operators having a single vector or scalar argument
as appropriate. Valid combinations of operator and argument, and the type of the
result are shown in table 16.2.
All other combinations of operator and argument type cause error messages to be
issued. The differential operators have their usual meanings [3]. The coordinate
system used by these operators is set by invoking VSTART (cf. Sec. 16.46.2). The
names h1, h2 and h3 are reserved for the scale factors, and u1, u2 and u3 are
used for the coordinates.
A vector extension, VDF, of the REDUCE procedure DF allows the differentiation
of a vector (scalar) with respect to a scalar to be performed. Allowed forms are
VDF(v, s) → v and VDF(s, s) → s , where, for example
∂B
vdf(B, x) ≡
∂x
759
v v v v
v v v s
v s s s
s v v v
s v v s
s s s s
The standard REDUCE procedures DEPEND and NODEPEND have been rede-
fined to allow dependences of vectors to be compactly defined. For example
a := svec(a1,a2,a3)$;
depend a,x,y;
depend a3,z;
vtaylor(vex,vx,vpt,vorder);
returns the series expansion of the expression VEX with respect to variable VX
about point VPT to order VORDER. Valid combinations of argument types are
shown in table 16.3.
Any other combinations cause error messages to be issued. Elements of VORDER
must be non-negative integers, otherwise error messages are issued. If scalar
VORDER is given for a vector expansion, expansions in each component are trun-
cated at the same order, VORDER.
The new version of Taylor expansion applies l’Hôpital’s rule in evaluating coef-
ficients, so handle cases such as sin(x)/(x) , etc. which the original version of
ORTHOVEC could not. The procedure used for this is LIMIT, which can be used
directly to find the limit of a scalar function ex of variable x at point pt:-
ans := limit(ex,x,pt);
760 CHAPTER 16. USER CONTRIBUTED PACKAGES
Definite and indefinite vector, volume and scalar line integration procedures are
included in ORTHOVEC. They are defined as follows:
Z
VINT(v, x) = v(x)dx
Z b
DVINT(v, x, a, b) = v(x)dx
Z a
In the vector and volume integrals, v are vector or scalar, a, b, x and n are scalar.
Vectors l and u contain expressions for lower and upper bounds to the integrals.
The integer index n defines the order in which the integrals over u1 , u2 and u3 are
performed in order to allow for functional dependencies in the integral bounds:
n order
1 u1 u2 u3
2 u3 u1 u2
3 u2 u3 u1
4 u1 u3 u2
5 u2 u1 u3
otherwise u3 u2 u1
The vector ω in the line integral’s arguments contain explicit paramterisation of the
coordinates u1 , u2 , u3 of the line u(t) along which the integral is taken.
Procedures Description
VSTART select coordinate system
Six simple examples are given in the Test Run Output file orthovectest.log to il-
lustrate the working of ORTHOVEC. The input lines were taken from the file
orthovectest.red (the Test Run Input), but could equally well be typed in at the
Terminal.
Example 34
Show that
(a × b) · (c × d) − (a · c)(b · d) + (a · d)(b · c) ≡ 0
Example 35
Write the equation of motion
∂v
+ v · ∇v + ∇p − curl(B) × B
∂t
in cylindrical coordinates.
Example 36
Taylor expand
• sin(x) cos(y) + ez about the point (0, 0, 0) to third order in x, fourth order
in y and fifth order in z.
762 CHAPTER 16. USER CONTRIBUTED PACKAGES
Procedures Description
DIV divergence of vector
GRAD gradient of scalar
CURL curl of vector
DELSQ laplacian of scalar or vector
DOTGRAD (vector).grad(scalar or vector)
Example 37
Obtain the second component of the equation of motion in example 35, and the
first component of the final vector Taylor series in example 36.
Example 38
Evaluate the line integral
Z r2
A · dr
r1
Bibliography
[1] James W. Eastwood. Orthovec: A REDUCE program for 3-D vector analysis
in orthogonal curvilinear coordinates. Comp. Phys. Commun., 47(1):139–147,
October 1987.
[2] James W. Eastwood. ORTHOVEC: version 2 of the REDUCE program for 3-D
vector analysis in orthogonal curvilinear coordinates. Comp. Phys. Commun.,
64(1):121–122, April 1991.
This package has been designed to meet the requirements of theoretical physicists
looking for a computer algebra tool to perform complicated calculations in quan-
tum theory with expressions containing operators. These operations consist mainly
of the calculation of commutators between operator expressions and in the evalua-
tions of operator matrix elements in some abstract space.
Author: Mathias Warns.
16.47.1 Introduction
The package PHYSOP has been designed to meet the requirements of theoretical
physicists looking for a computer algebra tool to perform complicated calculations
in quantum theory with expressions containing operators. These operations consist
mainly in the calculation of commutators between operator expressions and in the
evaluations of operator matrix elements in some abstract space. Since the capabil-
ities of the current REDUCE release to deal with complex expressions containing
noncommutative operators are rather restricted, the first step was to enhance these
possibilities in order to achieve a better usability of REDUCE for these kind of
calculations. This has led to the development of a first package called NONCOM2
which is described in section 2. For more complicated expressions involving both
scalar quantities and operators the need for an additional data type has emerged
in order to make a clear separation between the various objects present in the cal-
culation. The implementation of this new REDUCE data type is realized by the
PHYSOP (for PHYSical OPerator) package described in section 3.
NONCOM A,B;
NONCOM A,A;
Each operator gets a new property list containing the operators with which it does
not commute. A final example should make the use of the redefined NONCOM
statement clear:
NONCOM A,B,C;
The package PHYSOP implements a new REDUCE data type to perform calcula-
tions with physical operators. The noncommutativity of operators is implemented
using the NONCOM2 package so this file should be loaded prior to the use of
PHYSOP40 . In the following the new commands implemented by the package are
40
To build a fast loading version of PHYSOP the NONCOM2 source code should be read in prior
to the PHYSOP code
766 CHAPTER 16. USER CONTRIBUTED PACKAGES
described. Beside these additional commands, the full set of standard REDUCE
instructions remains available for performing any other calculation.
The new REDUCE data type PHYSOP implemented by the package allows the
definition of a new kind of operators (i.e. kernels carrying an arbitrary number
of arguments). Throughout this manual, the name “operator” will refer, unless
explicitly stated otherwise, to this new data type. This data type is in turn divided
into 5 subtypes. For each of this subtype, a declaration command has been defined:
It is very important to understand precisely the way how the type declaration com-
mands work in order to avoid type mismatch errors when using the PHYSOP pack-
age. The following examples should illustrate the way the program interprets type
declarations. Assume that the declarations listed above have been typed in by the
user, then:
BUT: V(X),V(X,3),V(X,N,M) are all scalar operators since the special index
X addresses a specific component of the vector operator (which is a scalar
operator). Accordingly, C(X,X,X) is also a scalar operator because the di-
agonal component Cxxx of the tensor operator C is meant here (C has rank 3
so 3 special indices must be used for the components).
In view of these examples, every time the following text refers to scalar operators,
it should be understood that this means not only operators defined by the SCALOP
statement but also components of vector and tensor operators. Depending on the
situation, in some case when dealing only with the components of vector or tensor
operators it may be preferable to use an operator declared with SCALOP rather than
addressing the components using several special indices (throughout the manual,
indices declared with the PHYSINDEX command are referred to as special indices).
Another important feature of the system is that for each operator declared using
the statements described above, the system generates 2 additional operators of the
same type: the adjoint and the inverse operator. These operators are accessible to
the user for subsequent calculations without any new declaration. The syntax is as
following:
If A has been declared to be an operator (scalar, vector or tensor) the adjoint oper-
ator is denoted A!+ and the inverse operator is denoted A!-1 (an inverse adjoint
operator A!+!-1 is also generated). The exclamation marks do not appear when
these operators are printed out by REDUCE (except when the switch NAT is set to
off) but have to be typed in when these operators are used in an input expression.
An adjoint (but no inverse) state is also generated for every state defined by the
user. One may consider these generated operators as ”placeholders” which means
that these operators are considered by default as being completely independent of
the original operator. Especially if some value is assigned to the original operator,
this value is not automatically assigned to the generated operators. The user must
code additional assignement statements in order to get the corresponding values.
Exceptions from these rules are (i) that inverse operators are always ordered at
the same place as the original operators and (ii) that the expressions A!-1*A and
A*A!-1 are replaced41 by the unit operator UNIT . This operator is defined as a
scalar operator during the initialization of the PHYSOP package. It should be used
to indicate the type of an operator expression whenever no other PHYSOP occur
in it. For example, the following sequence:
41
This may not always occur in intermediate steps of a calculation due to efficiency reasons.
768 CHAPTER 16. USER CONTRIBUTED PACKAGES
SCALOP A;
A:= 5;
SCALOP A;
A:=5*UNIT;
The operator UNIT is a reserved variable of the system and should not be used for
other purposes.
All other kernels (including standard REDUCE operators) occurring in expressions
are treated as ordinary scalar variables without any PHYSOP type (referred to as
scalars in the following). Assignement statements are checked to ensure correct
operator type assignement on both sides leading to an error if a type mismatch
occurs. However an assignement statement of the form A:= 0 or LET A = 0 is
always valid regardless of the type of A.
Finally a command CLEARPHYSOP has been defined to remove the PHYSOP type
from an identifier in order to use it for subsequent calculations (e.g. as an ordinary
REDUCE operator). However it should be remembered that no substitution rule
is cleared by this function. It is therefore left to the user’s responsibility to clear
previously all substitution rules involving the identifier from which the PHYSOP
type is removed.
Users should be very careful when defining procedures or statements of the type
FOR ALL ... LET ... that the PHYSOP type of all identifiers occurring
in such expressions is unambigously fixed. The type analysing procedure is rather
restrictive and will print out a ”PHYSOP type conflict” error message if such am-
biguities occur.
including objects not defined as operators (i.e. scalars or indices) in the argument
list of the OPORDER command leads to an error.
3. Adjoint operators are placed by the declaration commands just after the original
operators on the OPORDER list. Changing the place of an operator on this list
means not that the adjoint operator is moved accordingly. This adjoint operator can
be moved freely by including it in the argument list of the OPORDER command.
VECOP V,W;
V DOT W;
V(IDX1) * W(IDX1)
SCALOP A; A**2;
- --> A*A
VECOP V; V**4;
- --> V(IDX1)*V(IDX1)*V(IDX2)*V(IDX2)
770 CHAPTER 16. USER CONTRIBUTED PACKAGES
Note in particular the way how the system interprets powers of tensor operators
which is different from the notation used in matrix algebra.
6. Quotients of operators are only defined between scalar operator expressions.
The system transforms the quotient of 2 scalar operators into the product of the
first operator times the inverse of the second one. Example42 :
SCALOP A,B; A / B;
-1
--> (B )*A
7. Combining the last 2 rules explains the way how the system handles negative
powers of operators:
SCALOP B;
B**(-3);
-1 -1 -1
--> (B )*(B )*(B )
The method of inserting dummy indices and expanding powers of operators has
been chosen to facilitate the handling of complicated operator expressions and par-
ticularly their application on states (see section 3.4.3). However it may be use-
ful to get rid of these dummy indices in order to enhance the readability of the
system’s final output. For this purpose the switch CONTRACT has to be turned
on (CONTRACT is normally set to OFF). The system in this case contracts over
dummy indices reinserting the DOT operator and reassembling the expanded pow-
ers. However due to the predefined operator ordering the system may not remove
all the dummy indices introduced previously.
SCALOP A,B,C,D;
LET COMM(A,B)=C;
42
This shows how inverse operators are printed out when the switch NAT is on
771
Note that if special indices are used as dummy variables in FOR ALL ...
LET constructs then these indices should have been declared previously using the
PHYSINDEX command.
Every time the system encounters a product term involving 2 noncommutative
operators which have to be reordered on account of the given operator ordering,
the list of available (anti-) commutators is checked in the following way: First the
system looks for a commutation relation which matches the product term. If it fails
then the defined anticommutation relations are checked. If there is no successful
match the product term A*B is replaced by:
A*B;
--> COMM(A,B) + B*A
so that the user may introduce the commutation relation later on.
The user may want to force the system to look for anticommutators only; for this
purpose a switch ANTICOM is defined which has to be turned on (ANTICOM is
normally set to OFF). In this case, the above example is replaced by:
ON ANTICOM;
A*B;
--> ANTICOMM(A,B) - B*A
Once the operator ordering has been fixed (in the example above B has to be or-
dered ahead of A), there is no way to prevent the system from introducing (anti-
)commutators every time it encounters a product whose terms are not in the right
order. On the other hand, simply by changing the OPORDER statement and reeval-
uating the expression one can change the operator ordering without the need to
introduce new commutation relations. Consider the following example:
The functions COMM and ANTICOMM should only be used to define elemen-
772 CHAPTER 16. USER CONTRIBUTED PACKAGES
tary (anti-) commutation relations between single operators. For the calcula-
tion of (anti-) commutators between complex operator expressions, the functions
COMMUTE and ANTICOMMUTE have been defined. Example (is included as ex-
ample 1 in the test file):
VECOP P,A,K;
PHYSINDEX X,Y;
FOR ALL X,Y LET COMM(P(X),A(Y))=K(X)*A(Y);
COMMUTE(P**2,P DOT A);
Adjoint expressions As has been already mentioned, for each operator and state
defined using the declaration commands quoted in section 3.1, the system generates
automatically the corresponding adjoint operator. For the calculation of the adjoint
representation of a complicated operator expression, a function ADJ has been
defined. Example43 :
SCALOP A,B;
ADJ(A*B);
+ +
--> (B )*(A )
SCALOP A; STATE U;
FOR ALL N,P LET OPAPPLY((A(N),U(P))= EXP(I*N*P)*U(P);
(ii) LET OPAPPLY(state, state) = scalar exp.; This form is to define scalar prod-
ucts between states and normalization conditions. Example:
STATE U;
FOR ALL N,M LET OPAPPLY(U(N),U(M)) = IF N=M THEN 1 ELSE 0;
(i) Some spurious negative powers of operators may appear in the result of a cal-
culation using the PHYSOP package. This is a purely ”cosmetic” effect which is
due to an additional factorization of the expression in the output printing routines
of REDUCE. Setting off the REDUCE switch ALLFAC (ALLFAC is normally on)
should make these terms disappear and print out the correct result (see example 1
in the test file).
(ii) The current release of the PHYSOP package is not optimized w.r.t. computa-
tion speed. Users should be aware that the evaluation of complicated expressions
involving a lot of commutation relations requires a significant amount of CPU time
and memory. Therefore the use of PHYSOP on small machines is rather limited.
A minimal hardware configuration should include at least 4 MB of memory and a
reasonably fast CPU (type Intel 80386 or equiv.).
(iii) Slightly different ordering of operators (especially with multiple occurrences
of the same operator with different indices) may appear in some calculations due
to the internal ordering of atoms in the underlying LISP system (see last example
in the test file). This cannot be entirely avoided by the package but does not affect
the correctness of the results.
The package PHYSOP has been presented by the author at the IV inter. Conference
on Computer Algebra in Physical Research, Dubna (USSR) 1990 (see M. Warns,
44
The source code can also be modified to choose another special character for the function
774 CHAPTER 16. USER CONTRIBUTED PACKAGES
Acknowledgements
The main ideas for the implementation of a new data type in the REDUCE envi-
ronnement have been taken from the VECTOR package developed by Dr. David
Harper (D. Harper, Comp. Phys. Comm. 54 (1989) 295). Useful discussions with
Dr. Eberhard Schrüfer and Prof. John Fitch are also gratefully acknowledged.
In the following the error (E) and warning (W) messages specific to the PHYSOP
package are listed.
cannot declare x as data type (W): An attempt has been made to declare
an object x which cannot be used as a PHYSOP operator of the required type.
The declaration command is ignored.
x already defined as data type (W): The object x has already been de-
clared using a REDUCE type declaration command and can therefore not
be used as a PHYSOP operator. The declaration command is ignored.
x already declared as data type (W): The object x has already been de-
clared with a PHYSOP declaration command. The declaration command is
ignored.
PHYSOP type conflict in expr (E): A ambiguity has been detected dur-
ing the type analysis of the expression. Check the expression.
16.48.1 M(exp,temp)
The template temp is matched against the expression exp. If the template is
literally equal to the expression T is returned. If the template is literally equal to
the expression after replacing the generic variables by their bindings then the set of
bindings is returned as a set of replacements. Otherwise 0 (nil) is returned.
Examples:
A “literal” template:
m(f(a), f(a));
t
m(f(a), f(b));
0
Nested operators:
m(f(a,h(b)), f(a,h(b)));
t
“Generic” templates:
m(f(a,b), f(a,?a));
{?a -> b}
m(f(a,b), f(?a,?b));
{?b -> b, ?a -> a}
m(f(a,b), f(??a));
{??a -> {[a, b]}
m(f(a,b), f(?a));
0
Flag h as “associative”:
flag(’(h), ’assoc);
778 CHAPTER 16. USER CONTRIBUTED PACKAGES
m(h(a,b,d,e), h(?a,d,?b));
{?b -> e, ?a -> h(a,b)}
m(a+b+c, c+?a+?b);
{?b -> a, ?a -> b}
m(a+b+c, b+?a);
{?a -> c + a}
m(a+b+c,b+??c);
{??c -> [c,a]}
A template may be qualified by the use of the conditional operator _=, such!-that.
When a such-that condition is encountered in a template, it is held until all
generic variables appearing in logical_exp are bound.
On the binding of the last generic variable, logical_exp is simplified and if
the result is not T the condition fails and the pattern matcher backtracks. When
the template has been fully parsed any remaining held such-that conditions are
evaluated and compared to T.
Examples:
m(f(a,b), f(?a,?b\_=(?a=?b)));
0
m(f(a,a), f(?a,?b\_=(?a=?b)));
{?b -> a, ?a -> a}
Examples:
The next three examples use a rule set that defines the factorial function. Substitute
780 CHAPTER 16. USER CONTRIBUTED PACKAGES
once:
Substitute twice:
Examples:
fac(?x) :- Gamma(?x+1);
gamma(?X + 1)
fac(3);
6
fac(3/2);
gamma(5/2)
16.48.5 Arep({rep1,rep2,. . . })
16.48.6 Drep({rep1,rep2,..})
Examples:
16.48.7 Switches
TRPM Produces a trace of the rules applied during a substitution. This is useful to
see how the pattern matcher works, or to understand an unexpected result.
but not {?a -> a+b, ??b -> c}, etc. No sane template should require
these types of matches. However they can be made available by turning the
switch off.
783
2. Set and export an environment variable QHULL to the complete path, e.g., in
the Bash:
export QHULL=/usr/bin/qhull
3. Inside Reduce set the variable qhull_call!* to the complete path, e.g.,
symbolic(qhull_call!* := "/usr/bin/qhull");
Example: Compute the convex hull of a list integer points as a subset of that list as
follows:
{{2,0,0},{0,2,0},{0,2,2},{0,0,0}}
2: symbolic;
nil
((2 0 0) (0 2 0) (0 2 2) (0 0 0))
16.50.1 Introduction
• qpochhammer(a,q,infinity)@
∞
Y
1 − a qj
(a; q)∞ :=
j=0
• qpochhammer(a,q,k)
Q
k−1 j
j=0 1 − a q if k > 0
(a; q)k := 1 if k = 0
Qk −1
1 − a q −j
j=1 if k < 0
• qbrackets(k,q)
qk − 1
[q, k] :=
q−1
• qfactorial(k,q)
(q; q)k
[k]q ! :=
(1 − q)k
45
The ZEILBERG package (see [7]) contains the hypergeometric versions. Those algorithms are
described in [4],[11],[12] and [6].
785
• qbinomial(n,k,q)
n (q; q)n
:=
k q (q; q)k · (q; q)n−k
where (a1 , a2 , . . . , ar ; q)k is a short form to write the product rj=1 (aj ; q)k . An
Q
−n with
r φs series terminates if one of its numerator parameters is of the form q
h k
i1+s−r
n ∈ N. The additional factor (−1)k q (2) (which does not occur in the
corresponding definition of the generalized hypergeometric function) is due to a
confluence process. With this factor one gets the simple formula:
a1 , a2 , . . . , ar a1 , a2 , . . . , ar−1
lim r φs q, z = r−1 φs q, z .
ar →∞ b1 , b2 , . . . , bs b1 , b2 , . . . , bs
Another variation is the bilateral basic hypergeometric series (see e. g. [3], Chapter
5) that is defined as
∞
a1 , a2 , . . . , ar X (a1 , a2 , . . . , ar ; q)k k h k (k2)
is−r
r ψs q, z := z (−1) q .
b1 , b2 , . . . , bs (b1 , b2 , . . . , bs ; q)k
k=−∞
• qphihyperterm(a1,a2,...,a3,b1,b2,...,b3,q,z,k) and
• qpsihyperterm(a1,a2,...,a3,b1,b2,...,b3,q,z,k)
respectively.
The q-Zeilberger algorithm [8] deals with the definite summation of q-hypergeo-
metric terms f(n, k) wrt. n and k:
∞
X
s(n) := f(n, k)
k=−∞
At this stage the implementation assumes that the summation bounds are infinite
and the input term has finite support wrt. k. If those input requirements are not
fulfilled the resulting recursion is probably not valid. Thus we strongly advise the
user to check those requirements.
787
Despite this restriction you may still be able to get valuable information by the
program: On request it returns the left hand side of the recurrence equation (16.92)
and the antidifference g(k) of equation (16.91).
Once you have the certificate g(k) it is trivial (at least theoretically) to prove equat-
ion (16.92) as long as the input requirements are fulfilled. Let’s assume somone
gives us equation (16.91). If we divide it by f(n, k) we get a rational identity (in
q n and q k ) —due to the fact that g(k)/f(n, k) is rational in q n and q k . Once we
confirmed this identity we sum equation (16.91) over k ∈ Z:
J
XX X
σj (n) · f(n + j, k) = (g(k) − g(k − 1)), (16.93)
k∈Z j=0 k∈Z
Again we exploit the fact that g(k) is a rational multiple of f(n, k) and thus g(k)
has finite support which makes the telescoping sum on the right hand side vanish.
If we exchange the order of summation we get equation (16.92) which finishes the
proof.
Note that we may relax the requirements for f(n, k): An infinite support is possible
as long as lim g(k) = 0. (This is certainly true if lim p(k) f(k) = 0 for all
k→∞ k→∞
polynomials p(k).)
For a quite general class of q-hypergeometric terms (proper q-hypergeometric
terms) the q-Zeilberger algorithm always finds a recurrence equation, not necessar-
ily of lowest order though. Unlike Zeilberger’s original algorithm its q-analogue
more often fails to determine the recursion of lowest possible order, however (see
[10]).
If the resulting recurrence equation is of first order
1: load qsum;
Examples: The following two examples can be found in [3] ((II.3) and (2.3.4)).
2: qgosper(qpochhammer(a,q,k)*q^k/qpochhammer(q,q,k),q,k);
k
(q *a - 1)*qpochhammer(a,q,k)
-------------------------------
(a - 1)*qpochhammer(q,q,k)
3: qgosper(qpochhammer(a,q,k)*qpochhammer(a*q^2,q^2,k)*
qpochhammer(q^(-n),q,k)*q^(n*k)/(qpochhammer(a,q^2,k)*
qpochhammer(a*q^(n+1),q,k)*qpochhammer(q,q,k)),q,k);
k*n k k n 1
( - q *(q *a - 1)*(q - q )*qpochhammer(----,q,k)
n
q
2 2 2*k n
*qpochhammer(a*q ,q ,k)*qpochhammer(a,q,k))/((q *a - 1)*(q - 1)
n 2
*qpochhammer(q *a*q,q,k)*qpochhammer(a,q ,k)*qpochhammer(q,q,k))
4: qgosper(qpochhammer(q^(-n),q,k)*z^k/qpochhammer(q,q,k),q,k);
5: off qgosper_down;
6: qgosper(q^k*qbrackets(k,q),q,k);
789
k k
- q *(q + 1 - q )*qbrackets(k,q)
-----------------------------------
k
(q - 1)*(q + 1)*(q - 1)
7: on qgosper_down;
8: qgosper(q^k,q,k,0,n);
n
q *q - 1
----------
q - 1
If successful the left hand side of the recurrence equation (16.92) is returned.
There are three different ways to pass a summand f(n, k) to qsumrecursion:
i. e. upper and lower are lists of upper and lower parameters of the generalized
q-hypergeometric function. The third form is handy if you have any additional
factors.
For all three instances the following variations are allowed:
790 CHAPTER 16. USER CONTRIBUTED PACKAGES
• If for some reason the recursion order is known in advance you can spec-
ify it as an additional (optional ) argument at the very end of the parame-
ter sequence. There are two ways. If you just specify a positive integer,
qsumrecursion looks only for a recurrence equation of this order. You
can also specify a range by a list of two positive integers, i. e. the first one
specifying the lowest and the second one the highest order.
By default qsumrecursion will search for recurrences of order from 1
to 5. (The global variable qsumrecursion_recrange!* controls this
behavior, see § 16.50.8.)
provided that |z|, |q| < 1. It is the q-analogue of the binomial theorem in the sense
that
∞ ∞
X (q a ; q)k k X (a)k k
lim z = z = (1 − z)−a .
q→1− (q; q)k k!
k=0 k=0
9: qsumrecursion(qpochhammer(q^(-n),q,k)*z^k/
qpochhammer(q,q,k),q,k,n);
n n
- ((q - z)*summ(n - 1) - q *summ(n))
Notice that the input requirements are fulfilled. For n ∈ N the summand is zero
for all k > n as (q −n ; q)k = 0 and the (q; q)k -term in the denominator makes the
summand vanish for all k < 0.
With the switch qsumrecursion_certificate it is possible to get the an-
tidifference gk described above. When switched on, qsumrecursion returns a
list with five entries, see § 16.50.8. For the last example we get:
10: on qsumrecursion_certificate;
n n
proof := - ((q - z)*summ(n - 1) - q *summ(n)),
791
k n
- (q - q )*z
----------------,
n
q - 1
k 1
z *qpochhammer(----,q,k)
n
q
--------------------------,
qpochhammer(q,q,k)
k,
downward_antidifference
k k n n 1
z *(q *(q - z) + q *(z - 1))*qpochhammer(----,q,k)
n
q
lhside := -----------------------------------------------------
n
(q - 1)*qpochhammer(q,q,k)
k k n n k 1
- z *((q - q )*z - q *(q - 1))*qpochhammer(----,q,k)
n
792 CHAPTER 16. USER CONTRIBUTED PACKAGES
q
rhside := ---------------------------------------------------------
n
(q - 1)*qpochhammer(q,q,k)
15: qsimpcomb((rhside-lhside)/part(proof,3));
17: qsumrecursion(qpochhammer(q^(alpha+1),q,n)/qpochhammer(q,q,n),
{q^(-n)}, {q^(alpha+1)}, q, -x*q^(n+alpha+1), qlaguerre(n));
n alpha + n n
((q + 1 - q )*q - q *(q *x + q))*qlaguerre(n - 1)
alpha + n n
+ ((q - q)*qlaguerre(n - 2) + (q - 1)*qlaguerre(n))*q
18: qsumrecursion({q^(-n),q^(-x)},{0},q,-q^(n+1)/a,qcharlier(n));
x n n 2* n
- ((q *((q + 1 - q )*a + q )*q - q )*qcharlier(n - 1)
x n n
+ q *((q + a*q)*(q - q)*qcharlier(n - 2) - qcharlier(n)*a*q))
19: on qsum_nullspace;
21: qsumrecursion(term,q,k,n,2);
*summ(n - 2)))
The following switches can be used in connection with the QSUM package:
r = cert*f - sub(k=k-1,cert*f)
or
r = sub(k=k+1,cert*f) - cert*f
if dir=downward_antidifference or dir=upward_antidifference
respectively.
16.50.9 Messages
or
• If you call qgosper with a summand term that is free of the summation
variable you get
With all the examples we tested, our procedures decided properly whether
the input term was q-hypergeometric or not. However, we cannot guarantee
in general that qsimpcomb always returns an expression that looks rational
in q k if it actually is.
Bibliography
[1] Askey R. and Wilson, J.: Some Basic Hypergeometric Orthogonal Polynom-
ials that Generalize Jacobi Polynomials. Memoirs Amer. Math. Soc. 319,
Providence, RI, 1985.
[4] Gosper Jr., R. W.: Decision procedure for indefinite hypergeometric summa-
tion. Proc. Natl. Acad. Sci. USA 75, 1978, 40–42.
[7] Koepf, W.: REDUCE package for indefinite and definite summation.
SIGSAM Bulletin 29, 1995, 14–30.
798 CHAPTER 16. USER CONTRIBUTED PACKAGES
[11] Zeilberger, D.: A fast algorithm for proving terminating hypergeometric iden-
tities. Discrete Math. 80, 1990, 207–211.
This package is based on a port of the Maple random polynomial generator together
with some support facilities for the generation of random numbers and anonymous
procedures.
Author: Francis J. Wright.
This package is based on a port of the Maple random polynomial generator together
with some support facilities for the generation of random numbers and anonymous
procedures.
16.51.1 Introduction
The operator randpoly is based on a port of the Maple random polynomial gen-
erator. In fact, although by default it generates a univariate or multivariate poly-
nomial, in its most general form it generates a sum of products of arbitrary integer
powers of the variables multiplied by arbitrary coefficient expressions, in which the
variable powers and coefficient expressions are the results of calling user-supplied
functions (with no arguments). Moreover, the “variables” can be arbitrary expres-
sions, which are composed with the underlying polynomial-like function.
The user interface, code structure and algorithms used are essentially identical to
those in the Maple version. The package also provides an analogue of the Maple
rand random-number-generator generator, primarily for use by randpoly.
There are principally two reasons for translating these facilities rather than de-
signing comparable facilites anew: (1) the Maple design seems satisfactory and
has already been “proven” within Maple, so there is no good reason to repeat the
design effort; (2) the main use for these facilities is in testing the performance of
other algebraic code, and there is an advantage in having essentially the same test
data generator implemented in both Maple and REDUCE. Moreover, it is interest-
ing to see the extent to which a facility can be translated without change between
two systems. (This aspect will be described elsewhere.)
Sections 16.51.2 and 16.51.3 describe respectively basic and more advanced use of
randpoly; §16.51.4 describes subsidiary functions provided to support advanced
use of randpoly; §16.51.5 gives examples; an appendix gives some details of the
only non-trivial algorithm, that used to compute random sparse polynomials. Ad-
ditional examples of the use of randpoly are given in the test and demonstration
file randpoly.tst.
800 CHAPTER 16. USER CONTRIBUTED PACKAGES
The operator randpoly requires at least one argument corresponding to the poly-
nomial variable or variables, which must be either a single expression or a list of
expressions.46 In effect, randpoly replaces each input expression by an internal
variable and then substitutes the input expression for the internal variable in the
generated polynomial (and by default expands the result as usual), although in fact
if the input expression is a REDUCE kernel then it is used directly. The rest of
this document uses the term “variable” to refer to a general input expression or the
internal variable used to represent it, and all references to the polynomial structure,
such as its degree, are with respect to these internal variables. The actual degree of
a generated polynomial might be different from its degree in the internal variables.
By default, the polynomial generated has degree 5 and contains 6 terms. Therefore,
if it is univariate it is dense whereas if it is multivariate it is sparse.
Other arguments can optionally be specified, in any order, after the first compulsory
variable argument. All arguments receive full algebraic evaluation, subject to the
current switch settings etc. The arguments are processed in the order given, so that
if more than one argument relates to the same property then the last one specified
takes effect. Optional arguments are either keywords or equations with keywords
on the left.
In general, the polynomial is sparse by default, unless the keyword dense is spec-
ified as an optional argument. (The keyword sparse is also accepted, but is the
default.) The default degree can be changed by specifying an optional argument of
the form
In the multivariate case this is the total degree, i.e. the sum of the degrees with
respect to the individual variables. The keywords deg and maxdeg can also be
used in place of degree. More complicated monomial degree bounds can be
constructed by using the coefficient function described below to return a monomial
or polynomial coefficient expression. Moreover, randpoly respects internally
the REDUCE “asymptotic” commands let, weight etc. described in §10.4 of
the REDUCE 3.6 manual, which can be used to exercise additional control over
the polynomial generated.
46
If it is a single expression then the univariate code is invoked; if it is a list then the multivariate
code is invoked, and in the special case of a list of one element the multivariate code is invoked to
generate a univariate polynomial, but the result should be indistinguishable from that resulting from
specifying a single expression not in a list.
801
In the sparse case (only), the default maximum number of terms generated can be
changed by specifying an optional argument of the form
The actual number of terms generated will be the minimum of the value of terms
and the number of terms in a dense polynomial of the specified degree, number of
variables, etc.
The default order (or minimum or trailing degree) can be changed by specifying an
optional argument of the form
The keyword is ord rather than order because order is a reserved command
name in REDUCE. The keyword mindeg can also be used in place of ord. In the
multivariate case this is the total degree, i.e. the sum of the degrees with respect to
the individual variables. The order normally defaults to 0.
However, the input expressions to randpoly can also be equations, in which case
the order defaults to 1 rather than 0. Input equations are converted to the difference
of their two sides before being substituted into the generated polynomial. The
purpose of this facility is to easily generate polynomials with a specified zero – for
example
randpoly(x = a);
these equations; when called with a single argument rand returns an anonymous
function of no variables that generates a random integer. The single argument of
rand should normally be an integer range in the form a .. b, where a, b are integers
such that a < b. The spaces around (or at least before) the infix operator “..” are
necessary in some cases in REDUCE and generally recommended. For example,
the expons argument might take the form
expons = rand(0 .. n)
where n will be the maximum degree with respect to each variable independently.
In the case of coeffs the lower limit will often be the negative of the upper limit
to give a balanced coefficient range, so that the coeffs argument might take the
form
coeffs = rand(-n .. n)
which will generate random integer coefficients in the range [−n, n].
The first argument of rand must be either an integer range in the form a .. b, where
a, b are integers such that a < b, or a positive integer n which is equivalent to the
range 0 .. n − 1. The operator rand constructs a function of no arguments that
calls the REDUCE random number generator function random to return a random
integer in the range specified; in the case that the first argument of rand is a single
positive integer n the function constructed just calls random(n), otherwise the
call of random is scaled and shifted.
As an additional convenience, if rand is called with a second argument that is an
identifier then the call of rand acts exactly like a procedure definition with the
identifier as the procedure name. The procedure generated can then be called with
an empty argument list by the algebraic processor.
[Note that rand() with no argument is an error in REDUCE and does not return
directly a random number in a default range as it does in Maple – use instead the
REDUCE function random (see below).]
when the arguments to randpoly are evaluated, which is too early. Proc accepts
a single argument which is converted into the body of an anonymous procedure,
which is returned as the value of proc. (If a named procedure is required then the
normal REDUCE procedure statement should be used instead.) Examples are
given in the following sections, and in the file randpoly.tst.
although rand is marginally more efficient. However, proc and the generalized
random interface allow expressions such as the following anonymous random
fraction generator to be easily constructed:
Rand is a special case of proc, and (for either) if the switch comp is on (and the
compiler is available) then the generated procedure body is compiled.
Rand with a single argument and proc both return as their values anonymous
procedures, which if they are not compiled are Lisp lambda expressions. However,
if compilation is in effect then they return only an identifier that has no external
significance47 but which can be applied as a function in the same way as a lambda
expression.
It is primarily intended that such “proc expressions” will be used immediately as
input to randpoly. The algebraic processor is not intended to handle lambda ex-
pressions. However, they can be output or assigned to variables in algebraic mode,
although the output form looks a little strange and is probably best not displayed.
But beware that lambda expressions cannot be evaluated by the algebraic processor
(at least, not without declaring some internal Lisp functions to be algebraic oper-
ators). Therefore, for testing purposes or curious users, this package provides the
operators showproc and evalproc respectively to display and evaluate “proc
expressions” output by rand or proc (or in fact any lambda expression), in the
case of showproc provided they are not compiled.
47
It is not interned on the oblist.
804 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.51.5 Examples
randpoly(x);
5 4 3 2
- 54*x - 92*x - 30*x + 73*x - 69*x - 67
5 4 4 3 2 3 3
31*x - 17*x *y - 48*x - 15*x *y + 80*x *y + 92*x
2 3 2 2 4 3 2
+ 86*x *y + 2*x *y - 44*x + 83*x*y + 85*x*y + 55*x*y
5 4 3 2
- 27*x*y + 33*x - 98*y + 51*y - 2*y + 70*y - 60*y - 10
4 3 3
sin(x)*( - 4*cos(x) - 85*cos(x) *x + 50*sin(x)
2
- 20*sin(x) *x + 76*sin(x)*x + 96*sin(x))
4 3 -3 -4 -5
- 39*z + 14*z - 77*z - 37*z - 8*z
805
5 5 5 4 5 3 5 2 5 5
95*x *y - 53*x *y - 78*x *y + 69*x *y + 58*x *y - 58*x
4 5 4 4 4 3 4 2 4
+ 64*x *y + 93*x *y - 21*x *y + 24*x *y - 13*x *y
4 3 5 3 4 3 3 3 2
- 28*x - 57*x *y - 78*x *y - 44*x *y + 37*x *y
3 3 2 5 2 4 2 3 2 2
- 64*x *y - 95*x - 71*x *y - 69*x *y - x *y - 49*x *y
2 2 5 4 3 2
+ 77*x *y + 48*x + 38*x*y + 93*x*y - 65*x*y - 83*x*y
5 4 3 2
+ 25*x*y + 51*x + 35*y - 18*y - 59*y + 73*y - y + 31
5 4 4 3 2 3 3
85*x + 43*x *y + 68*x + 87*x *y - 93*x *y - 20*x
2 2 2 2 4 3 2
- 74*x *y - 29*x *y + 7*x + 10*x*y + 62*x*y - 86*x*y
5 4 3 2
+ 15*x*y - 97*x - 53*y + 71*y - 46*y - 28*y + 79*y + 44
The only part of this package that involves any mathematics that is not completely
trivial is the procedure to generate a sparse set of monomials of specified maximum
806 CHAPTER 16. USER CONTRIBUTED PACKAGES
and minimum total degrees in a specified set of variables. This involves some com-
binatorics, and the Maple implementation calls some procedures from the Maple
Combinatorial Functions Package combinat (of which I have implemented re-
stricted versions in REDUCE).
Given the maximum possible number N of terms (in a dense polynomial), the re-
quired number of terms (in the sparse polynomial) is selected as a random subset of
the natural numbers up to N , where each number indexes a term. In the univariate
case these indices are used directly as monomial exponents, but in the multivari-
ate case they are converted to monomial exponent vectors using a lexicographic
ordering.
Proof Suppose the first part of the proposition is true, namely that there are at most
r+n (r + n)n
Cn =
n!
where xn = x(x − 1)(x − 2) · · · (x − n + 1) denotes a falling factorial, and
b
X
nxn+1
x = .
n + 1 a
a≤x<b
(See, for example, D. H. Greene & D. E. Knuth, Mathematics for the Analysis of
Algorithms, Birkhäuser, Second Edn. 1982, equation (1.37)). Hence the second
part of the proposition follows from the first.
807
The proposition holds for 1 variable (n = 1), because there is clearly 1 distinct
monomial of each degree precisely r and hence at most d + 1 distinct monomials
in a polynomial of maximum degree d.
Suppose that the proposition holds for n variables, which are represented by the
vector X. Then a homogeneous polynomial of degree r in the n + 1 variables X
together with the single variable x has the form
distinct monomials. Hence the proposition holds for n + 1 variables, and therefore
by induction it holds for all n.
The previous proposition is also the basis of the algorithm to map term indices
m ∈ N to exponent vectors v ∈ Nn , where n is the number of variables.
Define a norm k · k on exponent vectors by kvk = ni=1 vi , which corresponds
P
to the total degree of the monomial. Then, from the previous proposition, the
number of exponent vectors of length n with norm kvk ≤ d is N (n, d) = d+n Cn .
The elements of the mth exponent vector are constructed recursively by applying
the algorithm to successive tail vectors, so let a subscript denote the length of the
vector to which a symbol refers.
The aim is to compute the vector of length n with index m = mn . If this vector
has norm dn then the index and norm must satisfy
which can be used (as explained below) to compute dn given n and mn . Since
there are N (n, dn − 1) vectors with norm less than dn , the index of the (n − 1)-
element tail vector must be given by mn−1 = mn − N (n, dn − 1), which can be
used recursively to compute the norm dn−1 of the tail vector. From this, the first
element of the exponent vector is given by v1 = dn − dn−1 .
The algorithm therefore has a natural recursive structure that computes the norm of
each tail subvector as the recursion stack is built up, but can only compute the first
term of each tail subvector as the recursion stack is unwound. Hence, it constructs
the exponent vector from right to left, whilst being applied to the elements from
808 CHAPTER 16. USER CONTRIBUTED PACKAGES
The division of one integer by another often results in a period in the decimal
part. The rational2periodic function in this package can recognise and
represent such an answer in a periodic representation. The inverse function,
periodic2rational, converts a periodic representation back to a rational
number.
SYNTAX: rational2periodic(n);
rational2periodic(n, b);
INPUT:
n is a rational number
b is the number base, if absent the default is 10.
RESULT:
periodic({a1,...,an},{b1,...,bm},{c1,...,ck},±b)
where {a1,...,an} is a list of the digits in the integer part,
{b1,...,bm} is a list of the digits in the non-periodic part,
{c1,...,ck} is a list of the digits in the periodic part
and ±b where b is the number base 2 ≤ b ≤ 16,
a minus indicating the rational number n was negative.
EXAMPLES:
−59/70 written as −0.8428571
1: rational2periodic(-59/70);
periodic({0}, {8}, {4,2,8,5,7,1}, -10)
Normally the operator periodic will not be seen as the output will be prettyprinted
as −0.8428571 and 0.03 (base 16) respectively. Currently pretty-printed output
looks better when the switch FANCY is OFF.
810 CHAPTER 16. USER CONTRIBUTED PACKAGES
SYNTAX:
periodic2rational(periodic({a1,...,an},{b1...bm},{c1,...,ck},±b)
periodic2rational({a1,...,an},{b1...bm},{c1,...,ck},±b)
INPUT:
{a1,...,an} is a list of the digits in the integer part,
{b1,...,bm} is a list of the digits in the non-periodic part,
{c1,...,ck} is a list of the digits in the periodic part
and b is the number base 2 ≤ b ≤ 16, a minus
indicating the rational number result should be negative.
If the base is omitted, 10 is assumed.
RESULT:
A rational number.
EXAMPLES:
59
---
70
4: periodic2rational({0},{8},{4,2,8,5,7,1}, -10);
59
- ---
70
Note that periodic2rational will produce the correct rational result when
passed a parameter for the periodic part which is not minimal. Similarly, a par-
ameter for the periodic part which consists of all 9’s (or in base b, all (b − 1)’s)
is treated correctly although such periodic parts are not canonical and are never
generated by calls to rational2periodic.
For example,
periodic2rational({0}, {}, {1, 2, 1, 2});
periodic2rational({0}, {1}, {2, 1});
811
4
all produce the same rational result, namely 33 , as the canonical input
periodic2rational({0}, {}, {1, 2});
Similarly,
periodic2rational({0}, {}, {9});
periodic2rational({0}, {9}, {9});
periodic2rational({0}, {}, {9, 9, 9, 9});
all produce the same rational result, namely 1, as the canonical input
periodic2rational({1}, {}, {});
a1 | a2 | a3 |
a0 + + + + ... .
|b1 |b2 |b3
cfrac(hnumi)
cfrac(hnumi,hlengthi)
cfrac(hfunci,hvari)
cfrac(hfunci,hvari,hlengthi)
INPUT:
hnumi is any real number
hfunci is a function
hvari is the function main variable
hlengthi is the maximum number of terms (continuents) to be generated and is
optional.
For non-rational function or irrational number input the hlengthi argument specifies
the number of continuents (ordered pairs, {ai , bi }), to be returned. Its default value
is five. For rational function or rational number input the length argument can
only truncate the answer, it cannot return additional pairs even if the precision is
increased. The default for rational function or rational number input is the complete
continued fraction.
For a non-rational function, power series expansion is necessary. The new switch
cf_taylor controls whether the TAYLOR or the TPS package is used to produce
the power series required. By default this switch is OFF and so the TPS package is
normally employed. In most cases the choice is not important, but the TPS option
is somewhat better at handling cases where the series expansion is rather sparse. In
a few cases TPS may fail to produce a series expansion when TAYLOR succeeds
and vice-versa.
For numerical input the default value is exact for rational number arguments whilst
for irrational or rounded input it is dependent on the precision of the session. The
length argument will only take effect if is smaller than the number of ordered
pairs which the default value would return.
If the number of continuent pairs returned does not exceed twelve, the result will
usually be pretty-printed as a two element list consisting of the convergent followed
by a rendering of the traditional continued fraction expansion. For a larger number
of pairs the output is of the second element is printed as a list of pairs. Thus, usually
the operator contfrac is not seen in the output.
EXAMPLES
813
cfrac(pi, 4);
355 1
{pi,-----,3 + ----------------}
113 1
7 + ----------
1
15 + ---
1
cfrac(sqrt 2, 5);
41 1
{sqrt(2),----,1 + ---------------------}
29 1
2 + ---------------
1
2 + ---------
1
2 + ---
2
cfrac(23.696, 4);
2962 237 1
{------,-----,23 + ---------------}
125 10 1
1 + ---------
1
2 + ---
3
cfrac((x+2/3)^2/(6*x-5), x, 10);
2
9*x + 12*x + 4
{-----------------, exact,
54*x - 45
6*x + 13 1
---------- + -------------}
36 24*x - 20
814 CHAPTER 16. USER CONTRIBUTED PACKAGES
-----------
9
cfrac(e^x, x);
3 2
x x + 9*x + 36*x + 60
{e , -----------------------,
2
3*x - 24*x + 60
x
1 + ---------------------------}
x
1 - ---------------------
x
2 + ---------------
x
3 - ---------
x
2 + ---
5
cf(hnumi)
cf(hnumi,hsizei)
cf(hnumi,hsizei,hnumtermsi)
The meaning of the arguments is the same as for the operator CONTINUED_FRACTION:
the original number to be expanded hnumi, an optional maximum size hsizei
permitted for the denominator of the convergent and an optional maximum
number of continuents hnumtermsi to be generated.
The output is in the same format as that of CFRAC described above. As with
the operator CFRAC output of CF is normally pretty-printed so the operator
confract will not be seen.
The accessor operators CF_EXPRESSION, CF_CONVERGENT and
CF_CONTINUENTS allow the various parts of a continued fraction
object hcf_objecti (as returned by any of the operators cf, cfrac,
continued_fraction and cf_euler) to be extracted.
These three operators return, respectively, the originating expression of the
815
cf_expression(hcf_objecti)
cf_convergent(hcf_objecti)
cf_continuents(hcf_objecti)
cf_convergents(hcf_objecti)
EXAMPLES
2: cf(6/11);
6 6 1
{----,----,---------------}
11 11 1
1 + ---------
1
1 + ---
5
3: a := cf(pi,1000);
355 1
a := {pi,-----,3 + ----------------}
113 1
7 + ----------
1
15 + ---
1
4: cf_convergents a;
22 333 355
{3,----,-----,-----}
7 106 113
5: cf_continuents a;
{3,7,15,1}
816 CHAPTER 16. USER CONTRIBUTED PACKAGES
6: precision 20;
12
7: cf pi;
21053343141
{pi,-------------,{3,7,15,1,292,1,1,1,2,1,3,1,14,2,1,1,2,2,2,2,1
6701487259
cf_euler(hfunci,hvari)
cf_euler(hfunci,hvari,hlengthi)
INPUT:
hfunci is a function
hvari is the function main variable
hlengthi is the maximum number of continuents to be generated and is
optional.
The meaning of the parameters is similar to those of CFRAC, but the contin-
ued fraction expansion generated will usually be different. Note that unlike
CFRAC, CF_EULER cannot currently generate continued fraction expan-
sion of numbers and for a rational function argument (with a non-constant
denominator) the expansion will not be exact.
A number of operators are provided for transforming their continued frac-
tion argument hcf_objecti into an equivalent expansion, that is one with
exactly the same convergents. They all accept as their single argument any
continued fraction object hcf_objecti. These are:
cf_unit_denominators
converts all partial denominators to 1.
cf_unit_numerators
converts all partial numerators to 1.
cf_remove_fractions
converts the denominators of the partial numerators and partial denomina-
tors in the continuents to 1.
817
cf_remove_constant
removes the zeroth continuent (if non-zero) absorbing it into the first con-
tinuent pair.
cf_transform(hcf_objecti,hmultiplier-listi)
cf_even_odd(hcf_objecti)
The convergents of the even part are the even-numbered convergents of the
original expansion and those of the odd part are the odd-numbered ones
(except the zeroth convergent which is necessarily zero). For the contin-
ued fraction expansions generated by the operators cf and cfrac with a
numerical first argument hnumi. The convergents of the even part form a
monotonically increasing sequence whilst those of the odd part (after the
zeroth) form a monotonically decreasing sequence.
EXAMPLES
cf_remove_fractions(cf_euler(e^x, x, 4));
3 2
x x + 3*x + 6*x + 6
818 CHAPTER 16. USER CONTRIBUTED PACKAGES
{e , ---------------------,
6
1
-------------------------------------}
x
1 - -------------------------------
x
(x + 1) - -------------------
2*x
(x + 2) - -------
x + 3
a := cf_remove_fractions(cf_euler(4*atan x, x, 4));
a := {4*atan(x),
7 5 3
- 60*x + 84*x - 140*x + 420*x
-----------------------------------,
105
4*x
-----------------------------------------------------}
2
x
1 + -----------------------------------------------
2
2 9*x
( - x + 3) + -------------------------------
2
2 25*x
( - 3*x + 5) + -------------
2
- 5*x + 7
304 4
b := {pi,-----,----------------------}
105 1
1 + ----------------
819
9
2 + ----------
25
2 + ----
2
c := cf(pi, 0, 6);
104348 1
c := {pi,--------,3 + ------------------------------}
33215 1
7 + ------------------------
1
15 + -----------------
1
1 + -----------
1
292 + ---
1
cf_remove_constant c;
104348 22
{pi,--------,-------------------------------}
33215 1
7 + -------------------------
22
333 + -----------------
1
1 + -----------
1
292 + ---
1
208341 15
d := {{pi,--------,3 + ----------------------},
66317 292
106 - --------------
15
820 CHAPTER 16. USER CONTRIBUTED PACKAGES
4687 - -----
585
312689 22
{pi,--------,-------------------------}}
99532 1
7 + -------------------
22
355 - -----------
1
294 - ---
3
cf_convergents c;
cf_convergents first d;
cf_convergents second d;
INPUT:
RESULT:
Padé Approximant, ie. a rational function.
ERROR MESSAGES:
The Taylor series expansion for the function, f, has not yet been imple-
mented in the REDUCE Taylor Package.
A Padé Approximant of this order (ie. the specified numerator and denom-
inator orders) does not exist but one of a different order may exist.
EXAMPLES
822 CHAPTER 16. USER CONTRIBUTED PACKAGES
23: pade(sin(x),x,0,3,3);
2
x*( - 7*x + 60)
------------------
2
3*(x + 20)
24: pade(tanh(x),x,0,5,5);
4 2
x*(x + 105*x + 945)
-----------------------
4 2
15*(x + 28*x + 63)
25: pade(atan(x),x,0,5,5);
4 2
x*(64*x + 735*x + 945)
--------------------------
4 2
15*(15*x + 70*x + 63)
26: pade(exp(1/x),x,0,5,5);
27: pade(factorial(x),x,1,3,3);
28: pade(asech(x),x,0,3,3);
2 2 2
- 3*log(x)*x + 8*log(x) + 3*log(2)*x - 8*log(2) + 2*x
--------------------------------------------------------
2
3*x - 8
29: taylor(ws-asech(x),x,0,10);
823
11
log(x)*(0 + O(x ))
13 6 43 8 1611 10 11
+ (-----*x + ------*x + -------*x + O(x ))
768 2048 81920
30: pade(sin(x)/x^2,x,0,10,0);
31: pade(sin(x)/x^2,x,0,10,2);
10 8 6 4 2
( - x + 110*x - 7920*x + 332640*x - 6652800*x
+ 39916800)/(39916800*x)
32: pade(exp(x),x,0,10,10);
10 9 8 7 6
(x + 110*x + 5940*x + 205920*x + 5045040*x
5 4 3
+ 90810720*x + 1210809600*x + 11762150400*x
2
+ 79394515200*x + 335221286400*x + 670442572800)/
10 9 8 7 6
(x - 110*x + 5940*x - 205920*x + 5045040*x
5 4
- 90810720*x + 1210809600*x
3 2
- 11762150400*x + 79394515200*x
- 335221286400*x + 670442572800)
824 CHAPTER 16. USER CONTRIBUTED PACKAGES
33: pade(sin(sqrt(x)),x,0,3,3);
(sqrt(x)*
3 2
(56447*x - 4851504*x + 132113520*x - 885487680))\
3 2
(7*(179*x - 7200*x - 2209680*x - 126498240))
Bibliography
ratint(p,q,var)
where p/q is a rational function in var. The output of ratint is a list of two
elements: the first is the polynomial part of the integral, the second is the
logarithmic part. The integral is the sum of these parts.
16.53.1.2 Examples
ratint(1,x^2-2,x);
sqrt(2)*x-2 sqrt(2)*x+2
log(-------------) - log(-------------)
sqrt(2) sqrt(2)
{ 0, --------------------------------------- }
2*sqrt(2)
826 CHAPTER 16. USER CONTRIBUTED PACKAGES
p:=441*x^7+780*x^6-2861*x^5+4085*x^4+7695*x^3+3713*x^2-43253*x
+24500;
q:=9*x^6+6*x^5-65*x^4+20*x^3+135*x^2-154*x+49;
ratint(p,q,x);
k:=36*x^6+126*x^5+183*x^4+(13807/6)*x^3-407*x^2-(3242/5)*x+(3044
l:=(x^2+(7/6)*x+(1/3))^2*(x-(2/5))^3;
ratint(k,l,x);
ratint(1,x^2+1,x);
2 1
827
r ← b ∗ c0 − quo(b ∗ d0 , d) + d ∗ a;
for i from 0 to m + n − 1 do
828 CHAPTER 16. USER CONTRIBUTED PACKAGES
{
eqns(i) ← coef f (p, i) = coef f (r, i);
};
for i from 1 to k do
{
d ← degree(ri (z))
if d = 1 then
{
c ← solve(ri (z) = 0, z)
v ← GCD(a − cb0 , b)
v ← v/lcoef f (v)
integral ← integral + c ∗ log(v)
}
else {
% we need to do a GCD over algebraic number field
v ← GCD(a − α ∗ b0 , b)
v ← v/lcof f (v), where α = roof _of (ri (z))
if d=2 then {
% give answer in terms of radicals
c ← solve(ri (z) = 0, z)
for j from 1 to 2 do {
v[j] ← substitute(α = c[j], v)
integral ← integral + c[j] ∗ log(v[j])
}
else {
% Need answer in terms of root_of notation
for j from 1 to d do {
v[j] ← substitute(α = c[j], v)
integral ← integral + c[j] ∗ log(v[j])
829
where R ∈ K[z] is square free, and S ∈ K[z, x]. In the cases where the
degree of R(α) is less than two, this is merely a sum of logarithms. For
cases where the degree is two or more, I have chosen to adopt this notation
as the answer to the original problem of integrating the rational function.
For example, consider the integral
2x5 − 19x4 + 60x3 − 159 + x2 + 50x + 11
Z Z
a
= dx
b x6 − 13x5 + 58x4 − 85x3 − 66x2 − 17x + 1
Calculating the resultant R(z) = resx (a − zb0 , b) and factorising gives
R2 (z) = z 3 − z 2 + z + 1
which does not split over the constant field Q. Continuting with the Roth-
stein Trager algorithm, we now calculate
gcd(a − α b0 , b) = z 2 + (2 ∗ α − 5) ∗ z + α2 ,
and this is the answer now returned by REDUCE, via a function called
log_sum. This has the following syntax:
830 CHAPTER 16. USER CONTRIBUTED PACKAGES
Z
1 1
dx = log(x + 1)
x5 +1 5
1 1 1 1
+ 5log_sum(β, β 4 + β 3 + β 2 + β+ , 0, log(5 ∗ β + x) ∗ β)
5 25 125 625
16.53.4 Options
There are several alternative forms that the answer to the integration prob-
lem can take. One output is the log_sum form shown in the examples
above. There is an option with this package to convert this to a "normal"
sum of logarithms in the case when the degree of eqn in α is two, and α can
be expressed in surds. To do this, use the function convert, which has the
following syntax:
831
convert(exp)
If exp is free of log_sum terms, then exp itself is returned. If exp con-
tains log_sum terms, then α is represented as surds, and substituted into
the log_sum expression. For example, using the last example, we have in
REDUCE:
2: ratint(a,b,x);
{0,
2 1
log_sum(alpha,alpha - alpha - ---,0,
4
2 7 2
log( - 2*alpha*x - 2*alpha*x + x + x - 1)*alpha,x)}
3: convert(ws);
1 2 7
---*(sqrt(2)*log( - sqrt(2)*x - sqrt(2)*x + x - x - 1)
2
2 7
- sqrt(2)*log(sqrt(2)*x + sqrt(2)*x + x - x - 1)
2 7
+ log( - sqrt(2)*x - sqrt(2)*x + x - x - 1)
2 7
+ log(sqrt(2)*x + sqrt(2)*x + x - x - 1))
832 CHAPTER 16. USER CONTRIBUTED PACKAGES
The user could then combine these to form a more elegant answer, using the
switch combinelogs if one so wished. Another option is to convert complex
logarithms to real arctangents [Bron97], which is recommended if definite
integration is the goal. This is implemented in REDUCE via a function
convert_log, which has the following syntax:
convert_log(exp),
Example:
x4 − 3 ∗ x2 + 6
Z X
dx = α log(x3 + 2αx2 − 3x − 4α)
x6 − 5 ∗ x4 + 5 ∗ x2 + 4
α|4α+1=0
x4 − 3 ∗ x2 + 6 x5 − 3x3 + x
Z
dx = arctan( )+arctan(x3 )+arctan(x),
x6 − 5 ∗ x4 + 5 ∗ x2 + 4 2
and this is the formula which should be used for definite integration.
1: ratint(1,x^2+1,x);
833
2 1
{0,log_sum(beta,beta + ---,0,log(2*beta*x - 1)*beta)}
4
13: part(ws,2);
2 1
log_sum(beta,beta + ---,0,log(2*beta*x - 1)*beta)
4
14: on combinelogs;
15: convertlog(ws);
1 - i*x + 1
---*log(------------)*i
2 i*x + 1
logtoAtan(-x,1,x);
2*atan(x)
The package also implements Hermite’s method to reduce the integral into
its polynomial and logarithmic parts, but occasionally, REDUCE returns the
incorrect answer when this algorithm is used. This is due to the REDUCE
operator pf, which performs a complete partial fraction expansion when
given a rational function as input. Work is presently being done to give the
pf operator a facility which tells it that the input is already factored. This
would then enable REDUCE to perform a partial fraction decomposition
with respect to a square free denominator, which may not necessarily be
fully factored over Q.
For a complete explanation of this and the other algorithms used in this
package, including the theoretical justification and proofs, please consult
[Ged92].
834 CHAPTER 16. USER CONTRIBUTED PACKAGES
The package includes a facility to trace in some detail the inner workings of
the ratint program. Messages are given at the key stages of the algorithm,
together with the results obtained. These messages are displayed when the
switch traceratint is on, which is done in REDUCE with the command
on traceratint;
1: load_package ratint;
2: on traceratint;
3: ratint(1+x,x^2-2*x+1,x);
x + 1
performing Howoritz reduction on --------------
2
x - 2*x + 1
- 2 1
Howoritz gives: {-------,0,-------}
x - 1 x - 1
1
computing Rothstein Trager on -------
x - 1
- 2
{-------,log(x - 1)}
x - 1
835
This package was written when the author was working as a placement stu-
dent at ZIB Berlin. All comments should therefore be reported to Winfried
Neun, ZIB, Takustrasse 7, D 14195 Berlin Dahlem, Germany
(email: [email protected]).
Bibliography
[Ged92] Geddes, K.O. et al, Algorithms for Computer Algebra, Klewer Aca-
demic Publishers, 1992.
[Red36] Hearn, Anthony C. and Fitch, John F. REDUCE User’s Manual 3.6,
RAND Corporation, 1995
This package allows a user to transform chemical reaction systems into or-
dinary differential equation systems (ODE) corresponding to the laws of
pure mass action.
Author: Herbert Melenk.
A single reaction equation is an expression of the form
or
where the hsii are arbitrary names of species (REDUCE symbols) and the
hnii are positive integer numbers. The number 1 can be omitted. The con-
nector -> describes a one way reaction, while <> describes a forward and
backward reaction.
836 CHAPTER 16. USER CONTRIBUTED PACKAGES
species := {A1,A2,A3,A4,A5};
2
{DF(A1,T)=RHO*A1*A4 - BETA*A1 - GAMMA*A1*A2 + EPSILON*A3,
2
DF(A4,T)= - RHO*A1*A4 + BETA*A1 ,
DF(A5,T)=THETA*A3 - MUE*A2*A5}
inputmat;
[ 1 0 0 1 0 ]
[ ]
[ 1 1 0 0 0 ]
[ ]
[ 0 0 1 0 0 ]
outputmat;
[ 2 0 0 0 0 ]
[ ]
[ 0 0 1 0 0 ]
[ ]
[ 0 1 0 0 1 ]
838 CHAPTER 16. USER CONTRIBUTED PACKAGES
reactmat := outputmat-inputmat;
[ 1 0 0 -1 0 ]
[ ]
REACTMAT := [ -1 -1 1 0 0 ]
[ ]
[ 0 1 -1 0 1 ]
species := {};
new species: A1
new species: A4
new species: A3
new species: A2
new species: A5
2
{DF(A1,T)= - A1 *RATE(2) + A1*A4*RATE(1) - A1*A2*RATE(3) +
A3*RATE(4),
2
DF(A4,T)=A1 *RATE(2) - A1*A4*RATE(1),
species := {};
new species: A1
new species: A4
2
{DF(A1,T)= - 4.24065*A1 + 1834.08*A1*A4,
2
DF(A4,T)=4.24065*A1 - 1834.08*A1*A4}
840 CHAPTER 16. USER CONTRIBUTED PACKAGES
The name REDLOG stand for REDuce LOGic system. Redlog implements
symbolic algorithms on first-order formulas with respect to user-chosen
first-order languages and theories. The available domains include real num-
bers, integers, complex numbers, p-adic numbers, quantified propositional
calculus, term algebras.
Documentation for this package can be found online.
Authors: Andreas Dolzmann and Thomas Sturm
then
Res f (z) = a−1 . (16.94)
z=a
If a = ∞, one defines on the other hand
Res f (z) = −a−1 (16.95)
z=∞
1: load residue;
Note that both functions use the taylor package in connection with rep-
resentations (16.94)–(16.95).
Here are some examples:
842 CHAPTER 16. USER CONTRIBUTED PACKAGES
2: residue(x/(x^2-2),x,sqrt(2));
1
---
2
3: poleorder(x/(x^2-2),x,sqrt(2));
4: residue(sin(x)/(x^2-2),x,sqrt(2));
sqrt(2)*sin(sqrt(2))
----------------------
4
5: poleorder(sin(x)/(x^2-2),x,sqrt(2));
6: residue(1/(x-1)^m/(x-2)^2,x,2);
- m
7: poleorder(1/(x-1)/(x-2)^2,x,2);
8: residue(sin(x)/x^2,x,0);
9: poleorder(sin(x)/x^2,x,0);
10: residue((1+x^2)/(1-x^2),x,1);
-1
11: poleorder((1+x^2)/(1-x^2),x,1);
843
12: residue((1+x^2)/(1-x^2),x,-1);
13: poleorder((1+x^2)/(1-x^2),x,-1);
14: residue(tan(x),x,pi/2);
-1
15: poleorder(tan(x),x,pi/2);
16: residue((x^n-y^n)/(x-y),x,y);
17: poleorder((x^n-y^n)/(x-y),x,y);
18: residue((x^n-y^n)/(x-y)^2,x,y);
n
y *n
------
y
19: poleorder((x^n-y^n)/(x-y)^2,x,y);
20: residue(tan(x)/sec(x-pi/2)+1/cos(x),x,pi/2);
-2
21: poleorder(tan(x)/sec(x-pi/2)+1/cos(x),x,pi/2);
844 CHAPTER 16. USER CONTRIBUTED PACKAGES
b*f - c*e
-----------
2
f
23: residue(x^3/sin(1/x)^2,x,infinity);
- 1
------
15
24: residue(x^3*sin(1/x)^2,x,infinity);
-1
Note that the residues of factorial and Γ function terms are not yet sup-
ported.
845
The latter can even be used by users unfamiliar with the REDUCE system,
because the REDUCE input syntax of formulas is almost the same as the
syntax of the majority of programming languages. We aimed at speeding
up the process of formula typesetting, because we are convinced, that the
writing of correct complicated formulas in the REDUCE syntax is a much
more simpler task than writing them in the LATEX syntax full of keywords
and special characters \, {, ^ etc. It is clear, that not every formula
produced by the interface is typeset in the best format from an aesthetic
point of view. When a user is not satisfied with the result, he can add some
LATEX commands to the REDUCE output - LATEX input.
846 CHAPTER 16. USER CONTRIBUTED PACKAGES
There are still some problems unsolved in the present version of the inter-
face as follows:
Warning
The RLFI package can be used only on systems supporting lower case let-
ters with off raise statement. The package distinquishes the upper and
lower case letters, so be carefull in typing them. In REDUCE 3.6 the RE-
DUCE commands have to be typed in lower-case while the switch latex
is on, in previous versions the commands had to be typed in upper-case.
Switches
Operators
infix - //
prefix - int,dint,df,pdf,sum,product,sqrt and all REDUCE
prefix operators defined in the REDUCE kernel and the SOLVE mod-
ule.
mathstyle <m-style>;
849
For special symbols and accents see [6], p. 43, 45, 51.
defindex <d-operators>;
<d-operators> ::= <d-operator> | <d-operator>,<d-operators>
<d-operator> ::= <prefix operator>(<descriptions>)
<prefix operator> ::= <identifier>
<descriptions> ::= <description> | <description>,
<descriptions>
<description> ::= arg | up | down | leftup | leftdown
Bibliography
This root finding package can be used to find some or all of the roots of
a univariate polynomial with real or complex coefficients, to the accuracy
specified by the user.
It is designed so that it can be used as an independent package, or it may be
called from SOLVE if ROUNDED is on. For example, the evaluation of
on rounded,complex;
solve(x**3+x+5,x);
16.59.1 Introduction
For all polynomials handled by the root finding package, strategies of fac-
toring are employed where possible to reduce the amount of required work.
These include square-free factoring and separation of complex polynomials
into a product of a polynomial with real coefficients and one with complex
coefficients. Whenever these succeed, the resulting smaller polynomials
are solved separately, except that the root accuracy takes into account the
possibility of close roots on different branches. One other strategy used
where applicable is the powergcd method of reducing the powers of the ini-
tial polynomial by a common factor, and deriving the roots in two stages, as
roots of the reduced power polynomial. Again here, the possibility of close
roots on different branches is taken into account.
852 CHAPTER 16. USER CONTRIBUTED PACKAGES
The top level functions can be called either as symbolic operators from
algebraic mode, or they can be called directly from symbolic mode with
symbolic mode arguments. Outputs are expressed in forms that print out
correctly in algebraic mode.
Three top level functions refer only to real roots. Each of these functions
can receive 1, 2 or 3 arguments.
The first argument is the polynomial p, that can be complex and can have
multiple or zero roots. If arg2 and arg3 are not present, all real roots are
found. If the additional arguments are present, they restrict the region of
consideration.
REALROOTS This function finds the real roots of the polynomial p, using
the REALROOT package to isolate real roots by the method of Sturm
sequences, then polishing the root to the desired accuracy. Precision
853
ROOTS p; This is the main top level function of the roots package. It will
find all roots, real and complex, of the polynomial p to an accuracy
that is sufficient to separate them and which is a minimum of 6 deci-
mal places. The value returned by ROOTS is a list of equations for all
roots. In addition, ROOTS stores separate lists of real roots and com-
plex roots in the global variables ROOTSREAL and ROOTSCOMPLEX.
integer and complex modes (off ROUNDED) any real polynomial can be
input using integer coefficients of any size; integer or rational coef-
ficients can be used to input any real or complex polynomial, inde-
pendent of the setting of the switch COMPLEX. These are the most
versatile input modes, since any real or complex polynomial can be
input exactly.
modes rounded and complex-rounded (on ROUNDED) polynomials can
be input using integer coefficients of any size. Floating point coef-
ficients will be truncated or rounded, to a size dependent upon the
system. If complex is on, real coefficients can be input to any preci-
sion using integer form, but coefficients of imaginary parts of complex
coefficients will be rounded or truncated.
856 CHAPTER 16. USER CONTRIBUTED PACKAGES
COMPLEX The root finding package controls the switch COMPLEX inter-
nally, turning the switch on if it is processing a complex polynomial.
For a polynomial with real coefficients, the starting point argument
for NEARESTROOT can be given in algebraic mode in complex form
as rl + im * I and will be handled correctly, independent of the set-
ting of the switch COMPLEX. Complex roots will be computed and
printed correctly regardless of the setting of the switch COMPLEX.
However, if COMPLEX is off, the imaginary part will print out ahead
of the real part, while the reverse order will be obtained if COMPLEX
is on.
ROUNDED The root finding package performs computations using the
arithmetic mode that is required at the time, which may be integer,
Gaussian integer, rounded, or complex rounded. The switch BFTAG is
used internally to govern the mode of computation and precision is ad-
justed whenever necessary. The initial position of switches ROUNDED
and COMPLEX are ignored. At output, these switches will emerge in
their initial positions.
16.60 RSOLVE:
Rational/integer polynomial solvers
This package provides operators that compute the exact rational zeros of a
single univariate polynomial using fast modular methods. The algorithm
used is that described by R. Loos (1983): Computing rational zeros of inte-
gral polynomials by p-adic expansion, SIAM J. Computing, 12, 286–293.
Author: Francis J. Wright.
This package provides the operators r/i_solve that compute respec-
tively the exact rational or integer zeros of a single univariate polynomial
using fast modular methods.
16.60.1 Introduction
This package provides operators that compute the exact rational zeros of a
single univariate polynomial using fast modular methods. The algorithm
used is that described by R. Loos (1983): Computing rational zeros of in-
tegral polynomials by p-adic expansion, SIAM J. Computing, 12, 286–293.
The operator r_solve computes all rational zeros whereas the operator
i_solve computes only integer zeros in a way that is slightly more ef-
ficient than extracting them from the rational zeros. The r_solve and
i_solve interfaces are almost identical, and are intended to be completely
compatible with that of the general solve operator, although r_solve
and i_solve give more convenient output when only rational or integer
zeros respectively are required. The current implementation appears to be
faster than solve by a factor that depends on the example, but is typically
up to about 2.
I plan to extend this package to compute Gaussian integer and rational zeros
and zeros of polynomial systems.
The first argument is required and must simplify to either a univariate poly-
nomial expression or equation with integer, rational or rounded coefficients.
Symbolic coefficients are not allowed (and currently complex coefficients
are not allowed either.) The argument is simplified to a quotient of integer
polynomials and the denominator is silently ignored.
Subsequent arguments are optional. If the polynomial variable is to be spec-
ified then it must be the first optional argument, and if the first optional
860 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.60.3 Examples
{x = 3, x = −3}
See the test/demonstration file rsolve.tst for more examples.
16.60.4 Tracing
16.61.1 Introduction
The package rtrace provides portable tracing facilities for REDUCE pro-
gramming. These include
load_package rtrace;
that supports algebraic mode better. An additional set of rule tracing facili-
ties for inactive rules has been provided. Beware that the rtrace package
is still experimental!
This package is intended to be portable, and has been tested with both
CSL- and PSL-based REDUCE. However, it is intended not as a replace-
ment for rdebug but as a partial re-implementation of rdebug that works
with CSL-REDUCE, and it is assumed that PSL users will continue to use
rdebug. It should, in principle, be possible to use both. Any rtrace
functions with the same names as rdebug functions should either be iden-
tical or compatible; rtrace should be loaded after rdebug in order to
retain any enhancements provided by rtrace. Perhaps at some future
time the two packages should be merged. However, note that rtrace cur-
rently provides only tracing (hence the name) and does not support break
points. (The current version also does not support conditional tracing.)
rtr power;
(power)
power(x+1, 2);
x: x + 1$
n: 2$
Enter (2) power
x: x + 1$
n: 1$
Enter (3) power
x: x + 1$
n: 0$
Leave (3) power = 1$
Leave (2) power = x + 1$
Leave (1) power = x**2 + 2*x + 1$
2
x + 2*x + 1
off rtrace;
power(x+1, 2);
2
x + 2*x + 1
on rtrace;
unrtr power;
(power)
with different names. If an internal procedure with the specified name does
not exist then rtrace tracing automatically applies to the appropriate in-
ternal procedure and returns a list of the names of the internal procedures,
e.g.
rtr int;
(simpint)
all explicit assignments executed (as either the symbolic-mode setq or the
algebraic-mode setk) inside these procedures are displayed during pro-
cedure execution. All procedure tracing (assignment and entry-exit) is re-
moved by the command unrtrst (or unrtr, for which it is just a syn-
onym):
mand, or vice versa, toggles the type of tracing applied (and displays an
explanatory message).
Note that when a program contains a for loop, REDUCE translates this to
a sequence of Lisp instructions. When using rtrst, the printout is driven
by the “unfolded” code. When the code contains a for each ... in
statement, the name of the control variable is internally used to keep the
remainder of the list during the loop, and you will see the corresponding
assignments in the trace rather than the individual values in the loop steps,
e.g.
procedure fold u;
for each x in u sum x$
rtrst fold;
(fold)
y*z + y + z
unrtrst fold;
(fold)
In this example, the printed assignments for x show the various stages of
the loop. The variable G0 is an internally generated place-holder for the
sum, and may have a slightly different name depending on the underlying
867
Lisp systems.
The command trrl initiates tracing when they fire of individual rules or
rule lists that have been activated using let.
The specified rules are (re-) activated in REDUCE such that each of them
prints a report every time it fires. The report is composed of the name of
the rule or the name of the rule list together with the number of the rule in
the list, the form matching the left side (“input”) and the resulting right side
(“output”). For an explicitly given rule or rule list, trrl assigns a unique
generated name.
Note, however, that trrl does not trace rules with constant expressions on
the left, on the assumption that they are not particularly interesting. [This
behaviour may be made user-controllable in a future version.]
The command untrrl removes the tracing from rules:
The rules are reactivated in their original form. Alternatively you can use
the command clearrules to remove the rules totally from the system.
868 CHAPTER 16. USER CONTRIBUTED PACKAGES
Please do not modify the rules between trrl and untrrl – the result may
be unpredictable.
Here are two simple examples that show tracing via the rule name and via
the operator name:
2 2
trigrules := {sin(~x) => 1 - cos(x) }
let trigrules;
trrl trigrules;
1 - sin(x)^2;
2
cos(x)
untrrl trigrules;
trrl sin;
1 - sin(x)^2;
2
cos(x)
untrrl sin;
clearrules trigrules;
The command trrlid initiates tracing of individual rule lists that have
been assigned to variables, but have not been activated using let:
where each of the < rlidi > is an identifier of a rule list (that is, a non-
869
trrlid trigrules;
2
cos(x)
untrrlid trigrules;
The trace output (only) can be redirected to a separate file by using the
command rtrout, followed by a file name in string quotes. A second call
of rtrout closes any current output file and opens a new one. The file
name NIL (without string quotes) closes any current output file and causes
the trace output to be redirected to the standard output device.
The rdebug variables trlimit and trprinter!* are not imple-
mented in rtrace. If you want to select Lisp-style tracing then turn off
the switch rtrace:
off rtrace;
after loading the rtrace package. Note that the rtrace switch controls
the display format of both procedure and rule tracing.
870 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.63.1 Introduction
The set operators are currently inserted into the standard REDUCE prece-
dence list (see page 28, §2.7, of the REDUCE 3.6 manual) as follows:
or and not member memq = set_eq neq eq >= > <= < subset_eq
subset freeof + - setdiff union intersection * / ^ .
Explicit sets are represented by lists, and this package does not require any
restrictions at all on the forms of lists that are regarded as sets. Nevertheless,
duplicate elements in a set correspond by definition to the same element and
it is conventional and convenient to represent them by a single element, i.e.
to remove any duplicate elements. I will call this a normal representation.
Since the order of elements in a set is irrelevant it is also conventional and
may be convenient to sort them into some standard order, and an appro-
priate ordering of a normal representation gives a canonical representation.
This means that two identical sets have identical representations, and there-
fore the standard REDUCE equality predicate (=) correctly determines set
equality; without a canonical representation this is not the case.
Pre-processing of explicit set-valued arguments of the set-valued operators
to remove duplicates is always done because of the obvious efficiency ad-
vantage if there were any duplicates, and hence explicit sets appearing in the
values of such operators will never contain any duplicate elements. Such
sets are also currently sorted, mainly because the result looks better. The
ordering used satisfies the ordp predicate used for most sorting within RE-
DUCE, except that explicit integers are sorted into increasing numerical
order rather than the decreasing order that satisfies ordp.
Hence explicit sets appearing in the result of any set operator are currently
returned in a canonical form. Any explicit set can also be put into this form
by applying the operator mkset to the list representing it. For example
mkset {1,2,y,x*y,x+y};
873
{x + y,x*y,y,1,2}
The operator intersection (the name used internally) has the shorter
synonym intersect. These operators will probably most commonly be
used as binary infix operators applied to explicit sets, e.g.
{1,2,3,4}
{2,3}
They can also be used as n-ary operators with any number of arguments, in
which case it saves typing to use them as prefix operators (which is possible
with all REDUCE infix operators), e.g.
{1,2,3,4,5}
{3}
union {1,5,3,5,1};
{1,3,5}
tion will evaluate to an expression that still contains the union or intersection
operator. These two operators are symmetric, and so if they remain symb-
olic their arguments will be sorted as for any symmetric operator. Such
symbolic set expressions are simplified, but the simplification may not be
complete in non-trivial cases. For example:
a intersect {};
{}
b intersection c union a
Intersection distributes over union, which is not applied by default but is im-
plemented as a rule list assigned to the variable set_distribution_rule,
e.g.
(b union c) intersection a
{1,2,3} \ {2,4};
{1,3}
{1,2,3} \ {};
{1,2,3}
a \ {1,2};
a\{1,2}
a \ a;
{}
a \ {};
{} \ a;
{}
These are all binary infix operators. Currently, like all REDUCE predicates,
they can only be used within conditional statements (if, while, repeat)
or within the argument of the evalb operator provided by this package,
and they cannot remain symbolic – a predicate that cannot be evaluated to
a Boolean value causes a normal REDUCE error.
The evalb operator provides a convenient shorthand for an if statement
designed purely to display the value of any Boolean expression (not only
predicates defined in this package). It has some similarity with the evalb
function in Maple, except that the values returned by evalb in REDUCE
(the identifiers true and false) have no significance to REDUCE itself.
Hence, in REDUCE, use of evalb is never necessary.
876 CHAPTER 16. USER CONTRIBUTED PACKAGES
true
evalb(a = a);
true
false
evalb(a = b);
false
evalb 1;
true
evalb 0;
false
Set membership is tested by the predicate member. Its left operand is re-
garded as a potential set element and its right operand must evaluate to an
explicit set. There is currently no sense in which the right operand could
be an implicit set; this would require a mechanism for declaring implicit set
membership (akin to implicit variable dependence) which is currently not
implemented. Set membership testing works like this:
true
true
true
true
false
true
true
false
false
evalb({1,2,3} = {1,2,3});
true
evalb({2,1,3} = {1,3,2});
false
evalb(mkset{2,1,3} = mkset{1,3,2});
true
true
true
879
16.64.1 Introduction
A very powerful feature of REDUCE is the ease with which matrix calcula-
tions can be performed. This package extends the available matrix feature
to enable calculations with sparse matrices. This package also provides a
selection of functions that are useful in the world of linear algebra with
respect to sparse matrices.
sparse aa(10,1),bb(200,200);
Once a matix has been declared a sparse matrix all elements of the matrix
are initialized to 0. Thus when a sparse matrix is initially referred to the
881
message
is returned. When printing out a matrix only the non-zero elements are
printed. This is due to the fact that only the non-zero elements of the matrix
are stored. To assign the elements of the declared matrix we use the follow-
ing syntax. Assuming AA and BB have been declared as spasre matrices, we
simply write,
aa(1,1):=10;
bb(100,150):=a;
etc. This then sets the element in the first row and first column to 10, or the
element in the 100th row and 150th column to a.
These follow the normal rules of matrix algebra. Sums and products must
be of compatible size; otherwise an error will result during evaluation. Sim-
ilarly, only square matrices may be raised to a power. A negative power is
computed as the inverse of the matrix raised to the corresponding positive
power. For more information and the syntax for matrix algebra see the Ma-
trix Expressions section (14.3).
The operators in the Sparse Matix Package are the same as those in the Ma-
trix Packge with the exception that the NULLSPACE operator is not defined.
See section Operators with Matrix Arguments (14.4) for more details.
16.64.4.1 Examples
det ppp;
135
trace ppp;
18
rank ppp;
spmateigen(ppp,eta);
{{eta - 1,1,
spm(1,1) := arbcomplex(4)$
},
{eta - 3,1,
spm(2,1) := arbcomplex(5)$
},
{eta - 5,1,
spm(3,1) := arbcomplex(6)$
},
{eta - 9,1,
spm(4,1) := arbcomplex(7)$
}}
883
16.64.5.2 Constructors
16.64.5.4 Predicates
Note on examples:
Notation
Syntax:
spadd_columns(A,c1,c2,expr);
A :- a sparse matrix.
c1, c2 :- positive integers.
expr :- a scalar expression.
Synopsis:
spadd_columns replaces column c2 of A by
expr ∗ column(A,c1) + column(A,c2).
add_rows performs the equivalent task on the rows of A.
885
Examples:
1 x 0
spadd_columns(A, 1, 2, x) = 0 5 0
0 0 9
1 0 0
spadd_rows(A, 2, 3, 5) = 0 5 0
0 25 9
Related functions:
spadd_to_columns, spadd_to_rows, spmult_columns,
spmult_rows.
16.64.6.2 spadd_rows
See: spadd_columns.
Syntax:
spadd_to_columns(A,column_list,expr);
A :- a sparse matrix.
column_list :- a positive integer or a list of positive integers.
expr :- a scalar expression.
Synopsis:
spadd_to_columns adds expr to each column specified in col-
umn_list of A.
spadd_to_rows performs the equivalent task on the rows of A.
Examples:
11 10 0
spadd_to_columns(A, {1, 2}, 10) = 10 15 0
10 10 9
1 0 0
spadd_to_rows(A, 2, −x) = −x −x + 5 −x
0 0 9
Related functions:
spadd_columns, spadd_rows, spmult_rows, spmult_columns.
886 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.64.6.4 spadd_to_rows
See: spadd_to_columns.
Syntax:
spaugment_columns(A,column_list);
A :- a sparse matrix.
column_list :- either a positive integer or a list of positive integers.
Synopsis:
spaugment_columns gets hold of the columns of A specified in
column_list and sticks them together.
spstack_rows performs the same task on rows of A.
Examples:
1 0
spaugment_columns(A, {1, 2}) = 0 5
0 0
1 0 0
spstack_rows(A, {1, 3}) =
0 0 9
Related functions:
spget_columns, spget_rows, spsub_matrix.
16.64.6.6 spband_matrix
Syntax:
spband_matrix(expr_list,square_size);
expr_list :- either a single scalar expression or a list of an odd
number of scalar expressions.
square_size :- a positive integer.
Synopsis:
spband_matrix creates a sparse square matrix of dimension
square_size.
887
y z 0 0 0 0
x y z 0 0 0
0 x y z 0 0
Examples: spband_matrix({x, y, z}, 6) =
0 0 x y z 0
0 0 0 x y z
0 0 0 0 x y
Related functions:
spdiagonal.
16.64.6.7 spblock_matrix
Syntax:
spblock_matrix(r,c,matrix_list);
r,c :- positive integers.
matrix_list :- a list of matrices of either sparse or matrix type.
Synopsis:
spblock_matrix creates a sparse matrix that consists of r by c
matrices filled from the matrix_list row wise.
Examples:
1 0 5 22 0
B= , C= , D=
0 1 0 0 0
1 0 5 22 0
0 1 0 0 0
spblock_matrix(2, 3, {B, C, D, D, C, B}) =
22
0 5 1 0
0 0 0 0 1
16.64.6.8 spchar_matrix
Syntax:
spchar_matrix(A, λ);
A :- a square sparse matrix.
λ :- a symbol or algebraic expression.
Synopsis:
spchar_matrix creates the characteristic matrix C of A.
This is C = λ ∗ I − A.
888 CHAPTER 16. USER CONTRIBUTED PACKAGES
x−1 0 0
Examples: spchar_matrix(A, x) = 0 x−5 0
0 0 x−9
Related functions:
spchar_poly.
16.64.6.9 spchar_poly
Syntax:
spchar_poly(A, λ);
A :- a sparse square matrix.
λ :- a symbol or algebraic expression.
Synopsis:
spchar_poly finds the characteristic polynomial of A.
This is the determinant of λ ∗ I − A.
Examples:
spchar_poly(A,x) = x3 − 15 ∗ x2 − 59 ∗ x − 45
Related functions:
spchar_matrix.
16.64.6.10 spcholesky
Syntax:
spcholesky(A);
A :- a positive definite sparse matrix containing numeric entries.
Synopsis:
spcholesky computes the cholesky decomposition of A.
It returns {L, U} where L is a lower matrix, U is an upper matrix,
A = LU, and U = LT .
889
Examples:
1 0 0
F = 0 5 0
0 0 9
1 √0 0 1 √0 0
cholesky(F) = 0 5 0 , 0 5 0
0 0 3 0 0 3
Related functions:
splu_decom.
16.64.6.11 spcoeff_matrix
Syntax:
spcoeff_matrix({lin_eqn1 ,lin_eqn2 , ...,lin_eqnn });
lin_eqn1 ,lin_eqn2 , . . . ,lin_eqnn :- linear equations. Can be of the
form equation = number or
just equation which is equiv-
alent to equation = 0.
Synopsis:
spcoeff_matrix creates the coefficient matrix C of the linear
equations.
It returns {C, X , B} such that CX = B.
Examples:
Syntax:
column_dim(A);
A :- a sparse matrix.
890 CHAPTER 16. USER CONTRIBUTED PACKAGES
Synopsis:
spcol_dim finds the column dimension of A.
sprow_dim finds the row dimension of A.
Examples:
spcol_dim(A) = 3
16.64.6.13 spcompanion
Syntax:
spcompanion(poly,x);
poly :- a monic univariate polynomial in x.
x :- the variable.
Synopsis:
spcompanion creates the companion matrix C of poly.
This is the square matrix of dimension n, where n is the degree of poly
w.r.t. x. The entries of C are: C(i, n) = −coeffn(poly, x, i − 1)
for i = 1 . . . n, C(i, i − 1) = 1 for i = 2 . . . n and the rest are 0.
Examples:
0 0 0 −11
1 0 0 0
spcompanion(x4 + 17 ∗ x3 − 9 ∗ x2 + 11, x) =
0
1 0 9
0 0 1 −17
Related functions:
spfind_companion.
16.64.6.14 spcopy_into
Syntax:
spcopy_into(A, B,r,c);
A, B :- matrices of type sparse or matrix.
r,c :- positive integers.
Synopsis:
spcopy_into copies matrix A into B with A(1,1) at B(r,c).
891
Examples:
0 0 0 0
0 0 0 0
G= 0
0 0 0
0 0 0 0
0 1 0 0
0 0 5 0
spcopy_into(A, G, 1, 2) =
0
0 0 9
0 0 0 0
Related functions:
spaugment_columns, spextend, spmatrix_augment, spmatrix_stack,
spstack_rows, spsub_matrix.
16.64.6.15 spdiagonal
Syntax:
spdiagonal({mat1 ,mat2 , ...,matn });48
mat1 ,mat2 , . . . ,matn :- each can be either a scalar expr or a
square matrix of sparse or matrix type.
Synopsis:
spdiagonal creates a sparse matrix that contains the input on the
diagonal.
Examples:
66 77
H=
88 99
1 0 0 0 0 0
0 5 0 0 0 0
0 0 9 0 0 0
spdiagonal({A, x, H}) =
0 0 0 x 0 0
0 0 0 0 66 77
0 0 0 0 88 99
Related functions:
spjordan_block.
48
The {}’s can be omitted.
892 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.64.6.16 spextend
Syntax:
spextend(A,r,c,expr);
A :- a sparse matrix.
r,c :- positive integers.
expr :- algebraic expression or symbol.
Synopsis:
spextend returns a copy of A that has been extended by r rows and
c columns. The new entries are made equal to expr.
1 0 0 0 0
0 5 0 0 0
Examples: spextend(A, 1, 2, 0) = 0 0 9 0 0
0 0 0 0 0
Related functions:
spcopy_into, spmatrix_augment, spmatrix_stack, spremove_columns,
spremove_rows.
16.64.6.17 spfind_companion
Syntax:
spfind_companion(A,x);
A :- a sparse matrix.
x :- the variable.
Synopsis:
Given a sparse companion matrix, spfind_companion finds the
polynomial from which it was made.
Examples:
0 0 0 −11
1 0 0 0
C=
0
1 0 9
0 0 1 −17
spfind_companion(C, x) = x4 + 17 ∗ x3 − 9 ∗ x2 + 11
Related functions:
spcompanion.
893
Syntax:
spget_columns(A,column_list);
A :- a sparse matrix.
c :- either a positive integer or a list of positive integers.
Synopsis:
spget_columns removes the columns of A specified in col-
umn_list and returns them as a list of column matrices.
spget_rows performs the same task on the rows of A.
Examples:
1 0
spget_columns(A, {1, 3}) = 0 , 0
0 9
spget_rows(A, 2) = 0 5 0
Related functions:
spaugment_columns, spstack_rows, spsub_matrix.
16.64.6.19 spget_rows
See: spget_columns.
16.64.6.20 spgram_schmidt
Syntax:
spgram_schmidt({vec1 ,vec2 , ...,vecn });
vec1 ,vec2 , . . . ,vecn :- linearly independent vectors. Each vec-
tor must be written as a list of prede-
fined sparse (column) matrices, eg: sparse
a(4,1);, a(1,1):=1;
Synopsis:
spgram_schmidt performs the gram_schmidt orthonormalisation
on the input vectors.
It returns a list of orthogonal normalised vectors.
894 CHAPTER 16. USER CONTRIBUTED PACKAGES
Examples:
Suppose a,b,c,d correspond to sparse matrices representing the fol-
lowing lists: {{1,0,0,0},{1,1,0,0},{1,1,1,0},{1,1,1,1}}.
spgram_schmidt({{a},{b},{c},{d}}) =
{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}
16.64.6.21 sphermitian_tp
Syntax:
sphermitian_tp(A);
A :- a sparse matrix.
Synopsis:
sphermitian_tp computes the hermitian transpose of A.
Examples:
i+1 i+2 i+3
J = 0 0 0
0 i 0
−i + 1 0 0
sphermitian_tp(J ) = −i + 2 0 −i
−i + 3 0 0
Related functions:
tp49 .
16.64.6.22 sphessian
Syntax:
sphessian(expr,variable_list);
expr :- a scalar expression.
variable_list :- either a single variable or a list of variables.
Synopsis:
sphessian computes the hessian matrix of expr w.r.t. the variables
in variable_list.
49
standard reduce call for the transpose of a matrix - see section 14.4.
895
0 0 0 0
0 2 z y
Examples: sphessian(x ∗ y ∗ z + x2 , {w, x, y, z}) =
0
z 0 x
0 y x 0
16.64.6.23 spjacobian
Syntax:
spjacobian(expr_list,variable_list);
expr_list :- either a single algebraic expression or a list of al-
gebraic expressions.
variable_list :- either a single variable or a list of variables.
Synopsis:
spjacobian computes the jacobian matrix of expr_list w.r.t. vari-
able_list.
Examples:
Related functions:
sphessian, df50 .
16.64.6.24 spjordan_block
Syntax:
spjordan_block(expr,square_size);
expr :- an algebraic expression or symbol.
square_size :- a positive integer.
Synopsis:
spjordan_block computes the square jordan block matrix J of
dimension square_size.
50
standard reduce call for differentiation - see 7.8.
896 CHAPTER 16. USER CONTRIBUTED PACKAGES
x 1 0 0 0
0 x 1 0 0
0
Examples: spjordan_block(x,5) = 0 x 1 0
0 0 0 x 1
0 0 0 0 x
Related functions:
spdiagonal, spcompanion.
16.64.6.25 splu_decom
Syntax:
splu_decom(A);
A :- a sparse matrix containing either numeric entries or imagi-
nary entries with numeric coefficients.
Synopsis:
splu_decom performs LU decomposition on A, ie: it returns
{L, U} where L is a lower diagonal matrix, U an upper diagonal ma-
trix and A = LU.
Caution: The algorithm used can swap the rows of A during the cal-
culation. This means that LU does not equal A but a row equiva-
lent of it. Due to this, splu_decom returns {L, U,vec}. The call
spconvert(A,vec) will return the sparse matrix that has been
decomposed, ie: LU = spconvert(A,vec).
1 0 0
Examples: K = 0 5 0
0 0 9
1 0 0 1 0 0
lu := splu_decom(K) = 0 5 0 , 0 1 0 ,[ 1 2 3 ]
0 0 9 0 0 1
1 0 0
first lu * second lu = 0 5 0
0 0 9
1 0 0
convert(K,third lu) = 0 5 0
0 0 9
897
Related functions:
spcholesky.
16.64.6.26 spmake_identity
Syntax:
spmake_identity(square_size);
square_size :- a positive integer.
Synopsis:
spmake_identity creates the identity matrix of dimension square_size.
1 0 0 0
0 1 0 0
Examples: spmake_identity(4) = 0 0 1 0
0 0 0 1
Related functions:
spdiagonal.
Syntax:
spmatrix_augment({mat1 ,mat2 , ...,matn });51
mat1 ,mat2 , . . . ,matn :- matrices.
Synopsis:
spmatrix_augment joins the matrices in matrix_list together hor-
izontally.
spmatrix_stack joins the matrices in matrix_list together verti-
cally.
51
The {}’s can be omitted.
898 CHAPTER 16. USER CONTRIBUTED PACKAGES
Examples:
1 0 0 1 0 0
spmatrix_augment({A, A}) = 0 5 0 0 5 0
0 0 9 0 0 9
1 0 0
0 5 0
0 0 9
spmatrix_stack({A, A}) =
1 0 0
0 5 0
0 0 9
Related functions:
spaugment_columns, spstack_rows, spsub_matrix.
16.64.6.28 matrixp
Syntax:
matrixp(test_input);
test_input :- anything you like.
Synopsis:
matrixp is a boolean function that returns t if the input is a matrix
of type sparse or matrix and nil otherwise.
Examples:
matrixp(A) = t
matrixp(doodlesackbanana) = nil
Related functions:
squarep, symmetricp, sparsematp.
16.64.6.29 spmatrix_stack
See: spmatrix_augment.
16.64.6.30 spminor
Syntax:
spminor(A,r,c);
899
A :- a sparse matrix.
r,c :- positive integers.
Synopsis:
spminor computes the (r,c)’th minor of A.
0 5
Examples: spminor(A, 1, 3) =
0 0
Related functions:
spremove_columns, spremove_rows.
Syntax:
spmult_columns(A,column_list,expr);
A :- a sparse matrix.
column_list :- a positive integer or a list of positive integers.
expr :- an algebraic expression.
Synopsis:
spmult_columns returns a copy of A in which the columns spec-
ified in column_list have been multiplied by expr.
spmult_rows performs the same task on the rows of A.
Examples:
x 0 0
spmult_columns(A, {1, 3}, x) = 0 5 0
0 0 9∗x
1 0 0
spmult_rows(A, 2, 10) = 0 50 0
0 0 9
Related functions:
spadd_to_columns, spadd_to_rows.
16.64.6.32 spmult_rows
See: spmult_columns.
900 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.64.6.33 sppivot
Syntax:
sppivot(A,r,c);
A :- a sparse matrix.
r,c :- positive integers such that A(r,c) neq 0.
Synopsis:
sppivot pivots A about it’s (r,c)’th entry.
To do this, multiples of the r’th row are added to every other row in
the matrix.
This means that the c’th column will be 0 except for the (r,c)’th entry.
Related functions:
sprows_pivot.
16.64.6.34 sppseudo_inverse
Syntax:
sppseudo_inverse(A);
A :- a sparse matrix containing only real numeric entries.
Synopsis:
sppseudo_inverse, also known as the Moore-Penrose inverse,
computes the pseudo inverse of A.
Given the singular value decomposition of A, i.e: A = UΣV T , then
the pseudo inverse A† is defined by A† = VΣ† U T . For the diagonal
matrix Σ, the pseudoinverse Σ† is computed by taking the reciprocal
of only the nonzero diagonal elements.
If A is square and non-singular, then A† = A. In general, however,
AA† A = A, and A† AA† = A† .
Perhaps more importantly, A† solves the following least-squares prob-
lem: given a rectangular matrix A and a vector b, find the x minimiz-
ing kAx − bk2 , and which, in addition, has minimum `2 (euclidean)
Norm, kxk2 . This x is A† b.
901
Examples:
0 0 3 0
R=
9 0 7 0
−0.26 0.11
0 0
sppseudo_inverse(R) =
0.33
0
0.25 −0.05
Related functions:
spsvd.
Syntax:
spremove_columns(A,column_list);
A :- a sparse matrix.
column_list :- either a positive integer or a list of positive integers.
Synopsis:
spremove_columns removes the columns specified in column_list
from A.
spremove_rows performs the same task on the rows of A.
Examples:
1 0
spremove_columns(A, 2) = 0 0
0 9
spremove_rows(A, {1, 3}) = 0 5 0
Related functions:
spminor.
16.64.6.36 spremove_rows
See: spremove_columns.
16.64.6.37 sprow_dim
See: spcolumn_dim.
902 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.64.6.38 sprows_pivot
Syntax:
sprows_pivot(A,r,c,{row_list});
A :- a sparse matrix.
r,c :- positive integers such that A(r,c) neq 0.
row_list :- positive integer or a list of positive integers.
Synopsis:
sprows_pivot performs the same task as sppivot but applies
the pivot only to the rows specified in row_list.
Related functions:
sppivot.
16.64.6.39 sparsematp
Syntax:
sparsematp(A);
A :- a matrix.
Synopsis:
sparsematp is a boolean function that returns t if the matrix is de-
clared sparse and nil otherwise.
Examples:
L := mat((1,2,3),(4,5,6),(7,8,9));
sparsematp(A) = t
sparsematp(L) = nil
Related functions:
matrixp, symmetricp, squarep.
16.64.6.40 squarep
Syntax:
squarep(A);
A :- a matrix.
903
Synopsis:
squarep is a boolean function that returns t if the matrix is square
and nil otherwise.
Examples:
L= 1 3 5
squarep(A) = t
squarep(L) = nil
Related functions:
matrixp, symmetricp, sparsematp.
16.64.6.41 spstack_rows
See: spaugment_columns.
16.64.6.42 spsub_matrix
Syntax:
spsub_matrix(A,row_list,column_list);
A :- a sparse matrix.
row_list, column_list :- either a positive integer or a list of positive
integers.
Synopsis:
spsub_matrix produces the matrix consisting of the intersection
of the rows specified in row_list and the columns specified in col-
umn_list.
5 0
Examples: spsub_matrix(A, {1, 3}, {2, 3}) =
0 9
Related functions:
spaugment_columns, spstack_rows.
Syntax:
spsvd(A);
A :- a sparse matrix containing only real numeric entries.
904 CHAPTER 16. USER CONTRIBUTED PACKAGES
Synopsis:
spsvd computes the singular value decomposition of A.
If A is an m × n real matrix of (column) rank r, svd returns the
3-element list {U, Σ, V} where A = UΣV T .
Let k = min(m, n). Then U is m × k, V is n × k, and and Σ =
diag(σ1 , . . . , σk ), where σi ≥ 0 are the singular values of A; only r of
these are non-zero. The singular values are the non-negative square
roots of the eigenvalues of AT A.
U and V are such that UU T = VV T = V T V = Ik .
Note: there are a number of different definitions of SVD in the litera-
ture, in some of which Σ is square and U and V rectangular, as here,
but in others U and V are square, and Σ is rectangular.
Examples:
1 0
Q=
0 3
−1 0 1.0 0
svd(Q) = , ,
0 0 0 5.0
−1 0
0 −1
Syntax:
spswap_columns(A,c1,c2);
A :- a sparse matrix.
c1,c1 :- positive integers.
Synopsis:
spswap_columns swaps column c1 of A with column c2.
spswap_rows performs the same task on 2 rows of A.
1 0 0
Examples: spswap_columns(A, 2, 3) = 0 0 5
0 9 0
Related functions:
spswap_entries.
905
16.64.6.45 swap_entries
Syntax:
spswap_entries(A,{r1,c1},{r2,c2});
A :- a sparse matrix.
r1,c1,r2,c2 :- positive integers.
Synopsis:
spswap_entries swaps A(r1,c1) with A(r2,c2).
9 0 0
Examples: spswap_entries(A, {1, 1}, {3, 3}) = 0 5 0
0 0 1
Related functions:
spswap_columns, spswap_rows.
16.64.6.46 spswap_rows
See: spswap_columns.
16.64.6.47 symmetricp
Syntax:
symmetricp(A);
A :- a matrix.
Synopsis:
symmetricp is a boolean function that returns t if the matrix is sym-
metric and nil otherwise.
Examples:
1 2
M=
2 1
symmetricp(A) = nil
symmetricp(M) = t
Related functions:
matrixp, squarep, sparsematp.
906 CHAPTER 16. USER CONTRIBUTED PACKAGES
By turning the fast_la switch on, the speed of the following functions
will be increased:
spadd_columns spadd_rows spaugment_columns spcol_dim
spcopy_into spmake_identity spmatrix_augment spmatrix_stack
spminor spmult_column spmult_row sppivot
spremove_columns spremove_rows sprows_pivot squarep
spstack_rows spsub_matrix spswap_columns spswap_entries
spswap_rows symmetricp
The increase in speed will be insignificant unless you are making a signifi-
cant number(i.e: thousands) of calls. When using this switch, error check-
ing is minimised. This means that illegal input may give strange error mes-
sages. Beware.
16.64.8 Acknowledgments
This package is an extention of the code from the Linear Algebra Package
for REDUCE by Matt Rebbeck (cf. section 16.37).
The algorithms for spcholesky, splu_decom, and spsvd are taken
from the book Linear Algebra - J.H. Wilkinson & C. Reinsch[3].
The spgram_schmidt code comes from Karin Gatermann’s Symmetry
package[4] for REDUCE.
Bibliography
[1] Matt Rebbeck: A Linear Algebra Package for REDUCE, ZIB , Berlin.
(1994)
[2] Anthony C. Hearn: REDUCE User’s Manual 3.6. RAND (1995)
[3] J. H. Wilkinson & C. Reinsch: Linear Algebra (volume II). Springer-
Verlag (1971)
[4] Karin Gatermann: Symmetry: A REDUCE package for the computa-
tion of linear representations of groups. ZIB, Berlin. (1992)
907
The package SPDE provides a set of functions which may be used to de-
termine the symmetry group of Lie- or point-symmetries of a given system
of partial differential equations. In many cases the determining system is
solved completely automatically. In other cases the user has to provide ad-
ditional input information for the solution algorithm to terminate.
Author: Fritz Schwarz.
The package SPDE provides a set of functions which may be applied to
determine the symmetry group of Lie- or point-symmetries of a given sys-
tem of partial differential equations. Preferably it is used interactively on a
computer terminal. In many cases the determining system is solved com-
pletely automatically. In some other cases the user has to provide some
additional input information for the solution algorithm to terminate. The
package should only be used in compiled form.
For all theoretical questions, a description of the algorithm and numerous
examples the following articles should be consulted: “Automatically De-
termining Symmetries of Partial Differential Equations”, Computing vol.
34, page 91-106(1985) and vol. 36, page 279-280(1986), “Symmetries of
Differential Equations: From Sophus Lie to Computer Algebra”, SIAM Re-
view, to appear, and Chapter 2 of the Lecture Notes “Computer Algebra and
Differential Equations of Mathematical Physics”, to appear.
Some other useful functions for obtaining various kinds of output are:
908 CHAPTER 16. USER CONTRIBUTED PACKAGES
There are several global variables defined by the system which should not
be used for any other purpose than that given in Table 16.8 and 16.9. The
three globals of the type integer are:
are legal calls. If it is called without any argument, all current assignments
to deq are taken into account. Example: If deq 1, deq 2 and deq 3 have been
assigned a differential equation and the symmetry group of the full system
comprising all three equations is desired, equivalent calls are
The first alternative saves some typing. If later in the session the symmetry
group of deq 1 alone has to be determined, the correct call is
CRESYS deq 1;
After the determining system has bee created, SIMPSYS which has no ar-
guments may be called for solving it. The amount of intermediate output
produced by SIMPSYS is controlled by the global variable PCLASS with
the default value 0. With PCLASS equal to 0, no intermediate steps are
shown. With PCLASS equal to 1, all intermediate steps are displayed so
that the solution algorithm may be followed through in detail. Each time
the algorithm passes through the top of the main solution loop the message
in agreement with the current number of functions which have alreday been
introduced. This value is returned by SIMPSYS too.
After the determining system has been solved, the procedure RESULT,
which has no arguments, may be called. It displays the infinitesimal gener-
ators and its non-vanishing commutators.
deq 1:=u(1,1)+u(1,2,2);
The latter call is compulsory if there are other assignments to the operator
deq i than for i=1.
The error message
PRSYS();
GL(1):=2*DF(ETA(1),U(1),X(2)) - DF(XI(2),X(2),2) -
DF(XI(2),X(1))
911
GL(2):=DF(ETA(1),U(1),2) - 2*DF(XI(2),U(1),X(2))
GL(3):=DF(ETA(1),X(2),2) + DF(ETA(1),X(1))
GL(4):=DF(XI(2),U(1),2)
GL(5):=DF(XI(2),U(1)) - DF(XI(1),U(1),X(2))
GL(7):=DF(XI(1),U(1),2)
GL(8):=DF(XI(1),U(1))
GL(9):=DF(XI(1),X(2))
The last message means that all three functions XI(1), XI(2) and ETA(1)
depend on X(1), X(2) and U(1). Without this information the nine equations
GL(1) to GL(9) forming the determining system are meaningless. Now the
solution algorithm may be activated by calling
SIMPSYS();
If the print flag PCLASS has its default value which is 0 no intermediate
output is produced and the answer is
GL(1):=DF(C(1),X(2),2) + DF(C(1),X(1))
Number of functions is 16
912 CHAPTER 16. USER CONTRIBUTED PACKAGES
DF(C(1),X(1)) := - DF(C(1),X(2),2);
SIMPSYS();
the solution algorithm terminates without any further message, i.e. there
are no equations of the determining system left unsolved. To obtain the
symmetry generators one has to say finally
RESULT();
DEQ(1):=U(1,2,2) + U(1,1)
GEN(1):= DX(1)
GEN(2):= DX(2)
GEN(4):= DU(1)*U(1)
2
GEN(6):= 4*DX(1)*X(1)
+ 4*DX(2)*X(2)*X(1)
2
+ DU(1)*U(1)*(X(2) - 2*X(1))
GEN(7):= DU(1)*C(1)
Constraints
DF(C(1),X(1)):= - DF(C(1),X(2),2)
COMM(1,3):= 2*DX(2)
COMM(1,5):= 2*DX(1)
COMM(2,3):= DU(1)*U(1)
COMM(2,5):= DX(2)
2
914 CHAPTER 16. USER CONTRIBUTED PACKAGES
COMM(5,6):= 8*DX(1)*X(1)
+ 8*DX(2)*X(2)*X(1)
2
+ 2*DU(1)*U(1)*(X(2) - 2*X(1))
have to be made. If now PRSYS() is called all GL(K) are zero proving the
correctness of this generator.
Sometimes a user only wants to know some of the functions ZETA for for
various values of its possible arguments and given values of MM and NN.
In these cases the user has to assign the desired values of MM and NN and
may call the ZETAs after that. Example:
MM:=1; NN:=2;
FACTOR U(1,2),U(1,1),U(1,1,2),U(1,1,1);
ON LIST;
ZETA(1,1);
-U(1,2)*U(1,1)*DF(XI(2),U(1))
-U(1,2)*DF(XI(2),X(1))
915
2
-U(1,1) *DF(XI(1),U(1))
+U(1,1)*(DF(ETA(1),U(1)) -DF(XI(1),X(1)))
+DF(ETA(1),X(1))
ZETA(1,1,1);
-2*U(1,1,2)*U(1,1)*DF(XI(2),U(1))
-2*U(1,1,2)*DF(XI(2),X(1))
-U(1,1,1)*U(1,2)*DF(XI(2),U(1))
-3*U(1,1,1)*U(1,1)*DF(XI(1),U(1))
+U(1,1,1)*(DF(ETA(1),U(1)) -2*DF(XI(1),X(1)))
2
-U(1,2)*U(1,1) *DF(XI(2),U(1),2)
-2*U(1,2)*U(1,1)*DF(XI(2),U(1),X(1))
-U(1,2)*DF(XI(2),X(1),2)
3
-U(1,1) *DF(XI(1),U(1),2)
2
+U(1,1) *(DF(ETA(1),U(1),2) -2*DF(XI(1),U(1),X(1)))
+U(1,1)*(2*DF(ETA(1),U(1),X(1)) -DF(XI(1),X(1),2))
+DF(ETA(1),X(1),2)
is returned. Often the functions ZETA are desired for special values of its
916 CHAPTER 16. USER CONTRIBUTED PACKAGES
Z11:=ZETA(1,1)$ Z111:=ZETA(1,1,1)$
XI 1:=4*X(1)**2; XI 2:=4*X(2)*X(1);
They correspond to the generator GEN 6 of the diffusion equation which has
been obtained above. Now the desired expressions are obtained by calling
Z11;
2
- (4*U(1,2)*X(2) - U(1,1)*X(2) + 10*U(1,1)*X(1) + 2*U(1))
Z111;
2
- (8*U(1,1,2)*X(2) - U(1,1,1)*X(2) + 18*U(1,1,1)*X(1) +
12*U(1,1))
This appendix is a test file. The symmetry groups for various equations or
systems of equations are determined. The variable PCLASS has the default
value 0 and may be changed by the user before running it. The output may
be compared with the results which are given in the references.
deq 1:=3*u(1,3,3)+u(1,2,2,2,2)+6*u(1,2,2)*u 1
+6*u(1,2)**2+4*u(1,1,2)$
deq 1:=u(1,1,2)-u(1,2,2,2,2)-3*u(1,3,3)
+6*u(1,2)**2*u(1,2,2)+6*u(1,3)*u(1,2,2)$
%are necessary.
deq 2:=u(2,1)+u(2,2,2)$
cresys()$ simpsys()$
simpsys()$ result()$
This special function package is separated into two portions to make it eas-
ier to handle. The packages are called SPECFN and SPECFN2. The first
one is more general in nature, whereas the second is devoted to special spe-
cial functions. Documentation for the first package can be found in the
file specfn.tex in the “doc” directory, and examples in specfn.tst and specf-
mor.tst in the examples directory.
Author: Chris Cannam, with contributions from Winfried Neun, Herbert
Melenk, Victor Adamchik, Francis Wright and several others.
The package SPECFN is designed to provide algebraic and numeric manip-
ulations of several common special functions, namely:
All algorithms whose sources are uncredited are culled from series or ex-
pressions found in the Dover Handbook of Mathematical Functions[1].
There is a nice collection of plot calls for special functions in the file
specplot.tst in the subfolder plot of the packages folder. These
examples will reproduce a number of well-known pictures from [1].
All of the operators supported by this package have certain algebraic sim-
plification rules to handle special cases, poles, derivatives and so on. Such
rules are applied whenever they are appropriate. However, if the ROUNDED
switch is on, numeric evaluation is also carried out. Unless otherwise stated
below, the result of an application of a special function operator to real or
complex numeric arguments in rounded mode will be approximated numer-
ically whenever it is possible to do so. All approximations are to the current
precision.
921
Most algebraic simplifications within the special function package are de-
fined in the form of a REDUCE ruleset. Therefore, in order to get a quick
insight into the simplification rules one can use the ShowRules operator,
e.g.
ShowRules BesselI;
1 ~z - ~z
{besseli(~n,~z) => ---------------*(e - e )
sqrt(pi*2*~z)
1
when numberp(~n) and ~n=---,
2
1 ~z - ~z
besseli(~n,~z) => ---------------*(e + e )
sqrt(pi*2*~z)
1
when numberp(~n) and ~n= - ---,
2
besseli(~n,~z) => 0
df(besseli(~n,~z),~z)
df(besseli(~n,~z),~z)
16.66.2 Constants
The following well-known constants are defined in the REDUCE core, but
the code for computing their numerical value when the switch ROUNDED is
on is contained in the special function package.
Stirling numbers of the first and second kind are computed by the binary
operators Stirling1 and Stirling2 using explicit formulae.
range −30 < z < 16. Outside this range the values become a little un-
wieldy.
Numerical evaluation of ζ is only carried out if the argument is real. The
algorithms used for ζ are: for odd integral arguments, an expression re-
lating ζ(n) with ψ n−1 (3); for even arguments, a trivial relationship with
the Bernoulli numbers; and for other arguments the approach is either (for
larger arguments) to take the first few primes in the standard over-all-primes
expansion, and then continue with the defining series with natural num-
bers not divisible by these primes, or (for smaller arguments) to use a fast-
converging series obtained from [2].
There are no rules for differentiation or integration of ζ.
Support is provided for the Bessel functions J and Y, the modified Bessel
functions I and K, and the Hankel functions of the first and second kinds.
The relevant operators are, respectively, BesselJ, BesselY, BesselI,
BesselK, Hankel1 and Hankel2, which are all binary operators.
The following initial transformations are performed:
used for the other Bessels are generally implementations of standard as-
cending series for J, Y and I, together with asymptotic series for J and Y;
usually, the asymptotic series are tried first, and if the argument is too small
for them to attain the current precision, the standard series are applied. An
obvious optimization prevents an attempt with the asymptotic series if it is
clear from the outset that it will fail.
There are no rules for the integration of Bessel and Hankel functions.
This package also provides some support for other functions, in the form of
algebraic simplifications:
• The Beta function, a variation upon the Γ function[1], with the binary
operator Beta;
• The Struve H and L functions, through the binary operators StruveH
and StruveL, for which manipulations are provided to handle spe-
cial cases, simplify to more readily handled functions where appro-
priate, and differentiate with respect to the second argument;
• The Lommel functions of the first and second kinds, through the
ternary operators Lommel1 and Lommel2, for which manipulations
are provided to handle special cases and simplify where appropriate;
• The Kummer confluent hypergeometric functions M and U (the hyper-
geometric 1 F1 or Φ, and z −a 2 F0 or Ψ, respectively), with the ternary
operators KummerM and KummerU, for which there are manipula-
tions for special cases and simplifications, derivatives and, for the M
function, numerical approximations for real arguments;
• The Whittaker M and W functions, variations upon the Kummer
functions, which, with the ternary operators WhittakerM and
WhittakerW, simplify to expressions in the Kummer functions.
The numerical approximation for the Integral functions suffer from the fact
that the precision is not set correctly for values of the argument above 10.0
(approx.) and from the usage of summations even for large arguments.
li(z) is simplified towards Ei(ln(z)) .
Support is provided for the Airy Functions Ai and Bi and for the Airyprime
Functions Aiprime and Biprime. The relevant operators are respectively
Airy_Ai, Airy_Bi, Airy_Aiprime, and Airy_Biprime, which
are all unary operators with one argument.
The following cases can be performed:
• Trivial cases of Airy_Ai and Airy_Bi and their primes are handled.
• All cases can handle both complex and real arguments.
• The Airy Functions can also be represented in terms of Bessel Funct-
ions by activating an inactive rule set.
In order to activate the Airy Function to Bessel Rules one should type:
let Airy2Bessel_rules;. As a result the Airy_Ai function, for ex-
ample will be calculated using the formula :-
1√ 2 2
Ai(z) = z I−1/3 (ζ) − I1/3 (ζ) , where ζ = z 3
3 3
Note:- In order to obtain satisfactory approximations to results both the
COMPLEX and ROUNDED switches must be on.
The algorithms used for the Airy Functions are implementations of stand-
ard ascending series, together with asymptotic series. At some point it is
better to use the asymptotic approach, rather than the series. This value is
calculated by the program and depends on the given precision.
There are no rules for the integration of Airy Functions.
Euler polynomials. Most definitions are equivalent to [1], except for the
ternary (associated) Legendre Polynomials.
There are 2*n+1 independent such polynomials for any given n >= 0 and
with:-
S(n,m,w!-,w!0,w!+) =
(1/(2*pi)) *
for u:=-pi:pi integrate (w!0 + w!+ * exp(i*u) + w!- *
exp(-i*u))^n * exp(i*m*u) * du;
which is obviously zero if |m| > n since then all terms in the expanded
integrand contain the factor exp(i*k*u) with k neq 0,
S(n,m,x,y,z) is proportional to
929
The implementation of the functions in this and the next two subsections
have, in 2019, been substantially revised by Alan Barnes. This is to bring
the notation more into line with standard (British) texts such as Whittaker
& Watson [9] and Lawden [8] and also to correct a number of errors and
omissions. These changes and additions will be itemised in the relevant
sections below.
930 CHAPTER 16. USER CONTRIBUTED PACKAGES
• jacobisn(u,k)
• jacobidn(u,k)
• jacobicn(u,k)
• jacobicd(u,k)
• jacobisd(u,k)
• jacobind(u,k)
• jacobidc(u,k)
• jacobinc(u,k)
• jacobisc(u,k)
• jacobins(u,k)
• jacobids(u,k)
• jacobics(u,k)
To determine
√ √ Integrals K(m), E(m) we use initial values a0 = 1;
the Elliptic
b0 = 1 − m ; c0 = m.
This procedure and the following one are primarily intended for use in the
numerical evaluation of the various elliptic functions and integrals rather
than for direct use by users.
Also in the original implementation there was some confusion between Leg-
endre’s form and Jacobi’s form of the incomplete elliptic integrals of the
second kind; E(u, k) denoted the first in numerical evaluations and the sec-
ond in the derivative formulae for the Jacobi elliptic functions with respect
to their second argument. This confusion was perhaps understandable as in
the literature some authors use the notation E(u, k) for the Legendre form
and others for Jacobi’s form.
To avoid any possible confusion, following Lawden [8], the notation
D(φ, k) will be used for the Legendre form.
A number of rule lists have been provided to implement, where appropri-
ate, derivatives of these functions, addition rules and periodicity and quasi-
periodicity properties and to provide simplifications for special values of
the arguments.
16.66.14.1 Elliptic F
16.66.14.2 Elliptic K
The Elliptic K function can be used as EllipticK(k) and will return the
value of the Complete Elliptic Integral of the First Kind:
Z π/2
K(k) = (1 − k 2 sin2 θ)−1/2 dθ.
0
This is one of the quarter periods of the Jacobi elliptic functions and is often
used in the calculation of other elliptic functions.
16.66.14.3 Elliptic K0
16.66.14.4 Elliptic D
16.66.14.5 Elliptic E
The Elliptic E function comes with either one or two arguments; used with
two arguments as EllipticE(u,k) it will return the value of Jacobi’s
form of the Incomplete Elliptic Integral of the Second Kind:
Z u
E(u, k) = dn2 (v, k)dv.
0
The relationship between the two forms of incomplete elliptic integrals can
be expressed as
E(u, k) = D(am(u), k).
When called with one argument EllipticE(k) will return the value of
the Complete Elliptic Integral of the Second Kind:
Z K(k)
E(k) = E(K(k), k) = dn2 (v, k)dv
0
or equivalently
Z π/2 p
E(k) = D(π/2, k) = ( 1 − k 2 sin2 θdθ.
0
16.66.14.6 Elliptic E0
These theta functions differ from those originally defined by Lisa Temme
in a number of respects. Firstly four separate functions of two arguments
are defined
• elliptictheta1(u,q) ϑ1 (u, q)
• elliptictheta2(u,q) ϑ2 (u, q)
• elliptictheta3(u,q) ϑ3 (u, q)
• ellipticthetas(u,q) ϑ4 (u, q)
rather than a single function with three arguments (with the first argument
taking integer values in the range 1 to 4). Secondly the periods are 2π, 2π, π
and π respectively (NOT 4K, 4K, 2K and 2K). Thirdly the second argument
is the nome q where |q| < 1 and hence the quasi-period is −i log q.
elliptictheta1 and elliptictheta2 are consequently multi-
valued owing to the appearance of q 1/4 in their defining expansions.
elliptictheta3 and elliptictheta4 are, however, single-valued
functions of q.
Regarded as functions of the ’parameter’ (usually denoted by τ where
q = exp(iπτ )), elliptictheta1 and elliptictheta2 are single-
valued functions of τ .
Recall that in order that |q| < 1, the imaginary part of τ must be positive.
Note also in this case q 1/4 is interpreted as exp(iπτ /4) rather than the prin-
cipal value of q 1/4 . Thus τ, 2 + τ, 4 + τ and 6 + τ produce four different
values of both elliptictheta1 and elliptictheta2 although they
all produce the same nome q.
Utilising the periodicity and quasi-periodicity of the theta functions some
generalised shift rules are implemented to shift their first argument into the
base period parallelogram with vertices
(π/2, πτ /2), (−π/2, πτ /2), (−π/2, −πτ /2), (π/2, −πτ /2).
Together with the relation ϑ1 (0, q) = 0, these shift rules serve to simplify
all four theta functions to zero when appropriate.
When the switch rounded is on and the arguments are purely numerical,
the theta functions are evaluated numerically. For complex numerical argu-
ments the switch complex must also be on.
935
• nome2mod(q)
• nome2mod!0 (q)
• nome2!K(q)
• nome2!K!0 (q)
• nome(k)
These are only operative when the switch rounded is on and their argu-
ment is numerical. The first√pair relate the nome q of the theta functions
with the moduli k and k 0 = 1 − k 2 of the associated Jacobi elliptic funct-
ions.
The second pair return the quarter-periods K and K0 respectively of the Ja-
cobi elliptic functions associated with the nome q.
Finally, nome(k) returns the nome q associated with the modulus k of a
Jacobi elliptic function and is essentially the inverse of nome2mod.
936 CHAPTER 16. USER CONTRIBUTED PACKAGES
ThreeJSymbol({J+1,M},{J,-M},{1,0});
Clebsch_Gordan({2,0},{2,0},{2,0});
16.66.18 6j symbols
SixJSymbol({7,6,3},{2,4,6});
16.66.19 Acknowledgements
Function Operator
Jν (z) BesselJ(nu,z)
Yν (z) BesselY(nu,z)
Iν (z) BesselI(nu,z)
Kν (z) BesselK(nu,z)
(1)
Hν (z) Hankel1(n,z)
(2)
Hν (z) Hankel2(n,z)
Hν (z) StruveH(nu,z)
Lν (z) StruveL(n,z)
sa,b (z) Lommel1(a,b,z)
Sa,b (z) Lommel2(a,b,z)
Ai(z) Airy_Ai(z)
Bi(z) Airy_Bi(z)
Ai0 (z) Airy_Aiprime(z)
Bi0 (z) Airy_Biprime(z)
M (a, b, z) or 1 F1 (a, b; z) or Φ(a, b; z) KummerM(a,b,z)
U (a, b, z) or z −a 2 F0 (a, b; z) or Ψ(a, b; z) KummerU(a,b,z)
Mκ,µ (z) WhittakerM(kappa,mu,z)
Wκ,µ (z) WhittakerW(kappa,mu,z)
Function Operator
(α,β)
Pn (x) JacobiP(n,alpha,beta,x)
Un (x) ChebyshevU(n,x)
Tn (x) ChebyshevT(n,x)
Ynm (x, y, z, r2) SolidHarmonicY(n,m,x,y,z,r2)
Ynm (θ, φ) SphericalHarmonicY(n,m,theta,phi)
j1 j2 j3
ThreeJSymbol({j1,m1},{j2,m2},{j3,m3})
m1 m2 m3
(j1 m1 j2 m2 |j1 j2 j3 − m3 ) Clebsch_Gordan({j1,m1},{j2,m2},{j3,m3})
j1 j2 j3
SixJSymbol({j1,j2,j3},{l1,l2,l3})
l1 l2 l3
sn(u, k) jacobisn(u,k)
dn(u, k) jacobidn(u,k)
cn(u, k) jacobicn(u,k)
cd(u, k) jacobicd(u,k)
sd(u, k) jacobisd(u,k)
nd(u, k) jacobind(u,k)
dc(u, k) jacobidc(u,k)
nc(u, k) jacobinc(u,k)
sc(u, k) jacobisc(u,k)
ns(u, k) jacobins(u,k)
ds(u, k) jacobids(u,k)
cs(u, k) jacobics(u,k)
am(u, k) jacobiam(u,k)
F (φ, k) ellipticF(phi,k)
K(k) ellipticK(k)
K 0 (k) ellipticK!’(k)
D(φ, k) ellipticD(phi,k)
E(u, k)orE(k) ellipticE(u,k) or ellipticE(k)
E 0 (k) ellipticE!’(k)
Z(u, k) jacobizeta(u,k)
ϑ1 (u, q) elliptictheta1(u,q)
ϑ2 (u, q) elliptictheta2(u,q)
ϑ3 (u, q) elliptictheta3(u,q)
ϑ4 (u, q) elliptictheta4(u,q)
Lambert ω(z) Lambert_W(z)
Function Operator
n
Binomial(n,m)
m
Motzkin(n) Motzkin(n)
Bernoulli(n) or Bn Bernoulli(n)
Euler(n) or En Euler(n)
(m)
Sn Stirling1(n,m)
(m)
Sn Stirling2(n,m)
B(z, w) Beta(z,w)
Γ(z) Gamma(z)
Bx (a, b)
normalized incomplete Beta Ix (a, b) = iBeta(a,b,x)
B(a, b)
γ(a, z)
normalized incomplete Gamma P (a, z) = iGamma(a,z)
Γ(a)
incomplete Gamma γ(a, z) m_gamma(a,z)
(a)k Pochhammer(a,k)
ψ(z) Psi(z)
ψ (n) (z) Polygamma(n,z)
Riemann’s ζ(z) Zeta(z)
Si(z) Si(z)
si(z) s_i(z)
Ci(z) Ci(z)
Shi(z) Shi(z)
Chi(z) Chi(z)
erf (z) erf(z)
erf c(z) erfc(z)
Ei(z) Ei(z)
li(z) li(z)
C(x) Fresnel_C(x)
S(x) Fresnel_S(x)
dilog(z) dilog(z)
Lin (z) Polylog(n,z)
Lerch’s transcendent Φ(z, s, a) Lerch_Phi(z,s,a)
940 CHAPTER 16. USER CONTRIBUTED PACKAGES
Bibliography
The function !
(a )
p
Gmn
pq z
(bq )
has been studied by C. S. Meijer beginning in 1936 and has been called
Meijer’s G function later on. The complete definition of Meijer’s G func-
tion can be found in [1]. Many well-known functions can be written as
G functions, e.g. exponentials, logarithms, trigonometric functions, Bessel
functions and hypergeometric functions.
Several hundreds of particular values can be found in [1].
hypergeometric ({},{},z);
z
e
hypergeometric ({1/2,1},{3/2},-x^2);
gives
atan(abs(x))
--------------
abs(x)
942 CHAPTER 16. USER CONTRIBUTED PACKAGES
The operator meijerg expects 3 arguments, namely the list of upper pa-
rameters (which may be empty), the list of lower parameters (which may be
empty too), and the argument.
The first element of the lists has to be the list of the first n or m respective
parameters, e.g. to describe
!
1
G10 x
11
0
sign( - x + 1) + sign(x + 1)
------------------------------
2
and for !
x2
G10
02
4 1 + 14 , 1 − 14
2 2
sqrt(pi)*sqrt(-----------)*sin(abs(x))*x
abs(x)*pi
-------------------------------------------
943
Bibliography
16.68.1 Overview
Purpose
Interactive Session
Loading Files
Notation
Initializations
The command coeffn
The procedure SSym
The procedure SSConL
The procedure FindSSWeights
The procedure Linearize
The procedure GenSSPoly
The procedure ToCoo
The procedure ToField
Discovery of recursion operators
Verification of symmetries
945
Bibliography
[1] Hussin, V., Kiselev, A.V., Krutov, A.O., Wolf, T.: N=2 Supersymmet-
ric a=4 - Korteweg-de Vries hierarchy derived via Gardner’s deforma-
tion of Kaup-Bousinesq equation, J. Math. Phys. 51, 083507 (2010);
doi:10.1063/1.3447731 (19 pages) link, pdf file
[2] Kiselev, A. and Wolf, T.: Supersymmetric Representations and In-
tegrable Super-Extensions of the Burgers and Bussinesq Equations,
SIGMA, Vol. 2 (2006), Paper 030, 19 pages (arXiv math-ph/0511071).
ps file, pdf file
[3] Kiselev, A. and Wolf, T.: On weakly non-local, nilpotent, and super-
recursion operators for N=1 homogeneous super-equations, Proc. Int.
Workshop “Supersymmetries and Quantum Symmetries” (SQS’05),
Dubna, July 24–31, 2005, JINR, p. 231–237. (arXiv nlin.SI/0511056)
http://theor.jinr.ru/ sqs05/SQS05.pdf dvi file, ps file,
[4] Kiselev, A. and Wolf, T.: Classification of integrable super-equations
by the SsTools environment, Comp Phys Comm, Vol. 177, no. 3
(2007) p 315-328 (and on arXiv: nlin.SI/0609065). dvi file, ps file,
pdf file
[5] I. S. Krasil’shchik, P. H. M. Kersten, Symmetries and recursion oper-
ators for classical and supersymmetric differential equations, Kluwer
Acad. Publ., Dordrecht etc, (2000)
946 CHAPTER 16. USER CONTRIBUTED PACKAGES
This package implements the Gosper algorithm for the summation of series.
It defines operators SUM and PROD. The operator SUM returns the indefinite
or definite summation of a given expression, and PROD returns the product
of the given expression.
This package loads automatically.
Author: Fujio Kako.
This package implements the Gosper algorithm for the summation of series.
It defines operators SUM and PROD. The operator SUM returns the indef-
inite or definite summation of a given expression, and the operator PROD
returns the product of the given expression. These are used with the syntax:
If there is no closed form solution, these operators return the input un-
changed. UPLIM and LOLIM are optional parameters specifying the lower
limit and upper limit of the summation (or product), respectively. If UPLIM
is not supplied, the upper limit is taken as K (the summation variable itself).
For example:
sum(n**3,n);
sum(a+k*r,k,0,n-1);
sum(1/((p+(k-1)*q)*(p+k*q)),k,1,n+1);
prod(k/(k-2),k);
n
X n
Y
log f (k) = log f (k)
k=n0 k=n0
n
Y n
X
exp f (k) = exp f (k)
k=n0 k=n0
Other functions, as shown in the test file for the case of binomials and for-
mal products, can be summed by providing LET rules which must relate the
functions evaluated at k and k − 1 (k being the summation variable).
There is a switch TRSUM (default OFF). If this switch is on, trace messages
are printed out during the course of Gosper’s algorithm.
948 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.70.1 Introduction
First the data structure for a linear representation has to be explained. rep-
resentation is a list consisting of the group identifier and equations which
assign matrices to the generators of the group.
Example:
949
rr:=mat((0,1,0,0),
(0,0,1,0),
(0,0,0,1),
(1,0,0,0));
sp:=mat((0,1,0,0),
(1,0,0,0),
(0,0,0,1),
(0,0,1,0));
representation:={D4,rD4=rr,sD4=sp};
In this section the operators are described which give access to the stored
information for a group. First the operators for the abstract groups are given.
Then it is described how to get the irreducible representations for a group.
availablegroups();
returns the list of all groups for which the information such as irreducible
representations is stored. In the following group is always one of these
group identifiers.
printgroup(group);
returns the list of all group elements;
generators(group);
returns a list of group elements which generates the group. For the definition
of a linear representation matrices for these generators have to be defined.
charactertable(group);
returns a list of the characters corresponding to the irreducible representa-
tions of this group.
charactern(group,nr);
returns the character corresponding to the nr-th irreducible representation
of this group as a list (see also character).
irreduciblereptable(group);
returns the list of irreducible representations of the group.
irreduciblerepnr(group,nr);
returns an irreducible representation of the group. The output is a list of
the group identifier and equations assigning the representation matrices to
group elements.
setgenerators(K4,{s1K4,s2K4},
{s1K4^2=id,s2K4^2=id,s1K4@s2K4=s2K4@s1K4});
setelements(group,relationlist);
The group elements except the neutral element are given as product of the
defined generators. The neutral element is always called id.
Example:
setelements(K4,
{s1K4=s1K4,s2K4=s2K4,rK4=s1K4@s2K4});
setgrouptable(group,grouptable);
installs the group table.
Example:
tab:=
mat((grouptable, id, s1K4, s2K4, rK4),
(id , id, s1K4, s2K4, rK4),
(s1K4 , s1K4, id, rK4,s2K4),
(s2K4 , s2K4, rK4, id,s1K4),
(rK4 , rK4, s2K4, s1K4, id));
setgrouptable(K4,tab);
952 CHAPTER 16. USER CONTRIBUTED PACKAGES
Rsetrepresentation(representation,type);
is used to define the real irreducible representations of the group. The vari-
able type is either realtype or complextype which indicates the type of the
real irreducible representation.
Example:
eins:=mat((1));
mineins:=mat((-1));
rep3:={K4,s1K4=eins,s2K4=mineins};
Rsetrepresentation(rep3,realtype);
Csetrepresentation(representation);
This defines the complex irreducible representations.
setavailable(group);
terminates the installation of the group203. It checks some properties of the
irreducible representations and makes the group available for the operators
in Sections 2 and 3.
storegroup(group,filename);
writes the information concerning the group to the file with name filename.
loadgroups(filename);
loads a user defined group from the file filename into the system.
Bibliography
TAYLOR(EXP:algebraic,
VAR:kernel,VAR0:algebraic,ORDER:integer[,...])
:algebraic.
taylor(e^(x^2+y^2),x,0,2,y,0,2);
2 2 2 2 3 3
1 + y + x + y *x + O(x ,y )
Note that once the expansion has been done it is not possible to calculate
higher orders. Instead of a kernel, VAR may also be a list of kernels. In this
case expansion will take place in a way so that the sum of the degrees of the
kernels does not exceed ORDER. If VAR0 evaluates to the special identifier
INFINITY, expansion is done in a series in 1/VAR instead of VAR.
The expansion is performed variable per variable, i.e. in the example above
by first expanding exp(x2 + y 2 ) with respect to x and then expanding every
coefficient with respect to y.
There are two extra operators to compute the Taylor expansions of implicit
954 CHAPTER 16. USER CONTRIBUTED PACKAGES
IMPLICIT_TAYLOR(F:algebraic,
VAR:kernel,DEPVAR:kernel,
VAR0:algebraic,DEPVAR0:algebraic,
ORDER:integer)
:algebraic
takes a function F depending on two variables VAR and DEPVAR and com-
putes the Taylor series of the implicit function DEPVAR(VAR) given by the
equation F(VAR,DEPVAR) = 0, around the point VAR0. (Violation of the
necessary condition F(VAR0,DEPVAR0)=0 causes an error.) For example,
1 2 1 4 6
1 - ---*x - ---*x + O(x )
2 8
The operator
INVERSE_TAYLOR(F:algebraic,VAR:kernel,DEPVAR:kernel,
VAR0:algebraic,ORDER:integer)
: algebraic
inverse_taylor(exp(x)-1,x,y,0,8);
yields
1 2 1 3 1 4 1 5 9
y - ---*y + ---*y - ---*y + ---*y + (3 terms) + O(y )
2 3 4 5
identifier ALL. The latter setting specifies that all terms are to be printed.
The default setting is 5.
The PART operator can be used to extract subexpressions of a Taylor expan-
sion in the usual way. All terms can be accessed, irregardless of the value
of the variable TAYLORPRINTTERMS.
If the switch TAYLORKEEPORIGINAL is set to ON the original expression
EXP is kept for later reference. It can be recovered by means of the operator
TAYLORORIGINAL(EXP:exprn):exprn
An error is signalled if EXP is not a Taylor kernel or if the original ex-
pression was not kept, i.e. if TAYLORKEEPORIGINAL was OFF during
expansion. The template of a Taylor kernel, i.e. the list of all variables with
respect to which expansion took place together with expansion point and
order can be extracted using .
TAYLORTEMPLATE(EXP:exprn):list
This returns a list of lists with the three elements (VAR,VAR0,ORDER).
As with TAYLORORIGINAL, an error is signalled if EXP is not a Taylor
kernel.
The operator
TAYLORTOSTANDARD(EXP:exprn):exprn
converts all Taylor kernels in EXP into standard form and resimplifies the
result.
The boolean operator
TAYLORSERIESP(EXP:exprn):boolean
may be used to determine if EXP is a Taylor kernel. (Note that this operator
is subject to the same restrictions as, e.g., ORDP or NUMBERP, i.e. it may
only be used in boolean expressions in IF or LET statements.
Finally there is
TAYLORCOMBINE(EXP:exprn):exprn
which tries to combine all Taylor kernels found in EXP into one. Opera-
tions currently possible are:
Application of unary operators like LOG and ATAN will nearly always suc-
956 CHAPTER 16. USER CONTRIBUTED PACKAGES
ceed. For binary operations their arguments have to be Taylor kernels with
the same template. This means that the expansion variable and the expan-
sion point must match. Expansion order is not so important, different order
usually means that one of them is truncated before doing the operation.
If TAYLORKEEPORIGINAL is set to ON and if all Taylor kernels in exp
have their original expressions kept TAYLORCOMBINE will also combine
these and store the result as the original expression of the resulting Taylor
kernel. There is also the switch TAYLORAUTOEXPAND (see below).
There are a few restrictions to avoid mathematically undefined expressions:
it is not possible to take the logarithm of a Taylor kernel which has no terms
(i.e. is zero), or to divide by such a beast. There are some provisions made
to detect singularities during expansion: poles that arise because the denom-
inator has zeros at the expansion point are detected and properly treated, i.e.
the Taylor kernel will start with a negative power. (This is accomplished by
expanding numerator and denominator separately and combining the re-
sults.) Essential singularities of the known functions (see above) are han-
dled correctly.
Differentiation of a Taylor expression is possible. If you differentiate with
respect to one of the Taylor variables the order will decrease by one.
Substitution is a bit restricted: Taylor variables can only be replaced by
other kernels. There is one exception to this rule: you can always substi-
tute a Taylor variable by an expression that evaluates to a constant. Note
that REDUCE will not always be able to determine that an expression is
constant.
Only simple taylor kernels can be integrated. More complicated expressions
that contain Taylor kernels as parts of themselves are automatically con-
verted into a standard representation by means of the TAYLORTOSTANDARD
operator. In this case a suitable warning is printed.
It is possible to revert a Taylor series of a function f , i.e., to compute the
first terms of the expansion of the inverse of f from the expansion of f .
This is done by the operator
TAYLORREVERT(EXP:exprn,OLDVAR:kernel, NEWVAR:kernel):exprn
EXP must evaluate to a Taylor kernel with OLDVAR being one of its ex-
pansion variables. Example:
gives
957
2 3 4 5 6
x + x + 2*x + 5*x + 14*x + O(x )
16.71.2 Caveats
taylor(x*y/(x+y),x,0,2,y,0,2);
causes an error
Note that it is not generally possible to apply the standard REDUCE oper-
ators to a Taylor kernel. For example, PART, COEFF, or COEFFN cannot
be used. Instead, the expression at hand has to be converted to standard
form first using the TAYLORTOSTANDARD operator.
958 CHAPTER 16. USER CONTRIBUTED PACKAGES
axis. Those of the arc tangent and arc cotangent functions are cho-
sen to be compatible with this: both have essential singularities at the
points ±i. The branch cut of arc tangent is the straight line along the
imaginary axis connecting +1 to −1 going through ∞ whereas that of
arc cotangent goes through the origin. Consequently, the branch cut
of the inverse hyperbolic tangent resp. cotangent lies on the real axis
and goes from −1 to +1, that of the latter across 0, the other across
∞.
The error message can currently only appear when you try to calculate
the inverse tangent or cotangent of a Taylor kernel that starts with a
negative degree. The case of a logarithm of a Taylor kernel whose
constant term is a negative real number is not caught since it is difficult
to detect this in general.
At the moment there is only one REDUCE package that I know of: the
extendible power series package by Alan Barnes and Julian Padget. In my
opinion there are two major differences:
961
• The interface. They use the domain mechanism for their power series,
I decided to invent a special kind of kernel. Both approaches have
advantages and disadvantages: with domain modes, it is easier to do
certain things automatically, e.g., conversions.
• The concept of an extendible series: their idea is to remember the
original expression and to compute more coefficients when more of
them are needed. My approach is to truncate at a certain order and
forget how the unexpanded expression looked like. I think that their
method is more widely usable, whereas mine is more efficient when
you know in advance exactly how many terms you need.
962 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.72.1 Introduction
16.72.2 PS Operator
Syntax:
PS(EXPRN:algebraic,DEPVAR:kernel, ABOUT:algebraic):ps object
The PS operator returns a power series object (a tagged domain element)
representing the univariate formal power series expansion of EXPRN with
respect to the dependent variable DEPVAR about the expansion point
ABOUT. EXPRN may itself contain power series objects.
The algebraic expression ABOUT should simplify to an expression which
963
psexplim 6;
ps(log x,x,1);
ps(e**(sin x),x,0);
ps(x/(1+x),x,infinity);
ps(sin x/(1-cos x),x,0);
For example
operator sech;
forall x let df(sech x,x)= - sech x * tanh x;
let sech 0 = 1;
ps(sech(x**2),x,0);
ps(int(e**x/x,x),x,1);
964 CHAPTER 16. USER CONTRIBUTED PACKAGES
Note that if the integration variable is the same as the expansion variable
then REDUCE’s integration package is not called; if on the other hand the
two variables are different then the integrator is called to integrate each of
the coefficients in the power series expansion of the integrand. The constant
of integration is zero by default.
Syntax:
PSEXPLIM(UPTO:integer):integer
or
PSEXPLIM():integer
Calling this operator sets an internal variable of the TPS package to the
value of UPTO (which should evaluate to an integer).
This internal variable controls how many terms of a power series are printed.
The value returned by PSEXPLIM is the previous value of this variable. The
default value is six.
If PSEXPLIM is called with no argument, the current value for the expan-
sion limit is returned.
Syntax:
ON PSPRINTORDER
or
OFF PSPRINTORDER
When ON this switch causes the remainder of the power series to be printed
in big-O notation. Otherwise, three dots are printed. The default is ON.
Syntax:
PSORDLIM(UPTO:integer):integer
or
PSORDLIM():integer
965
where the expression being expanded is identically zero, but is not recog-
nized as such by REDUCE.
Syntax:
PSTERM(TPS:power series object, NTH:integer):algebraic
The operator PSTERM returns the NTH term of the existing power series
object TPS. If NTH does not evaluate to an integer or TPS to a power series
object an error results. It should be noted that an integer is treated as a
power series.
Syntax:
PSORDER(TPS:power series object):integer
The operator PSORDER returns the order, that is the degree of the first non-
zero term, of the power series object TPS. TPS should evaluate to a power
series object or an error results. If TPS is zero, the identifier UNDEFINED
is returned.
Syntax:
PSSETORDER(TPS:power series object, ORD:integer):integer
966 CHAPTER 16. USER CONTRIBUTED PACKAGES
The operator PSSETORDER sets the order of the power series TPS to the
value ORD, which should evaluate to an integer. If TPS does not evaluate
to a power series object, then an error occurs. The value returned by this
operator is the previous order of TPS, or 0 if the order of TPS was undefined.
This operator is useful for setting the order of the power series of a function
defined by a differential equation in cases where the power series package
is inadequate to determine the order automatically.
Syntax:
PSDEPVAR(TPS:power series object) :identifier
The operator PSDEPVAR returns the expansion variable of the power series
object TPS. TPS should evaluate to a power series object or an integer,
otherwise an error results. If TPS is an integer, the identifier UNDEFINED
is returned.
Syntax:
PSEXPANSIONPT(TPS:power series object):algebraic
The operator PSEXPANSIONPT returns the expansion point of the power
series object TPS. TPS should evaluate to a power series object or an inte-
ger, otherwise an error results. If TPS is integer, the identifier UNDEFINED
is returned. If the expansion is about infinity, the identifier INFINITY is
returned.
Syntax:
PSFUNCTION(TPS:power series object):algebraic
The operator PSFUNCTION returns the function whose expansion gave rise
to the power series object TPS. TPS should evaluate to a power series object
or an integer, otherwise an error results.
967
Syntax:
PSCHANGEVAR(TPS:power series object, X:kernel):power series ob-
ject
The operator PSCHANGEVAR changes the dependent variable of the power
series object TPS to the variable X. TPS should evaluate to a power series
object and X to a kernel, otherwise an error results. Also X should not
appear as a parameter in TPS. The power series with the new dependent
variable is returned.
Syntax:
PSREVERSE(TPS:power series object):power series
Power series reversion. The power series TPS is functionally inverted. Four
cases arise:
1. If the order of the series is 1, then the expansion point of the inverted
series is 0.
2. If the order is 0 and if the first order term in TPS is non-zero, then the
expansion point of the inverted series is taken to be the coefficient of
the zeroth order term in TPS.
3. If the order is -1 the expansion point of the inverted series is the point
at infinity. In all other cases a REDUCE error is reported because the
series cannot be inverted as a power series. Puiseux expansion would
be required to handle these cases.
4. If the expansion point of TPS is finite it becomes the zeroth order term
in the inverted series. For expansion about 0 or the point at infinity
the order of the inverted series is one.
ps(sin x,x,0);
psreverse(ws); % produces series for asin x about x=0.
ps(exp x,x,0);
968 CHAPTER 16. USER CONTRIBUTED PACKAGES
Syntax:
PSCOMPOSE(TPS1:power series, TPS2:power series):power series
PSCOMPOSE performs power series composition. The power series TPS1
and TPS2 are functionally composed. That is to say that TPS2 is substituted
for the expansion variable in TPS1 and the result expressed as a power se-
ries. The dependent variable and expansion point of the result coincide with
those of TPS2. The following conditions apply to power series composition:
1. If the expansion point of TPS1 is 0 then the order of the TPS2 must
be at least 1.
2. If the expansion point of TPS1 is finite, it should coincide with the
coefficient of the zeroth order term in TPS2. The order of TPS2 should
also be non-negative in this case.
3. If the expansion point of TPS1 is the point at infinity then the order of
TPS2 must be less than or equal to -1.
If these conditions do not hold the series cannot be composed (with the
current algorithm terms of the inverted series would involve infinite sums)
and a REDUCE error occurs.
Examples of power series composition include the following.
Syntax:
COEFF*(X-ABOUT)**POWER
COEFF*(1/X)**POWER
is constructed and returned. This enables power series whose general term
is known to be constructed and manipulated using the other procedures of
the power series package.
J and X should be distinct simple kernels. The algebraics ABOUT, COEFF
and POWER should not depend on the expansion variable X, similarly the
algebraic ABOUT should not depend on the summation variable J. The
algebraic POWER should be a strictly increasing integer valued function
of J for J in the range LOWLIM to INFINITY.
pssum(n=0,1,x,0,n*n);
% Produces the power series summation for n=0 to
% infinity of x**(n*n).
pssum(m=1,(-1)**(m-1)/(2m-1),y,1,2m-1);
% Produces the power series expansion of atan(y-1)
% about y=1.
pssum(j=1,-1/j,x,infinity,j);
% Produces the power series expansion of log(1-1/x)
% about the point at infinity.
pssum(n=0,1,x,0,2n**2+3n) + pssum(n=1,1,x,0,2n**2-3n);
% Produces the power series summation for n=-infinity
970 CHAPTER 16. USER CONTRIBUTED PACKAGES
% to +infinity of x**(2n**2+3n).
Syntax:
PSTAYLOR(EXPRN:algebraic,DEPVAR:kernel, ABOUT:algebraic):ps ob-
ject
The PSTAYLOR operator returns a power series object (a tagged domain
element) representing the univariate formal Taylor series expansion of EX-
PRN with respect to the dependent variable DEPVAR about the expansion
point ABOUT. Unlike the operator PS it directly evaluates the nth deriva-
tive of the expression EXPRN wrt the variable DEPVAR at the expansion
point ABOUT to find the nth term of the series. Poles (and other singulari-
ties) at the expansion point will cause an error – PS and TAYLOR are more
robust in this respect. The PSTAYLOR operator may be useful in contexts
where PS fails to build a suitable recurrence relation automatically and re-
ports too deep a recursion in ps!:unknown!-crule. A typical example
is the expansion of the Γ function about an expansion point which is not a
non-positive integer.
The algebraic expression ABOUT should simplify to an expression which
is independent of the dependent variable DEPVAR, otherwise an error will
result.
If ABOUT is the identifier INFINITY then the power series expansion
about DEPVAR = ∞ is obtained in ascending powers of 1/DEPVAR.
Syntax:
PSCOPY(TPS:power series):power series
This procedure returns a copy of the power series TPS. The copy has no
shared sub-structures in common with the original series. This enables sub-
stitutions to be performed on the series without side-effects on previously
computed objects. For example:
clear a;
b := ps(sin(a*x)), x, 0);
b where a => 1;
971
will result in a being set to 1 in each of the terms of the power series and
the resulting expressions being simplified. Owing to the way power series
objects are implemented using Lisp vectors, this has the side-effect that the
value of b is changed. This may be avoided by copying the series with
PSCOPY before applying the substitution, thus:
b := ps(sin(a*x)), x, 0);
pscopy b where a => 1;
Syntax:
PSTRUNCATE(TPS:power series POWER: integer) :algebraic
This procedure truncates the power series TPS discarding terms of order
higher than POWER. The series is extended automtically if the value of
POWER is greater than the order of last term calculated to date.
b := ps(sin x, x, 0);
a := pstruncate(b, 11);
will result in a being set to the eleventh order polynomial resulting in trun-
cating the series for sinx after the term involving x11 .
If POWER is less than the order of the series then 0 is returned. If POWER
does not simplify to an integer or if TPS is not a power series object then
Reduce errors result.
As power series objects are domain elements they may be combined to-
gether in algebraic expressions in algebraic mode of REDUCE in the nor-
mal way.
For example if A and B are power series objects then the commands such
as:
a*b;
a/b;
a**2+b**2;
will produce power series objects representing the product,quotient and the
972 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.72.20 Differentiation
a:=ps(1/(1+x),x,0);
b:=sin a;
b:=ps(sin(a),x,0);
or
b:=ps(sin(1/(1+x)),x,0);
or
***** Logarithmic Singularity
occurs but occasionally a division by zero error or some drastic error like
(for PSL) binding stack overflow may occur.
There is no simple way to write the results of power series calculation to a
file and read them back into REDUCE at a later stage.
974 CHAPTER 16. USER CONTRIBUTED PACKAGES
This module provides facilities for the numerical evaluation and algebraic
simplification of expressions involving trigonometrical functions with ar-
guments given in degrees rather than in radians. The degree-valued inverse
functions are also provided.
Author: Alan Barnes
16.74.1 Introduction
This module provides facilities for the numerical evaluation and algebraic
simplification of expressions involving trigonometrical functions with ar-
guments given in degrees rather than in radians. The degree-valued inverse
functions are also provided.
Any user at all familiar with the normal trig functions in REDUCE should
have no trouble in using the facilities of this module. The names of the
degree-based functions are those of the normal trig functions with the let-
ter D appended, for example SIND, COSD and TAND denote the sine, co-
sine and tangent repectively and their corresponding inverse functions are
ASIND, ACOSD and ATAND. The secant, cosecant and cotangent funct-
ions and their inverses are also supported and, indeed, are treated more as
first class objects than their corresponding radian-based functions which
are often converted to expressions involving sine and cosine by some of the
standard REDUCE simplifications rules.
Below I give a brief description of the facilities available together with
a few examples of their use. More examples and the output that they
should produce may be found in the test files trigd-num.tst and
trigd-simp.tst and their corresponding log files with extension .rlg
which may be found in the directory packages/misc of the REDUCE
distribution along with the source code of the module.
These degree-based functions are probably best regarded as functions de-
fined for real values only, but complex arguments are supported for com-
pleteness. The numerical evaluation routines are fairly comprehensive for
both real and complex arguments. However, few simplifications occur for
trigd functions with complex arguments.
The range of the principal values returned by the inverse functions is con-
sistent with those of the corresponding radian-valued functions. More pre-
cisely, for ASIND, ATAND and ACSCD the (closure of the) range is [-90,
976 CHAPTER 16. USER CONTRIBUTED PACKAGES
90] whilst for ACOSD, ACOTD and ASECD the (closure of the) range is [0,
180]. In addition the operator ATAN2D is the degree valued version of the
two argument inverse tangent function which returns an angle in the inter-
val (-180, 180] in the correct quadrant depending on the signs of its two
arguments. For X > 0, ATAN2D(Y, X) returns the same numerical value
as ATAND(Y/X). If X = 0 then ±90 is returned depending on the sign of
Y.
It might be thought that the facilities provided in this module couldbe easily
provided by defining suitable rule lists to convert between the radian and
degree-based versions of the trig functions. For example:
However, this approach seldom works — try it! The result produced by
step 4 defeats the current rule52 used to simplify expressions of the form
sin(x + 2π) although it does manage step 6. The rule list approach is more
reliable if differentiation, integration or numerical evaluation of expressions
involving SIND etc. is required. However it is not particularly convenient
even if the rules and operator declarations are stored in a file so that they
may be loaded at will.
This module aims to overcome these deficiences by providing the degree-
based trig functions as first class objects of the system just like their radian-
based cousins. The aim is to provide facilities for numerical evaluation,
symbolic simplification and differentiation totally analgous to those for the
the basic trig functions and their inverses. It is hoped that the module will
be of value to students and teachers at secondary school level as well as be-
ing sufficiently powerful and flexible to be of genuine utility in fields where
angles measured in degrees (and arc minutes and seconds) are in common
usage. For more advanced situations (involving integration, complex argu-
ments and values etc.), users are urged to use the standard trig functions
already provided by the system.
52
These rules may be improved in the next version of REDUCE.
977
16.74.2 Simplification
Extra rules can be added by the user for example addition formulae, dou-
ble angle rules and tangent half-angle formulae as and when required as
described in chapter 11.
978 CHAPTER 16. USER CONTRIBUTED PACKAGES
Rules are provided for the symbolic differentiation of all the trig functions
and their inverses. These rules are sufficient fot the power series of the trig
functions and their inverses to be found using either the TPS or TAYLOR
packages in the standard way.
When the switch ROUNDED is ON and the arguments of the operators evalu-
ate to numbers, then the floating point value of the expression is calculated
to the currently specified PRECISION in the normal way. The bigfloat
capabilities are the same as for the standard trig functions.
If these functions are supplied with complex numerical arguments, numeri-
cal evaluation will NOT be performed when the switch ROUNDED is ON, but
the switch COMPLEX is OFF — the input expression will be returned basi-
cally unaltered. Similarly inputs such as ASIND(2) or ASECD(0.5) are
not evaluated numerically. The values of these expressions are, of course,
complex.
If the switch COMPLEX is also ON , numerical evaluation is performed. For
example:
1: load_package trigd$
2: on rounded;
3: asecd(2);
60.0
4: asecd(0.5);
asecd(0.5)
5: on complex;
6: asecd(0.5);
75.4561292902*i
979
The function ATAN2D (like ATAN2) is only defined if BOTH its arguments
are real. If they are also numerical, it will be evaluated whenever ROUNDED
is ON. Attempting to evaluate it with complex numerical arguments will
cause either the unaltered expression to be returned or an error to be raised
when the switch COMPLEX is OFF or ON respectively.
These operators are not actually part of the TRIGD module but of the RE-
DUCE core system. However, they are not currently documented in the
main manual. Currently they are purely numeric operators; when ROUNDED
is OFF they basically return the input expression (perhaps with their param-
eter simplified somewhat).
Note the sine of an angle specified in degrees, minutes and seconds cannot
be calculated by calling SIND directly with a dms list (i.e. as a list of length
3). Instead one must first convert the dms values to degrees using a call to
DMS2DEG and then call SIND on the result. Applied directly to a list (of
980 CHAPTER 16. USER CONTRIBUTED PACKAGES
any length) any TRIGD function wil be applied to each member of the list
separately just like most other REDUCE operators. Here is an example
illustrating tese points:
1: load_package trigd$
2: on rounded;
0.872567064923
{0.866025403784,0.707106781187,0.5}
5: off rounded;
sqrt(3) sqrt(2) 1
{---------,---------,---}
2 2 2
Although not directly related to the trig functions, the module TRIGD also
provides an operator ARGD; when the switches ROUNDED and COMPLEX
are both ON, it will return the argument in degrees of the complex number
supplied as its parameter — supplying zero as the parameter causes an error
to be raised. If only ROUNDED is ON, ARGD will return the argument of the
real numerical value supplied as its parameter — this will be 0 or 180 when
the value is positive or negative respectively.
The operator ARG is similar to ARGD, but returns the argument expressed
in radians. There is also an operator NORM which returns the modulus (or
absolute value or norm) of a complex number. ARG and NORM are actu-
ally part of the REDUCE core system, but are not currently documented
981
in the main manual. Currently they are purely numeric operators; when
ROUNDED is OFF they basically return the input expression (perhaps with
their parameter simplified).
Example
1: load_package trigd$
2: on rounded;
3: {argd(-5), argd(1+i)};
{180.0,argd(i + 1)}
4: on complex;
5: {argd(1+i), argd(-1-i)};
{45.0, - 135.0}
6: {arg(3+4i), norm(3+4i)};
{0.927295218002,5.0}
The behaviour of the numerical evaluation routines for inverse trig functions
with complex arguments at branch points could be improved; these values
are undefined and attempting to evaluate such a function at one of its branch
points ought to raise an error, however sometimes the input expression will
be returned unaltered. It is hoped to improve this behaviour in due course.
Currently there are no facilities analogous to those provided in the module
TRIGSIMP for the standard trig. functions. There users have a wide range
of standard simplification formulae available for use and can control which
are to be used depending on the requirements of their particular applica-
tion: whether to eliminate sin in favour of cos or vice-versa or to get rid
of both in favour of tan of half-angles; or whether to use the trigonometri-
cal addition formulae in order to transform trig functions whose arguments
are sums into a form where the arguments are single terms or whether to
982 CHAPTER 16. USER CONTRIBUTED PACKAGES
53
One is perhaps reminded here of the (in)famous bilingual pun: peccavi attributed to Charles
James Napier — apparently no relation to his logarithmic namesake – see Wikipedia for details!
983
16.75.1 Introduction
16.75.1.1 Example
REDUCE computes an anti derivative to the given function using the Weirstrass
substitution u = tan( x2 ), and then the Risch algorithm is used, returning:
2 arctan(3 tan( x2 ))
,
3
which is discontinuous at all odd multiples of π. Yet our original function is contin-
uous everywhere on the real line, and so by the Fundamental Theorem of Calculus,
any anti-derivative should also be everywhere continuous. The problem arises from
the substitution used to transform the given trigonometric function to a rational
function: often, the substituted function is discontinuous, and spurious discontinu-
ities are introduced as a result.
Jeffery and Richs’ algorithm returns the following to the given problem:
x−π
Z
3 x
dx = 2 arctan(3 tan( )) + 2πb c
5 − 4 cos(x) 2 2π
which differs from (2) by the constant 2π, and this is the correct way of removing
the discontinuity.
984 CHAPTER 16. USER CONTRIBUTED PACKAGES
2u u2 − 1 −2du
Z Z
f (sin x, cos x) dx = f ( , ) .
1 + u2 1 + u2 1 + u2
The integral in u is now evaluated using the standard routines of the system, then
u is substituted for. Call the result ĝ(x). Next we calculate
where the point b is given in the table. the corrected integral is then
x−b
Z
g(x) = f (sin x, cos x) dx = ĝ(x) + Kb c,
p
where the period p is taken from the table, and bxc is the floor function.
The name of the function used in REDUCE to implement these ideas is trigint,
which has the following syntax:
trigint(exp,var),
985
where exp is the expression to be integrated, and var is the variable of integration.
If trigint is used to calculate the integrals of trigonometric functions for which no
substitution is necessary, then non standard results may occur. For example, if we
calculate
trigint(cos(x),x),
we obtain
2 tan x2
tan x2 2 + 1
which, by using simple trigonometric identities, simplifies to:
2 tan x2 2 tan x2 x x x
→ x → 2 sin cos → sin 2 → sin x,
tan x2 2 + 1 2
sec 2 2 2 2
which is the answer we would normally expect. In the absence of a normal form
for trigonometric functions though, both answers are equally valid, although most
would prefer the simpler answer sin x. Thus, some interesting trigonometric iden-
tities could be derived from the program if one so wished.
16.75.3.1 Examples
Using our example in (1), we compute the corrected result, and show a few other
examples as well:
1: trigint(3/(5-4*cos(x)),x);
x - pi + x
2*(atan(3*tan(---)) + floor(-----------)*pi)
2 2*pi
2: trigint(3/(5+4*sin(x)),x);
2
pi + 2*x - pi + 2*pi*x
2*(atan(3*tan(----------)) + floor(-----------------)*pi
4 4
986 CHAPTER 16. USER CONTRIBUTED PACKAGES
- pi + 2*x
+ floor(-------------)*pi)
4*pi
3: trigint(15/(cos(x)*(5-4*cos(x))),x);
x - pi + x x
8*atan(3*tan(---)) + 8*floor(-----------)*pi - 3*log(tan(---) - 1)
2 2*pi 2
x
+ 3*log(tan(---) + 1)
2
The corrected expressions can now be used to calculate some definite integrals,
provided the region of integration lies between adjacent singularities. For example,
using our earlier function, we can use the corrected primitive to calculate
Z 4π
1
dx (16.96)
0 2 + cos x
trigint returns the answer below to give an indefinite integral, F (x):
x
tan(---)
2 - pi + x
2*sqrt(3)*(atan(----------) + floor(-----------)*pi)
sqrt(3) 2*pi
------------------------------------------------------
3
sub(x=4*pi,F)-sub(x=0,F);
4*sqrt(3)*pi
-----------------
3
and this is the correct value of the definite integral. Note that although the expres-
sion in (*) is continuous, the functions value at the points x = π, 3π etc. must
be intepreted as a limit, and these values cannot substituted directly into the for-
mula given in (*). Hence care should be taken to ensure that the definite integral
is well defined, and that singularities are dealt with appropriately. For more details
of this in REDUCE,please see the documentation for the cwi addition to the def int
package.
The package includes a facility to trace in some detail the inner workings of the
ratint program. Messages are given at key points of the algorithm, together with
the results obtained. These messages are displayed whenever the switch tracetrig
is on, which is done in REDUCE with the following command:
on tracetrig;
This switch is off by default. In particular, the messages inform the user which
substitution is being tried, and the result of that substitution. The error message
means that REDUCE has tried all four of the Weierstraß substitutions, and the
system’s standard integrator is unable to integrate after the substitution has been
completed.
This program was written whilst the author was a placement student at ZIB Berlin.
Please refer all suggestions, comments or bugs therefore to Winfried Neun, Symbo-
lik, ZIB, Takustrasse 7, D- 14195 Berlin Dahlem, Germany (e-mail [email protected]).
988 CHAPTER 16. USER CONTRIBUTED PACKAGES
Bibliography
[Jeff] Jeffery, D.J. and Rich, A.D. The Evaluation of Trigonometric Integrals
avoiding Spurious Discontinuities , ACM Trans. Math Software 20, 1,
1994, pages 124–135, DOI: 10.1145/174603.174409.
16.76.1 Introduction
The REDUCE package TRIGSIMP is a useful tool for all kinds of problems re-
lated to trigonometric and hyperbolic simplification and factorization. There are
three operators included in TRIGSIMP: trigsimp, trigfactorize and triggcd. The
first is for simplifying trigonometric or hyperbolic expressions and has many opt-
ions, the second is for factorizing them and the third is for finding the greatest
common divisor of two trigonometric or hyperbolic polynomials. This package is
automatically loaded when one of these operators is used.
As there is no normal form for trigonometric and hyperbolic expressions, the same
function can convert in many different directions, e.g. sin(2x) ↔ 2 sin(x) cos(x).
The user has the possibility to give several parameters to the operator trigsimp
in order to influence the transformations. It is possible to decide whether or not a
rational expression involving trigonometric and hyperbolic functions vanishes.
To simplify an expression f, one uses trigsimp(f[,options]). For exam-
ple:
trigsimp(sin(x)^2+cos(x)^2);
1. sin∗ or cos;
2. sinh∗ or cosh;
989
5. keepalltrig;
From each of the first four groups one can use at most one option, otherwise an
error message will occur. Options can be given in any order.
The first group fixes the preference used while transforming a trigonometric ex-
pression:
trigsimp(sin(x)^2);
2
sin(x)
trigsimp(sin(x)^2, cos);
2
- cos(x) + 1
trigsimp(sin(2x+y));
2
2*cos(x)*cos(y)*sin(x) - 2*sin(x) *sin(y) + sin(y)
trigsimp(sin(x)*cos(y), combine);
sin(x - y) + sin(x + y)
-------------------------
2
With compact, the REDUCE operator compact [2] is applied to f. This often
leads to a simple form, but in contrast to expand one does not get a normal form.
990 CHAPTER 16. USER CONTRIBUTED PACKAGES
For example:
trigsimp((1-sin(x)^2)^20*(1-cos(x)^2)^20, compact);
40 40
cos(x) *sin(x)
With an option from the fourth group, the input expression is transformed to
trigonometric, hyperbolic or exponential form respectively:
trigsimp(sin(x), hyp);
- sinh(i*x)*i
trigsimp(sinh(x), expon);
2*x
e - 1
----------
x
2*e
trigsimp(e^x, trig);
cos(i*x) - sin(i*x)*i
Usually, tan, cot, sec, csc are expressed in terms of sin and cos. It can
sometimes be useful to avoid this, which is handled by the option keepalltrig:
trigsimp(tan(x+y), keepalltrig);
- (tan(x) + tan(y))
----------------------
tan(x)*tan(y) - 1
Alternatively, the options tan and/or tanh can be given to convert the output to
the specified form as far as possible:
trigsimp(tan(x+y), tan);
- (tan(x) + tan(y))
----------------------
tan(x)*tan(y) - 1
991
By default, the other functions used will be cos and/or cosh, unless the other
desired functions are also specified in which case this choice will be respected.
The final possibility is to specify additional target arguments for the trigonometric
or hyperbolic functions, each of which should have the form of a variable divided
by a positive integer. These additional arguments are treated as if they had oc-
curred within the expression to be simplified, and their denominators are used in
determining the overall denominator to use for each variable in the simplified form:
x y
tan(---) + tan(---)
2 2
cos(4*x) - 4*cos(2*x) + 3
---------------------------
8
trigsimp((sinh(x)+cosh(x))^n+(cosh(x)-sinh(x))^n, expon);
1 n n*x
(----) + e
x
e
trigsimp(ws, hyp);
2*cosh(n*x)
trigsimp((cosh(a*n)*sinh(a)*sinh(p)+cosh(a)*sinh(a*n)*sinh(p)+
sinh(a - p)*sinh(a*n))/sinh(a));
cosh(a*n)*sinh(p) + cosh(p)*sinh(a*n)
trigsimp(ws, combine);
sinh(a*n + p)
992 CHAPTER 16. USER CONTRIBUTED PACKAGES
The trigsimp operator can be applied to equations, lists and matrices (and com-
positions thereof) as well as scalar expressions, and automatically maps itself re-
cursively over such non-scalar data structures:
2
{2*cos(x)*sin(x)= - 2*sin(x) + 1}
trigfactorize(sin(x), x/2);
x x
{{2,1},{sin(---),1},{cos(---),1}}
2 2
If the polynomial is not coordinated or balanced [1], the output will equal the input.
In this case, changing the value for x can help to find a factorization, e.g.
trigfactorize(1+cos(x), x);
{{cos(x) + 1,1}}
trigfactorize(1+cos(x), x/2);
x
{{2,1},{cos(---),2}}
2
trigfactorize(sin(2x)*sinh(2x), x);
on nopowers;
trigfactorize(1+cos(x), x/2);
x x
{2,cos(---),cos(---)}
2 2
x
cos(---)
2
The polynomials p and q can consist of both trigonometric and hyperbolic funct-
ions:
cosh(x)*sin(x)
With the help of this package the user can create identities:
trigsimp(tan(x)*tan(y));
sin(x)*sin(y)
---------------
994 CHAPTER 16. USER CONTRIBUTED PACKAGES
cos(x)*cos(y)
trigsimp(ws, combine);
cos(x - y) - cos(x + y)
-------------------------
cos(x - y) + cos(x + y)
trigsimp((sin(x-a)+sin(x+a))/(cos(x-a)+cos(x+a)));
sin(x)
--------
cos(x)
trigsimp(cosh(n*acosh(x))-cos(n*acos(x)), trig);
trigsimp(sec(a-b), keepalltrig);
csc(a)*csc(b)*sec(a)*sec(b)
-------------------------------
csc(a)*csc(b) + sec(a)*sec(b)
trigsimp(tan(a+b), keepalltrig);
- (tan(a) + tan(b))
----------------------
tan(a)*tan(b) - 1
tan(a + b)
df(sqrt(1+cos(x)), x, 4);
5 4 3 2 3
( - 4*cos(x) - 4*cos(x) - 20*cos(x) *sin(x) + 12*cos(x)
2 2 2 4
- 24*cos(x) *sin(x) + 20*cos(x) - 15*cos(x)*sin(x)
995
2 4 2
+ 12*cos(x)*sin(x) + 8*cos(x) - 15*sin(x) + 16*sin(x) )/
(16*sqrt(cos(x) + 1)
4 3 2
* (cos(x) + 4* cos(x) + 6* cos(x) + 4*cos(x) + 1))
on rationalize;
trigsimp(ws);
sqrt(cos(x) + 1)
------------------
16
off rationalize;
load_package taylor;
taylor(sin(x+a)*cos(x+b), x, 0, 4);
2
- (cos(a)*sin(b) + cos(b)*sin(a))*x
cos(a)*sin(b) + cos(b)*sin(a) 4 5
+ -------------------------------*x + O(x )
3
trigsimp(ws, combine);
sin(a - b) + sin(a + b) 2
------------------------- + cos(a + b)*x - sin(a + b)*x
2
2*cos(a + b) 3 sin(a + b) 4 5
- --------------*x + ------------*x + O(x )
3 3
996 CHAPTER 16. USER CONTRIBUTED PACKAGES
Certain integrals whose evaluation was not possible in REDUCE (without prepro-
cessing) are now computable:
int(trigsimp(sin(x+y)*cos(x-y)*tan(x)), x);
2
(cos(x) *x - cos(x)*sin(x) - 2*cos(y)*log(cos(x))*sin(y)
2
+ sin(x) *x)/2
int(trigsimp(sin(x+y)*cos(x-y)/tan(x)), x);
x 2
(cos(x)*sin(x) - 2*cos(y)*log(tan(---) + 1)*sin(y)
2
x
+ 2*cos(y)*log(tan(---))*sin(y) + x)/2
2
Without the package, the integration fails, and in the second case one does not
receive an answer for many hours.
trigfactorize(sin(2x)*cos(y)^2, y/2);
{{2*cos(x)*sin(x),1},
y y
{cos(---) - sin(---),2},
2 2
y y
{cos(---) + sin(---),2}}
2 2
trigfactorize(sin(y)^4-x^2, y);
2 2
{{sin(y) + x,1},{sin(y) - x,1}}
trigfactorize(sin(x)*sinh(x), x/2);
997
{{4,1},
x
{sinh(---),1},
2
x
{cosh(---),1},
2
x
{sin(---),1},
2
x
{cos(---),1}}
2
x x
2*cos(---)*sin(---) + 1
2 2
x 2
2*sinh(---) + 1
2
Bibliography
Turtle Graphics was originally developed in the 1960’s as part of the LOGO sys-
tem, and used in the classroom as an introduction to graphics and using computers
to help with mathematics.
The LOGO language was created as part of an experiment to test the idea that
programming may be used as an educational discipline to teach children. It was
first intended to be used for problem solving, for illustrating mathematical concepts
usually difficult to grasp, and for creation of experiments with abstract ideas.
At first LOGO had no graphics capabilities, but fast development enabled the in-
corporation of graphics, known as “Turtle Graphics” into the language. “Turtle
Graphics” is regarded by many as the main use of LOGO.
Main Idea: To use simple commands directing a turtle, such as forward, back,
turnleft, in order to construct pictures as opposed to drawing lines connecting carte-
sian coordinate points.
The ‘turtle’ is at all times determined by its state {x,y,a,p}- where x,y determine its
position in the (x,y)-plane, a determines the angle (which describes the direction
the turtle is facing) and p signals whether the pen is up or down (i. e. whether or
not it is drawing on the paper).
16.77.2 Implementation
Some alterations to the original “Turtle Graphics” commands have been made in
this implementation due to the design of the graphics package gnuplot used in
REDUCE.
• It is not possible to draw lines individually and to see each seperate line as
it is added to the graph since gnuplot automatically replaces the last graph
each time it calls on the plot function.
Thus the whole sequence of commands must be input together if the com-
plete picture is to be seen.
999
• This implementation does not make use of the standard turtle commands
‘pen-up’ or ‘pen-down’ . Instead, ‘set’ commands are included which allow
the turtle to move without drawing a line.
• No facility is provided here to change the pen-colour, but gnuplot does have
the capability to handle a few different colours (which could be included
later).
• Many of the commands are long and difficult to type out repeatedly, there-
fore all the commands included under ‘Turtle Functions’ (below) are listed
alongside an equivalent abbreviated form.
• The user has no control over the range of output that can be seen on the
screen since the gnuplot program automatically adjusts the picture to fit the
window. Hence the size of each specified ‘step’ the turtle takes in any direc-
tion is not a fixed unit of length, rather it is relative to the scale chosen by
gnuplot.
As previously mentioned, the turtle is determined at all times by its state {x,y,a}:
its position on the (x,y)-plane and its angle(a) - its heading - which determines
the direction the turtle is facing, in degrees, relative anticlockwise to the positive
x-axis.
setheading Takes a number as its argument and resets the heading to this number.
If the number entered is negative or greater than or equal to 360 then it is
automatically checked to lie between 0 and 360.
Returns the turtle position {x,y}
SYNTAX: setheading(θ)
Abbreviated form: sh(θ)
leftturn The turtle is turned anticlockwise through the stated number of degrees.
Takes a number as its argument and resets the heading by adding this number
to the previous heading setting.
Returns the turtle position {x,y}
SYNTAX: leftturn(α)
Abbreviated form: slt(α)
1000 CHAPTER 16. USER CONTRIBUTED PACKAGES
rightturn Similar to leftturn, but the turtle is turned clockwise through the
stated number of degrees. Takes a number as its argument and resets the
heading by subtracting this number from the previous heading setting.
Returns the turtle position {x,y}
SYNTAX: rightturn(β)
Abbreviated form: srt(β)
setx Relocates the turtle in the x direction. Takes a number as its argument and
repositions the state of the turtle by changing its x-coordinate.
Returns {}
SYNTAX: setx(x)
Abbreviated form: sx(x)
sety Relocates the turtle in the y direction. Takes a number as its argument and
repositions the state of the turtle by changing its y-coordinate.
Returns {}
SYNTAX: sety(y)
Abbreviated form: sy(y)
setposition Relocates the turtle from its current position to the new cartesian co-
ordinate position described. Takes a pair of numbers as its arguments and
repositions the state of the turtle by changing the x and y coordinates.
Returns {}
SYNTAX: setposition(x,y)
Abbreviated form: spn(x,y)
setheadingtowards Resets the heading so that the turtle is facing towards the
given point, with respect to its current position on the coordinate axes. Takes
a pair of numbers as its arguments and changes the heading, but the turtle
stays in the same place.
Returns the turtle position {x,y}
SYNTAX: setheadingtowards(x,y)
Abbreviated form: shto(x,y)
setforward Relocates the turtle from its current position by moving forward (in
the direction of its heading) the number of steps given. Takes a number as
its argument and repositions the state of the turtle by changing the x and y
coordinates.
Returns {}
SYNTAX: setforward(n)
Abbreviated form: sfwd(n)
1001
setback As with setforward, but moves back (in the opposite direction of its
heading) the number of steps given.
Returns {}
SYNTAX: setback(n)
Abbreviated form: sbk(n)
forward Moves the turtle forward (in the direction its heading) the number of
steps given. Takes a number as its argument and draws a line from its current
position to a new position on the coordinate plane. The x and y coordinates
are reset to the new values.
Returns the list of points { {old x,old y}, {new x,new y} }
SYNTAX: forward(s)
Abbreviated form: fwd(s)
back As with forward except the turtle moves back (in the opposite direction to
its heading) the number of steps given.
Returns the list of points { {old x,old y}, {new x,new y} }
SYNTAX: back(s)
Abbreviated form: bk(s)
move Moves the turtle to a specified point on the coordinate plane. Takes a pair
of numbers as its arguments and draws a line from its current position to the
position described. The x and y coordinates are set to these new values.
Returns the list of points { {old x,old y}, {new x,new y} }
SYNTAX: move(x,y)
Abbreviated form: mv(x,y)
draw This is the function the user calls within REDUCE to draw the list of turtle
commands given into a picture. Takes a list as its argument, with each seper-
ate command being seperated by a comma, and returns the graph drawn by
following the commands.
SYNTAX: draw{command(command_args),...,command(command_args)}
Note: all commands may be entered in either long or shorthand form, and
with a space before the arguments instead of parentheses only if just one
argument is needed. Commands taking more than one argument must be
written in parentheses and arguments seperated by a comma.
1002 CHAPTER 16. USER CONTRIBUTED PACKAGES
fdraw This function is also called in REDUCE by the user and outputs the same as
the draw command, but it takes a filename as its argument. The file which
is called upon by fdraw must contain only the turtle commands and other
functions defined by the user for turtle graphics. (This is intended to make it
easier for the user to make small changes without constantly typing out long
series of commands.)
SYNTAX: fdraw{"filename"} Note: commands may be entered in
long or shorthand form but each command must be written on a separate
line of the file. Also, arguments are to be written without parentheses and
separated with a space, not a comma, regardless of the number of arguments
given to the function.
info This function is called on its own in REDUCE to tell user the current state of
the turtle. Takes no arguments but returns a list containing the current values
of the x and y coordinates and the heading variable.
Returns the list {x_coord,y_coord,heading}
SYNTAX: info() or simply info
clearscreen This is also called on its own in REDUCE to get rid of the last gnuplot
window, displaying the last turtle graphics picture, and to reset all the vari-
ables to 0. Takes no arguments and returns no printed output to the screen
but the graphics window is simply cleared.
SYNTAX: clearscreen() or simply clearscreen
Abbreviated form: cls() or cls
home This is a command which can be called within a plot function as well as out-
side of one. Takes no arguments, and simply resets the x and y coordinates
and the heading variable to 0. When used in a series of turtle commands, it
moves the turtle from its current position to the origin and sets the direction
of the turtle along the x-axis, without drawing a line.
Returns {0,0}
SYNTAX: home() or simply home
It is possible to use conditional statements (if . . . then . . . else . . . ) and ‘for’ state-
ments (for i:=. . . collect{. . . }) in calls to draw. However, care must be taken - when
using conditional statements the final else statement must return a point or at least
1003
procedure func_name(func_args);
begin [scalar additional variables];
..
.
(the procedure body containing some turtle commands)
..
.
return (a list, or label to a list, of turtle commands
as accepted by draw)
end;
16.77.4 Examples
The following examples are taken from the tur.tst file. Examples 1,2,5 & 6 are
simple calls to draw. Examples 3 & 4 show how more complicated commands can
be built (which can take their own set of arguments) using procedures. Examples 7
& 8 show the difference between the draw and fdraw commands.
REDUCE Plot
100
50
points
-50
-100
-100 -50 0 50 100
x
REDUCE Plot
150
100
50
points
-50
-100
-150
-150 -100 -50 0 50 100 150
x
procedure peak(r);
begin;
return for i:=0:r collect
{move(x_coord+5,y_coord-10), move(x_coord+10,y_coord+60),
move(x_coord+10,y_coord-60),move(x_coord+5,y_coord+10)};
end;
REDUCE Plot
50
40
30
points
20
10
-10
0 20 40 60 80 100 120
x
REDUCE Plot
100
50
0
points
-50
-100
-150
0 50 100 150 200 250
x
% (4) Write a recursive procedure which draws "trees" such that every
%branch is half the length of the previous branch.
1007
REDUCE Plot
250
200
150
100
50
points
-50
-100
-150
-200
-250
0 50 100 150 200 250
x
REDUCE Plot
100
80
60
points
40
20
0
-60 -40 -20 0 20 40 60
x
REDUCE Plot
150
100
50
points
-50
-100
-150
-150 -100 -50 0 50 100 150
x
1009
REDUCE Plot
150
100
50
points
-50
-100
-150
-150 -100 -50 0 50 100 150
x
% (8) Example 7 could have been tackled another way, which makes use of
%the fdraw command.
%By inputting gr2 and gr6 as procedures into reduce, they can then be
%used at any time in the same reduce session in a call to draw and even
%fdraw.
%First save the procedures in a file, say fxp (fdraw example procedures):
procedure gr2;
begin;
return {home, for i:=1:12 collect
1010 CHAPTER 16. USER CONTRIBUTED PACKAGES
procedure gr6;
begin;
return {home(), for i:=1:100 collect
{forward 150, rightturn(60), back(150),
rightturn(60), forward 150, setheading(i*3.6)} };
end;
%Then create another file where the functions may be called to fdraw,
%e.g. fx:
gr2
gr6
%Now in reduce, after loading the turtle package just type the followi
in "fxp";
fdraw ’"fx";
%This method is useful if the user wants to define many of their own
%functions, and, using fdraw, subtle changes can be made quickly witho
%having to type out the whole string of commands to plot each time. It
%is particularly useful if there are several pictures to plot at once
%it is an easy way to build pictures so that the difference an extra
%command makes to the overall picture can be clearly seen.
%(In the above example, the file called to fdraw was only 2 lines long
%so this method did not have any advantage over the normal draw comman
%However, when the list of commands is longer it is clearly advantageo
%to use fdraw)
16.77.5 References
calls wu with the named polynomials, and with the variable ordering x > y > z.
In this example, r is a parameter.
The result is
2 3 2
{{{r + z - z - 1,
2 2 2 2 4 2 2 2
r *y + r *z + r - y - y *z + z - z - 2,
2
x*y + z - 1},
y},
6 4 6 2 6 4 7 4 6 4 5 4 4
{{r *z - 2*r *z + r + 3*r *z - 3*r *z - 6*r *z + 3*r *z + 3*
4 3 4 2 4 2 10 2 9 2 8 2 7
r *z + 3*r *z - 3*r + 3*r *z - 6*r *z - 3*r *z + 6*r *z +
2 6 2 5 2 4 2 3 2 13 12 11
3*r *z + 6*r *z - 6*r *z - 6*r *z + 3*r + z - 3*z + z
1013
10 9 8 7 6 4 3 2
+ 2*z + z + 2*z - 6*z - z + 2*z + 3*z - z - 1,
2 2 3 2
y *(r + z - z - 1),
2
x*y + z - 1},
2 3 2
y*(r + z - z - 1)}}
namely, a list of pairs of characteristic sets and initials for the characteristic sets.
Thus, the first pair above has the characteristic set
r2 + z 3 − z 2 − 1, r2 y 2 + r2 z + r2 − y 4 − y 2 z 2 + z 2 − z − 2, xy + z 2 − 1
and initial y.
According to Wu’s theorem, the set of roots of the original polynomials is the
union of the sets of roots of the characteristic sets, with the additional constraints
that the corresponding initial is non-zero. Thus, for the first pair above, we find
the roots of {r2 + z 3 − z 2 − 1, . . . } under the constraint that y 6= 0. These
roots, together with the roots of the other characteristic set (under the constraint of
y(r2 + z 3 − z 2 − 1) 6= 0), comprise all the roots of the original set.
Additional information about the working of the algorithm can be gained by
on trwu;
This prints out details of the choice of basic sets, and the computation of charac-
teristic sets.
The second argument (the list of variables) may be omitted, when all the variables
in the input polynomials are implied with some random ordering.
1014 CHAPTER 16. USER CONTRIBUTED PACKAGES
This package calculates the color factor in non-abelian gauge field theories using
an algorithm due to Cvitanovich.
Documentation for this package is in plain text.
Author: A. Kryukov.
Program "xCOLOR" is intended for calculation the colour factor in non-abelian
gauge field theories. It is realized Cvitanovich algorithm [1]. In comparision with
"COLOR" program [2] it was made many improvements. The package was writen
by symbolic mode. This version is faster then [2] more then 10 times.
After load the program by the following command load xcolor;
user can be able to use the next additional commands and operators.
Command SUdim.
Command SpTT.
Operator QG.
Format: QG(inQuark,outQuark,Gluon)
Describe the quark-gluon vertex. Parameters may be any identifiers. First and
second of then must be in- and out- quarks correspondently. Third one is a gluon.
Operator G3.
Format: G3(Gluon1,Gluon2,Gluon3)
Describe the three-gluon vertex. Parameters may be any identifiers. The order of
gluons must be clock.
In terms of QG and G3 operators you input diagram in "color" space as a product
of these operators. For example.
1015
e1
---->---
/ \
| e2 |
v1*..........*v2 <===> QG(e3,e1,e2)*QG(e1,e3,e2)
| |
\ e3 /
----<---
....... gluon
XIDEAL constructs Gröbner bases for solving the left ideal membership problem:
Gröbner left ideal bases or GLIBs. For graded ideals, where each form is homo-
geneous in degree, the distinction between left and right ideals vanishes. Further-
more, if the generating forms are all homogeneous, then the Gröbner bases for the
non-graded and graded ideals are identical. In this case, XIDEAL is able to save
time by truncating the Gröbner basis at some maximum degree if desired.
Author: David Hartley.
16.80.1 Description
16.80.2 Declarations
xorder
xorder sets the term ordering for all other calculations. The syntax is
xorder k
xvars
xvars U,V,W,...
where the arguments are either kernels or lists of kernels. All variables specified
in the xvars declaration are treated as exterior variables in subsequent XIDEAL
calculations with exterior polynomials, and any other scalars are treated as param-
eters. This is true whether or not the variables have been declared as 0-forms. The
declaration
xvars {}
xvars nil
restores the default. Of course, p-form kernels with p 6= 0 are always considered
as exterior variables. The order of the variables in an xvars declaration has no
1018 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.80.3 Operators
xideal
xideal calculates a Gröbner left ideal basis in an exterior algebra. The syntax is
xideal calculates a Gröbner basis for the left ideal generated by S using the
current term ordering. The resulting list can be used for subsequent reductions
with xmod as long as the term ordering is not changed. Which 0-form variables
are to be regarded as exterior variables can be specified in an optional argument V
(just like an xvars declaration). The order of variables in V has no effect on the
term ordering. If the set of generators S is graded, an optional parameter R can be
given, and xideal produces a truncated basis suitable for reducing exterior forms
of degree less than or equal to R in the left ideal. This can save time and space with
large problems, but the result cannot be used for exterior forms of degree greater
than R. The forms returned by xideal are sorted in increasing order. See also the
switches trxideal and xfullreduction.
xmodideal
xmodideal reduces exterior forms to their (unique) normal forms modulo a left
ideal. The syntax is
or
F xmodideal S.
xmodideal(F,S) first calculates a Gröbner basis for the left ideal generated by
S, and then reduces F. F may be either a single exterior form, or a list of forms,
and S is a list of forms. If F is a list of forms, each element is reduced, and any
which vanish are deleted from the result. If the set of generators S is graded, then a
1019
truncated Gröbner basis is calculated using the degree of F (or the maximal degree
in F). See also trxmod.
xmod
xmod reduces exterior forms to their (not necessarily unique) normal forms mod-
ulo a set of exterior polynomials. The syntax is
or
F xmod S.
xauto
xauto S returns a set of exterior polynomials which generate the same left ideal,
but which are in normal form with respect to each other. For linear expressions,
this is equivalent to finding the reduced row echelon form of the coefficient matrix.
excoeffs
excoeffs(F:form):list of expressions
returns the coefficients from an exterior form as a list. The coefficients are always
1020 CHAPTER 16. USER CONTRIBUTED PACKAGES
exvars
exvars(F:form):list of kernels
returns the exterior powers from an exterior form as a list. All non-scalar vari-
ables are returned, but which degree 0 variables count as coefficient parameters is
controlled by the command xvars.
16.80.4 Switches
xfullreduce
trxideal
trxmod
16.80.5 Examples
Suppose XIDEAL has been loaded, the switches are at their default settings, and
the following exterior variables have been declared:
pform x=0,y=0,z=0,t=0,f(i)=1,h=0,hx=0,ht=0;
1021
{d t^d z + d x^d y,
d x^d y^d z,
d t^d x^d y}
f(3)^f(4)^f(5)^f(6)
xmodideal {f(1)^f(2) + f(3)^f(4) + f(5)^f(6)};
The heat equation, hxx = ht can be represented by the following exterior differen-
tial system.
S := {d h - ht*d t - hx*d x,
d ht^d t + d hx^d x,
d hx^d t - ht*d x^d t};
xmodideal can be used to check that the exterior differential system is closed
under exterior differentiation.
d S xmodideal S;
{}
d x*a + d y*y
{---------------}
a
xvars {a};
xideal {a*d x+y*d y};
{d x*a + d y*y,
d x^d y*y}
{1, - a*p + q}
{d u,d y}
{ - a,1,1}
{d y*p,d y*q,d u}
xvars nil;
- 2*d t^d z
{1}
1023
Bibliography
[3] J. Apel, A relationship between Gröbner bases of ideals and vector modules
of G-algebras, Contemporary Math. 131(1992)195–204.
[5] E. Schrüfer, EXCALC, a system for doing calculations in the calculus of mod-
ern differential geometry, User’s manual, (The Rand Corporation, Santa Mon-
ica, 1986).
1024 CHAPTER 16. USER CONTRIBUTED PACKAGES
16.81.1 Introduction
The Gosper algorithm [1] is a decision procedure, that decides by algebraic calcu-
lations whether or not a given hypergeometric term ak has a hypergeometric term
antidifference gk , i. e. gk − gk−1 = ak with rational gk /gk−1 , and returns gk if the
procedure is successful, in which case we call ak Gosper-summable. Otherwise
no hypergeometric term antidifference exists. Therefore if the Gosper algorithm
does not return a closed form solution, it has proved that no such solution exists,
an information that may be quite useful and important. The Gosper algorithm is
the discrete analogue of the Risch algorithm for integration in terms of elementary
functions.
Any antidifference is uniquely determined up to a constant, and is denoted by
X
gk = ak .
k
e. g. is not of this type since the summand nk depends on the upper boundary
point n explicitly. This is an example of a definite sum that we consider in the next
section.
Our package supports the input of powers (a^k), factorials (factorial(k)), Γ
function terms (gamma(a)), binomial coefficients (binomial(n,k)), shifted
factorials (pochhammer(a,k)= a(a + 1) · · · (a + k − 1) = Γ(a + k)/Γ(a)),
and partially products (prod(f,k,k1,k2)). It takes care of the necessary sim-
plifications, and therefore provides you with the solution of the decision problem
as long as the memory or time requirements are not too high for the computer used.
The (fast) Zeilberger algorithm [10]–[11] deals with the definite summation of
hypergeometric terms. Zeilberger’s paradigm is to find (and return) a linear ho-
mogeneous recurrence equation with polynomial coefficients (called holonomic
equation) for an infinite sum
∞
X
s(n) = f (n, k) ,
k=−∞
s(n) turns out to be a hypergeometric term, and a closed form solution can be
easily established using a suitable initial value, and is represented by a ratio of
Pochhammer or Γ function terms if the polynomials p, and q can be factored.
1026 CHAPTER 16. USER CONTRIBUTED PACKAGES
Zeilberger’s algorithm does not guarantee to find the holonomic equation of lowest
order, but often it does.
If the resulting recurrence equation has order larger than one, this information can
be used for identification purposes: Any other expression satisfying the same re-
currence equation, and the same initial values, represents the same function.
m
P2
Note that a definite sum f (n, k) is an infinite sum if f (n, k) = 0 for
k=m1
k < m1 and k > m2 . This is often the case, an example of which is the
sum (16.98) considered above, for which the hypergeometric recurrence equation
2s(n − 1) − s(n) = 0 is generated by Zeilberger’s algorithm, leading to the closed
form solution s(n) = 2n .
Definite summation is trivial if the corresponding indefinite sum is Gosper-
summable analogously to the fact that definite integration is trivial as soon as an el-
ementary antiderivative is known. If this is not the case, the situation is much more
difficult, and it is therefore quite remarkable and non-obvious that Zeilberger’s
method is just a clever application of Gosper’s algorithm.
Our implementation is mainly based on [3] and [2]. More examples can be found in
[5], [7], [8], and [9] many of which are contained in the test file zeilberg.tst.
1: load zeilberg;
• gosper(a,k,m,n) determines
n
X
ak
k=m
Example:
2: gosper((-1)^(k+1)*(4*k+1)*factorial(2*k)/
(factorial(k)*4^k*(2*k-1)*factorial(k+1)),k);
1027
k
- ( - 1) *factorial(2*k)
------------------------------------
2*k
2 *factorial(k + 1)*factorial(k)
This solves a problem given in SIAM Review ([6], Problem 94–2) where it was
asked to determine the infinite sum
n
X (−1)k+1 (4k + 1)(2k − 1)!!
S = lim Sn , Sn = ,
n→∞ 2k (2k − 1)(k + 1)!
k=1
3: gosper(sub(n=n+1,binomial(n,k)^2/binomial(2*n,n))-
binomial(n,k)^2/binomial(2*n,n),k);
2
((binomial(n + 1,k) *binomial(2*n,n)
2
- binomial(2*(n + 1),n + 1)*binomial(n,k) )*(2*k - 3*n - 1)
2 3 2
* (k - n - 1) )/((2 (2
* * (n + 1) - k) (2
* * n + 1)* k - 3 *n - 7 *n - 5*n
4: gosper(binomial(k,n),k);
(k + 1)*binomial(k,n)
-----------------------
n + 1
5: gosper((-25+15*k+18*k^2-2*k^3-k^4)/
(-23+479*k+613*k^2+137*k^3+53*k^4+5*k^5+k^6),k);
2
- (2*k - 15*k + 8)*k
----------------------------
3 2
23*(k + 4*k + 27*k + 23)
1028 CHAPTER 16. USER CONTRIBUTED PACKAGES
The Gosper algorithm is not capable to give antidifferences depending on the har-
monic numbers
k
X 1
Hk := ,
j
j=1
P
e. g. k Hk = (k + 1)(Hk+1 − 1), but, is able to give a proof, instead, for the fact
that Hk does not possess a closed form evaluation:
6: gosper(1/k,k);
7: operator ff,gg$
10: gosper(ff(k-1)/gg(k),k);
ff(k)
---------------
(a - e)*gg(k)
P fk−m
Similarly closed form solutions of k gk for positive integers m can be ob-
P f
tained, as well as of k k−1
gk for
k
Y k
Y
fk = (a + b j + c j 2 + d j 3 ) and gk = (e + b j + c j 2 + d j 3 )
j=1 j=1
If it does not return a solution, then such a solution does not exist.
Examples:
12: extended_gosper(binomial(k/2,n),k);
k k - 1
(k + 2)*binomial(---,n) + (k + 1)*binomial(-------,n)
2 2
-------------------------------------------------------
2*(n + 1)
13: extended_gosper(k*factorial(k/7),k,7);
k
(k + 7)*factorial(---)
7
14: sumrecursion(binomial(n,k),k,n);
2*sum(n - 1) - sum(n)
15: summand:=factorial(a+k-1)*factorial(b+k-1)/(factorial(k)*
factorial(-1/2+a+b+k))*factorial(a+n-k-1)*factorial(b+n-k-1)/
(factorial(n-k)*factorial(-1/2+a+b+n-k))$
16: sumrecursion(summand,k,n);
17: summand:=pochhammer(d,k)*pochhammer(1+d/2,k)*pochhammer(d+b-a,k)*
pochhammer(d+c-a,k)*pochhammer(1+a-b-c,k)*pochhammer(n+a,k)*
pochhammer(-n,k)/(factorial(k)*pochhammer(d/2,k)*
pochhammer(1+a-b,k)*pochhammer(1+a-c,k)*pochhammer(b+c+d-a,k)*
pochhammer(1+d-a-n,k)*pochhammer(1+d+n,k))$
18: sumrecursion(summand,k,n);
55
Note that with REDUCE Version 3.5 we use the global operator summ instead of sum to denote
the sum.
1031
*sum(n)
and
!
d , 1 + d/2 , d + b − a , d + c − a , 1 + a − b − c , n + a , −n
7 F6 1
d/2 , 1 + a − b , 1 + a − c , b + c + d − a , 1 + d − a − n , 1 + d + n
e. g., we may prove that both sums satisfy the same recurrence equation
19: sumrecursion(binomial(n,k)^3,k,n);
2 2 2
(7*n - 7*n + 2)*sum(n - 1) + 8*(n - 1) *sum(n - 2) - sum(n)*n
20: sumrecursion(binomial(n,k)^2*binomial(2*k,n),k,n);
2 2 2
(7*n - 7*n + 2)*sum(n - 1) + 8*(n - 1) *sum(n - 2) - sum(n)*n
21: sub(n=0,k=0,binomial(n,k)^3);
22: sub(n=0,k=0,binomial(n,k)^2*binomial(2*k,n));
1
1032 CHAPTER 16. USER CONTRIBUTED PACKAGES
23: sub(n=1,k=0,binomial(n,k)^3)+sub(n=1,k=1,binomial(n,k)^3);
24: sub(n=1,k=0,binomial(n,k)^2*binomial(2*k,n))+
sub(n=1,k=1,binomial(n,k)^2*binomial(2*k,n));
F (n, k) F (n, k)
and
F (n − m, k) F (n, k − l)
are rational functions with respect to both n and k. The resulting expression
equals zero.
Examples:
25: extended_sumrecursion(binomial(n,k)*binomial(k/2,n),k,n,1,2);
sum(n - 1) + 2*sum(n)
26: sumrecursion(binomial(n,k)*binomial(k/2,n),k,n);
sum(n - 1) + 2*sum(n)
Similarly, we get
27: extended_sumrecursion(binomial(n/2,k),k,n,2,1);
1033
2*sum(n - 2) - sum(n)
28: sumrecursion(binomial(n/2,k),k,n);
2*sum(n - 2) - sum(n)
29: sumrecursion(hyperterm({a,b,a+1/2-b,1+2*a/3,-n},
{2*a+1-2*b,2*b,2/3*a,1+a+n/2},4,k)/(factorial(n)*2^(-n)/
factorial(n/2))/hyperterm({a+1,1},{a-b+1,b+1/2},1,n/2),k,n);
sum(n - 2) - sum(n)
In the last example, the progam chooses m = 2, and l = 1 to derive the resulting
recurrence equation (see [2], Table 3, (1.3)).
Sums to which the Zeilberger algorithm applies, in general are special cases of the
generalized hypergeometric function
∞
a1 , a2 , · · · , ap X (a1 )k · (a2 )k · · · (ap )k k
p Fq x := x
b1 , b2 , · · · , bq (b1 )k · (b2 )k · · · (bq )k k!
k=0
Therefore
30: hyperrecursion({-n,b},{c},1,n);
(b - c - n + 1)*sum(n - 1) + (c + n - 1)*sum(n)
1034 CHAPTER 16. USER CONTRIBUTED PACKAGES
whereas
31: hyperrecursion({d,1+d/2,d+b-a,d+c-a,1+a-b-c,n+a,-n},
{d/2,1+a-b,1+a-c,b+c+d-a,1+d-a-n,1+d+n},1,n);
*sum(n)
32: krawtchoukterm:=
(-1)^n*p^n*binomial(NN,n)*hyperterm({-n,-x},{-NN},1/p,k)$
33: sumrecursion(krawtchoukterm,k,n);
34: sumrecursion(krawtchoukterm,k,x);
35: sumrecursion(krawtchoukterm,k,NN);
+ (nn - x - 1)*sum(nn - 2)
• hypersum(upper,lower,x,n)
determines
a closed form representa-
a1 , a2 , · · · , ap
tion for p Fq x , where upper= {a1 , a2 , . . . , ap }
b1 , b2 , · · · , bq
is the list of upper parameters, and lower= {b1 , b2 , . . . , bq } is the list of
lower parameters depending on n. The result is given as a hypergeometric
term with respect to n.
If the result is a list of length m, we call it m-fold symmetric, which is to be
interpreted as follows: Its j th part is the solution valid for all n of the form
n = mk + j − 1 (k ∈ N0 ). In particular, if the resulting list contains two
terms, then the first part is the solution for even n, and the second part is the
solution for odd n.
Examples [2]:
36: hypersum({a,1+a/2,c,d,-n},{a/2,1+a-c,1+a-d,1+a+n},1,n);
37: hypersum({a,1+a/2,d,-n},{a/2,1+a-d,1+a+n},-1,n);
pochhammer(a + 1,n)
-------------------------
pochhammer(a - d + 1,n)
38: togamma(ws);
gamma(a - d + 1)*gamma(a + n + 1)
-----------------------------------
gamma(a - d + n + 1)*gamma(a + 1)
39: hypersum({-n,-n,-n},{1,1},1,n);
n/2 2 n 1 n
( - 27) * pochhammer(---,---) * pochhammer(---,---)
3 2 3 2
{----------------------------------------------------,
n 2
factorial(---)
2
0}
40: hypersum({-n,n+3*a,a},{3*a/2,(3*a+1)/2},3/4,n);
2 n 1 n
pochhammer(---,---)*pochhammer(---,---)
3 3 3 3
{-----------------------------------------------------,
3*a + 2 n 3*a + 1 n
pochhammer(---------,---)*pochhammer(---------,---)
3 3 3 3
0,
0}
and
! 0 if n 6= 0 (mod 3)
−n , n + 3a , a 3
3 F2 = (1/3)n/3 (2/3)n/3 .
3a/2 , (3a + 1)/2 4 otherwise
(a + 1/3)n/3 (a + 2/3)n/3
41: sumtohyper(binomial(n,k)^3,k);
hypergeometric({ - n, - n, - n},{1,1},-1)
42: sumtohyper(binomial(n,k)/2^n-sub(n=n-1,binomial(n,k)/2^n),k);
- n + 2 - n
- hypergeometric({----------, - n,1},{1,------},-1)
2 2
------------------------------------------------------
n
2
43: simplify_combinatorial(sub(k=k+1,krawtchoukterm)/krawtchoukterm);
(k - n)*(k - x)
--------------------
(k - nn)*(k + 1)*p
From this calculation, we see again that the upper parameters of the hypergeometric
representation of the Krawtchouk polynomials are given by {−n, −x}, its lower
parameter is {−N }, and the argument of the hypergeometric function is 1/p.
Other examples are
44: simplify_combinatorial(binomial(n,k)/binomial(2*n,k-1));
46: simplify_gamma2(gamma(2*n)/gamma(n));
2*n 2*n + 1
2 *gamma(---------)
2
-----------------------
2*sqrt(pi)
47: simplify_gamman(gamma(3*n)/gamma(n),3);
3*n 3*n + 2 3* n + 1
3 *gamma(---------) *gamma(---------)
3 3
----------------------------------------
2*sqrt(3)*pi
16.81.12 Tracing
If you set
48: on zb_trace;
49: gosper(pochhammer(k-n,n),k);
k - 1
a(k)/a(k-1):= -----------
k - n - 1
p:= 1
q:= k - 1
r:= k - n - 1
degreebound := 0
1040 CHAPTER 16. USER CONTRIBUTED PACKAGES
1
f:= -------
n + 1
pochhammer(k - n,n)*k
-----------------------
n + 1
50: sumrecursion(binomial(n,k)^2,k,n);
2
n
F(n,k)/F(n-1,k):= ----------
2
(k - n)
2
(k - n - 1)
F(n,k)/F(n,k-1):= --------------
2
k
2 2 2
p:= zb_sigma(1)*k - 2*zb_sigma(1)*k*n + zb_sigma(1)*n + n
2 2
q:= k - 2*k*n - 2*k + n + 2*n + 1
2
r:= k
degreebound := 1
2*k - 3*n + 2
f:= ---------------
n
2 2 2 3 2
- 4*k *n + 2*k + 8*k*n - 4*k*n - 3*n + 2*n
p:= -------------------------------------------------
n
1041
The following global variables and switches can be used in connection with the
ZEILBERG package:
ak = gk − gk−1 or ak = gk+1 − gk ,
respectively.
In the case of the Zeilberger algorithm, either a downward or an upward
recurrence equation is returned. Example:
52: zb_direction:=up$
53: sumrecursion(binomial(n,k)^2,k,n);
54: zb_direction:=down$
55: on zb_proof;
56: gosper(k*factorial(k),k);
(k + 1)*factorial(k)
57: gosper_representation;
{k,k,1,1}
58: gosper(
1/(k+1)*binomial(2*k,k)/(n-k+1)*binomial(2*n-2*k,n-k),k);
59: gosper_representation;
{1,
- (2*k - n + 1)
------------------}
(n + 2)*(n + 1)
16.81.14 Messages
Bibliography
[1] Gosper Jr., R. W.: Decision procedure for indefinite hypergeometric summa-
tion. Proc. Natl. Acad. Sci. USA 75, 1978, 40–42.
[2] Koepf, W.: Algorithms for the indefinite and definite summation. Konrad-
Zuse-Zentrum Berlin (ZIB), Preprint SC 94-33, 1994.
[7] Strehl, V.: Binomial sums and identities. Maple Technical Newsletter 10,
1993, 37–49.
[9] Wilf, H. S.: Identities and their computer proofs. “SPICE” Lec-
ture Notes, August 31–September 2, 1993. Anonymous ftp file
pub/wilf/lecnotes.ps on the server ftp.cis.upenn.edu.
[10] Zeilberger, D.: A fast algorithm for proving terminating hypergeometric iden-
tities. Discrete Math. 80, 1990, 207–211.
16.82.1 Z-Transform
The Z-Transform of a sequence {fn } is the discrete analogue of the Laplace Trans-
form, and
X∞
Z{fn } = F (z) = fn z −n .
n=0
p
n
This series converges in the region outside the circle |z| = |z0 | = lim sup |fn | .
n→∞
The calculation of the Laurent coefficients of a regular function results in the fol-
lowing inverse formula for the Z-Transform:
If F (z) is a regular function in the region |z| > ρ then ∃ a sequence {fn } with
Z{fn } = F (z) given by
I
1
fn = F (z)z n−1 dz
2πi
This package can compute the Z-Transforms of the following list of fn , and
certain combinations thereof.
1
1 eαn (n+k)
1 1 1
n! (2n)! (2n+1)!
1046 CHAPTER 16. USER CONTRIBUTED PACKAGES
sin(βn)
n! sin(αn + φ) eαn sin(βn)
cos(βn)
n! cos(αn + φ) eαn cos(βn)
sin(β(n+1)) cos(β(n+1))
n+1 sinh(αn + φ) n+1
n+k
cosh(αn + φ) m
Other Combinations
d
Multiplication by n Z{nk · fn } = −z dz Z{nk−1 · fn , n, z}
z
Multiplication by λn Z{λn · fn } = F
λ
!
k−1
Z{fn+k } = z k fj z −j
P
Shift Equation F (z) −
j=0
n
P z
Symbolic Sums Z fk = z−1 · Z{fn }
k=0
( )
n+q
P
Z fk combination of the above
k=p
where k,λ ∈ N−{0}; and a,b are variables or fractions; and p,q ∈ Z or
are functions of n; and α, β & φ are angles in radians.
This package can compute the Inverse Z-Transforms of any rational function,
whose denominator can be factored over Q, in addition to the following list
of F (z).
cos(β) cos(β)
sin(β) sin(β)
sin z e z
cos z e z
pz pz pz
A sin A cos A
pz pz pz
A sinh A cosh A
1047
√
z z 2 +Az+B
z log √
z 2 −Az+B
z log z
sin(β)
arctan z+cos(β)
where k,λ ∈ N−{0} and A,B are fractions or variables (B > 0) and α,β, & φ are
angles in radians.
16.82.6 EXAMPLES
1: ztrans((-1)^n*n^2,n,z);
z*( - z + 1)
---------------------
3 2
z + 3*z + 3*z + 1
2: ztrans(cos(n*omega*t),n,z);
z*(cos(omega*t) - z)
1048 CHAPTER 16. USER CONTRIBUTED PACKAGES
---------------------------
2
2*cos(omega*t)*z - z - 1
3: ztrans(cos(b*(n+2))/(n+2),n,z);
z
z*( - cos(b) + log(------------------------------)*z)
2
sqrt( - 2*cos(b)*z + z + 1)
4: ztrans(n*cos(b*n)/factorial(n),n,z);
1/z
e *z
--------
z - 1
6: operator f$
7: ztrans((1+n)^2*f(n),n,z);
2
df(ztrans(f(n),n,z),z,2)*z - df(ztrans(f(n),n,z),z)*z
+ ztrans(f(n),n,z)
8: invztrans((z^2-2*z)/(z^2-4*z+1),z,n);
n n n
(sqrt(3) - 2) *( - 1) + (sqrt(3) + 2)
-----------------------------------------
2
1049
9: invztrans(z/((z-a)*(z-b)),z,n);
n n
a - b
---------
a - b
10: invztrans(z/((z-a)*(z-b)*(z-c)),z,n);
n n n n n n
a *b - a *c - b *a + b *c + c *a - c *b
-----------------------------------------
2 2 2 2 2 2
a *b - a *c - a*b + a*c + b *c - b*c
11: invztrans(z*log(z/(z-a)),z,n);
n
a *a
-------
n + 1
12: invztrans(e^(1/(a*z)),z,n);
1
-----------------
n
a *factorial(n)
13: invztrans(z*(z-cosh(a))/(z^2-2*z*cosh(a)+1),z,n);
cosh(a*n)
fn = 2n + (−2)n − cos π2 n .
The following REDUCE session shows how the present package can
be used to solve the above problem.
20: equation:=ztrans(f(n+5)-2*f(n+3)+2*f(n+2)-3*f(n+1)+2*f(n),n,z);
5 3
equation := ztrans(f(n),n,z)*z - 2*ztrans(f(n),n,z)*z
2
+ 2*ztrans(f(n),n,z)*z - 3*ztrans(f(n),n,z)*z
3 2
+ 2*ztrans(f(n),n,z) - 9*z + 2*z - 5*z
21: ztransresult:=solve(equation,ztrans(f(n),n,z));
2
z*(9*z - 2*z + 5)
ztransresult := {ztrans(f(n),n,z)=----------------------------}
5 3 2
z - 2*z + 2*z - 3*z + 2
22: result:=invztrans(part(first(ztransresult),2),z,n);
n n n n
2*( - 2) - i *( - 1) - i + 4*n
result := -----------------------------------
2
z 1 z
= z−1 z 2 −4z+3
+ z 2 −4z+3
.
The following REDUCE session shows how the present package can
be used to solve the above problem.
27: equation:=ztrans(f(n+2)-4*f(n+1)+3*f(n)-1,n,z);
3 2
equation := (ztrans(f(n),n,z)*z - 5*ztrans(f(n),n,z)*z
2
+ 7*ztrans(f(n),n,z)*z - 3*ztrans(f(n),n,z) - z )/(z - 1)
28: ztransresult:=solve(equation,ztrans(f(n),n,z));
2
z
result := {ztrans(f(n),n,z)=---------------------}
3 2
z - 5*z + 7*z - 3
29: result:=invztrans(part(first(ztransresult),2),z,n);
n
3*3 - 2*n - 3
result := ----------------
4
1052 CHAPTER 16. USER CONTRIBUTED PACKAGES
(n + 1) · fn+1 − fn = 0
34: equation:=ztrans((n+1)*f(n+1)-f(n),n,z);
2
equation := - (df(ztrans(f(n),n,z),z)*z + ztrans(f(n),n,z))
36: equation:=sub(ztrans(f(n),n,z)=tmp(z),equation);
2
equation := - (df(tmp(z),z)*z + tmp(z))
37: load(odesolve);
38: ztransresult:=odesolve(equation,tmp(z),z);
1/z
ztransresult := {tmp(z)=e *arbconst(1)}
39: preresult:=invztrans(part(first(ztransresult),2),z,n);
arbconst(1)
preresult := --------------
factorial(n)
40: solve({sub(n=0,preresult)=f(0),sub(n=1,preresult)=f(1)},
arbconst(1));
{arbconst(1)=1}
1053
1
result := --------------
factorial(n)
Bibliography
[1] Bronstein, I.N. and Semedjajew, K.A., Taschenbuch der Mathematik, Verlag
Harri Deutsch, Thun und Frankfurt(Main), 1981.
ISBN 3 87144 492 8.
1054 CHAPTER 16. USER CONTRIBUTED PACKAGES
Chapter 17
Symbolic Mode
eval_mode;
1055
1056 CHAPTER 17. SYMBOLIC MODE
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
symbolic(x := ’a);
symbolic x := a;
symbolic(x) := a;
For convenience, it is assumed that any operator whose 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:
car ’(a);
Except where explicit limitations have been made, most REDUCE algebraic con-
structions carry over into 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 vari-
ables and array elements are initialized to NIL rather than 0. (In fact, any variables
not explicitly declared INTEGER are also initialized to NIL in algebraic mode, but
the algebraic evaluator recognizes NIL as 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.
17.1. SYMBOLIC INFIX OPERATORS 1057
There are three binary infix operators in REDUCE intended for use in symbolic
mode, namely . (CONS), EQ and MEMQ. The precedence of these operators was
given in another section.
These consist of scalar variables and operators and follow the normal rules of the
Lisp meta language.
Examples:
x
car u . reverse v
simp (u+v^2)
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 QUOTE function. This is provided by the single quote mark ’. For
example,
Note, however, that strings are constants and therefore evaluate to themselves in
symbolic mode. Thus, to print the string "A String", one would write
Within a quoted expression, identifier syntax rules are those of REDUCE. Thus
(A !. B) is the list consisting of the three elements A, ., and B, whereas (A
. B) is the dotted pair of A and B.
LAMBDA expressions provide the means for constructing Lisp LAMBDA expres-
sions in symbolic mode. They may not be used in algebraic mode.
1058 CHAPTER 17. SYMBOLIC MODE
Syntax:
hLAMBDA expressioni −→
LAMBDA hvarlistihterminatorihstatementi
where
e.g.,
The FOR EACH form of the FOR statement, designed for iteration down a list, is
more general in symbolic mode. Its syntax is:
DO COLLECT JOIN
IN MAPC MAPCAR MAPCAN
ON MAP MAPLIST MAPCON
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 ASSOC, the following could be used:
If the default mode were symbolic, then SYMBOLIC could be omitted in the above
definition. MACROs may be defined by prefixing the keyword PROCEDURE by the
word MACRO. (In fact, ordinary functions may be defined with the keyword EXPR
prefixing PROCEDURE as was used in the Standard Lisp Report.) For example,
we could define a MACRO CONSCONS by
Another form of macro, the SMACRO is also available. These are described in the
1060 CHAPTER 17. SYMBOLIC MODE
Standard Lisp Report. The Report also defines a function type 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 FEXPRs in the core REDUCE
system.
A user can obtain the Standard Lisp equivalent of his REDUCE input by turning
on the switch DEFN (for definition). The system then prints the Lisp translation
of his input but does not evaluate it. Normal operation is resumed when DEFN is
turned off.
One of the principal motivations for a user of the algebraic facilities of REDUCE to
learn about symbolic mode is that it gives one access to a wider range of techniques
than is possible in 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 con-
siders 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 ex-
pression 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 SHARE is available. 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.,
share x,y;
x := (a+b)^2;
assuming that X was declared shared as above. If we now change to symbolic mode
and say
x;
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 re-
convert standard forms (which represent polynomials) and standard quotients back
to a true Lisp prefix form for the expression (which would result in excessive com-
putation). So *SQ is used to tell the algebraic processor that it is dealing with a
prefix form which is really a standard quotient and the second argument (T or NIL)
tells it whether it needs further processing (essentially, an already simplified flag).
So to get the true standard quotient form in symbolic mode, one needs CADR of the
variable. E.g.,
z := cadr x;
REDUCE Selectors
1062 CHAPTER 17. SYMBOLIC MODE
REDUCE Constructors
.+ add a term to a polynomial
./ divide (two polynomials to get quotient)
.* multiply power by coefficient to produce term
.^ raise a variable to a power
For example, to find the numerator of the standard quotient above, one could say:
numr z;
lt numr z;
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 (expt (plus a b) 2) for (a+b)^2, or
the format (*sq hstandard quotienti 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:
For example, to pass the leading term of (a+b)^2 back to algebraic mode, one
could say:
where Y has been declared shared as above. If you now go back to algebraic mode,
you can work with Y in the usual way.
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.
If one wishes to define a procedure in symbolic mode for use as an operator in alge-
braic mode, it is necessary to declare this fact to the system by using the declaration
OPERATOR in symbolic mode. Thus
Note that this operator has a different effect than the operator 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 REVAL can be used. The one argument of REVAL
must be the prefix form of an expression. REVAL returns the evaluated expression
as a true Lisp prefix form.
1066 CHAPTER 17. SYMBOLIC MODE
Rlisp ’88 is a superset of the Rlisp that has been traditionally used for the support
of REDUCE. It is fully documented in the book Marti, J.B., “RLISP ’88: An Evo-
lutionary Approach to Program Design and Reuse”, World Scientific, Singapore
(1993). Rlisp ’88 adds to the traditional Rlisp the following facilities:
1. more general versions of the looping constructs for, repeat and while;
In addition, “-” is a letter in Rlisp ’88. In other words, A-B is an identifier, not
the difference of the identifiers A and B. If the latter construct is required, it is
necessary to put spaces around the - character. For compatibility between the two
versions of Rlisp, we recommend this convention be used in all symbolic mode
programs.
To use Rlisp ’88, type on rlisp88;. This switches to symbolic mode with the
Rlisp ’88 syntax and extensions. While in this environment, it is impossible to
switch to algebraic mode, or prefix expressions by “algebraic”. However, symb-
olic mode programs written in Rlisp ’88 may be run in algebraic mode provided the
rlisp88 package has been loaded. We also expect that many of the extensions de-
fined in Rlisp ’88 will migrate to the basic Rlisp over time. To return to traditional
Rlisp or to switch to algebraic mode, say “off rlisp88;”.
17.11 References
There are a number of useful books which can give you further information about
LISP. Here is a selection:
Allen, J.R., “The Anatomy of LISP”, McGraw Hill, New York, 1978.
McCarthy J., P.W. Abrahams, J. Edwards, T.P. Hart and M.I. Levin, “LISP 1.5
Programmer’s Manual”, M.I.T. Press, 1965.
Touretzky, D.S, “LISP: A Gentle Introduction to Symbolic Computation”, Harper
& Row, New York, 1984.
Winston, P.H. and Horn, B.K.P., “LISP”, Addison-Wesley, 1981.
Chapter 18
Syntax:
(EXPRN1:vector_expression)
. (EXPRN2:vector_expression):algebraic.
The binary . operator, which is normally used to denote the addition of an element
to the front of a list, can also be used in algebraic mode to denote the scalar product
of two Lorentz four-vectors. For this to happen, the second argument must be
recognizable as a vector expression at the time of evaluation. With this meaning,
this operator is often referred to as the dot operator. In the present system, the index
handling routines all assume that Lorentz four-vectors are used, but these routines
could be rewritten to handle other cases.
Components of vectors can be represented by including representations of unit vec-
tors in the system. Thus if EO represents the unit vector (1,0,0,0), (p.eo)
represents the zeroth component of the four-vector P. Our metric and notation fol-
1067
1068 CHAPTER 18. CALCULATIONS IN HIGH ENERGY PHYSICS
index u;
p.u * q.u
would result in
P.Q
Syntax:
G(ID:identifier[,EXPRN:vector_expression])
:gamma_matrix_expression.
g(l1,p) * g(l2,q)
denotes the product of γ.p associated with a fermion line identified as L1, and
γ.q associated with another line identified as L2 and where p and q are Lorentz
18.2. VECTOR VARIABLES 1069
four-vectors. A product of γ matrices associated with the same line may be written
in a contracted form.
Thus
g(l1,p1,p2,...,p3) = g(l1,p1)*g(l1,p2)*...*g(l1,p3) .
Syntax:
EPS(EXPRN1:vector_expression,...,EXPRN4:vector_exp)
:vector_exp.
The operator EPS has four arguments, and is used only to denote the completely
antisymmetric tensor of order 4 and its contraction with Lorentz four-vectors. Thus
+1 if i, j, k, l is an even permutation of 0,1,2,3
ijkl = −1 if i, j, k, l is an odd permutation of 0,1,2,3
0 otherwise
Apart from the line identification identifier in the G operator, all other arguments
of the operators in this section are vectors. Variables used as such must be declared
so by the type declaration VECTOR, for example:
vector p1,p2;
1070 CHAPTER 18. CALCULATIONS IN HIGH ENERGY PHYSICS
Two additional expression types are necessary for high energy calculations, namely
These follow the normal rules of vector combination. Thus the product of a scalar
or numerical expression and a vector expression is a vector, as are the sum and
difference of vector expressions. If these rules are not followed, error messages are
printed. Furthermore, if the system finds an undeclared variable where it expects
a vector variable, it will ask the user in interactive mode whether to make that
variable a vector or not. In batch mode, the declaration will be made automatically
and the user informed of this by a message.
Examples:
Assuming P and Q have been declared vectors, the following are vector expressions
p
2*q/3
2*x*y*p - p.q*q/(3*q.q)
When a Dirac expression is evaluated, the system computes one quarter of the trace
of each γ matrix product in the expansion of the expression. One quarter of each
trace is taken in order to avoid confusion between the trace of the scalar M, say,
and M representing M * hunit 4 by 4 matrixi. Contraction over indices
occurring in such expressions is also performed. If an unmatched index is found in
such an expression, an error occurs.
The algorithms used for trace calculations are the best available at the time this
system was produced. For example, in addition to the algorithm developed by
Chisholm for contracting indices in products of traces, REDUCE uses the elegant
algorithm of Kahane for contracting indices in γ matrix products. These algorithms
are described in Chisholm, J. S. R., Il Nuovo Cimento X, 30, 426 (1963) and
Kahane, J., Journal Math. Phys. 9, 1732 (1968).
It is possible to prevent the trace calculation over any line identifier by the declara-
tion NOSPUR. For example,
nospur l1,l2;
will mean that no traces are taken of γ matrix terms involving the line numbers L1
and L2. However, in some calculations involving more than one line, a catastrophic
error
can occur (for the reason stated!) If you encounter this error, please let us know!
A trace of a γ matrix expression involving a line identifier which has been declared
NOSPUR may be later taken by making the declaration SPUR.
See also the CVIT package for an alternative mechanism (chapter 16.17).
It is often necessary to put a particle “on the mass shell” in a calculation. This can,
of course, be accomplished with a LET command such as
but an alternative method is provided by two commands MASS and MSHELL. MASS
takes a list of equations of the form:
for example,
The only effect of this command is to associate the relevant scalar variable as a
mass with the corresponding vector. If we now say
and a mass has been associated with these arguments, a substitution of the form
18.6 Example
γ · ki γ · eγ · e0 γ · kf γ · e0 γ · e
γ · pi + m
+
2m 2k.pi 2k 0 · pi
where ki and kf are the four-momenta of incoming and outgoing photons (with
polarization vectors e and e0 and laboratory energies k and k 0 respectively) and pi ,
pf are incident and final electron four-momenta.
0 2
α2 k
Omitting therefore an overall factor 2
we need to find one quarter of
2m k
the trace of
γ · e0 γ · eγ · ki γ · eγ · e0 γ · kf
(γ · pf + m) + ×
2k.pi 2k 0 .pi
γ · ki γ · eγ · e0 γ · kf γ · e0 γ · e
(γ · pi + m) +
2k.pi 2k 0 .pi
A straightforward REDUCE program for this, with appropriate substitutions (using
P1 for pi , PF for pf , KI for ki and KF for kf ) is
18.7. EXTENSIONS TO MORE THAN FOUR DIMENSIONS 1073
(We use P1 instead of PI in the above to avoid confusion with the reserved variable
PI).
This program will print the following result
2 1 -1 1 -1
The Compton cxn is 2*E.EP + ---*K*KP + ---*K *KP - 1
2 2
In our discussion so far, we have assumed that we are working in the normal four
dimensions of QED calculations. However, in most cases, the programs will also
work in an arbitrary number of dimensions. The command
vecdim hexpressionihterminatori
sets the appropriate dimension. The dimension can be symbolic as well as numer-
ical. Users should note however, that the EPS operator and the γ5 symbol (A) are
not properly defined in other than four dimensions and will lead to an error if used.
1074 CHAPTER 18. CALCULATIONS IN HIGH ENERGY PHYSICS
Chapter 19
REDUCE and its associated support language system Rlisp include a number of
utilities which have proved useful for program development over the years. The
following are supported in most of the implementations of REDUCE currently
available.
PLAP If ON, causes the printing of the portable macros produced by the compiler;
PGWD If ON, causes the printing of the actual assembly language instructions gen-
erated from the macros;
1075
1076 CHAPTER 19. REDUCE AND RLISP UTILITIES
In most versions of REDUCE, it is possible to take any set of Lisp, Rlisp or RE-
DUCE commands and build a fast loading version of them. In Rlisp or REDUCE,
one does the following:
faslout <filename>;
<commands or IN statements>
faslend;
To load such a file, one uses the command LOAD, e.g. load foo; or load
foo,bah;
This process produces a fast-loading version of the original file. In some imple-
mentations, this means another file is created with the same name but a different
extension. For example, in PSL-based systems, the extension is b (for binary). In
CSL-based systems, however, this process adds the fast-loading code to a single
file in which all such code is stored. Particular functions are provided by CSL for
managing this file, and described in the CSL user documentation.
In doing this build, as with the production of a Standard Lisp form of such state-
ments, it is important to remember that some of the commands must be instantiated
during the building process. For example, macros must be expanded, and some
property list operations must happen. The REDUCE sources should be consulted
for further details on this.
To avoid excessive printout, input statements should be followed by a $ instead of
the semicolon. With LOAD however, the input doesn’t print out regardless of which
terminator is used with the command.
If you subsequently change the source files used in producing a fast loading file,
don’t forget to repeat the above process in order to update the fast loading file
correspondingly. Remember also that the text which is read in during the creation
of the fast load file, in the compiling process described above, is not stored in your
REDUCE environment, but only translated and output. If you want to use the file
just created, you must then use LOAD to load the output of the fast-loading file
generation program.
When the file to be loaded contains a complete package for a given application,
LOAD_PACKAGE rather than LOAD should be used. The syntax is the same. How-
ever, LOAD_PACKAGE does some additional bookkeeping such as recording that
this package has now been loaded, that is required for the correct operation of the
system.
19.3. THE STANDARD LISP CROSS REFERENCE PROGRAM 1077
CREF is a Standard Lisp program for processing a set of Standard LISP function
definitions to produce:
1. A “summary” showing:
The program will also check that functions are called with the correct number of
arguments, and print a diagnostic message otherwise.
The output is alphabetized on the first seven characters of each function name.
1078 CHAPTER 19. REDUCE AND RLISP UTILITIES
19.3.1 Restrictions
19.3.2 Usage
To invoke the cross reference program, the switch CREF is used. on cref causes
the cref program to load and the cross-referencing process to begin. After all the
required definitions are loaded, off cref will cause the cross-reference listing
to be produced. For example, if you wish to cross-reference all functions in the
file tst.red, and produce the cross-reference listing in the file tst.crf, the
following sequence can be used:
out "tst.crf";
on cref;
in "tst.red"$
off cref;
shut "tst.crf";
To process more than one file, more IN statements may be added before the call of
off cref, or the IN statement changed to include a list of files.
19.3.3 Options
Functions with the flag NOLIST will not be examined or output. Initially, all
Standard Lisp functions are so flagged. (In fact, they are kept on a list NOLIST!*,
so if you wish to see references to all functions, then CREF should be first loaded
with the command load cref, and this variable then set to NIL).
It should also be remembered that any macros with the property list flag EXPAND,
or, if the switch FORCE is on, without the property list flag NOEXPAND, will be
expanded before the definition is seen by the cross-reference program, so this flag
can also be used to select those macros you require expanded and those you do not.
Maintaining REDUCE
http://reduce-algebra.sourceforge.net/
We mention here three ways in which REDUCE is maintained. The first is the
collection of queries, observations and bug-reports. All users are encouraged to
subscribe to the mailing list that Sourceforge.net provides so that they will re-
ceive information about updates and concerns. Also on SourceForge there is a bug
tracker and a forum. The expectation is that the maintainers and keen users of RE-
DUCE will monitor those and try to respond to issues. However these resources
are not there to seek answers to Maths homework problems - they are intended
specifically for issues to do with the use and support of REDUCE.
The second level of support is provided by the fact that all the sources of REDUCE
are available, so any user who is having difficulty either with a bug or understand-
ing system behaviour can consult the code to see if (for instance) comments in it
clarify something that was unclear from the regular documentation.
The source files for REDUCE are available on SourceForge in the Subversion
repository. Check the "code/SVN" tab on the SourceForge page to find instruc-
tions for using a Subversion client to fetch the most up to date copy of everything.
From time to time there may be one-file archives of a snapshot of the sources placed
in the download area on SourceForge, and eventually some of these mat be marked
as “stable” releases, but at present it is recommended that developers use a copy
from the Subversion repository.
The files fetched there come with a directory called “trunk” that holds the main
current REDUCE, and one called “branches” that is reserved for future experimen-
tal versions. All the files that we have for creating help files and manuals should
also be present in the files you fetch.
The packages that make up the source for the algebraic capabilities of REDUCE
1081
1082 CHAPTER 20. MAINTAINING REDUCE
are in the “packages” sub-directory, and often there are test files for a package
present there and especially for contributed packages there will be documentation
in the form of a LATEX file. Although REDUCE is coded in its own language many
people in the past have found that it does not take too long to start to get used to it.
In various cases even fairly “ordinary end users” may wish to fetch the source ver-
sion of REDUCE and compile it all for themselves. This may either be because
they need the benefit of a bug-fix only recently checked into the subversion repos-
itory or because no pre-compiled binary is available for the particular computer
and operating system they use. This latter is to some extent unavoidable since RE-
DUCE can run on both 32 and 64-bit Windows, the various MacOSX options (eg
Intel and Powerpc), many different distributions of Linux, some BSD variants and
Solaris (at least). It is not practically feasible for us to provide a constant stream of
up to date ready-built binaries for all these.
There are instructions for compiling REDUCE present at the top of the trunk source
tree. Usually the hardest issue seems to be encuring that your computer has an
adequate set of development tools and libraries installled before you start, but once
that is sorted out the hope is that the compilation of REDUCE should proceed
uneventfully if sometimes tediously.
In a typical Open Source way the hope is that some of those who build REDUCE
from source or explore the source (out of general interest or to pursue an under-
standing of some bug or detail) will transform themselves into contributors or de-
velopers which moves on to the third level of support.
At this third level any user can contribute proposals for bug fixes or extensions to
REDUCE or its documentation. It might be valuable to collect a library of addi-
tional user-contributed examples illustrating the use of the system too. To do this
first ensure that you have a fully up to date copy of the sources from Subversion,
and then depending on just what sort of change is being proposed provide the up-
dates to the developers via the SourceForge bug tracker or other route. In time we
may give more concrete guidance about the format of changes that will be easiest to
handle. It is obviously important that proposed changes have been properly tested
and that they are accompanied with a clear explanation of why they are of benefit.
A specific concern here is that in the past fixes to a bug in one part of REDUCE
have had bad effects on some other applications and packages, so some degree of
caution is called for. Anybody who develops a significant whole new package for
REDUCE is encouraged to make the developers aware so that it can be considered
for inclusion.
So the short form explanation about Support and Maintenance is that it is mainly
focussed around the SourceForge system. That if discussions about bugs, require-
ments or issues are conducted there then all users and potential users of REDUCE
will be able to benefit from reviewing them, and the Sourceforge mailing lists,
tracker, forums and wiki will grow to be both a static repository of answers to
1083
common questions, an active set of locations to to get new issues looked at and a
focus for guiding future development.
1084 CHAPTER 20. MAINTAINING REDUCE
Appendix A
Reserved Identifiers
We list here all identifiers that are normally reserved in REDUCE including names
of commands, operators and switches initially in the system. Excluded are words
that are reserved in specific implementations of the system.
1085
1086 APPENDIX A. RESERVED IDENTIFIERS
1089
1090 BIBLIOGRAPHY
Appendix B
New packages assert bibasis breduce cde cdiff clprl gcref guardian lalr lessons
libreduce listvecops lpdo redfront reduce4 sstools utf8
1091
1092 APPENDIX B. CHANGES SINCE VERSION 3.8
Package specfn psi (digamma) function can now be calculated numerically for
complex arguments.
1093
1094 INDEX
Curl DELSQ
vector field, 262 operator, 262
CURL DELSQ operator, 758
operator, 262 delta, 362, 363, 365, 377, 379, 384
CURL operator, 758 delta function, 364, 379
C VIT package, 474 DEMO, 68
Cylindrical coordinates, 755 DEN, 129, 142
DEP_VAR global variable (CDE), 399
d DEPEND, 103
exterior differentiation, 532 DEPEND
dd_groebner, 612 CANTENS package, 349
Declaration, 67 DEPEND command, 107
array, 67 DEPEND declaration, 395
KORDER, 124 DEPEND statement, 759
mode handling, 68 DEQ(I), 908
DECOMPOSE, 140 DER_DEG_ORDERING operator (CDE),
decomposition 414
partial fraction, 93 Derivative
Default variational, 520
term order, 593 derivatives, 500
Defaults D ESIR package, 493
TAYLOR package, 957 DET, 179
DEFINE command, 69 DET operator, 109
DEFINE_SPACES, 345, 359 detectunits (CALI), 292, 302
Definite integration (simple), 264 Determinant
DEFINT function, 264 in DETM!*, 525
D EFINT package, 90, 483 DETM!* variable, 525
D EFINT package, 90 DETRAFO, 213
DEFLINEINT function, 265 DF, 350
DEFN switch, 1060, 1079 DF operator, 86, 89
DEFPOLY statement, 219 DF_ODD operator (CDE), 402
DEG, 141 DFINT switch, 88
Degree, 141 DFP, 501
degree, 318 D FPART package, 500
degree arguments, 975 DIAGONAL operator, 666
degree vectors (CALI), 286 DIAGONALIZE, 948
degree!*, 310 Differential geometry, 512
degreeorder procedure (CALI), 287 Differentiation, 86, 89, 107
degreeorder!*, 296 partial, 515
degsfromresolution, 318 vector, 262
del, 362, 375, 387 Digamma, 919
deleteunits Digamma function, 919, 924
* (CALI), 302 DILOG, 76, 90, 919
deleteunits, 318 Dilogarithm function, 919
INDEX 1099
XPND
@, 532
XPND
@, 517
D, 517
XPND command, 532
XVARS, 1017