Interface to Mathematica

The Mathematica interface will only work if Mathematica is installed on your computer with a command line interface that runs when you give the math command. The interface lets you send certain Sage objects to Mathematica, run Mathematica functions, import certain Mathematica expressions to Sage, or any combination of the above.

To send a Sage object sobj to Mathematica, call mathematica(sobj). This exports the Sage object to Mathematica and returns a new Sage object wrapping the Mathematica expression/variable, so that you can use the Mathematica variable from within Sage. You can then call Mathematica functions on the new object; for example:

sage: mobj = mathematica(x^2-1)             # optional - mathematica
sage: mobj.Factor()                         # optional - mathematica
(-1 + x)*(1 + x)

In the above example the factorization is done using Mathematica’s Factor[] function.

To see Mathematica’s output you can simply print the Mathematica wrapper object. However if you want to import Mathematica’s output back to Sage, call the Mathematica wrapper object’s sage() method. This method returns a native Sage object:

sage: mobj = mathematica(x^2-1)             # optional - mathematica
sage: mobj2 = mobj.Factor(); mobj2          # optional - mathematica
(-1 + x)*(1 + x)
sage: mobj2.parent()                        # optional - mathematica
Mathematica
sage: sobj = mobj2.sage(); sobj             # optional - mathematica
(x + 1)*(x - 1)
sage: sobj.parent()                         # optional - mathematica
Symbolic Ring

If you want to run a Mathematica function and don’t already have the input in the form of a Sage object, then it might be simpler to input a string to mathematica(expr). This string will be evaluated as if you had typed it into Mathematica:

sage: mathematica('Factor[x^2-1]')          # optional - mathematica
(-1 + x)*(1 + x)
sage: mathematica('Range[3]')               # optional - mathematica
{1, 2, 3}

If you don’t want Sage to go to the trouble of creating a wrapper for the Mathematica expression, then you can call mathematica.eval(expr), which returns the result as a Mathematica AsciiArtString formatted string. If you want the result to be a string formatted like Mathematica’s InputForm, call repr(mobj) on the wrapper object mobj. If you want a string formatted in Sage style, call mobj._sage_repr():

sage: mathematica.eval('x^2 - 1')           # optional - mathematica
               2
         -1 + x
sage: repr(mathematica('Range[3]'))         # optional - mathematica
'{1, 2, 3}'
sage: mathematica('Range[3]')._sage_repr()  # optional - mathematica
'[1, 2, 3]'

Finally, if you just want to use a Mathematica command line from within Sage, the function mathematica_console() dumps you into an interactive command-line Mathematica session. This is an enhanced version of the usual Mathematica command-line, in that it provides readline editing and history (the usual one doesn’t!)

Tutorial

We follow some of the tutorial from http://library.wolfram.com/conferences/devconf99/withoff/Basic1.html/.

For any of this to work you must buy and install the Mathematica program, and it must be available as the command math in your PATH.

Syntax

Now make 1 and add it to itself. The result is a Mathematica object.

sage: m = mathematica
sage: a = m(1) + m(1); a                # optional - mathematica
2
sage: a.parent()                        # optional - mathematica
Mathematica
sage: m('1+1')                          # optional - mathematica
2
sage: m(3)**m(50)                       # optional - mathematica
717897987691852588770249

The following is equivalent to Plus[2, 3] in Mathematica:

sage: m = mathematica
sage: m(2).Plus(m(3))                   # optional - mathematica
5

We can also compute \(7(2+3)\).

sage: m(7).Times(m(2).Plus(m(3)))       # optional - mathematica
35
sage: m('7(2+3)')                       # optional - mathematica
35

Some typical input

We solve an equation and a system of two equations:

sage: eqn = mathematica('3x + 5 == 14') # optional - mathematica
sage: eqn                               # optional - mathematica
5 + 3*x == 14
sage: eqn.Solve('x')                    # optional - mathematica
{{x -> 3}}
sage: sys = mathematica('{x^2 - 3y == 3, 2x - y == 1}')  # optional - mathematica
sage: print(sys)                        # optional - mathematica
           2
         {x  - 3 y == 3, 2 x - y == 1}
sage: sys.Solve('{x, y}')               # optional - mathematica
{{x -> 0, y -> -1}, {x -> 6, y -> 11}}

Assignments and definitions

If you assign the mathematica \(5\) to a variable \(c\) in Sage, this does not affect the \(c\) in Mathematica.

sage: c = m(5)                          # optional - mathematica
sage: print(m('b + c x'))               # optional - mathematica
             b + c x
sage: print(m('b') + c*m('x'))          # optional - mathematica
         b + 5 x

The Sage interfaces changes Sage lists into Mathematica lists:

sage: m = mathematica
sage: eq1 = m('x^2 - 3y == 3')          # optional - mathematica
sage: eq2 = m('2x - y == 1')            # optional - mathematica
sage: v = m([eq1, eq2]); v              # optional - mathematica
{x^2 - 3*y == 3, 2*x - y == 1}
sage: v.Solve(['x', 'y'])               # optional - mathematica
{{x -> 0, y -> -1}, {x -> 6, y -> 11}}

