newuser,topic10

(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);

[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...
[Add, Adjoint, BackwardSubstitute, BandMatrix, Basi...

> with(codegen);

[C, GRAD, GRADIENT, HESSIAN, JACOBIAN, cost, declar...
[C, GRAD, GRADIENT, HESSIAN, JACOBIAN, cost, declar...
[C, GRAD, GRADIENT, HESSIAN, JACOBIAN, cost, declar...
[C, GRAD, GRADIENT, HESSIAN, JACOBIAN, cost, declar...

Consider the symbolic matrix A .

> A := Matrix( 3, 3, (i,j) -> a[i,j] );

A := _rtable[4132852]

Compute the symbolic inverse of the matrix. Store the result as A_inv :

> A_inv := MatrixInverse(A);

A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]
A_inv := _rtable[4245332]

The fortran command generates the necessary FORTRAN code for computing A_inv .

> 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;

Procedures

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 f a user-defined procedure that adds its two arguments, x and y .

> f := proc( x, y )

x + y;

end proc;

f := proc (x, y) x+y end proc

Evaluate f with the arguments 3 and 5.

> f( 3, 5 );

8

You can also invoke f with symbolic input.

> f( cat, dog );

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 );

z5 := module () export `+`, `*`, `-`, `/`; end modu...

0

1

Modules constructed by Zmod() satisfy the following "interface":

> `type/ring` := '`module`( `+`, `*`, `-`, `/` )':
type( z5, 'ring' );

true

It also satisfies the simpler interface for abelian groups.

> `type/abelianGroup` := '`module`( `+` )':
type( z5, 'abelianGroup' );

true

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;

aff := proc (R::ring, a, b) R:-`+`(a,R:-`*`(a,b)) e...

This procedure can be used with any modules that implements the required interface.

> aff( z5, 2, 3 );
aff( Zmod( 8 ), 2, 3 );

3

0

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 n (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;

Chebyshev := proc (n::nonnegint) local p, k; p := A...
Chebyshev := proc (n::nonnegint) local p, k; p := A...
Chebyshev := proc (n::nonnegint) local p, k; p := A...
Chebyshev := proc (n::nonnegint) local p, k; p := A...
Chebyshev := proc (n::nonnegint) local p, k; p := A...
Chebyshev := proc (n::nonnegint) local p, k; p := A...
Chebyshev := proc (n::nonnegint) local p, k; p := A...
Chebyshev := proc (n::nonnegint) local p, k; p := A...
Chebyshev := proc (n::nonnegint) local p, k; p := A...

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 .

> a[3];

4*x^3-3*x

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);

proc (Rate, N) option `Copyright (c) 1994 by Je'ro^...
proc (Rate, N) option `Copyright (c) 1994 by Je'ro^...
proc (Rate, N) option `Copyright (c) 1994 by Je'ro^...
proc (Rate, N) option `Copyright (c) 1994 by Je'ro^...
proc (Rate, N) option `Copyright (c) 1994 by Je'ro^...
proc (Rate, N) option `Copyright (c) 1994 by Je'ro^...

Once finished viewing the code for a particular command or procedure, always reset to the default output level.

interface(verboseproc=1):

Click here to return to the Main Menu.

© 2009 by the Rector and Visitors of the University of Virginia.

The information contained on the University of Virginia’s Department of Information Technology and Communication (ITC) website is provided as a public service with the understanding that ITC makes no representations or warranties, either expressed or implied, concerning the accuracy, completeness, reliability or suitability of the information, including warrantees of title, non-infringement of copyright or patent rights of others. These pages are expected to represent the University of Virginia community and the State of Virginia in a professional manner in accordance with the University of Virginia’s Computing Policies.