14.8.1 Tutorial

Author: Gregg Musiker (2006-02-02): initial version.

This tutorial is based on the Maple Tutorial for number theory from http://www.math.mun.ca/~drideout/m3370/numtheory.html.

There are several ways to use the Maple Interface in Sage. We will discuss two of those ways in this tutorial.

  1. If you have a maple expression such as
    factor( (x^5-1));
    
    We can write that in sage as

    sage: maple('factor(x^5-1)')
    (x-1)*(x^4+x^3+x^2+x+1)
    

    Notice, there is no need to use a semicolon.

  2. Since Sage is written in Python, we can also import maple commands and write our scripts in a pythonic way. For example, factor() is a maple command, so we can also factor in Sage using

    sage: maple('(x^5-1)').factor()
    (x-1)*(x^4+x^3+x^2+x+1)
    

    where expression.command() means the same thing as command(expression) in Maple. We will use this second type of syntax whenever possible, resorting to the first when needed.

    sage: maple('(x^12-1)/(x-1)').simplify()
    x^11+x^10+x^9+x^8+x^7+x^6+x^5+x^4+x^3+x^2+x+1
    

The normal command will always reduce a rational function to the lowest terms. The factor command will factor a polynomial with rational coefficients into irreducible factors over the ring of integers. So for example,

sage: maple('(x^12-1)').factor( )
(x-1)*(x+1)*(x^2+x+1)*(x^2-x+1)*(x^2+1)*(x^4-x^2+1)

sage: maple('(x^28-1)').factor( )
(x-1)*(x^6+x^5+x^4+x^3+x^2+x+1)*(x+1)*(1-x+x^2-x^3+x^4-x^5+x^6)*(x^2+1)*(x^
12-x^10+x^8-x^6+x^4-x^2+1)

Another important feature of maple is its online help. We can access this through sage as well. After reading the description of the command, you can press q to immediately get back to your original prompt.

Incidentally you can always get into a maple console by the command

sage: maple.console()          # not tested
sage: !maple                   # not tested

Note that the above two commands are slightly different, and the first is preferred.

For example, for help on the maple command fibonacci, we type

sage: maple.help('fibonacci')  # not tested, since it uses a pager

We see there are two choices. Type

sage: maple.help('combinat, fibonacci')   # not tested, since it uses a pager

We now see how the Maple command fibonacci works under the combinatorics package. Try typing in

sage: maple.fibonacci(10)
fibonacci(10)

You will get fibonacci(10) as output since Maple has not loaded the combinatorics package yet. To rectify this type

sage: maple('combinat[fibonacci]')(10)
55

instead.

If you want to load the combinatorics package for future calculations, in Sage this can be done as

sage: maple.with_package('combinat')

or

sage: maple.load('combinat')

Now if we type maple.fibonacci(10), we get the correct output:

sage: maple.fibonacci(10)
55

Some common maple packages include combinat, linalg, and numtheory. To produce the first 19 Fibonacci numbers, use the sequence command.

sage: maple('seq(fibonacci(i),i=1..19)')
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584,
4181

Two other useful Maple commands are ifactor and isprime. For example

sage: maple.isprime(maple.fibonacci(27))
false
sage: maple.ifactor(maple.fibonacci(27))
``(2)*``(17)*``(53)*``(109)

Note that the isprime function that is included with Sage (which uses PARI) is better than the Maple one (it is faster and gives a provably correct answer, whereas Maple is sometimes wrong).

sage: alpha = maple('(1+sqrt(5))/2')
sage: beta = maple('(1-sqrt(5))/2')
sage: f19  = alpha^19 - beta^19/maple('sqrt(5)')
sage: f19
(1/2+1/2*5^(1/2))^19-1/5*(1/2-1/2*5^(1/2))^19*5^(1/2)
sage: f19.simplify()                # somewhat randomly ordered output...
6765+5778/5*5^(1/2)

Let's say we want to write a maple program now that squares a number if it is positive and cubes it if it is negative. In maple, that would look like