Function definitions

Define mathematica functions by simply sending the definition to the interpreter.

sage: m = mathematica
sage: _ = mathematica('f[p_] = p^2');   # optional - mathematica
sage: m('f[9]')                         # optional - mathematica
81

Numerical Calculations

We find the \(x\) such that \(e^x - 3x = 0\).

sage: e = mathematica('Exp[x] - 3x == 0') # optional - mathematica
sage: e.FindRoot(['x', 2])                # optional - mathematica
{x -> 1.512134551657842}

Note that this agrees with what the PARI interpreter gp produces:

sage: gp('solve(x=1,2,exp(x)-3*x)')
1.512134551657842473896739678              # 32-bit
1.5121345516578424738967396780720387046    # 64-bit

Next we find the minimum of a polynomial using the two different ways of accessing Mathematica:

sage: mathematica('FindMinimum[x^3 - 6x^2 + 11x - 5, {x,3}]')  # optional - mathematica
{0.6150998205402516, {x -> 2.5773502699629733}}
sage: f = mathematica('x^3 - 6x^2 + 11x - 5')  # optional - mathematica
sage: f.FindMinimum(['x', 3])                  # optional - mathematica
{0.6150998205402516, {x -> 2.5773502699629733}}

Polynomial and Integer Factorization

We factor a polynomial of degree 200 over the integers.

sage: R.<x> = PolynomialRing(ZZ)
sage: f = (x**100+17*x+5)*(x**100-5*x+20)
sage: f
x^200 + 12*x^101 + 25*x^100 - 85*x^2 + 315*x + 100
sage: g = mathematica(str(f))            # optional - mathematica
sage: print(g)                           # optional - mathematica
                           2       100       101    200
         100 + 315 x - 85 x  + 25 x    + 12 x    + x
sage: g                                  # optional - mathematica
100 + 315*x - 85*x^2 + 25*x^100 + 12*x^101 + x^200
sage: print(g.Factor())                  # optional - mathematica
                      100               100
         (20 - 5 x + x   ) (5 + 17 x + x   )

We can also factor a multivariate polynomial:

sage: f = mathematica('x^6 + (-y - 2)*x^5 + (y^3 + 2*y)*x^4 - y^4*x^3')  # optional - mathematica
sage: print(f.Factor())                  # optional - mathematica
          3                  2    3
         x  (x - y) (-2 x + x  + y )

We factor an integer:

sage: n = mathematica(2434500)           # optional - mathematica
sage: n.FactorInteger()                  # optional - mathematica
{{2, 2}, {3, 2}, {5, 3}, {541, 1}}
sage: n = mathematica(2434500)           # optional - mathematica
sage: F = n.FactorInteger(); F           # optional - mathematica
{{2, 2}, {3, 2}, {5, 3}, {541, 1}}
sage: F[1]                               # optional - mathematica
{2, 2}
sage: F[4]                               # optional - mathematica
{541, 1}

Mathematica’s ECM package is no longer available.

Long Input

The Mathematica interface reads in even very long input (using files) in a robust manner.

sage: t = '"%s"'%10^10000   # ten thousand character string.
sage: a = mathematica(t)        # optional - mathematica
sage: a = mathematica.eval(t)   # optional - mathematica

Loading and saving

Mathematica has an excellent InputForm function, which makes saving and loading Mathematica objects possible. The first examples test saving and loading to strings.

sage: x = mathematica(pi/2)     # optional - mathematica
sage: print(x)                  # optional - mathematica
         Pi
         --
         2
sage: loads(dumps(x)) == x      # optional - mathematica
True
sage: n = x.N(50)               # optional - mathematica
sage: print(n)                  # optional - mathematica
              1.5707963267948966192313216916397514420985846996876
sage: loads(dumps(n)) == n      # optional - mathematica
True

Complicated translations

The mobj.sage() method tries to convert a Mathematica object to a Sage object. In many cases, it will just work. In particular, it should be able to convert expressions entirely consisting of:

  • numbers, i.e. integers, floats, complex numbers;

  • functions and named constants also present in Sage, where:

    • Sage knows how to translate the function or constant’s name from Mathematica’s, or
    • the Sage name for the function or constant is trivially related to Mathematica’s;
  • symbolic variables whose names don’t pathologically overlap with objects already defined in Sage.

This method will not work when Mathematica’s output includes:

  • strings;
  • functions unknown to Sage;
  • Mathematica functions with different parameters/parameter order to the Sage equivalent.

If you want to convert more complicated Mathematica expressions, you can instead call mobj._sage_() and supply a translation dictionary:

sage: m = mathematica('NewFn[x]')       # optional - mathematica
sage: m._sage_(locals={'NewFn': sin})   # optional - mathematica
sin(x)

For more details, see the documentation for ._sage_().

OTHER Examples:

