(10) Programming
Before examining this topic, please make sure that you have read: (1) Working Through the New User's Tour.
Maple features a full, procedural, fourth-generation programming language (4GL). It is specifically designed for the rapid development of mathematical subroutines and custom applications.
The syntax is similar to that of C, FORTRAN, BASIC, and Pascal. If you have used any of these languages, you can easily take advantage of the programming capabilities of Maple .
Use the restart command to clear Maple's internal memory and get started with this topic of the tour.
> restart;
Code Generation
Maple can generate code that is compatible with the programming languages FORTRAN and C, and the typesetting language LaTeX. One application of this feature is to access specialized numerical solvers that provide maximum speed for complex problems. For example, you could develop a mathematical model using Maple, and then use Maple to generate C code corresponding to the model.
The following examples generate FORTRAN and C code for matrix inversion, but code generation is by no means limited to the Linear Algebra package.
To access the functions in Linear Algebra and in codegen by their short names, use the with command.
> with(LinearAlgebra);
> with(codegen);
Consider the symbolic matrix
.
> A := Matrix( 3, 3, (i,j) -> a[i,j] );
Compute the symbolic inverse of the matrix. Store the result as
:
> A_inv := MatrixInverse(A);
The
fortran
command generates the necessary FORTRAN code for computing
.
> fortran(A_inv);
unknown(1,1) = -(a(2,2)*a(3,3)-a(2,3)*a(3,2))/(-a(3,1)*a(1,2)*a(2,
#3)+a(3,1)*a(1,3)*a(2,2)+a(2,1)*a(1,2)*a(3,3)-a(2,1)*a(1,3)*a(3,2)-
#a(1,1)*a(2,2)*a(3,3)+a(1,1)*a(2,3)*a(3,2))
unknown(1,2) = (a(1,2)*a(3,3)-a(1,3)*a(3,2))/(-a(3,1)*a(1,2)*a(2,3
#)+a(3,1)*a(1,3)*a(2,2)+a(2,1)*a(1,2)*a(3,3)-a(2,1)*a(1,3)*a(3,2)-a
#(1,1)*a(2,2)*a(3,3)+a(1,1)*a(2,3)*a(3,2))
unknown(1,3) = -(a(1,2)*a(2,3)-a(1,3)*a(2,2))/(-a(3,1)*a(1,2)*a(2,
#3)+a(3,1)*a(1,3)*a(2,2)+a(2,1)*a(1,2)*a(3,3)-a(2,1)*a(1,3)*a(3,2)-
#a(1,1)*a(2,2)*a(3,3)+a(1,1)*a(2,3)*a(3,2))
unknown(2,1) = (-a(3,1)*a(2,3)+a(2,1)*a(3,3))/(-a(3,1)*a(1,2)*a(2,
#3)+a(3,1)*a(1,3)*a(2,2)+a(2,1)*a(1,2)*a(3,3)-a(2,1)*a(1,3)*a(3,2)-
#a(1,1)*a(2,2)*a(3,3)+a(1,1)*a(2,3)*a(3,2))
unknown(2,2) = (a(3,1)*a(1,3)-a(1,1)*a(3,3))/(-a(3,1)*a(1,2)*a(2,3
#)+a(3,1)*a(1,3)*a(2,2)+a(2,1)*a(1,2)*a(3,3)-a(2,1)*a(1,3)*a(3,2)-a
#(1,1)*a(2,2)*a(3,3)+a(1,1)*a(2,3)*a(3,2))
unknown(2,3) = -(-a(1,1)*a(2,3)+a(2,1)*a(1,3))/(-a(3,1)*a(1,2)*a(2
#,3)+a(3,1)*a(1,3)*a(2,2)+a(2,1)*a(1,2)*a(3,3)-a(2,1)*a(1,3)*a(3,2)
#-a(1,1)*a(2,2)*a(3,3)+a(1,1)*a(2,3)*a(3,2))
unknown(3,1) = -(a(2,1)*a(3,2)-a(3,1)*a(2,2))/(-a(3,1)*a(1,2)*a(2,
#3)+a(3,1)*a(1,3)*a(2,2)+a(2,1)*a(1,2)*a(3,3)-a(2,1)*a(1,3)*a(3,2)-
#a(1,1)*a(2,2)*a(3,3)+a(1,1)*a(2,3)*a(3,2))
unknown(3,2) = -(-a(1,1)*a(3,2)+a(3,1)*a(1,2))/(-a(3,1)*a(1,2)*a(2
#,3)+a(3,1)*a(1,3)*a(2,2)+a(2,1)*a(1,2)*a(3,3)-a(2,1)*a(1,3)*a(3,2)
#-a(1,1)*a(2,2)*a(3,3)+a(1,1)*a(2,3)*a(3,2))
unknown(3,3) = (a(2,1)*a(1,2)-a(1,1)*a(2,2))/(-a(3,1)*a(1,2)*a(2,3
#)+a(3,1)*a(1,3)*a(2,2)+a(2,1)*a(1,2)*a(3,3)-a(2,1)*a(1,3)*a(3,2)-a
#(1,1)*a(2,2)*a(3,3)+a(1,1)*a(2,3)*a(3,2))
You can similarly generate C code.
> C( A_inv, optimized );
t4 = a[2][0]*a[0][1];
t6 = a[2][0]*a[0][2];
t8 = a[1][0]*a[0][1];
t10 = a[1][0]*a[0][2];
t12 = a[0][0]*a[1][1];
t14 = a[0][0]*a[1][2];
t17 = 1/(-t4*a[1][2]+t6*a[1][1]+t8*a[2][2]-t10*a[2][1]-t12*a[2][2]+t14*a
[2][1]);
unknown[0][0] = -(a[1][1]*a[2][2]-a[2][1]*a[1][2])*t17;
unknown[0][1] = (a[0][1]*a[2][2]-a[0][2]*a[2][1])*t17;
unknown[0][2] = -(a[0][1]*a[1][2]-a[0][2]*a[1][1])*t17;
unknown[1][0] = (-a[2][0]*a[1][2]+a[1][0]*a[2][2])*t17;
unknown[1][1] = (t6-a[0][0]*a[2][2])*t17;
unknown[1][2] = -(-t14+t10)*t17;
unknown[2][0] = -(a[1][0]*a[2][1]-a[2][0]*a[1][1])*t17;
unknown[2][1] = -(-a[0][0]*a[2][1]+t4)*t17;
unknown[2][2] = (t8-t12)*t17;
One of the principal Maple tools used to help you customize and extend Maple's capabilities is the procedure . A procedure definition is a valid expression that can be assigned to a name. An example of a predefined procedure in Maple is the solve command.
The command below assigns to the symbol
a user-defined procedure that adds its two arguments,
and
.
> f := proc( x, y )
x + y;
end proc;
Evaluate
with the arguments 3 and 5.
> f( 3, 5 );
You can also invoke
with symbolic input.
> f( cat, dog );
Modules
For large-scale application development, or for programming generic algorithms, Maple provides modules.
A module can be thought of as a collection of procedures and other data that are "exported," as well as private ("local") data that is not accessible to the user of the module.
Here is a procedure that generates a module that can be used to represent the quotient rings Z/nZ. It is a parameterized module, because it depends on the parameter 'n' to its constructor.
>
Zmod := proc(n)
module()
export `+`, `*`, `-`, `/`;
`+` := ( a, b ) -> a + b mod n;
`*` := ( a, b ) -> a * b mod n;
`-` := x -> (-s) mod n;
`/` := x -> (1/s) mod n;
end module
end proc:
z5 := Zmod( 5 );
z5:-`+`( 2, 3 );
z5:-`*`( 2, 3 );
Modules constructed by Zmod() satisfy the following "interface":
>
`type/ring` := '`module`( `+`, `*`, `-`, `/` )':
type( z5, 'ring' );
It also satisfies the simpler interface for abelian groups.
>
`type/abelianGroup` := '`module`( `+` )':
type( z5, 'abelianGroup' );
Write a procedure that takes a ring R and computes an affine combination of two of its members.
>
aff := proc(R::ring, a, b)
use `+` = R:-`+`, `*` = R:-`*` in
a + a*b
end use
end proc;
This procedure can be used with any modules that implements the required interface.
>
aff( z5, 2, 3 );
aff( Zmod( 8 ), 2, 3 );
Modules can also be used to write packages of routines.
Local Variables
Maple supports
local variables
. These are programming variables that are used only during execution of a procedure or module, and then discarded. Consider a procedure that computes Chebyshev polynomials of degree 0 through
(supplied by the user).
>
Chebyshev := proc( n::nonnegint )
local p, k;
p := Array(0..n);
p[0] := 1;
p[1] := x;
if n <= 1 then
return p;
end if;
for k from 2 to n do
p[k] := expand( 2*x*p[k-1] - p[k-2] );
end do;
p;
end proc;
You can use this procedure to construct a table of the first five Chebyshev polynomials.
a := Chebyshev(5):
The third Chebyshev polynomial is the third entry in the table named
.
> a[3];
The Chebyshev example also shows you how to use the conditional ( if ) statement in Maple.
Viewing Source Code
For programmers, a tremendous benefit of Maple is its open architecture. You can access the source code to more than ninety-five percent of the math routines available. This accessibility is essential for enhancing existing routines to meet your specific needs.
The interface command allows you to view code for Maple procedures.
> interface(verboseproc=2);
For example, you can view the code for the effectiverate command in the finance package. The eval command evaluates the procedure fully.
> with(finance):
> eval(effectiverate);
Once finished viewing the code for a particular command or procedure, always reset to the default output level.
interface(verboseproc=1):