mysqcu := proc(x) 
if x > 0 then x^2;
else x^3; fi;
end;
In SAGE, we write

sage: mysqcu = maple('proc(x) if x > 0 then x^2 else x^3 fi end')
sage: mysqcu(5)
25
sage: mysqcu(-5)
-125

More complicated programs should be put in a separate file and loaded.

Module-level Functions

maple_console( )

Spawn a new Maple command-line session.

sage: maple_console() #not tested
    |\^/|     Maple 11 (IBM INTEL LINUX)
._|\|   |/|_. Copyright (c) Maplesoft, a division of Waterloo Maple Inc.
2007
 \  MAPLE  /  All rights reserved. Maple is a trademark of
 <____ ____>  Waterloo Maple Inc.
      |       Type ? for help.
>

reduce_load_Maple( )

Returns the maple object created in sage.interfaces.maple.

sage: from sage.interfaces.maple import reduce_load_Maple
sage: reduce_load_Maple()
Maple

Class: Maple

class Maple
Interface to the Maple interpreter.

Type maple.[tab] for a list of all the functions available from your Maple install. Type maple.[tab]? for Maple's help about a given function. Type maple(...) to create a new Maple object, and maple.eval(...) to run a string using Maple (and get the result back as a string).

Maple( self, [maxread=100], [script_subdirectory=], [server=None], [server_tmpdir=None], [logfile=None])

Create an instance of the Maple interpreter.

sage: maple == loads(dumps(maple))
True

Functions: clear,$ \,$ completions,$ \,$ console,$ \,$ cputime,$ \,$ expect,$ \,$ get,$ \,$ help,$ \,$ load,$ \,$ set,$ \,$ source,$ \,$ trait_names,$ \,$ with_package

clear( self, var)

Clear the variable named var.

Unfortunately, Maple does not have a clear command. The next best thing is to set equal to the constant 0, so that memory will be freed.

sage: maple.set('xx', '2')  #optional -- requires Maple
sage: maple.get('xx')       #optional
'2'
sage: maple.clear('xx')     #optional
sage: maple.get('xx')       #optional
'0'

completions( self, s)

Return all commands that complete the command starting with the string s. This is like typing s[Ctrl-T] in the maple interpreter.

sage: c = maple.completions('di')  #optional -- requires Maple
sage: 'dilog' in c                 #optional
True

console( self)

Spawn a new Maple command-line session.

sage: maple.console() #not tested
    |\^/|     Maple 11 (IBM INTEL LINUX)
._|\|   |/|_. Copyright (c) Maplesoft, a division of Waterloo Maple Inc.
2007
 \  MAPLE  /  All rights reserved. Maple is a trademark of
 <____ ____>  Waterloo Maple Inc.
      |       Type ? for help.
>

cputime( self, [t=None])

Returns the amount of CPU time that the Maple session has used. If t is not None, then it returns the difference between the current CPU time and t.

sage: t = maple.cputime() #optional -- requires Maple
sage: t                   #optional, random
0.02
sage: maple.diff(x^2, x)  #optional
2*x
sage: maple.cputime(t)    #optional, random
0.0

expect( self)

Returns the pexpect object for this Maple session.

sage: m = Maple()
sage: m.expect() is None
True
sage: m._start() #optional -- requires Maple
sage: m.expect() #optional
<pexpect.spawn instance at 0x...>
sage: m.quit()   #optional

get( self, var)

Get the value of the variable var.

sage: maple.set('xx', '2') #optional -- requires Maple
sage: maple.get('xx')      #optional
'2'

help( self, str)

Display Maple help about str. This is the same as typing "?str" in the Maple console.

Input:

str
- a string to search for in the maple help system

sage: maple.help('digamma') #not tested
Psi - the Digamma and Polygamma functions
...

load( self, package)

Make a package of Maple procedures available in the interpreter.

Input:

package
- string

Some functions are unknown to Maple until you use with to include the appropriate package.

