login  home  contents  what's new  discussion  bug reports     help  links  subscribe  changes  refresh  edit

Edit detail for SandBoxSageAxiomInterface revision 1 of 1

1
Editor:
Time: 2007/11/18 18:34:41 GMT-8
Note: update

changed:
-
\documentclass{article}
\def\code#1{{\tt #1}}
\def\url#1{{\it #1}}
\def\sage#1{{\bf #1}}
\def\note#1{#1}
\usepackage{axiom}

\begin{document}

\title{A Sage Interface to Axiom}
\author{
AUTHORS OF THIS MODULE:
    - William Stein (2006-10): Initial version based on Maxima interface
    - Bill Page (2006-10): Axiom version
}
\abstract{

Interface to Axiom

Axiom is a free GPL-compatible (modified BSD license)  general purpose
computer algebra system whose development started in 1973 at IBM.  It
contains symbolic manipulation algorithms, as well as implementations
of special functions, including elliptic functions and generalized
hypergeometric functions. Moreover, Axiom has implementations of many
functions relating to the invariant theory of the symmetric group $S_n$. 
For many links to Axiom documentation see

         \url{http://wiki.axiom-developer.org}.

EXAMPLES:
We evaluate a very simple expression in axiom.
\begin{verbatim}
    sage: axiom('3 * 5')
    15
                                          Type: PositiveInteger
\end{verbatim}
We factor $x^5 - y^5$ in Axiom in several different ways.
The first way yields a Axiom object.
\begin{verbatim}
    sage: F = axiom.factor('x^5 - y^5')
    sage: type(F)
    <class 'axiom.interfaces.axiom.AxiomElement'>
\end{verbatim}
Note that Axiom objects are normally displayed using ``ASCII art'';
to see a normal linear representation of any Axiom object x,
use \code{str(x)}. no emph

\begin{verbatim}
    sage: F
                               4      3    2  2    3      4
                   - (y - x) (y  + x y  + x  y  + x  y + x )
\end{verbatim}

You can always use \code{x.str()} to obtain the linear representation
of an object, even without changing the display2d flag.  This can
be useful for moving axiom data to other systems. 
\begin{verbatim}
    sage: F.str()
    '-(y - x)*(y^4 + x*y^3 + x^2*y^2 + x^3*y + x^4)'
    
    sage: axiom.display2d(False)
    sage: F
    -(y - x)*(y^4 + x*y^3 + x^2*y^2 + x^3*y + x^4)
\end{verbatim}

The \code{axiom.eval} command evaluates an expression in axiom
and returns the result as a string.
\begin{verbatim}
    sage: print axiom.eval('factor(x^5 - y^5)')
    -(y - x)*(y^4 + x*y^3 + x^2*y^2 + x^3*y + x^4)
\end{varbatim}
We can create the polynomial $f$ as a Axiom polynomial, then call
the factor method on it.  Notice that the notation \code{f.factor()}
is consistent with how the rest of \sage works.
\begin{verbatim}
    sage: f = axiom('x^5 - y^5')
    sage: f^2
    (x^5 - y^5)^2
    sage: f.factor()
    -(y - x)*(y^4 + x*y^3 + x^2*y^2 + x^3*y + x^4)
\end{verbatim}
Control-C interruption works well with the axiom interface,
because of the excellent implementation of axiom.  For example,
try the following sum but with a much bigger range, and hit
control-C.
\begin{verbatim}
    sage: axiom('sum(1/x^2, x, 1, 10)')
    1968329/1270080
\end{verbatim}
\subsection{Tutorial}
We follow the tutorial at
\url{http://wiki.axiom-developer.org/AxiomTutorial}.
\begin{verbatim}
    sage: axiom('1/100 + 1/101')
    201/10100

    sage: a = axiom('(1 + sqrt(2))^5'); a
    (sqrt(2) + 1)^5
    sage: a.expand()
    29*sqrt(2) + 41

    sage: a = axiom('(1 + sqrt(2))^5')
    sage: float(a)                
    82.012193308819747
    sage: a.numer()
    82.01219330881975

    sage: axiom.eval('fpprec : 100')
    '100'
    sage: a.bfloat()
    8.20121933088197564152489730020812442785204843859314941221237124017312418754011041266612384955016056b1

    sage: axiom('100!')
    93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

    sage: f = axiom('(x + 3*y + x^2*y)^3')
    sage: f.expand()
    x^6*y^3 + 9*x^4*y^3 + 27*x^2*y^3 + 27*y^3 + 3*x^5*y^2 + 18*x^3*y^2 + 27*x*y^2 + 3*x^4*y + 9*x^2*y + x^3
    sage: f.subst('x=5/z')
    (5/z + 25*y/z^2 + 3*y)^3
    sage: g = f.subst('x=5/z')
    sage: h = g.ratsimp(); h
    (27*y^3*z^6 + 135*y^2*z^5 + (675*y^3 + 225*y)*z^4 + (2250*y^2 + 125)*z^3 + (5625*y^3 + 1875*y)*z^2
      + 9375*y^2*z + 15625*y^3)/z^6
    sage: h.factor()
    (3*y*z^2 + 5*z + 25*y)^3/z^6

    sage: eqn = axiom(['a+b*c=1', 'b-a*c=0', 'a+b=5'])
    sage: s = eqn.solve('[a,b,c]'); s
    [[a = (25*sqrt(79)*%i + 25)/(6*sqrt(79)*%i - 34),b = (5*sqrt(79)*%i + 5)/(sqrt(79)*%i + 11),
      c = (sqrt(79)*%i + 1)/10],
     [a = (25*sqrt(79)*%i - 25)/(6*sqrt(79)*%i + 34),b = (5*sqrt(79)*%i - 5)/(sqrt(79)*%i - 11),
      c =  - (sqrt(79)*%i - 1)/10]]
\end{varbatim}
Here is an example of solving an algebraic equation:
\begin{verbatim}
    sage: axiom('x^2+y^2=1').solve('y')
    [y =  - sqrt(1 - x^2),y = sqrt(1 - x^2)]
    sage: axiom('x^2 + y^2 = (x^2 - y^2)/sqrt(x^2 + y^2)').solve('y')
    [y =  - sqrt(( - y^2 - x^2)*sqrt(y^2 + x^2) + x^2),y = sqrt(( - y^2 - x^2)*sqrt(y^2 + x^2) + x^2)]
\end{verbatim}

You can even nicely typeset the solution in latex:
\begin{verbatim}
    sage: latex(s)
    \left[ \left[ a=\frac{25 \sqrt{79} i+25}{6 \sqrt{79} i-34} , b=  \frac{5 \sqrt{79} i+5}{\sqrt{79} i+11} , c=\frac{\sqrt{79} i+1}{10}   \right]  , \left[ a=\frac{25 \sqrt{79} i-25}{6 \sqrt{79} i+34} , b=  \frac{5 \sqrt{79} i-5}{\sqrt{79} i-11} , c=-\frac{\sqrt{79} i-1}{10}   \right]  \right]
\end{verbatim}
To have the above appear onscreen via \code{xdvi}, type \code{view(s)}.
(TODO: For OS X should create pdf output and use preview instead?)
\begin{verbatim}
    sage: e = axiom('sin(u + v) * cos(u)^3'); e
    cos(u)^3*sin(v + u)
    sage: f = e.trigexpand(); f
    cos(u)^3*(cos(u)*sin(v) + sin(u)*cos(v))
    sage: f.trigreduce()
    (sin(v + 4*u) + sin(v - 2*u))/8 + (3*sin(v + 2*u) + 3*sin(v))/8
    sage: w = axiom('3 + k*%i')
    sage: f = w^2 + axiom('%e')^w
    sage: f.realpart()
    %e^3*cos(k) - k^2 + 9
    
    sage: f = axiom('x^3 * %e^(k*x) * sin(w*x)'); f
    x^3*%e^(k*x)*sin(w*x)
    sage: f.diff('x')
    k*x^3*%e^(k*x)*sin(w*x) + 3*x^2*%e^(k*x)*sin(w*x) + w*x^3*%e^(k*x)*cos(w*x)
    sage: f.integrate('x')
    (((k*w^6 + 3*k^3*w^4 + 3*k^5*w^2 + k^7)*x^3 + (3*w^6 + 3*k^2*w^4 - 3*k^4*w^2 - 3*k^6)*x^2 + ( - 18*k*w^4 - 12*k^3*w^2 + 6*k^5)*x - 6*w^4 + 36*k^2*w^2 - 6*k^4)*%e^(k*x)*sin(w*x) + (( - w^7 - 3*k^2*w^5 - 3*k^4*w^3 - k^6*w)*x^3 + (6*k*w^5 + 12*k^3*w^3 + 6*k^5*w)*x^2 + (6*w^5 - 12*k^2*w^3 - 18*k^4*w)*x - 24*k*w^3 + 24*k^3*w)*%e^(k*x)*cos(w*x))/(w^8 + 4*k^2*w^6 + 6*k^4*w^4 + 4*k^6*w^2 + k^8)

    sage: f = axiom('1/x^2')
    sage: f.integrate('x', 1, 'inf')
    1
    sage: g = axiom('f/sinh(k*x)^4')
    sage: g.taylor('x', 0, 3)
    f/(k^4*x^4) - 2*f/(3*k^2*x^2) + 11*f/45 - 62*k^2*f*x^2/945

    sage: axiom.taylor('asin(x)','x',0, 10)
    x + x^3/6 + 3*x^5/40 + 5*x^7/112 + 35*x^9/1152
\end{verbatim}
\subsection{Examples involving matrices}
We illustrate computing with the matrix whose $i,j$ entry
is $i/j$, for $i,j=1,\ldots,4$.
\begin{verbatim}
    sage: f = axiom.eval('f[i,j] := i/j')
    sage: A = axiom('genmatrix(f,4,4)'); A
    matrix([1,1/2,1/3,1/4],[2,1,2/3,1/2],[3,3/2,1,3/4],[4,2,4/3,1])
    sage: A.determinant()
    0
    sage: A.echelon()
    matrix([1,1/2,1/3,1/4],[0,0,0,0],[0,0,0,0],[0,0,0,0])
    sage: A.eigenvalues()
    [[0,4],[3,1]]
    sage: A.eigenvectors()
    [[[0,4],[3,1]],[1,0,0, - 4],[0,1,0, - 2],[0,0,1, - 4/3],[1,2,3,4]]
\end{verbatim}

We can also compute the echelon form in \sage:
\begin{verbatim}
    sage: B = matrix(QQ, A)
    sage: B.echelon_form()
    [  1 1/2 1/3 1/4]
    [  0   0   0   0]
    [  0   0   0   0]
    [  0   0   0   0]
    sage: B.charpoly().factor()
    (x - 4) * x^3
\end{verbatim}
\subsection{Laplace Transforms}
We illustrate Laplace transforms:
\begin{verbatim}
    sage: _ = axiom.eval("f(t) := t*sin(t)")
    sage: axiom("laplace(f(t),t,s)")
    2*s/(s^2 + 1)^2

    sage: axiom("laplace(delta(t-3),t,s)") #Dirac delta function
    %e^-(3*s)
    
    sage: _ = axiom.eval("f(t) == exp(t)*sin(t)")
    sage: axiom("laplace(f(t),t,s)")
    1/(s^2 - 2*s + 2)
    
    sage: _ = axiom.eval("f(t) := t^5*exp(t)*sin(t)")
    sage: axiom("laplace(f(t),t,s)")
    360*(2*s - 2)/(s^2 - 2*s + 2)^4 - 480*(2*s - 2)^3/(s^2 - 2*s + 2)^5 + 120*(2*s - 2)^5/(s^2 - 2*s + 2)^6
    sage: axiom("laplace(f(t),t,s)")
                                             3                 5
               360 (2 s - 2)    480 (2 s - 2)     120 (2 s - 2)
              --------------- - --------------- + ---------------
                2           4     2           5     2           6
              (s  - 2 s + 2)    (s  - 2 s + 2)    (s  - 2 s + 2)

    sage: axiom("laplace(diff(x(t),t),t,s)")
    s*laplace(x(t),t,s) - x(0)
    
    sage: axiom("laplace(diff(x(t),t,2),t,s)")
    -at('diff(x(t),t,1),t = 0) + s^2*laplace(x(t),t,s) - x(0)*s

    sage.: axiom("laplace(diff(x(t),t,2),t,s)")
                         !
                d        !         2
              - -- (x(t))!      + s  laplace(x(t), t, s) - x(0) s
                dt       !
                         !t = 0
\end{verbatim}
Even better, use \code{view(axiom("laplace(diff(x(t),t,2),t,s)"))} to see
a typeset version.
    
\subsection{Continued Fractions}

A continued fraction $a + 1/(b + 1/(c + \cdots))$ is
represented in axiom by the list $[a, b, c, \ldots]$.
\begin{verbatim}
    sage: axiom("cf((1 + sqrt(5))/2)")
    [1,1,1,1,2]
    sage: axiom("cf ((1 + sqrt(341))/2)")
    [9,1,2,1,2,1,17,1,2,1,2,1,17,1,2,1,2,1,17,2]
\end{verbatim}    
\subsection{Special examples}

In this section we illustrate calculations that would be awkward to do
(as far as I know) in non-symbolic computer algebra systems like MAGMA
or GAP.

We compute the gcd of $2x^{n+4} - x^{n+2}$ and $4x^{n+1} + 3x^n$
for arbitrary $n$.
\begin{verbatim}
    sage: f = axiom('2*x^(n+4) - x^(n+2)')
    sage: g = axiom('4*x^(n+1) + 3*x^n')
    sage: f.gcd(g)
    x^n
\end{verbatim}
You can plot 3d graphs (via gnuplot):
\begin{verbatim}
    sage.: axiom('plot3d(x^2-y^2, [x,-2,2], [y,-2,2], [grid,12,12])')
    [displays a 3 dimensional graph]
\end{verbatim}
You can formally evaluate sums (note the \code{nusum} command):
\begin{verbatim}
    sage: S = axiom('nusum(exp(1+2*i/n),i,1,n)')
    sage.: S
                            2/n + 3                   2/n + 1
                          %e                        %e
                   ----------------------- - -----------------------
                      1/n         1/n           1/n         1/n
                   (%e    - 1) (%e    + 1)   (%e    - 1) (%e    + 1)
\end{verbatim}
We formally compute the limit as $n\to\infty$ of $2S/n$ as follows:
\begin{verbatim}
    sage: T = S*axiom('2/n')
    sage: T.tlimit('n','inf')
    %e^3 - %e
\end{verbatim}
\subsection{Miscellaneous}
Obtaining digits of $\pi$:
\begin{verbatim}
    sage: axiom.eval('fpprec : 100')
    '100'
    sage: axiom(pi).bfloat()
    3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068b0
\end{verbatim}
Defining functions in axiom:
\begin{verbatim}
    sage: axiom.eval('fun(a) == a^2')
    'fun[a] := a^2'
    sage: axiom('fun(10)')
    100
\end{verbatim}
\subsection{Interactivity}
Axiom has a non-interactive mode that is initiated via the command
")read file.input". 

\subsection{Latex Output}
The latex output of Axiom is not perfect.  E.g.,
\begin{verbatim}
    sage: axiom.eval('tex(sin(u) + sinh(v^2))')
    '$$\\sinhv^2 + \\sinu$$false'
\end{verbatim}    
Notice the lack of space after the sin macro, which is a latex syntax
error.  In \sage this is automatically fixed via a substition for
trig functions, which may have potentially bad side effects:
\begin{verbatim}
    sage: latex(axiom('sin(u) + sinh(v^2)'))
    \sinh v^2+\sin u
\end{verbatim}
It would be nice if somebody would fix this problem.  One way would
be to improve Axiom by making the fix to Axiom and giving this back
to the Axiom people.

Here's another example:
\begin{verbatim}
    sage: g = axiom('exp(3*%i*x)/(6*%i) + exp(%i*x)/(2*%i) + c')
    sage: latex(g)
     -\frac{i e^{3 i x}}{6}-\frac{i e^{i x}}{2}+c
\end{verbatim}
\subsection{Long Input}
The Axiom interface reads in even very long input (using files) in a
robust manner, as long as you are creating a new object.
\note{Using \code{axiom.eval} for long input
is much less robust, and is not recommended.}
\begin{verbatim}
    sage: t = '"%s"'%10^10000   # ten thousand character string.
    sage: a = axiom(t)
\end{verbatim}         
}

\maketitle
<<axiom.py>>=
r"""
Interface to Axiom

Axiom is a free GPL-compatible (modified BSD license)  general purpose
computer algebra system whose development started in 1973 at IBM.  It
contains symbolic manipulation algorithms, as well as implementations
of special functions, including elliptic functions and generalized
hypergeometric functions. Moreover, Axiom has implementations of many
functions relating to the invariant theory of the symmetric group $S_n$. 
For many links to Axiom documentation see
         \url{http://wiki.axiom-developer.org}.

AUTHORS OF THIS MODULE:
    - William Stein (2006-10): Initial version based on Maxima interface
    - Bill Page (2006-10): Axiom version
    
If the string "error" (case insensitive) occurs in the output of
anything from axiom, a RuntimeError exception is raised.

EXAMPLES:
We evaluate a very simple expression in axiom.
    sage: axiom('3 * 5')
    15
                                          Type: PositiveInteger

We factor $x^5 - y^5$ in Axiom in several different ways.
The first way yields a Axiom object.
    sage: F = axiom.factor('x^5 - y^5')
    sage: type(F)
    <class 'axiom.interfaces.axiom.AxiomElement'>

Note that Axiom objects are normally displayed using ``ASCII art'';
to see a normal linear representation of any Axiom object x,
use \code{str(x)}.
    sage: F
                               4      3    2  2    3      4
                   - (y - x) (y  + x y  + x  y  + x  y + x )

You can always use \code{x.str()} to obtain the linear representation
of an object, even without changing the display2d flag.  This can
be useful for moving axiom data to other systems. 
    sage: F.str()
    '-(y - x)*(y^4 + x*y^3 + x^2*y^2 + x^3*y + x^4)'
    
    sage: axiom.display2d(False)
    sage: F
    -(y - x)*(y^4 + x*y^3 + x^2*y^2 + x^3*y + x^4)


The \code{axiom.eval} command evaluates an expression in axiom
and returns the result as a string.

    sage: print axiom.eval('factor(x^5 - y^5)')
    -(y - x)*(y^4 + x*y^3 + x^2*y^2 + x^3*y + x^4)

We can create the polynomial $f$ as a Axiom polynomial, then call
the factor method on it.  Notice that the notation \code{f.factor()}
is consistent with how the rest of \sage works.
    sage: f = axiom('x^5 - y^5')
    sage: f^2
    (x^5 - y^5)^2
    sage: f.factor()
    -(y - x)*(y^4 + x*y^3 + x^2*y^2 + x^3*y + x^4)

Control-C interruption works well with the axiom interface,
because of the excellent implementation of axiom.  For example,
try the following sum but with a much bigger range, and hit
control-C.
    sage: axiom('sum(1/x^2, x, 1, 10)')
    1968329/1270080

\subsection{Tutorial}
We follow the tutorial at
\url{http://wiki.axiom-developer.org/AxiomTutorial}.

    sage: axiom('1/100 + 1/101')
    201/10100

    sage: a = axiom('(1 + sqrt(2))^5'); a
    (sqrt(2) + 1)^5
    sage: a.expand()
    29*sqrt(2) + 41

    sage: a = axiom('(1 + sqrt(2))^5')
    sage: float(a)                
    82.012193308819747
    sage: a.numer()
    82.01219330881975

    sage: axiom.eval('fpprec : 100')
    '100'
    sage: a.bfloat()
    8.20121933088197564152489730020812442785204843859314941221237124017312418754011041266612384955016056b1

    sage: axiom('100!')
    93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

    sage: f = axiom('(x + 3*y + x^2*y)^3')
    sage: f.expand()
    x^6*y^3 + 9*x^4*y^3 + 27*x^2*y^3 + 27*y^3 + 3*x^5*y^2 + 18*x^3*y^2 + 27*x*y^2 + 3*x^4*y + 9*x^2*y + x^3
    sage: f.subst('x=5/z')
    (5/z + 25*y/z^2 + 3*y)^3
    sage: g = f.subst('x=5/z')
    sage: h = g.ratsimp(); h
    (27*y^3*z^6 + 135*y^2*z^5 + (675*y^3 + 225*y)*z^4 + (2250*y^2 + 125)*z^3 + (5625*y^3 + 1875*y)*z^2 + 9375*y^2*z + 15625*y^3)/z^6
    sage: h.factor()
    (3*y*z^2 + 5*z + 25*y)^3/z^6

    sage: eqn = axiom(['a+b*c=1', 'b-a*c=0', 'a+b=5'])
    sage: s = eqn.solve('[a,b,c]'); s
    [[a = (25*sqrt(79)*%i + 25)/(6*sqrt(79)*%i - 34),b = (5*sqrt(79)*%i + 5)/(sqrt(79)*%i + 11),c = (sqrt(79)*%i + 1)/10],[a = (25*sqrt(79)*%i - 25)/(6*sqrt(79)*%i + 34),b = (5*sqrt(79)*%i - 5)/(sqrt(79)*%i - 11),c =  - (sqrt(79)*%i - 1)/10]]

Here is an example of solving an algebraic equation:
    sage: axiom('x^2+y^2=1').solve('y')
    [y =  - sqrt(1 - x^2),y = sqrt(1 - x^2)]
    sage: axiom('x^2 + y^2 = (x^2 - y^2)/sqrt(x^2 + y^2)').solve('y')
    [y =  - sqrt(( - y^2 - x^2)*sqrt(y^2 + x^2) + x^2),y = sqrt(( - y^2 - x^2)*sqrt(y^2 + x^2) + x^2)]

You can even nicely typeset the solution in latex:
    sage: latex(s)
    \left[ \left[ a=\frac{25 \sqrt{79} i+25}{6 \sqrt{79} i-34} , b=  \frac{5 \sqrt{79} i+5}{\sqrt{79} i+11} , c=\frac{\sqrt{79} i+1}{10}   \right]  , \left[ a=\frac{25 \sqrt{79} i-25}{6 \sqrt{79} i+34} , b=  \frac{5 \sqrt{79} i-5}{\sqrt{79} i-11} , c=-\frac{\sqrt{79} i-1}{10}   \right]  \right]

To have the above appear onscreen via \code{xdvi}, type \code{view(s)}.
(TODO: For OS X should create pdf output and use preview instead?)

    sage: e = axiom('sin(u + v) * cos(u)^3'); e
    cos(u)^3*sin(v + u)
    sage: f = e.trigexpand(); f
    cos(u)^3*(cos(u)*sin(v) + sin(u)*cos(v))
    sage: f.trigreduce()
    (sin(v + 4*u) + sin(v - 2*u))/8 + (3*sin(v + 2*u) + 3*sin(v))/8
    sage: w = axiom('3 + k*%i')
    sage: f = w^2 + axiom('%e')^w
    sage: f.realpart()
    %e^3*cos(k) - k^2 + 9
    
    sage: f = axiom('x^3 * %e^(k*x) * sin(w*x)'); f
    x^3*%e^(k*x)*sin(w*x)
    sage: f.diff('x')
    k*x^3*%e^(k*x)*sin(w*x) + 3*x^2*%e^(k*x)*sin(w*x) + w*x^3*%e^(k*x)*cos(w*x)
    sage: f.integrate('x')
    (((k*w^6 + 3*k^3*w^4 + 3*k^5*w^2 + k^7)*x^3 + (3*w^6 + 3*k^2*w^4 - 3*k^4*w^2 - 3*k^6)*x^2 + ( - 18*k*w^4 - 12*k^3*w^2 + 6*k^5)*x - 6*w^4 + 36*k^2*w^2 - 6*k^4)*%e^(k*x)*sin(w*x) + (( - w^7 - 3*k^2*w^5 - 3*k^4*w^3 - k^6*w)*x^3 + (6*k*w^5 + 12*k^3*w^3 + 6*k^5*w)*x^2 + (6*w^5 - 12*k^2*w^3 - 18*k^4*w)*x - 24*k*w^3 + 24*k^3*w)*%e^(k*x)*cos(w*x))/(w^8 + 4*k^2*w^6 + 6*k^4*w^4 + 4*k^6*w^2 + k^8)

    sage: f = axiom('1/x^2')
    sage: f.integrate('x', 1, 'inf')
    1
    sage: g = axiom('f/sinh(k*x)^4')
    sage: g.taylor('x', 0, 3)
    f/(k^4*x^4) - 2*f/(3*k^2*x^2) + 11*f/45 - 62*k^2*f*x^2/945

    sage: axiom.taylor('asin(x)','x',0, 10)
    x + x^3/6 + 3*x^5/40 + 5*x^7/112 + 35*x^9/1152

\subsection{Examples involving matrices}
We illustrate computing with the matrix whose $i,j$ entry
is $i/j$, for $i,j=1,\ldots,4$.

    sage: f = axiom.eval('f[i,j] := i/j')
    sage: A = axiom('genmatrix(f,4,4)'); A
    matrix([1,1/2,1/3,1/4],[2,1,2/3,1/2],[3,3/2,1,3/4],[4,2,4/3,1])
    sage: A.determinant()
    0
    sage: A.echelon()
    matrix([1,1/2,1/3,1/4],[0,0,0,0],[0,0,0,0],[0,0,0,0])
    sage: A.eigenvalues()
    [[0,4],[3,1]]
    sage: A.eigenvectors()
    [[[0,4],[3,1]],[1,0,0, - 4],[0,1,0, - 2],[0,0,1, - 4/3],[1,2,3,4]]

We can also compute the echelon form in \sage:
    sage: B = matrix(QQ, A)
    sage: B.echelon_form()
    [  1 1/2 1/3 1/4]
    [  0   0   0   0]
    [  0   0   0   0]
    [  0   0   0   0]
    sage: B.charpoly().factor()
    (x - 4) * x^3

\subsection{Laplace Transforms}
We illustrate Laplace transforms:
    sage: _ = axiom.eval("f(t) := t*sin(t)")
    sage: axiom("laplace(f(t),t,s)")
    2*s/(s^2 + 1)^2

    sage: axiom("laplace(delta(t-3),t,s)") #Dirac delta function
    %e^-(3*s)
    
    sage: _ = axiom.eval("f(t) == exp(t)*sin(t)")
    sage: axiom("laplace(f(t),t,s)")
    1/(s^2 - 2*s + 2)
    
    sage: _ = axiom.eval("f(t) := t^5*exp(t)*sin(t)")
    sage: axiom("laplace(f(t),t,s)")
    360*(2*s - 2)/(s^2 - 2*s + 2)^4 - 480*(2*s - 2)^3/(s^2 - 2*s + 2)^5 + 120*(2*s - 2)^5/(s^2 - 2*s + 2)^6
    sage: axiom("laplace(f(t),t,s)")
                                             3                 5
               360 (2 s - 2)    480 (2 s - 2)     120 (2 s - 2)
              --------------- - --------------- + ---------------
                2           4     2           5     2           6
              (s  - 2 s + 2)    (s  - 2 s + 2)    (s  - 2 s + 2)

    sage: axiom("laplace(diff(x(t),t),t,s)")
    s*laplace(x(t),t,s) - x(0)
    
    sage: axiom("laplace(diff(x(t),t,2),t,s)")
    -at('diff(x(t),t,1),t = 0) + s^2*laplace(x(t),t,s) - x(0)*s

    sage.: axiom("laplace(diff(x(t),t,2),t,s)")
                         !
                d        !         2
              - -- (x(t))!      + s  laplace(x(t), t, s) - x(0) s
                dt       !
                         !t = 0

Even better, use \code{view(axiom("laplace(diff(x(t),t,2),t,s)"))} to see
a typeset version.
    
\subsection{Continued Fractions}

A continued fraction $a + 1/(b + 1/(c + \cdots))$ is
represented in axiom by the list $[a, b, c, \ldots]$.

    sage: axiom("cf((1 + sqrt(5))/2)")
    [1,1,1,1,2]
    sage: axiom("cf ((1 + sqrt(341))/2)")
    [9,1,2,1,2,1,17,1,2,1,2,1,17,1,2,1,2,1,17,2]
    
\subsection{Special examples}

In this section we illustrate calculations that would be awkward to do
(as far as I know) in non-symbolic computer algebra systems like MAGMA
or GAP.

We compute the gcd of $2x^{n+4} - x^{n+2}$ and $4x^{n+1} + 3x^n$
for arbitrary $n$.

    sage: f = axiom('2*x^(n+4) - x^(n+2)')
    sage: g = axiom('4*x^(n+1) + 3*x^n')
    sage: f.gcd(g)
    x^n

You can plot 3d graphs (via gnuplot):

    sage.: axiom('plot3d(x^2-y^2, [x,-2,2], [y,-2,2], [grid,12,12])')
    [displays a 3 dimensional graph]

You can formally evaluate sums (note the \code{nusum} command):

    sage: S = axiom('nusum(exp(1+2*i/n),i,1,n)')
    sage.: S
                            2/n + 3                   2/n + 1
                          %e                        %e
                   ----------------------- - -----------------------
                      1/n         1/n           1/n         1/n
                   (%e    - 1) (%e    + 1)   (%e    - 1) (%e    + 1)

We formally compute the limit as $n\to\infty$ of $2S/n$ as follows:

    sage: T = S*axiom('2/n')
    sage: T.tlimit('n','inf')
    %e^3 - %e

\subsection{Miscellaneous}
Obtaining digits of $\pi$:
    sage: axiom.eval('fpprec : 100')
    '100'
    sage: axiom(pi).bfloat()
    3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068b0

Defining functions in axiom:
    sage: axiom.eval('fun(a) == a^2')
    'fun[a] := a^2'
    sage: axiom('fun(10)')
    100

\subsection{Interactivity}
Axiom has a non-interactive mode that is initiated via the command
")read file.input". 

\subsection{Latex Output}
The latex output of Axiom is not perfect.  E.g.,

    sage: axiom.eval('tex(sin(u) + sinh(v^2))')
    '$$\\sinhv^2 + \\sinu$$false'
    
Notice the lack of space after the sin macro, which is a latex syntax
error.  In \sage this is automatically fixed via a substition for
trig functions, which may have potentially bad side effects:

    sage: latex(axiom('sin(u) + sinh(v^2)'))
    \sinh v^2+\sin u

It would be nice if somebody would fix this problem.  One way would
be to improve Axiom by making the fix to Axiom and giving this back
to the Axiom people.

Here's another example:

    sage: g = axiom('exp(3*%i*x)/(6*%i) + exp(%i*x)/(2*%i) + c')
    sage: latex(g)
     -\frac{i e^{3 i x}}{6}-\frac{i e^{i x}}{2}+c

\subsection{Long Input}
The Axiom interface reads in even very long input (using files) in a
robust manner, as long as you are creating a new object.
\note{Using \code{axiom.eval} for long input
is much less robust, and is not recommended.}

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

#*****************************************************************************
#       Copyright (C) 2005 William Stein <wstein@gmail.com>
#
#  Distributed under the terms of the GNU General Public License (GPL)
#
#    This code is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#    General Public License for more details.
#
#  The full text of the GPL is available at:
#
#                  http://www.gnu.org/licenses/
#*****************************************************************************

import os, re

from expect import Expect, ExpectElement, FunctionElement, ExpectFunction, tmp

from sage.misc.misc import verbose

from sage.misc.multireplace import multiple_replace

cnt = 0
seq = 0

from sage.misc.all import pager, verbose, DOT_SAGE, SAGE_ROOT

COMMANDS_CACHE = '%s/axiom_commandlist_cache.sobj'%DOT_SAGE

import sage.server.support

# The Axiom commands ")what thing det" ")show Matrix" and ")display
# op det" commands, gives a list of all identifiers that begin in
# a certain way.  This could maybe be useful somehow... (?)  Also
# axiom has a lot a lot of ways for getting documentation from the
# system -- this could also be useful.

class Axiom(Expect):
    """
    Interface to the Axiom interpreter.
    """
    def __call__(self, x):
        import sage.rings.all
        if sage.rings.all.is_Infinity(x):
            return Expect.__call__(self, 'inf')
        else:
            return Expect.__call__(self, x)
        
    def __init__(self, script_subdirectory=None, logfile=None, server=None):
        """
        Create an instance of the Axiom interpreter.   
        """
        eval_using_file_cutoff = 200
        self.__eval_using_file_cutoff = eval_using_file_cutoff
        Expect.__init__(self,
                        name = 'axiom',
                        prompt = '\([0-9]+\) -> ',
                        command = "axiom -nox",
                        maxread = 1,  # CRUCIAL to use less buffering for Axiom!
                        script_subdirectory = script_subdirectory,
                        restart_on_ctrlc = False,
                        verbose_start = False,
                        init_code = [],
                        logfile = logfile,
                        eval_using_file_cutoff=eval_using_file_cutoff)

    def __getattr__(self, attrname):
        if attrname[:1] == "_":
            raise AttributeError
        return AxiomExpectFunction(self, attrname)

    def _start(self):
        # For some reason sending a single input line at startup avoids
        # lots of weird timing issues when doing doctests.
        Expect._start(self)
        #out = self._eval_line(')set output algebra off', reformat=False)
        #out = self._eval_line(')set output tex on', reformat="False")
        out = self._eval_line(')set message autoload off', reformat=False)
        self._expect.expect(self._prompt)
        #out = self._expect.before
        #print "out 0 = '%s'"%out
        #self(1)    

    def _eval_line_using_file(self, line, tmp):
        F = open(tmp, 'w')
        F.write(line)
        F.close()
        if self._expect is None:
            self._start()
        # For some reason this trivial comp
        # keeps certain random freezes from occuring.  Do not remove this.
        # The space before the \n is also important.
        self._expect.sendline(')read "%s"\n'%tmp)
        self._expect.expect(self._prompt)
        return ''

    def __reduce__(self):
        return reduce_load_Axiom, tuple([])

    def _quit_string(self):
        return ')lisp (quit)'

    def _eval_line(self, line, reformat=True, allow_use_file=False,
                   wait_for_prompt=True):
        if not wait_for_prompt:
            return Expect._eval_line(self, line)
        line = line.rstrip().rstrip(';')
        if line == '':
            return ''
        global seq
        seq += 1
        #start = SAGE_START + str(seq)
        #end = SAGE_END + str(seq)
        #line = '%s;\n%s; %s;'%(start, line, end)
        if self._expect is None:
            self._start()
        if allow_use_file and self.__eval_using_file_cutoff and \
                            len(line) > self.__eval_using_file_cutoff:
            return self._eval_line_using_file(line, tmp)
        try:
            E = self._expect
            # debug
            # print "in = '%s'"%line
            E.sendline(line)
            self._expect.expect(self._prompt)
            out = self._expect.before
            # debug
            # print "out = '%s'"%out
                
        except KeyboardInterrupt:
            self._keyboard_interrupt()

        if 'Incorrect syntax:' in out:
            raise RuntimeError, out

        if not reformat:
            return out
        if 'error' in out:
            return out
        #out = out.lstrip()
        i = out.find('\n')
        out = out[i+1:]
        outs = out.split("\n")
        i = 0
        outline = ''
        for line in outs:
            line = line.rstrip()
            # print "'%s'"%line
            if line[:4] == '   (':
                i = line.find('(')
                i += line[i:].find(')')
                if line[i+1:] == "":
                    i = 0
                    outs = outs[1:]
                break;
        out = "\n".join(line[i+1:] for line in outs[1:])
        return out

    ###########################################
    # Interactive help
    ###########################################

    def help(self, s):
        if sage.server.support.EMBEDDED_MODE:
            os.system('asq "describe(%s); "< /dev/null'%s)
        else:
            os.system('asq "describe(%s);"'%s)

    def example(self, s):
        if sage.server.support.EMBEDDED_MODE:
            os.system('axiom -ht -nogr "example(%s);" < /dev/null'%s)
        else:
            os.system('axiom -ht "example(%s);"'%s)

    describe = help

    def demo(self, s):
        if sage.server.support.EMBEDDED_MODE:
            os.system('axiom -ht "demo(%s);" < /dev/null'%s)
        else:
            os.system('axiom -ht "demo(%s);"'%s)

    def completions(self, s):
        """
        Return all commands that complete the command starting with the
        string s.   This is like typing s[tab] in the maple interpreter.
        """
        s = self.eval('apropos(%s)'%s).replace('\\ - ','-')
        return [x for x in s[1:-1].split(',') if x[0] != '?']

    def _commands(self):
        """
        Return list of all commands defined in Axiom.
        """
        try:
            return self.__commands
        except AttributeError:
            self.__commands = sum([self.completions(chr(97+n)) for n in range(26)], [])
        return self.__commands

    def trait_names(self, verbose=True, use_disk_cache=True):
        try:
            return self.__trait_names
        except AttributeError:
            import sage.misc.persist
            if use_disk_cache:
                try:
                    self.__trait_names = sage.misc.persist.load(COMMANDS_CACHE)
                    return self.__trait_names
                except IOError:
                    pass
            if verbose:
                print "\nBuilding Axiom command completion list (this takes"
                print "a few seconds only the first time you do it)."
                print "To force rebuild later, delete %s."%COMMANDS_CACHE
            v = self._commands()
            self.__trait_names = v
            sage.misc.persist.save(v, COMMANDS_CACHE)
            return v

    def _object_class(self):
        return AxiomElement

    def _true_symbol(self):
        return 'true'

    def _false_symbol(self):
        return 'false'

    def function(self, args, defn, repr=None, latex=None):
        """
        Return the Axiom function with given arguments
        and definition.

        INPUT:
            args -- a string with variable names separated by commas
            defn -- a string (or Axiom expression) that defines
                    a function of the arguments in Axiom.
            repr -- an optional string; if given, this is how the function will print.
        
        EXAMPLES:
            sage: f = axiom.function('x', 'sin(x)')
            sage: f(3.2)
            -0.058374143427580086
            sage: f = axiom.function('x,y', 'sin(x)+cos(y)')
            sage: f(2,3.5)
            sin(2) - 0.9364566872907963
            sage: f
            sin(x)+cos(y)
            
            sage: g = f.integrate('z'); g
            (cos(y) + sin(x))*z
            sage: g(1,2,3)
            3*(cos(2) + sin(1))

        The function definition can be an axiom object:
            sage: an_expr = axiom('sin(x)*gamma(x)')
            sage: t = axiom.function('x', an_expr)
            sage: t
            gamma(x)*sin(x)
            sage: t(2)
            sin(2)
            sage: float(t(2))
            0.90929742682568171
            sage: loads(t.dumps())
            gamma(x)*sin(x)
        """
        name = self._next_var_name()
        defn = str(defn)
        args = str(args)
        axiom.eval('%s(%s) := %s'%(name, args, defn))
        if repr is None:
            repr = defn
        f = AxiomFunction(self, name, repr, args, latex)
        return f

    def set(self, var, value):
        """
        Set the variable var to the given value.
        """
        cmd = '%s := %s'%(var, value)
        out = self._eval_line(cmd, reformat=False)
        #out = self._eval_line(cmd, reformat=False, allow_use_file=True)
        
        if out.find("error") != -1:
            raise TypeError, "Error executing code in Axiom\nCODE:\n\t%s\nAxiom ERROR:\n\t%s"%(cmd, out)


    def get(self, var):
        """
        Get the string value of the variable var.
        """
        s = self._eval_line('%s'%var)
        return s
        
    #def clear(self, var):
    #    """
    #    Clear the variable named var.
    #    """
    #    if self._expect is None:
    #        return
    #    self._expect.sendline('kill(%s);'%var)
    #    self._expect.expect(self._prompt)
        
    def console(self):
        axiom_console()
    
    def plot2d(self, *args):
        r"""
        Plot a 2d graph using Axiom / Viewman.

        axiom.plot2d(f, '[var, min, max]', options)

        INPUT:
            f -- a string representing a function (such as f="sin(x)")
            [var, xmin, xmax] 
            options -- an optional string representing plot2d options in gnuplot format

        EXAMPLES:
            sage.: axiom.plot2d('sin(x)','[x,-5,5]') 
            sage.: opts = '[gnuplot_term, ps], [gnuplot_out_file, "sin-plot.eps"]'
            sage.: axiom.plot2d('sin(x)','[x,-5,5]',opts) 

        The eps file is saved in the current directory.
        """
        self('plot2d(%s)'%(','.join([str(x) for x in args])))

    def plot2d_parametric(self, r, var, trange, nticks=50, options=None):
        r"""
        Plots r = [x(t), y(t)] for t = tmin...tmax using gnuplot with options

        INPUT:
            r -- a string representing a function (such as r="[x(t),y(t)]")
            var -- a string representing the variable (such as var = "t")
            trange -- [tmin, tmax] are numbers with tmin<tmax
            nticks -- int (default: 50)
            options -- an optional string representing plot2d options in gnuplot format

        EXAMPLES:
            sage.: axiom.plot2d_parametric(["sin(t)","cos(t)"], "t",[-3.1,3.1])

            sage.: opts = '[gnuplot_preamble, "set nokey"], [gnuplot_term, ps], [gnuplot_out_file, "circle-plot.eps"]'
            sage.: axiom.plot2d_parametric(["sin(t)","cos(t)"], "t", [-3.1,3.1], options=opts)
            
        The eps file is saved to the current working directory.

        Here is another fun plot:
            sage.: axiom.plot2d_parametric(["sin(5*t)","cos(11*t)"], "t", [0,2*pi()], nticks=400) 
        """
        tmin = trange[0]
        tmax = trange[1]
        cmd = "plot2d([parametric, %s, %s, [%s, %s, %s], [nticks, %s]]"%( \
                   r[0], r[1], var, tmin, tmax, nticks)
        if options is None:
            cmd += ")"
        else:
            cmd += ", %s)"%options
        self(cmd)

    def plot3d(self, *args):
        r"""
        Plot a 3d graph using Axiom / Viewman.

        axiom.plot3d(f, '[x, xmin, xmax]', '[y, ymin, ymax]', '[grid, nx, ny]', options)

        INPUT:
            f -- a string representing a function (such as f="sin(x)")
            [var, min, max] 

        EXAMPLES:
            sage.: axiom.plot3d('1 + x^3 - y^2', '[x,-2,2]', '[y,-2,2]', '[grid,12,12]') 
            sage.: axiom.plot3d('sin(x)*cos(y)', '[x,-2,2]', '[y,-2,2]', '[grid,30,30]')
            sage.: opts = '[gnuplot_term, ps], [gnuplot_out_file, "sin-plot.eps"]' 
            sage.: axiom.plot3d('sin(x+y)', '[x,-5,5]', '[y,-1,1]', opts)

        The eps file is saved in the current working directory.
        """
        self('plot3d(%s)'%(','.join([str(x) for x in args])))

    def plot3d_parametric(self, r, vars, urange, vrange, options=None):
        r"""
        Plot a 3d parametric graph with r=(x,y,z), x = x(u,v), y = y(u,v), z = z(u,v),
        for u = umin...umax, v = vmin...vmax using gnuplot with options.

        INPUT:
            x, y, z -- a string representing a function (such as x="u^2+v^2", ...)
            vars is a list or two strings representing variables (such as vars = ["u","v"])
            urange -- [umin, umax]
            vrange -- [vmin, vmax] are lists of numbers with
            umin < umax, vmin < vmax
            options -- optional string representing plot2d options in gnuplot format

        OUTPUT:
            displays a plot on screen or saves to a file

        EXAMPLES:
            sage.: axiom.plot3d_parametric(["v*sin(u)","v*cos(u)","v"], ["u","v"],[-3.2,3.2],[0,3])
            sage.: opts = '[gnuplot_term, ps], [gnuplot_out_file, "sin-cos-plot.eps"]'
            sage.: axiom.plot3d_parametric(["v*sin(u)","v*cos(u)","v"], ["u","v"],[-3.2,3.2],[0,3],opts)

        The eps file is saved in the current working directory.

        Here is a torus:

            sage.: _ = axiom.eval("expr_1: cos(y)*(10.0+6*cos(x)); expr_2: sin(y)*(10.0+6*cos(x)); expr_3: -6*sin(x);")  # optional
            sage.: axiom.plot3d_parametric(["expr_1","expr_2","expr_3"], ["x","y"],[0,6],[0,6])

        Here is a Mobius strip:
            sage.: x = "cos(u)*(3 + v*cos(u/2))"
            sage.: y = "sin(u)*(3 + v*cos(u/2))"
            sage.: z = "v*sin(u/2)"
            sage.: axiom.plot3d_parametric([x,y,z],["u","v"],[-3.1,3.2],[-1/10,1/10])
        """
        umin = urange[0]
        umax = urange[1]
        vmin = vrange[0]
        vmax = vrange[1]
        cmd = 'plot3d([%s, %s, %s], [%s, %s, %s], [%s, %s, %s]'%(
            r[0], r[1], r[2], vars[0], umin, umax, vars[1], vmin, vmax)
        if options is None:
            cmd += ')'
        else:
            cmd += ', %s)'%options
        axiom(cmd)

    def de_solve(axiom, de, vars, ics=None):
        """
        Solves a 1st or 2nd order ordinary differential equation (ODE)
        in two variables, possibly with initial conditions.

        INPUT:
            de -- a string representing the ODE
            vars -- a list of strings representing the two variables.
            ics -- a triple of numbers [a,b1,b2] representing
                   y(a)=b1, y'(a)=b2
                   
        EXAMPLES:
            sage.: axiom.de_solve('diff(y,x,2) + 3*x = y', ['x','y'], [1,1,1])
            y = 3*x - 2*%e^(x - 1)
            sage.: axiom.de_solve('diff(y,x,2) + 3*x = y', ['x','y'])
            y = %k1*%e^x + %k2*%e^ - x + 3*x
            sage.: axiom.de_solve('diff(y,x) + 3*x = y', ['x','y'])
            y = (%c - 3*( - x - 1)*%e^ - x)*%e^x
            sage.: axiom.de_solve('diff(y,x) + 3*x = y', ['x','y'],[1,1])
            y =  - %e^ - 1*(5*%e^x - 3*%e*x - 3*%e)
        """
        if not isinstance(vars, str):
            str_vars = '%s, %s'%(vars[1], vars[0])
        else:
            str_vars = vars
        axiom.eval('depends(%s)'%str_vars)
        m = axiom(de)
        a = 'ode2(%s, %s)'%(m.name(), str_vars)
        if ics != None:
            if len(ics) == 3:
                cmd = "ic2("+a+",%s=%s,%s=%s,diff(%s,%s)=%s);"%(vars[0],ics[0], vars[1],ics[1], vars[1], vars[0], ics[2])
                return axiom(cmd)
            if len(ics) == 2:
                return axiom("ic1("+a+",%s=%s,%s=%s);"%(vars[0],ics[0], vars[1],ics[1]))
        return axiom(a+";")

    def de_solve_laplace(self, de, vars, ics=None):
        """
        Solves an ordinary differential equation (ODE) using Laplace transforms.
        
        INPUT:
            de -- a string representing the ODE
                  (e.g., de = "diff(f(x),x,2)=diff(f(x),x)+sin(x)")
            vars -- a list of strings representing the variables
                  (e.g., vars = ["x","f"])
            ics -- a list of numbers representing initial conditions,
                   with symbols allowed which are represented by strings
                   (eg, f(0)=1, f'(0)=2 is ics = [0,1,2])

        EXAMPLES:
            sage.: axiom.clear('x'); axiom.clear('f')
            sage.: axiom.de_solve_laplace("diff(f(x),x,2) = 2*diff(f(x),x)-f(x)", ["x","f"], [0,1,2])
            f(x) = x*%e^x + %e^x
            
            sage.: axiom.clear('x'); axiom.clear('f')            
            sage.: f = axiom.de_solve_laplace("diff(f(x),x,2) = 2*diff(f(x),x)-f(x)", ["x","f"])
            sage.: f
                                               !
                                   x  d        !                  x          x
                        f(x) = x %e  (-- (f(x))!     ) - f(0) x %e  + f(0) %e
                                      dx       !
                                               !x = 0


        \note{The second equation sets the values of $f(0)$ and
        $f'(0)$ in axiom, so subsequent ODEs involving these
        variables will have these initial conditions automatically
        imposed.}
        """
        if not (ics is None):
            d = len(ics)
            for i in range(0,d-1):
                ic = 'atvalue(diff(%s(%s), %s, %s), %s = %s, %s)'%(
                    vars[1], vars[0], vars[0], i, vars[0], ics[0], ics[1+i])
                axiom.eval(ic)
        return axiom('desolve(%s, %s(%s))'%(de, vars[1], vars[0]))

    def solve_linear(self, eqns,vars):
        """
        Wraps axiom's linsolve.
        
        INPUT:
        eqns is a list of m strings, each rperesenting a linear question
        in m <= n variables
        vars is a list of n strings, each representing a variable

        EXAMPLES:
            sage: eqns = ["x + z = y","2*a*x - y = 2*a^2","y - 2*z = 2"]    
            sage: vars = ["x","y","z"]                                      
            sage: axiom.solve_linear(eqns, vars)                         
            [x = a + 1,y = 2*a,z = a - 1]
        """
        eqs = "["
        for i in range(len(eqns)):
            if i<len(eqns)-1:
                eqs = eqs + eqns[i]+","
            if  i==len(eqns)-1:
                eqs = eqs + eqns[i]+"]"
        vrs = "["
        for i in range(len(vars)):
            if i<len(vars)-1:
                vrs = vrs + vars[i]+","
            if  i==len(vars)-1:
                vrs = vrs + vars[i]+"]"
        return self('linsolve(%s, %s)'%(eqs, vrs))

    def unit_quadratic_integer(self, n):
        r"""
        Finds a unit of the ring of integers of the quadratic number
        field $\Q(\sqrt{n})$, $n>1$, using the qunit axiom command.

        EXAMPLE:
            sage: u = axiom.unit_quadratic_integer(101)           
            sage: u.parent()                                       
            Number Field in a with defining polynomial x^2 - 101
            sage: u                                                
            a + 10
            sage: u = axiom.unit_quadratic_integer(13)            
            sage: u                                                
            5*a + 18
            sage: u.parent()                                       
            Number Field in a with defining polynomial x^2 - 13
        """
        from sage.rings.all import QuadraticField, Integer
        # Take square-free part so sqrt(n) doesn't get simplified further by axiom
        # (The original version of this function would yield wrong answers if
        # n is not squarefree.)
        n = Integer(n).square_free_part()  
        if n < 1:
            raise ValueError, "n (=%s) must be >= 1"%n
        s = str(self('qunit(%s)'%n)).lower()
        r = re.compile('sqrt\(.*\)')
        s = r.sub('a', s)
        a = QuadraticField(n, 'a').gen()
        return eval(s)

    def plot_list(self, ptsx, ptsy, options=None):
        r"""
        Plots a curve determined by a sequence of points.

        INPUT:
            ptsx -- [x1,...,xn], where the xi and yi are real,
            ptsy -- [y1,...,yn]
            options -- a string representing axiom plot2d options.

        The points are (x1,y1), (x2,y2), etc.

        EXAMPLES:
            sage.: zeta_ptsx = [ (pari(1/2 + i*I/10).zeta().real()).precision(1) for i in range (70,150)]  
            sage.: zeta_ptsy = [ (pari(1/2 + i*I/10).zeta().imag()).precision(1) for i in range (70,150)]  
            sage.: axiom.plot_list(zeta_ptsx, zeta_ptsy)                   
            sage.: opts='[gnuplot_preamble, "set nokey"], [gnuplot_term, ps], [gnuplot_out_file, "zeta.eps"]'
            sage.: axiom.plot_list(zeta_ptsx, zeta_ptsy, opts)             
        """
        cmd = 'plot2d([discrete,%s, %s]'%(ptsx, ptsy)
        if options is None:
            cmd += ')'
        else:
            cmd += ', %s)'%options
        self(cmd)

    def plot_multilist(self, pts_list, options=None):
        r"""
        Plots a list of list of points pts_list=[pts1,pts2,...,ptsn],
        where each ptsi is of the form [[x1,y1],...,[xn,yn]]
        x's must be integers and y's reals
        options is a string representing axiom plot2d options.

        EXAMPLES:
            sage.: xx = [ i/10.0 for i in range (-10,10)]
            sage.: yy = [ i/10.0 for i in range (-10,10)]
            sage.: x0 = [ 0 for i in range (-10,10)]
            sage.: y0 = [ 0 for i in range (-10,10)]
            sage.: zeta_ptsx1 = [ (pari(1/2+i*I/10).zeta().real()).precision(1) for i in range (10)]
            sage.: zeta_ptsy1 = [ (pari(1/2+i*I/10).zeta().imag()).precision(1) for i in range (10)]
            sage.: axiom.plot_multilist([[zeta_ptsx1,zeta_ptsy1],[xx,y0],[x0,yy]])    
            sage.: zeta_ptsx1 = [ (pari(1/2+i*I/10).zeta().real()).precision(1) for i in range (10,150)]
            sage.: zeta_ptsy1 = [ (pari(1/2+i*I/10).zeta().imag()).precision(1) for i in range (10,150)]
            sage.: axiom.plot_multilist([[zeta_ptsx1,zeta_ptsy1],[xx,y0],[x0,yy]])    
            sage.: opts='[gnuplot_preamble, "set nokey"]'                 
            sage.: axiom.plot_multilist([[zeta_ptsx1,zeta_ptsy1],[xx,y0],[x0,yy]],opts)  
        """
        n = len(pts_list)
        cmd = '['
        for i in range(n):
            if i < n-1:
                cmd = cmd+'[discrete,'+str(pts_list[i][0])+','+str(pts_list[i][1])+'],'
            if i==n-1:
                cmd = cmd+'[discrete,'+str(pts_list[i][0])+','+str(pts_list[i][1])+']]'
        # debug
        # print cmd
        if options is None:
            self('plot2d('+cmd+')')
        else:
            self('plot2d('+cmd+','+options+')')
    

class AxiomElement(ExpectElement):
    def __call__(self, x):
        self._check_valid()
        P = self.parent()
        return P('%s[%s]'%(self.name(), x))
    
    def _cmp_(self, other):
        """
        EXAMPLES:
            sage: a = axiom(1); b = axiom(2)
            sage: a == b
            False
            sage: a < b
            True
            sage: a > b
            False
            sage: b < a
            False
            sage: b > a
            True

        We can also compare more complicated object such as functions:
            sage: f = axiom('sin(x)'); g = axiom('cos(x)')
            sage: -f == g.diff('x')
            True
        """

        # thanks to David Joyner for telling me about using "is".
        P = self.parent()
        if P.eval("is (%s < %s)"%(self.name(), other.name())) == P._true_symbol():
            return -1
        elif P.eval("is (%s > %s)"%(self.name(), other.name())) == P._true_symbol():
            return 1
        elif P.eval("is (%s = %s)"%(self.name(), other.name())) == P._true_symbol():
            return 0
        else:
            return -1  # everything is supposed to be comparable in Python, so we define
                       # the comparison thus when no comparable in interfaced system.
    def numer(self):
        P = self.parent()
        return P('numeric(%s)'%self._name)

    def real(self):
        return self.realpart()

    def imag(self):
        return self.imagpart()

    def str(self):
        self._check_valid()
        P = self.parent()
        return P.get('%s::InputForm'%self._name)

    def __repr__(self):
        self._check_valid()
        P = self.parent()
        return P.get(self._name)

    def diff(self, var='x', n=1):
        """
        Return the n-th derivative of self.  

        INPUT:
            var -- variable (default: 'x')
            n -- integer (default: 1)

        OUTPUT:
            n-th derivative of self with respect to the variable var

        EXAMPLES:
            sage: f = axiom('x^2')                          
            sage: f.diff()                                   
            2*x
            sage: f.diff('x')                                
            2*x
            sage: f.diff('x', 2)                             
            2
            sage: axiom('sin(x^2)').diff('x',4)             
            16*x^4*sin(x^2) - 12*sin(x^2) - 48*x^2*cos(x^2)  

            sage: f = axiom('x^2 + 17*y^2')                 
            sage: f.diff('x')
            2*x
            sage: f.diff('y')                                
            34*y
        """
        return ExpectElement.__getattr__(self, 'differentiate')(var, n)

    derivative = diff

    def nintegral(self, var='x', a=0, b=1,
                  desired_relative_error='1e-8',
                  maximum_num_subintervals=200):
        r"""
        Return a numerical approximation to the integral
        of self from a to b.

        INPUT:
            var -- variable to integrate with respect to
            a -- lower endpoint of integration
            b -- upper endpoint of integration
            desired_relative_error -- (default: '1e-8') the desired
                 relative error
            maximum_num_subintervals -- (default: 200) axiom number
                 of subintervals

        OUTPUT:
            -- approximation to the integral
            -- estimated absolute error of the approximation
            -- the number of integrand evaluations
            -- an error code:
                  0 -- no problems were encountered
                  1 -- too many subintervals were done
                  2 -- excessive roundoff error
                  3 -- extremely bad integrand behavior
                  4 -- failed to converge
                  5 -- integral is probably divergent or slowly convergent
                  6 -- the input is invalid

        EXAMPLES:
            sage: axiom('exp(-sqrt(x))').nintegral('x',0,1)
            (0.5284822353142306, 4.1633141378838445E-11, 231, 0)

        Note that GP also does numerical integration, and can do
        so to very high precision very quickly:
            sage: gp('intnum(x=0,1,exp(-sqrt(x)))')            
            0.5284822353142307136179049194             # 32-bit
            0.52848223531423071361790491935415653021   # 64-bit
            sage: _ = gp.set_precision(80)
            sage: gp('intnum(x=0,1,exp(-sqrt(x)))')
            0.52848223531423071361790491935415653021675547587292866196865279321015401702040079
        """
        from sage.rings.all import Integer
        v = self.quad_qags(var, a, b, desired_relative_error,
                           maximum_num_subintervals)
        return v[0], v[1], Integer(v[2]), Integer(v[3])

    def integral(self, var='x', min=None, max=None):
        r"""
        Return the integral of self with respect to the variable x.

        INPUT:
            var -- variable
            min -- default: None
            max -- default: None

        Returns the definite integral if xmin is not None,
        otherwise returns an indefinite integral.

        EXAMPLES:
            sage: axiom('x^2+1').integral()                   
            x^3/3 + x
            sage: axiom('x^2+ 1 + y^2').integral('y')         
            y^3/3 + x^2*y + y
            sage: axiom('x / (x^2+1)').integral()             
            log(x^2 + 1)/2
            sage: axiom('1/(x^2+1)').integral()               
            atan(x)
            sage.: axiom('1/(x^2+1)').integral('x', 0, infinity) 
            %pi/2
            sage: axiom('x/(x^2+1)').integral('x', -1, 1)     
            0

            sage: f = axiom('exp(x^2)').integral('x',0,1); f   
            -sqrt(%pi)*%i*erf(%i)/2
            sage: f.numer()         # I wonder how to get a real number (~1.463)?? 
            -0.8862269254527579*%i*erf(%i)
        """
        I = ExpectElement.__getattr__(self, 'integrate')
        if min is None:
            return I(var)
        else:
            if max is None:
                raise ValueError, "neither or both of min/max must be specified."
            return I(var, min, max)

    integrate = integral

    def __float__(self):
        return float(str(self.numer()))

    def __len__(self):
        """
        Return the length of a list.

        EXAMPLES:
            sage: v = axiom('[x^i for i in 0..5]')         
            sage: len(v)                                       
            6
        """
        self._check_valid()        
        return int(self.parent().eval('#(%s)'%self.name()))

    def __getattr__(self, attrname):
        if attrname[:1] == "_":
            raise AttributeError
        return AxiomFunctionElement(self, attrname)

    def __getitem__(self, n):
        r"""
        Return the n-th element of this list.

        \note{Lists are 0-based when accessed via the \sage interface,
        not 1-based as they are in the Axiom interpreter.}

        EXAMPLES:
            sage: v = axiom('[i*x^i for i in 0..5]'); v    
            [0,x,2*x^2,3*x^3,4*x^4,5*x^5]
            sage: v[3]                                         
            3*x^3
            sage: v[0]                                           
            0
            sage: v[10]                                          
            Traceback (most recent call last):
            ...
            IndexError: n = (10) must be between 0 and 5          
        """
        n = int(n)
        if n < 0 or n >= len(self):
            raise IndexError, "n = (%s) must be between %s and %s"%(n, 0, len(self)-1)
        return ExpectElement.__getitem__(self, n+1)

    def subst(self, val):
        P = self.parent()
        return P('subst(%s, %s)'%(self.name(), val))

    def comma(self, args):
        self._check_valid()
        P = self.parent()
        return P('%s, %s'%(self.name(), args))

    def _latex_(self):
        self._check_valid()
        P = self.parent()
        s = axiom._eval_line('outputAsTex(%s)'%self.name(), reformat=False)
        if not '$$' in s:
            raise RuntimeError, "Error texing axiom object."
        i = s.find('$$')
        j = s.rfind('$$')
        s = s[i+2:j]
        s = multiple_replace({'\r\n':' ',
                              '\\%':'', 
                              '\\arcsin ':'\\sin^{-1} ',
                              '\\arccos ':'\\cos^{-1} ',
                              '\\arctan ':'\\tan^{-1} '}, s)
        return s

    def trait_names(self):
        return self.parent().trait_names()

    def _matrix_(self, R):
        r"""
        If self is a Axiom matrix, return the corresponding \sage
        matrix over the \sage ring $R$.

        This may or may not work depending in how complicated the
        entries of self are!  It only works if the entries of self
        can be coerced as strings to produce meaningful elements
        of $R$.

        EXAMPLES:
            sage: _ = axiom.eval("f[i,j] := i/j")              
            sage: A = axiom('genmatrix(f,4,4)'); A             
            matrix([1,1/2,1/3,1/4],[2,1,2/3,1/2],[3,3/2,1,3/4],[4,2,4/3,1])
            sage: A._matrix_(QQ)                                
            [  1 1/2 1/3 1/4]
            [  2   1 2/3 1/2]
            [  3 3/2   1 3/4]
            [  4   2 4/3   1]

        You can also use the \code{matrix} command (which is defined
        in \code{sage.misc.functional}):
            sage: matrix(QQ, A)
            [  1 1/2 1/3 1/4]
            [  2   1 2/3 1/2]
            [  3 3/2   1 3/4]
            [  4   2 4/3   1]
        """
        from sage.matrix.all import MatrixSpace
        self._check_valid()
        P = self.parent()
        nrows = int(P.eval('length(%s)'%self.name()))
        if nrows == 0:
            return MatrixSpace(R, 0, 0)(0)
        ncols = int(P.eval('length(%s[1])'%self.name()))
        M = MatrixSpace(R, nrows, ncols)
        s = self.str().replace('matrix','').replace(',',"','").\
            replace("]','[","','").replace('([',"['").replace('])',"']")
        s = eval(s)
        return M([R(x) for x in s])
        
    def partial_fraction_decomposition(self, var='x'):
        """
        Return the partial fraction decomposition of self with respect to
        the variable var.

        EXAMPLES:
            sage: f = axiom('1/((1+x)*(x-1))')            
            sage: f.partial_fraction_decomposition('x') 
                                 1           1
                             --------- - ---------
                             2 (x - 1)   2 (x + 1)
        """
        return self.partfrac(var)

        
class AxiomFunctionElement(FunctionElement):
    def _sage_doc_(self):
        return self._obj.parent().help(self._name)

class AxiomExpectFunction(ExpectFunction):
    def _sage_doc_(self):
        M = self._parent
        return M.help(self._name)


class AxiomFunction(AxiomElement):
    def __init__(self, parent, name, defn, args, latex):
        AxiomElement.__init__(self, parent, name, is_name=True)
        self.__defn = defn
        self.__args = args
        self.__latex = latex
        
    def __call__(self, *x):
        self._check_valid()
        P = self.parent()
        if len(x) == 1:
            x = '(%s)'%x
        return P('%s%s'%(self.name(), x))

    def __repr__(self):
        return self.__defn

    def _latex_(self):
        if self.__latex is None:
            return '\\mbox{\\rm %s}'%self.__defn
        else:
            return self.__latex

    def integrate(self, var):
        return self.integral(var)

    def integral(self, var):
        self._check_valid()
        P = self.parent()
        f = P('integrate(%s(%s), %s)'%(self.name(), self.__args, var))
        if var in self.__args.split(','):
            args = self.__args
        else:
            args = self.__args + ',' + var
        return P.function(args, str(f))

def is_AxiomElement(x):
    return isinstance(x, AxiomElement)

# An instance
axiom = Axiom(script_subdirectory=None)

def reduce_load_Axiom():
    return axiom

import os
def axiom_console():
    os.system('axiom')

def __doctest_cleanup():
    import sage.interfaces.quit
    sage.interfaces.quit.expect_quitall()

@

\end{document}

Download: pdf dvi ps src tex log