sage: def math_bessel_K(nu,x):
....:     return mathematica(nu).BesselK(x).N(20)
sage: math_bessel_K(2,I)                      # optional - mathematica
-2.5928861754911969782 + 0.1804899720669620266 I
sage: slist = [[1, 2], 3., 4 + I]
sage: mlist = mathematica(slist); mlist     # optional - mathematica
{{1, 2}, 3., 4 + I}
sage: slist2 = list(mlist); slist2          # optional - mathematica
[{1, 2}, 3., 4 + I]
sage: slist2[0]                             # optional - mathematica
{1, 2}
sage: slist2[0].parent()                    # optional - mathematica
Mathematica
sage: slist3 = mlist.sage(); slist3         # optional - mathematica
[[1, 2], 3.0, I + 4]
sage: mathematica('10.^80')     # optional - mathematica
1.*^80
sage: mathematica('10.^80').sage()  # optional - mathematica
1e+80

AUTHORS:

  • William Stein (2005): first version
  • Doug Cutrell (2006-03-01): Instructions for use under Cygwin/Windows.
  • Felix Lawrence (2009-08-21): Added support for importing Mathematica lists and floats with exponents.
class sage.interfaces.mathematica.Mathematica(maxread=None, script_subdirectory=None, logfile=None, server=None, server_tmpdir=None, command=None, verbose_start=False)

Bases: sage.interfaces.tab_completion.ExtraTabCompletion, sage.interfaces.expect.Expect

Interface to the Mathematica interpreter.

chdir(dir)

Change Mathematica’s current working directory.

EXAMPLES:

sage: mathematica.chdir('/')          # optional - mathematica
sage: mathematica('Directory[]')      # optional - mathematica
"/"
console(readline=True)
eval(code, strip=True, **kwds)
get(var, ascii_art=False)

Get the value of the variable var.

AUTHORS:

  • William Stein
  • Kiran Kedlaya (2006-02-04): suggested using InputForm
help(cmd)
set(var, value)

Set the variable var to the given value.

class sage.interfaces.mathematica.MathematicaElement(parent, value, is_name=False, name=None)

Bases: sage.interfaces.expect.ExpectElement

N(precision=None)

Numerical approximation by calling Mathematica’s \(N[]\)

Calling Mathematica’s \(N[]\) function, with optional precision in decimal digits. Unlike Sage’s \(n()\), \(N()\) can be applied to symbolic Mathematica objects.

A workaround for trac ticket #18888 backtick issue, stripped away by \(get()\), is included.

Note

The base class way up the hierarchy defines an \(N\) (modeled after Mathematica’s) which overwrites the Mathematica one, and doesn’t work at all. We restore it here.

EXAMPLES:

sage: mathematica('Pi/2').N(10)        # optional -- mathematica
1.570796327
sage: mathematica('Pi').N(50)          # optional -- mathematica
3.1415926535897932384626433832795028841971693993751
sage: mathematica('Pi*x^2-1/2').N()    # optional -- mathematica
                2
-0.5 + 3.14159 x
n(*args, **kwargs)

Numerical approximation by converting to Sage object first

Convert the object into a Sage object and return its numerical approximation. See documentation of the function sage.misc.functional.n() for details.

EXAMPLES:

sage: mathematica('Pi').n(10)    # optional -- mathematica
3.1
sage: mathematica('Pi').n()      # optional -- mathematica
3.14159265358979
sage: mathematica('Pi').n(digits=10)   # optional -- mathematica
3.141592654
save_image(filename, ImageSize=600)

Save a mathematica graphics

INPUT:

  • filename – string. The filename to save as. The extension determines the image file format.
  • ImageSize – integer. The size of the resulting image.

EXAMPLES:

sage: P = mathematica('Plot[Sin[x],{x,-2Pi,4Pi}]')   # optional - mathematica
sage: filename = tmp_filename()                      # optional - mathematica
sage: P.save_image(filename, ImageSize=800)                # optional - mathematica
show(ImageSize=600)

Show a mathematica expression immediately.

This method attempts to display the graphics immediately, without waiting for the currently running code (if any) to return to the command line. Be careful, calling it from within a loop will potentially launch a large number of external viewer programs.

INPUT:

  • ImageSize – integer. The size of the resulting image.

OUTPUT:

This method does not return anything. Use save() if you want to save the figure as an image.

EXAMPLES:

sage: P = mathematica('Plot[Sin[x],{x,-2Pi,4Pi}]')   # optional - mathematica
sage: show(P)                                        # optional - mathematica
sage: P.show(ImageSize=800)                          # optional - mathematica
sage: Q = mathematica('Sin[x Cos[y]]/Sqrt[1-x^2]')   # optional - mathematica
sage: show(Q)                                        # optional - mathematica
<html><script type="math/tex">\frac{\sin (x \cos (y))}{\sqrt{1-x^2}}</script></html>
str()
class sage.interfaces.mathematica.MathematicaFunction(parent, name)

Bases: sage.interfaces.expect.ExpectFunction

class sage.interfaces.mathematica.MathematicaFunctionElement(obj, name)

Bases: sage.interfaces.expect.FunctionElement

sage.interfaces.mathematica.clean_output(s)
sage.interfaces.mathematica.mathematica_console(readline=True)
sage.interfaces.mathematica.reduce_load(X)