sage: maple.quit()   # optional -- to reset maple.
sage: maple('partition(10)')              # optional
partition(10)
sage: maple('bell(10)')                   # optional
bell(10)
sage: maple.with_package('combinat')               # optional
sage: maple('partition(10)')               # optional  
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 2], [1, 1, 1, 1,
1, 1, 2, 2], [1, 1, 1, 1, 2, 2, 2], [1, 1, 2, 2, 2, 2], [2, 2, 2, 2, 2],
[1, 1, 1, 1, 1, 1, 1, 3], [1, 1, 1, 1, 1, 2, 3], [1, 1, 1, 2, 2, 3], [1, 2,
2, 2, 3], [1, 1, 1, 1, 3, 3], [1, 1, 2, 3, 3], [2, 2, 3, 3], [1, 3, 3, 3],
[1, 1, 1, 1, 1, 1, 4], [1, 1, 1, 1, 2, 4], [1, 1, 2, 2, 4], [2, 2, 2, 4],
[1, 1, 1, 3, 4], [1, 2, 3, 4], [3, 3, 4], [1, 1, 4, 4], [2, 4, 4], [1, 1,
1, 1, 1, 5], [1, 1, 1, 2, 5], [1, 2, 2, 5], [1, 1, 3, 5], [2, 3, 5], [1, 4,
5], [5, 5], [1, 1, 1, 1, 6], [1, 1, 2, 6], [2, 2, 6], [1, 3, 6], [4, 6],
[1, 1, 1, 7], [1, 2, 7], [3, 7], [1, 1, 8], [2, 8], [1, 9], [10]]
sage: maple('bell(10)')                   # optional
115975
sage: maple('fibonacci(10)')              # optional
55

set( self, var, value)

Set the variable var to the given value.

sage: maple.set('xx', '2') #optional -- requires Maple
sage: maple.get('xx')      #optional
'2'

source( self, s)

Display the Maple source (if possible) about s. This is the same as returning the output produced by the following Maple commands:

interface(verboseproc=2): print(s)

Input:

s
- a string representing the function whose source code you want

sage: maple.source('curry')  #not tested
p -> subs('_X' = args[2 .. nargs], () -> p(_X, args))

trait_names( self, [verbose=True], [use_disk_cache=True])

Returns a list of all the commands defined in Maple and optionally (per default) store them to disk.

sage: c = maple.trait_names(use_disk_cache=False, verbose=False) #optional
sage: len(c) > 100  #optional
True
sage: 'dilog' in c  #optional
True

with_package( self, package)

Make a package of Maple procedures available in the interpreter.

Input:

package
- string

Some functions are unknown to Maple until you use with to include the appropriate package.

sage: maple.quit()   # optional -- to reset maple.
sage: maple('partition(10)')              # optional
partition(10)
sage: maple('bell(10)')                   # optional
bell(10)
sage: maple.with_package('combinat')               # optional
sage: maple('partition(10)')               # optional  
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 2], [1, 1, 1, 1,
1, 1, 2, 2], [1, 1, 1, 1, 2, 2, 2], [1, 1, 2, 2, 2, 2], [2, 2, 2, 2, 2],
[1, 1, 1, 1, 1, 1, 1, 3], [1, 1, 1, 1, 1, 2, 3], [1, 1, 1, 2, 2, 3], [1, 2,
2, 2, 3], [1, 1, 1, 1, 3, 3], [1, 1, 2, 3, 3], [2, 2, 3, 3], [1, 3, 3, 3],
[1, 1, 1, 1, 1, 1, 4], [1, 1, 1, 1, 2, 4], [1, 1, 2, 2, 4], [2, 2, 2, 4],
[1, 1, 1, 3, 4], [1, 2, 3, 4], [3, 3, 4], [1, 1, 4, 4], [2, 4, 4], [1, 1,
1, 1, 1, 5], [1, 1, 1, 2, 5], [1, 2, 2, 5], [1, 1, 3, 5], [2, 3, 5], [1, 4,
5], [5, 5], [1, 1, 1, 1, 6], [1, 1, 2, 6], [2, 2, 6], [1, 3, 6], [4, 6],
[1, 1, 1, 7], [1, 2, 7], [3, 7], [1, 1, 8], [2, 8], [1, 9], [10]]
sage: maple('bell(10)')                   # optional
115975
sage: maple('fibonacci(10)')              # optional
55

