REDUCE

17.9 Communicating with Algebraic Mode

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 considers expressions in two forms: prefix form, which follow the normal Lisp rules of function composition, and so-called canonical form, which uses a completely different syntax.

Once these details are understood, the most critical problem faced by a user is how to make expressions and procedures communicate between symbolic and algebraic mode. The purpose of this section is to teach a user the basic principles for this.

If one wants to evaluate an expression in algebraic mode, and then use that expression in symbolic mode calculations, or vice versa, the easiest way to do this is to assign a variable to that expression whose value is easily obtainable in both modes. To facilitate this, a declaration 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;

says that X and Y will receive values to be used in both modes.

If a SHARE declaration is made for a variable with a previously assigned algebraic value, that value is also made available in symbolic mode.

17.9.1 Passing Algebraic Mode Values to Symbolic Mode

If one wishes to work with parts of an algebraic mode expression in symbolic mode, one simply makes an assignment of a shared variable to the relevant expression in algebraic mode. For example, if one wishes to work with (a+b)^2, one would say, in algebraic mode:

        x := (a+b)^2;

assuming that X was declared shared as above. If we now change to symbolic mode and say

        x;

its value will be printed as a prefix form with the syntax:

        (*SQ <standard quotient> T)

This particular format reflects the fact that the algebraic mode processor currently likes to transfer prefix forms from command to command, but doesn’t like to reconvert standard forms (which represent polynomials) and standard quotients back to a true Lisp prefix form for the expression (which would result in excessive computation). 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;

would store in Z the standard quotient form for (a+b)^2.

Once you have this expression, you can now manipulate it as you wish. To facilitate this, a standard set of selectors and constructors are available for getting at parts of the form. Those presently defined are as follows:

REDUCE Selectors
DENR

denominator of standard quotient

LC

leading coefficient of polynomial

LDEG

leading degree of polynomial

LPOW

leading power of polynomial

LT

leading term of polynomial

MVAR

main variable of polynomial

NUMR

numerator (of standard quotient)

PDEG

degree of a power

RED

reductum of polynomial

TC

coefficient of a term

TDEG

degree of a term

TPOW

power of a term

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;

or to find the leading term of the numerator:

        lt numr z;

Conversion between various data structures is facilitated by the use of a set of functions defined for this purpose. Those currently implemented include:

!*A2F

convert an algebraic expression to a standard form. If result is rational, an error results;

!*A2K

converts an algebraic expression to a kernel. If this is not possible, an error results;

!*F2A

converts a standard form to an algebraic expression;

!*F2Q

convert a standard form to a standard quotient;

!*K2F

convert a kernel to a standard form;

!*K2Q

convert a kernel to a standard quotient;

!*P2F

convert a standard power to a standard form;

!*P2Q

convert a standard power to a standard quotient;

!*Q2F

convert a standard quotient to a standard form. If the quotient denominator is not 1, an error results;

!*Q2K

convert a standard quotient to a kernel. If this is not possible, an error results;

!*T2F

convert a standard term to a standard form

!*T2Q

convert a standard term to a standard quotient.

17.9.2 Passing Symbolic Mode Values to Algebraic Mode

In order to pass the value of a shared variable from symbolic mode to algebraic mode, the only thing to do is make sure that the value in symbolic mode is a prefix expression. E.g., one uses (expt (plus a b) 2) for (a+b)^2, or the format (*sq standard quotient t) as described above. However, if you have been working with parts of a standard form they will probably not be in this form. In that case, you can do the following:

  1. If it is a standard quotient, call PREPSQ on it. This takes a standard quotient as argument, and returns a prefix expression. Alternatively, you can call MK!*SQ on it, which returns a prefix form like (*SQ standard quotient T) and avoids translation of the expression into a true prefix form.
  2. If it is a standard form, call PREPF on it. This takes a standard form as argument, and returns the equivalent prefix expression. Alternatively, you can convert it to a standard quotient and then call MK!*SQ.
  3. If it is a part of a standard form, you must usually first build up a standard form out of it, and then go to step 2. The conversion functions described earlier may be used for this purpose. For example,
    1. If Z is an expression which is a term, !*T2F Z is a standard form.
    2. If Z is a standard power, !*P2F Z is a standard form.
    3. If Z is a variable, you can pass it direct to algebraic mode.

For example, to pass the leading term of (a+b)^2 back to algebraic mode, one could say:

        y:= mk!*sq !*t2q lt numr z;

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.

17.9.3 Complete Example

The following is the complete code for doing the above steps. The end result will be that the square of the leading term of (a + b)2 is calculated.

share x,y;                   % declare X and Y as shared  
x := (a+b)^2;                % store (a+b)^2 in X  
symbolic;                    % transfer to symbolic mode  
z := cadr x;                 % store a true standard quotient  
                             % in Z  
lt numr z;                   % print the leading term of the  
                             % numerataor of Z  
y := mk!*sq !*t2q lt numr z; % store the prefix form of this  
                             % leading term in Y  
algebraic;                   % return to algebraic mode  
y^2;                         % evaluate square of the  
                             % leading term of (a+b)^2

17.9.4 Defining Procedures for Intermode Communication

If one wishes to define a procedure in symbolic mode for use as an operator in algebraic mode, it is necessary to declare this fact to the system by using the declaration OPERATOR in symbolic mode. Thus

        symbolic operator leadterm;

would declare the procedure LEADTERM as an algebraic operator. This declaration must be made in symbolic mode as the effect in algebraic mode is different. The value of such a procedure must be a prefix form.

The algebraic processor will pass arguments to such procedures in prefix form. Therefore if you want to work with the arguments as standard quotients you must first convert them to that form by using the function SIMP!*. This function takes a prefix form as argument and returns the evaluated standard quotient.

For example, if you want to define a procedure LEADTERM which gives the leading term of an algebraic expression, one could do this as follows:

symbolic operator leadterm; % Declare LEADTERM as a symbolic  
                            % mode procedure to be used in  
                            % algebraic mode.  
 
symbolic procedure leadterm u; % Define LEADTERM.  
   mk!*sq !*t2q lt numr simp!* u;

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.