Special Functions: __init__,$ \,$ __reduce__,$ \,$ _assign_symbol,$ \,$ _commands,$ \,$ _equality_symbol,$ \,$ _eval_line,$ \,$ _function_class,$ \,$ _function_element_class,$ \,$ _help,$ \,$ _install_hints,$ \,$ _keyboard_interrupt,$ \,$ _object_class,$ \,$ _quit_string,$ \,$ _read_in_file_command,$ \,$ _source,$ \,$ _true_symbol

__reduce__( self)

sage: maple.__reduce__()
(<function reduce_load_Maple at 0x...>, ())
sage: f, args = _
sage: f(*args)
Maple

_assign_symbol( self)

Returns the symbol used for assignment in Maple.

sage: maple._assign_symbol()
':='

_commands( self)

Return list of all commands defined in Maple.

sage: c = maple._commands() #optional -- requires Maple
sage: len(c) > 100          #optional
True
sage: 'dilog' in c          #optional
True

_equality_symbol( self)

Returns the symbol used for equality testing in Maple.

sage: maple._equality_symbol()
'='

sage: maple(2) == maple(2) #optional -- requires Maples
True

_eval_line( self, line, [allow_use_file=True], [wait_for_prompt=True])

sage: maple._eval_line('2+2')  #optional -- requires Maple
'4'

_function_class( self)

sage: maple._function_class()
<class 'sage.interfaces.maple.MapleFunction'>

sage: type(maple.diff)
<class 'sage.interfaces.maple.MapleFunction'>

_function_element_class( self)

Returns the MapleFunctionElement class.

sage: maple._function_element_class()
<class 'sage.interfaces.maple.MapleFunctionElement'>

sage: two = maple(2)  #optional -- requires Maple
sage: type(two.gcd)   #optional
<class 'sage.interfaces.maple.MapleFunctionElement'>

_help( self, str)

Returns the Maple help on str.

sage: maple._help('gcd')  #optional -- requires Maple
"gcd - greatest common divisor of polynomials...

_install_hints( self)

Hints for installing Maple on your computer.

Author: William Stein and Justin Walker (2006-02-12).

sage: print maple._install_hints()
In order...

_object_class( self)

Returns the class of MapleElements.

sage: maple._object_class()
<class 'sage.interfaces.maple.MapleElement'>

sage: m = maple(2)  #optional -- requires Maple
sage: type(m)       #optional
<class 'sage.interfaces.maple.MapleElement'>

_quit_string( self)

sage: maple._quit_string()
'quit'

sage: m = Maple()
sage: a = m(2)           #optional -- requires Maple
sage: m.is_running()     #optional
True
sage: m.quit()           #optional
sage: m.is_running()     #optional
False

_read_in_file_command( self, filename)

Returns the string used to read filename into Maple.

sage: maple._read_in_file_command('test')
'read "test"'

            sage: filename = tmp_filename()
            sage: f = open(filename, 'w')
            sage: f.write('xx := 22;
')
            sage: f.close()
            sage: maple.read(filename)   #optional -- requires Maple
            sage: maple.get('xx').strip() #optional
            '22'

_source( self, s)

Tries to return the source code of a Maple function str as a string.

sage: print maple._source('curry').strip()  #optional requires maple
p -> subs('_X' = args[2 .. nargs], () -> p(_X, args))
sage: maple._source('ZZZ')                  #optional requires maple
Traceback (most recent call last):
...
Exception: no source code could be found

_true_symbol( self)

Returns the symbol used for truth in Maple.

sage: maple._true_symbol()
'true'

sage: maple(2) == maple(2) #optional -- requires Maples
True

Class: MapleElement

class MapleElement

Functions: trait_names

trait_names( self)

sage: a = maple(2) #optional -- requires Maple
sage: 'sin' in a.trait_names() #optional
True

Special Functions: __cmp__,$ \,$ __float__,$ \,$ __repr__,$ \,$ _latex_,$ \,$ _mul_

__cmp__( self, other)

Compare equality between self and other, using maple.

These examples are optional, and require Maple to be installed. You don't need to install any Sage packages for this.

sage: a = maple(5)
sage: b = maple(5)
sage: a == b
True
sage: a == 5
True

sage: c = maple(3)
sage: a == c
False
sage: a < c
False
sage: a < 6
True
sage: c <= a
True

sage: M = matrix(ZZ, 2, range(1,5))
sage: Mm = maple(M)
sage: Mm == Mm
True
sage: Mm < 5
True
sage: (Mm < 5) == (M < 5)
True
sage: 5 < Mm
False

TESTS:

sage: x = var('x')
sage: t = maple((x+1)^2)
sage: u = maple(x^2+2*x+1)
sage: u == t # todo: not implemented
True         # returns False, should use 'testeq' in maple
sage: maple.eval('testeq(%s = %s)'%(t.name(),u.name()))
'true'

__float__( self)

Returns a floating point version of self.

sage: float(maple(1/2))  #optional -- requires Maple
0.5
sage: type(_)            #optional
<type 'float'>

__repr__( self)

Return a string representation of self.

These examples are optional, and require Maple to be installed. You don't need to install any Sage packages for this.

sage: x = var('x')
sage: maple(x)
x
sage: maple(5)
5
sage: M = matrix(QQ,2,range(4))
sage: maple(M)
Matrix(2, 2, [[0,1],[2,3]])

_latex_( self)

You can output Maple expressions in latex.

sage: print latex(maple('(x^4 - y)/(y^2-3*x)'))      # optional
{\frac {{x}^{4}-y}{{y}^{2}-3\,x}}
sage: print latex(maple(pi - e^3))                   # optional
\pi - \left( {e^{1}} \right) ^{3}

Note: Some expressions might require the Maple style file maple2e.sty in order to latex correctly.

_mul_( self, right)

These examples are optional, and require Maple to be installed. You don't need to install any Sage packages for this.

sage: t = maple(5); u = maple(3)
sage: t*u
15
sage: M = matrix(ZZ,2,range(4))
sage: Mm = maple(M)
sage: Mm*Mm
Matrix(2, 2, [[2,3],[6,11]])

sage: v = vector(ZZ,2,[2,3])
sage: vm = maple(v)
sage: vm*Mm
Vector[row](2, [6,11])

sage: t*Mm
Matrix(2, 2, [[0,5],[10,15]])

Class: MapleFunction

class MapleFunction

Special Functions: _sage_doc_,$ \,$ _sage_src_

_sage_doc_( self)

Returns the Maple help for this function. This gets called when doing "?" on self.

sage: maple.gcd._sage_doc_()  #optional -- requires Maple
"gcd - greatest common divisor of polynomials...

_sage_src_( self)

Returns the source code of self. This is the function that eventually gets called when doing maple.gcd?? for example.

sage: print maple.curry._sage_src_().strip() #optional requires maple
p -> subs('_X' = args[2 .. nargs], () -> p(_X, args))
sage: maple.ZZZ._sage_src_()                 #optional requires maple
Traceback (most recent call last):
...
Exception: no source code could be found

Class: MapleFunctionElement

class MapleFunctionElement

Special Functions: _sage_doc_,$ \,$ _sage_src_

_sage_doc_( self)

Returns the Maple help for this function. This gets called when doing "?" on self.

sage: two = maple(2)  #optional -- requires Maple
sage: two.gcd._sage_doc_() #optional
"gcd - greatest common divisor of polynomials...

_sage_src_( self)

Returns the source code of self.

sage: g = maple('gcd')                   #optional requires maple
sage: print g.curry._sage_src_().strip() #optional 
p -> subs('_X' = args[2 .. nargs], () -> p(_X, args))
sage: m = maple('2')                     #optional 
sage: m.ZZZ._sage_src_()                 #optional 
Traceback (most recent call last):
...
Exception: no source code could be found

See About this document... for information on suggesting changes.