Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*- r""" Abstract interface to Maxima
Maxima is a free GPL'd general purpose computer algebra system whose development started in 1968 at MIT. It contains symbolic manipulation algorithms, as well as implementations of special functions, including elliptic functions and generalized hypergeometric functions. Moreover, Maxima has implementations of many functions relating to the invariant theory of the symmetric group `S_n`. (However, the commands for group invariants, and the corresponding Maxima documentation, are in French.) For many links to Maxima documentation see http://maxima.sourceforge.net/docs.shtml/.
AUTHORS:
- William Stein (2005-12): Initial version
- David Joyner: Improved documentation
- William Stein (2006-01-08): Fixed bug in parsing
- William Stein (2006-02-22): comparisons (following suggestion of David Joyner)
- William Stein (2006-02-24): *greatly* improved robustness by adding sequence numbers to IO bracketing in _eval_line
- Robert Bradshaw, Nils Bruin, Jean-Pierre Flori (2010,2011): Binary library interface
This is an abstract class implementing the functions shared between the Pexpect and library interfaces to Maxima. """
#***************************************************************************** # 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/ #***************************************************************************** from __future__ import print_function from __future__ import absolute_import from six import string_types
import os import re import sys import subprocess
from sage.env import DOT_SAGE COMMANDS_CACHE = '%s/maxima_commandlist_cache.sobj'%DOT_SAGE
from sage.misc.misc import ECL_TMP from sage.misc.multireplace import multiple_replace from sage.structure.richcmp import richcmp, rich_to_bool import sage.server.support
from .interface import (Interface, InterfaceElement, InterfaceFunctionElement, InterfaceFunction, AsciiArtString) from sage.interfaces.tab_completion import ExtraTabCompletion from sage.docs.instancedoc import instancedoc
# The Maxima "apropos" command, e.g., apropos(det) gives a list # of all identifiers that begin in a certain way. This could # maybe be useful somehow... (?) Also maxima has a lot for getting # documentation from the system -- this could also be useful.
class MaximaAbstract(ExtraTabCompletion, Interface): r""" Abstract interface to Maxima.
INPUT:
- ``name`` - string
OUTPUT: the interface
EXAMPLES:
This class should not be instantiated directly, but through its subclasses Maxima (Pexpect interface) or MaximaLib (library interface)::
sage: m = Maxima() sage: from sage.interfaces.maxima_abstract import MaximaAbstract sage: isinstance(m,MaximaAbstract) True """
def __init__(self, name='maxima_abstract'): r""" Create an instance of an abstract interface to Maxima. See ``MaximaAbstract`` for full documentation.
EXAMPLES::
sage: from sage.interfaces.maxima_abstract import MaximaAbstract sage: isinstance(maxima,MaximaAbstract) True
TESTS::
sage: from sage.interfaces.maxima_abstract import MaximaAbstract sage: loads(dumps(MaximaAbstract)) == MaximaAbstract True """
########################################### # System -- change directory, etc ########################################### def chdir(self, dir): r""" Change Maxima's current working directory.
INPUT:
- ``dir`` - string
OUTPUT: none
EXAMPLES::
sage: maxima.chdir('/') """
########################################### # Interactive help ########################################### def _command_runner(self, command, s, redirect=True): r""" Run ``command`` in a new Maxima session and return its output as an ``AsciiArtString``.
INPUT:
- ``command`` - string; function to call
- ``s`` - string; argument to the function
- ``redirect`` - boolean (default: True); if redirect is set to False, then the output of the command is not returned as a string. Instead, it behaves like os.system. This is used for interactive things like Maxima's demos. See maxima.demo?
OUTPUT:
Output of ``command(s)`` as an ``AsciiArtString`` if ``redirect`` is set to False; None otherwise.
EXAMPLES::
sage: maxima._command_runner('describe', 'gcd') -- Function: gcd (<p_1>, <p_2>, <x_1>, ...) ... """ cmd += '< /dev/null'
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # We get 4 lines of commented verbosity # every time Maxima starts, so we need to get rid of them else: subprocess.Popen(cmd, shell=True, env=env)
def help(self, s): r""" Return Maxima's help for ``s``.
INPUT:
- ``s`` - string
OUTPUT:
Maxima's help for ``s``
EXAMPLES::
sage: maxima.help('gcd') -- Function: gcd (<p_1>, <p_2>, <x_1>, ...) ... """ # Should this be implemented without launching a new Maxima session # i.e. using eval_line ?
def example(self, s): r""" Return Maxima's examples for ``s``.
INPUT:
- ``s`` - string
OUTPUT:
Maxima's examples for ``s``
EXAMPLES::
sage: maxima.example('arrays') a[n]:=n*a[n-1] a := n a n n - 1 a[0]:1 a[5] 120 a[n]:=n a[6] 6 a[4] 24 done """ # Should this be implemented without launching a new Maxima session # i.e. using eval_line ?
describe = help
def demo(self, s): r""" Run Maxima's demo for ``s``.
INPUT:
- ``s`` - string
OUTPUT: none
EXAMPLES::
sage: maxima.demo('cf') # not tested read and interpret file: .../share/maxima/5.34.1/demo/cf.dem
At the '_' prompt, type ';' and <enter> to get next demonstration. frac1:cf([1,2,3,4]) ... """ # Should this be implemented without launching a new Maxima session # i.e. using eval_line ? return self._command_runner("demo", s, redirect=False)
def completions(self, s, verbose=True): r""" Return all commands that complete the command starting with the string ``s``. This is like typing s[tab] in the Maxima interpreter.
INPUT:
- ``s`` - string
- ``verbose`` - boolean (default: True)
OUTPUT: array of strings
EXAMPLES::
sage: sorted(maxima.completions('gc', verbose=False)) ['gcd', 'gcdex', 'gcfactor', 'gctime'] """ print(s, end="") sys.stdout.flush() # in Maxima 5.19.1, apropos returns all commands that contain # the given string, instead of all commands that start with # the given string
def _commands(self, verbose=True): """ Return list of all commands defined in Maxima.
INPUT:
- ``verbose`` - boolean (default: True)
OUTPUT: array of strings
EXAMPLES::
# The output is kind of random sage: sorted(maxima._commands(verbose=False)) [... 'display', ... 'gcd', ... 'verbose', ...] """ [self.completions(chr(65+n), verbose=verbose)+ self.completions(chr(97+n), verbose=verbose) for n in range(26)], [])
def _tab_completion(self, verbose=True, use_disk_cache=True): r""" Return all Maxima commands, which is useful for tab completion.
INPUT:
- ``verbose`` - boolean (default: True)
- ``use_disk_cache`` - boolean (default: True); if set to True, try to read cached result from disk
OUTPUT: array of strings
EXAMPLES::
sage: t = maxima._tab_completion(verbose=False) sage: 'gcd' in t True sage: len(t) # random output 1840 """ except IOError: pass if verbose: print("\nBuilding Maxima 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(verbose=verbose) if verbose: print("\nDone!") self.__tab_completion = v sage.misc.persist.save(v, COMMANDS_CACHE) return v
def console(self): r""" Start the interactive Maxima console. This is a completely separate maxima session from this interface. To interact with this session, you should instead use ``maxima.interact()``.
INPUT: none
OUTPUT: none
EXAMPLES::
sage: maxima.console() # not tested (since we can't) Maxima 5.34.1 http://maxima.sourceforge.net Using Lisp ECL 13.5.1 Distributed under the GNU Public License. See the file COPYING. Dedicated to the memory of William Schelter. This is a development version of Maxima. The function bug_report() provides bug reporting information. (%i1)
::
sage: maxima.interact() # this is not tested either --> Switching to Maxima <-- maxima: 2+2 4 maxima: --> Exiting back to Sage <-- """ maxima_console()
def cputime(self, t=None): r""" Returns the amount of CPU time that this Maxima session has used.
INPUT:
- ``t`` - float (default: None); If \var{t} is not None, then it returns the difference between the current CPU time and \var{t}.
OUTPUT: float
EXAMPLES::
sage: t = maxima.cputime() sage: _ = maxima.de_solve('diff(y,x,2) + 3*x = y', ['x','y'], [1,1,1]) sage: maxima.cputime(t) # output random 0.568913 """ else:
def version(self): r""" Return the version of Maxima that Sage includes.
INPUT: none
OUTPUT: none
EXAMPLES::
sage: maxima.version() '5.39.0' """
#### # Overriding default values ###
def _assign_symbol(self): r""" Return the assign symbol in Maxima.
INPUT: none
OUTPUT: string
EXAMPLES::
sage: maxima._assign_symbol() ':' sage: maxima.eval('t : 8') '8' sage: maxima.eval('t') '8' """
def _true_symbol(self): """ Return the true symbol in Maxima.
INPUT: none
OUTPUT: string
EXAMPLES::
sage: maxima._true_symbol() 'true' sage: maxima.eval('is(2 = 2)') 'true' """
def _false_symbol(self): """ Return the false symbol in Maxima.
INPUT: none
OUTPUT: string
EXAMPLES::
sage: maxima._false_symbol() 'false' sage: maxima.eval('is(2 = 4)') 'false' """
def _equality_symbol(self): """ Returns the equality symbol in Maxima.
INPUT: none
OUTPUT: string
EXAMPLES::
sage: maxima._equality_symbol() '=' sage: var('x y') (x, y) sage: maxima(x == y) _SAGE_VAR_x=_SAGE_VAR_y """
def _inequality_symbol(self): """ Returns the inequality symbol in Maxima.
INPUT: none
OUTPUT: string
EXAMPLES::
sage: maxima._inequality_symbol() '#' sage: maxima((x != 1)) _SAGE_VAR_x#1 """
def _function_class(self): """ Return the Python class of Maxima functions.
INPUT: none
OUTPUT: type
EXAMPLES::
sage: maxima._function_class() <class 'sage.interfaces.interface.InterfaceFunction'> """ return MaximaAbstractFunction
def _object_class(self): """ Return the Python class of Maxima elements.
INPUT: none
OUTPUT: type
EXAMPLES::
sage: maxima._object_class() <class 'sage.interfaces.maxima.MaximaElement'> """ return MaximaAbstractElement
def _function_element_class(self): """ Return the Python class of Maxima functions of elements.
INPUT: none
OUTPUT: type
EXAMPLES::
sage: maxima._function_element_class() <class 'sage.interfaces.interface.InterfaceFunctionElement'> """ return MaximaAbstractFunctionElement
def _object_function_class(self): """ Return the Python class of Maxima user-defined functions.
INPUT: none
OUTPUT: type
EXAMPLES::
sage: maxima._object_function_class() <class 'sage.interfaces.maxima.MaximaElementFunction'> """ return MaximaAbstractElementFunction
#################### # Maxima functions # ####################
def function(self, args, defn, rep=None, latex=None): """ Return the Maxima function with given arguments and definition.
INPUT:
- ``args`` - a string with variable names separated by commas
- ``defn`` - a string (or Maxima expression) that defines a function of the arguments in Maxima.
- ``rep`` - an optional string; if given, this is how the function will print.
OUTPUT: Maxima function
EXAMPLES::
sage: f = maxima.function('x', 'sin(x)') sage: f(3.2) # abs tol 2e-16 -0.058374143427579909 sage: f = maxima.function('x,y', 'sin(x)+cos(y)') sage: f(2, 3.5) # abs tol 2e-16 sin(2)-0.9364566872907963 sage: f sin(x)+cos(y)
::
sage: g = f.integrate('z') sage: g (cos(y)+sin(x))*z sage: g(1,2,3) 3*(cos(2)+sin(1))
The function definition can be a Maxima object::
sage: an_expr = maxima('sin(x)*gamma(x)') sage: t = maxima.function('x', an_expr) sage: t gamma(x)*sin(x) sage: t(2) sin(2) sage: float(t(2)) 0.9092974268256817 sage: loads(t.dumps()) gamma(x)*sin(x) """ defn = str(defn) args = args.str() args = str(args)
## def display2d(self, flag=True): ## """ ## Set the flag that determines whether Maxima objects are ## printed using their 2-d ASCII art representation. When the ## maxima interface starts the default is that objects are not ## represented in 2-d.
## INPUT: ## flag -- bool (default: True)
## EXAMPLES ## sage: maxima('1/2') ## 1/2 ## sage: maxima.display2d(True) ## sage: maxima('1/2') ## 1 ## - ## 2 ## sage: maxima.display2d(False) ## """ ## self._display2d = bool(flag)
def plot2d(self, *args): r""" Plot a 2d graph using Maxima / gnuplot.
maxima.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: maxima.plot2d('sin(x)','[x,-5,5]') # not tested sage: opts = '[gnuplot_term, ps], [gnuplot_out_file, "sin-plot.eps"]' sage: maxima.plot2d('sin(x)','[x,-5,5]',opts) # not tested
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""" Plot 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 tmintmax
- ``nticks`` - int (default: 50)
- ``options`` - an optional string representing plot2d options in gnuplot format
EXAMPLES::
sage: maxima.plot2d_parametric(["sin(t)","cos(t)"], "t",[-3.1,3.1]) # not tested
::
sage: opts = '[gnuplot_preamble, "set nokey"], [gnuplot_term, ps], [gnuplot_out_file, "circle-plot.eps"]' sage: maxima.plot2d_parametric(["sin(t)","cos(t)"], "t", [-3.1,3.1], options=opts) # not tested
The eps file is saved to the current working directory.
Here is another fun plot::
sage: maxima.plot2d_parametric(["sin(5*t)","cos(11*t)"], "t", [0,2*pi()], nticks=400) # not tested """ 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 Maxima / gnuplot.
maxima.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]
- ``args`` should be of the form '[x, xmin, xmax]', '[y, ymin, ymax]', '[grid, nx, ny]', options
EXAMPLES::
sage: maxima.plot3d('1 + x^3 - y^2', '[x,-2,2]', '[y,-2,2]', '[grid,12,12]') # not tested sage: maxima.plot3d('sin(x)*cos(y)', '[x,-2,2]', '[y,-2,2]', '[grid,30,30]') # not tested sage: opts = '[gnuplot_term, ps], [gnuplot_out_file, "sin-plot.eps"]' sage: maxima.plot3d('sin(x+y)', '[x,-5,5]', '[y,-1,1]', opts) # not tested
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="u2+v2"``, ...) 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: maxima.plot3d_parametric(["v*sin(u)","v*cos(u)","v"], ["u","v"],[-3.2,3.2],[0,3]) # not tested sage: opts = '[gnuplot_term, ps], [gnuplot_out_file, "sin-cos-plot.eps"]' sage: maxima.plot3d_parametric(["v*sin(u)","v*cos(u)","v"], ["u","v"],[-3.2,3.2],[0,3],opts) # not tested
The eps file is saved in the current working directory.
Here is a torus::
sage: _ = maxima.eval("expr_1: cos(y)*(10.0+6*cos(x)); expr_2: sin(y)*(10.0+6*cos(x)); expr_3: -6*sin(x);") sage: maxima.plot3d_parametric(["expr_1","expr_2","expr_3"], ["x","y"],[0,6],[0,6]) # not tested
Here is a Möbius 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: maxima.plot3d_parametric([x,y,z],["u","v"],[-3.1,3.2],[-1/10,1/10]) # not tested """ 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 self(cmd)
def de_solve(self, 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: maxima.de_solve('diff(y,x,2) + 3*x = y', ['x','y'], [1,1,1]) y=3*x-2*%e^(x-1) sage: maxima.de_solve('diff(y,x,2) + 3*x = y', ['x','y']) y=%k1*%e^x+%k2*%e^-x+3*x sage: maxima.de_solve('diff(y,x) + 3*x = y', ['x','y']) y=(%c-3*((-x)-1)*%e^-x)*%e^x sage: maxima.de_solve('diff(y,x) + 3*x = y', ['x','y'],[1,1]) y=-%e^-1*(5*%e^x-3*%e*x-3*%e) """ else: str_vars = vars
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: maxima.clear('x'); maxima.clear('f') sage: maxima.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: maxima.clear('x'); maxima.clear('f') sage: f = maxima.de_solve_laplace("diff(f(x),x,2) = 2*diff(f(x),x)-f(x)", ["x","f"]) sage: f f(x)=x*%e^x*('at('diff(f(x),x,1),x=0))-f(0)*x*%e^x+f(0)*%e^x sage: print(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 Maxima, so subsequent ODEs involving these variables will have these initial conditions automatically imposed. """ vars[1], vars[0], vars[0], i, vars[0], ics[0], ics[1+i])
def solve_linear(self, eqns,vars): """ Wraps maxima's linsolve.
INPUT:
- ``eqns`` - a list of m strings; each representing a linear question in m = n variables
- ``vars`` - 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: maxima.solve_linear(eqns, vars) [x=a+1,y=2*a,z=a-1] """
def unit_quadratic_integer(self, n): r""" Finds a unit of the ring of integers of the quadratic number field `\QQ(\sqrt{n})`, `n>1`, using the qunit maxima command.
INPUT:
- ``n`` - an integer
EXAMPLES::
sage: u = maxima.unit_quadratic_integer(101); u a + 10 sage: u.parent() Number Field in a with defining polynomial x^2 - 101 sage: u = maxima.unit_quadratic_integer(13) sage: u 5*a + 18 sage: u.parent() Number Field in a with defining polynomial x^2 - 13 """ # Take square-free part so sqrt(n) doesn't get simplified # further by maxima # (The original version of this function would yield wrong answers if # n is not squarefree.) raise ValueError("n (=%s) must be >= 1" % n)
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 maxima plot2d options.
The points are (x1,y1), (x2,y2), etc.
This function requires maxima 5.9.2 or newer.
.. note::
More that 150 points can sometimes lead to the program hanging. Why?
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: maxima.plot_list(zeta_ptsx, zeta_ptsy) # not tested sage: opts='[gnuplot_preamble, "set nokey"], [gnuplot_term, ps], [gnuplot_out_file, "zeta.eps"]' sage: maxima.plot_list(zeta_ptsx, zeta_ptsy, opts) # not tested """ 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 maxima plot2d options.
INPUT:
- ``pts_lst`` - list of points; each point must be of the form [x,y] where ``x`` is an integer and ``y`` is a real
- ``var`` - string; representing Maxima's plot2d options
Requires maxima 5.9.2 at least.
.. note::
More that 150 points can sometimes lead to the program hanging.
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: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1],[xx,y0],[x0,yy]]) # not tested 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: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1],[xx,y0],[x0,yy]]) # not tested sage: opts='[gnuplot_preamble, "set nokey"]' sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1],[xx,y0],[x0,yy]],opts) # not tested """ 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])+']]' if options is None: self('plot2d('+cmd+')') else: self('plot2d('+cmd+','+options+')')
@instancedoc class MaximaAbstractElement(ExtraTabCompletion, InterfaceElement): r""" Element of Maxima through an abstract interface.
EXAMPLES:
Elements of this class should not be created directly. The targeted parent of a concrete inherited class should be used instead::
sage: from sage.interfaces.maxima_lib import maxima_lib sage: xp = maxima(x) sage: type(xp) <class 'sage.interfaces.maxima.MaximaElement'> sage: xl = maxima_lib(x) sage: type(xl) <class 'sage.interfaces.maxima_lib.MaximaLibElement'> """ _cached_repr = True
def __str__(self): """ Printing an object explicitly gives ASCII art.
INPUT: none
OUTPUT: string
EXAMPLES::
sage: f = maxima('1/(x-1)^3'); f 1/(x-1)^3 sage: print(f) 1 -------- 3 (x - 1) """
def bool(self): """ Convert ``self`` into a boolean.
INPUT: none
OUTPUT: boolean
EXAMPLES::
sage: maxima(0).bool() False sage: maxima(1).bool() True """
def _richcmp_(self, other, op): """ Compare this Maxima object with ``other``.
INPUT:
- ``other`` - an object to compare to
OUTPUT: boolean
EXAMPLES::
sage: a = maxima(1); b = maxima(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 = maxima('sin(x)'); g = maxima('cos(x)') sage: -f == g.diff('x') True """ # thanks to David Joyner for telling me about using "is". # but be careful, since for relations things like is(equal(a,b)) # are what Maxima needs except TypeError: pass # everything is supposed to be comparable in Python2, # so we define the comparison thus when no comparable # in interfaced system.
def _sage_(self): """ Attempt to make a native Sage object out of this Maxima object. This is useful for automatic coercions in addition to other things.
INPUT: none
OUTPUT: Sage object
EXAMPLES::
sage: a = maxima('sqrt(2) + 2.5'); a sqrt(2)+2.5 sage: b = a._sage_(); b sqrt(2) + 2.5 sage: type(b) <type 'sage.symbolic.expression.Expression'>
We illustrate an automatic coercion::
sage: c = b + sqrt(3); c sqrt(3) + sqrt(2) + 2.5 sage: type(c) <type 'sage.symbolic.expression.Expression'> sage: d = sqrt(3) + b; d sqrt(3) + sqrt(2) + 2.5 sage: type(d) <type 'sage.symbolic.expression.Expression'>
sage: a = sage.calculus.calculus.maxima('x^(sqrt(y)+%pi) + sin(%e + %pi)') sage: a._sage_() x^(pi + sqrt(y)) - sin(e) sage: var('x, y') (x, y) sage: v = sage.calculus.calculus.maxima.vandermonde_matrix([x, y, 1/2]) sage: v._sage_() [ 1 x x^2] [ 1 y y^2] [ 1 1/2 1/4]
Check if :trac:`7661` is fixed::
sage: var('delta') delta sage: (2*delta).simplify() 2*delta """ maxima=self.parent())
def _symbolic_(self, R): """ Return a symbolic expression equivalent to this Maxima object.
INPUT:
- ``R`` - symbolic ring to convert into
OUTPUT: symbolic expression
EXAMPLES::
sage: t = sqrt(2)._maxima_() sage: u = t._symbolic_(SR); u sqrt(2) sage: u.parent() Symbolic Ring
This is used when converting Maxima objects to the Symbolic Ring::
sage: SR(t) sqrt(2) """
def __complex__(self): """ Return a complex number equivalent to this Maxima object.
INPUT: none
OUTPUT: complex
EXAMPLES::
sage: complex(maxima('sqrt(-2)+1')) (1+1.4142135623730951j) """
def _complex_mpfr_field_(self, C): """ Return a mpfr complex number equivalent to this Maxima object.
INPUT:
- ``C`` - complex numbers field to convert into
OUTPUT: complex
EXAMPLES::
sage: CC(maxima('1+%i')) 1.00000000000000 + 1.00000000000000*I sage: CC(maxima('2342.23482943872+234*%i')) 2342.23482943872 + 234.000000000000*I sage: ComplexField(10)(maxima('2342.23482943872+234*%i')) 2300. + 230.*I sage: ComplexField(200)(maxima('1+%i')) 1.0000000000000000000000000000000000000000000000000000000000 + 1.0000000000000000000000000000000000000000000000000000000000*I sage: ComplexField(200)(maxima('sqrt(-2)')) 1.4142135623730950488016887242096980785696718753769480731767*I sage: N(sqrt(-2), 200) 8.0751148893563733350506651837615871941533119425962889089783e-62 + 1.4142135623730950488016887242096980785696718753769480731767*I """ return C(self._sage_())
def _mpfr_(self, R): """ Return a mpfr real number equivalent to this Maxima object.
INPUT:
- ``R`` - real numbers field to convert into
OUTPUT: real
EXAMPLES::
sage: RealField(100)(maxima('sqrt(2)+1')) 2.4142135623730950488016887242 """
def _complex_double_(self, C): """ Return a double precision complex number equivalent to this Maxima object.
INPUT:
- ``C`` - double precision complex numbers field to convert into
OUTPUT: complex
EXAMPLES::
sage: CDF(maxima('sqrt(2)+1')) 2.414213562373095 """
def _real_double_(self, R): """ Return a double precision real number equivalent to this Maxima object.
INPUT:
- ``R`` - double precision real numbers field to convert into
OUTPUT: real
EXAMPLES::
sage: RDF(maxima('sqrt(2)+1')) 2.414213562373095 """ return R(self._sage_())
def real(self): """ Return the real part of this Maxima element.
INPUT: none
OUTPUT: Maxima real
EXAMPLES::
sage: maxima('2 + (2/3)*%i').real() 2 """
def imag(self): """ Return the imaginary part of this Maxima element.
INPUT: none
OUTPUT: Maxima real
EXAMPLES::
sage: maxima('2 + (2/3)*%i').imag() 2/3 """
def numer(self): """ Return numerical approximation to self as a Maxima object.
INPUT: none
OUTPUT: Maxima object
EXAMPLES::
sage: a = maxima('sqrt(2)').numer(); a 1.41421356237309... sage: type(a) <class 'sage.interfaces.maxima.MaximaElement'> """
def str(self): """ Return string representation of this Maxima object.
INPUT: none
OUTPUT: string
EXAMPLES::
sage: maxima('sqrt(2) + 1/3').str() 'sqrt(2)+1/3' """
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 = maxima('x^2') sage: f.diff() 2*x sage: f.diff('x') 2*x sage: f.diff('x', 2) 2 sage: maxima('sin(x^2)').diff('x',4) 16*x^4*sin(x^2)-12*sin(x^2)-48*x^2*cos(x^2)
::
sage: f = maxima('x^2 + 17*y^2') sage: f.diff('x') 34*y*'diff(y,x,1)+2*x sage: f.diff('y') 34*y """
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) maxima 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: maxima('exp(-sqrt(x))').nintegral('x',0,1) (0.5284822353142306, 0.41633141378838...e-10, 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.52848223531423071361790491935415653022 # 64-bit sage: _ = gp.set_precision(80) sage: gp('intnum(x=0,1,exp(-sqrt(x)))') 0.52848223531423071361790491935415653021675547587292866196865279321015401702040079 """ limit=maximum_num_subintervals)
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
OUTPUT:
- the definite integral if xmin is not None
- an indefinite integral otherwise
EXAMPLES::
sage: maxima('x^2+1').integral() x^3/3+x sage: maxima('x^2+ 1 + y^2').integral('y') y^3/3+x^2*y+y sage: maxima('x / (x^2+1)').integral() log(x^2+1)/2 sage: maxima('1/(x^2+1)').integral() atan(x) sage: maxima('1/(x^2+1)').integral('x', 0, infinity) %pi/2 sage: maxima('x/(x^2+1)').integral('x', -1, 1) 0
::
sage: f = maxima('exp(x^2)').integral('x',0,1); f -(sqrt(%pi)*%i*erf(%i))/2 sage: f.numer() 1.46265174590718... """ else: raise ValueError("neither or both of min/max must be specified.")
integrate = integral
def __float__(self): """ Return floating point version of this Maxima element.
INPUT: none
OUTPUT: real
EXAMPLES::
sage: float(maxima("3.14")) 3.14 sage: float(maxima("1.7e+17")) 1.7e+17 sage: float(maxima("1.7e-17")) 1.7e-17 """ except ValueError: raise TypeError("unable to coerce '%s' to float"%repr(self))
def __len__(self): """ Return the length of a list.
INPUT: none
OUTPUT: integer
EXAMPLES::
sage: v = maxima('create_list(x^i,i,0,5)') sage: len(v) 6 """
def dot(self, other): """ Implements the notation self . other.
INPUT:
- ``other`` - matrix; argument to dot.
OUTPUT: Maxima matrix
EXAMPLES::
sage: A = maxima('matrix ([a1],[a2])') sage: B = maxima('matrix ([b1, b2])') sage: A.dot(B) matrix([a1*b1,a1*b2],[a2*b1,a2*b2]) """
def __getitem__(self, n): r""" Return the n-th element of this list.
INPUT:
- ``n`` - integer
OUTPUT: Maxima object
.. note::
Lists are 0-based when accessed via the Sage interface, not 1-based as they are in the Maxima interpreter.
EXAMPLES::
sage: v = maxima('create_list(i*x^i,i,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 """ # If you change the n+1 to n below, better change __iter__ as well.
def __iter__(self): """ Return an iterator for self.
INPUT: none
OUTPUT: iterator
EXAMPLES::
sage: v = maxima('create_list(i*x^i,i,0,5)') sage: L = list(v) sage: [e._sage_() for e in L] [0, x, 2*x^2, 3*x^3, 4*x^4, 5*x^5] """
def subst(self, val): """ Substitute a value or several values into this Maxima object.
INPUT:
- ``val`` - string representing substitution(s) to perform
OUTPUT: Maxima object
EXAMPLES::
sage: maxima('a^2 + 3*a + b').subst('b=2') a^2+3*a+2 sage: maxima('a^2 + 3*a + b').subst('a=17') b+340 sage: maxima('a^2 + 3*a + b').subst('a=17, b=2') 342 """
def comma(self, args): """ Form the expression that would be written 'self, args' in Maxima.
INPUT:
- ``args`` - string
OUTPUT: Maxima object
EXAMPLES::
sage: maxima('sqrt(2) + I').comma('numer') I+1.41421356237309... sage: maxima('sqrt(2) + I*a').comma('a=5') 5*I+sqrt(2) """
def _latex_(self): """ Return Latex representation of this Maxima object.
INPUT: none
OUTPUT: string
This calls the tex command in Maxima, then does a little post-processing to fix bugs in the resulting Maxima output.
EXAMPLES::
sage: maxima('sqrt(2) + 1/3 + asin(5)')._latex_() '\\sin^{-1}\\cdot5+\\sqrt{2}+{{1}\\over{3}}'
sage: y,d = var('y,d') sage: f = function('f') sage: latex(maxima(derivative(f(x*y), x))) \left(\left.{{{\it \partial}}\over{{\it \partial}\, {\it t_0}}}\,f\left({\it t_0}\right) \right|_{{\it t_0}={\it x}\, {\it y}}\right)\,{\it y} sage: latex(maxima(derivative(f(x,y,d), d,x,x,y))) {{{\it \partial}^4}\over{{\it \partial}\,{\it d}\, {\it \partial}\,{\it x}^2\,{\it \partial}\, {\it y}}}\,f\left({\it x} , {\it y} , {\it d}\right) sage: latex(maxima(d/(d-2))) {{{\it d}}\over{{\it d}-2}} """ raise RuntimeError("Error texing Maxima object.") '\\%':'', '\\arcsin ':'\\sin^{-1} ', '\\arccos ':'\\cos^{-1} ', '\\arctan ':'\\tan^{-1} ', '\\_SAGE\\_VAR\\_':''}, s)
# Fix a maxima bug, which gives a latex representation of multiplying # two numbers as a single space. This was really bad when 2*17^(1/3) # gets TeXed as '2 17^{\frac{1}{3}}' # # This regex matches a string of spaces preceded by either a '}', a # decimal digit, or a ')', and followed by a decimal digit. The spaces # get replaced by a '\cdot'.
def _tab_completion(self, verbose=False): """ Return all Maxima commands, which is useful for tab completion.
INPUT:
- ``verbose`` - boolean
OUTPUT: list of strings
EXAMPLES::
sage: m = maxima(2) sage: 'gcd' in m._tab_completion() True """
def _matrix_(self, R): r""" If self is a Maxima matrix, return the corresponding Sage matrix over the Sage ring `R`.
INPUT:
- ``R`` - ring to coerce into
OUTPUT: matrix
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: _ = maxima.eval("f[i,j] := i/j") sage: A = maxima('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 ``matrix`` command (which is defined in ``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] """ return MatrixSpace(R, 0, 0)(0) replace("]','[","','").replace('([',"['").replace('])',"']")
def partial_fraction_decomposition(self, var='x'): """ Return the partial fraction decomposition of self with respect to the variable var.
INPUT:
- ``var`` - string
OUTPUT: Maxima object
EXAMPLES::
sage: f = maxima('1/((1+x)*(x-1))') sage: f.partial_fraction_decomposition('x') 1/(2*(x-1))-1/(2*(x+1)) sage: print(f.partial_fraction_decomposition('x')) 1 1 --------- - --------- 2 (x - 1) 2 (x + 1) """
def _operation(self, operation, other=None): r""" Return the result of applying the binary operation ``operation`` on the arguments ``self`` and ``other``, or the unary operation on ``self`` if ``other`` is not given.
This is a utility function which factors out much of the commonality used in the arithmetic operations for interface elements.
INPUT:
- ``operation`` -- a string representing the operation being performed. For example, '*', or '1/'.
- ``other`` -- the other operand. If ``other`` is ``None``, then the operation is assumed to be unary rather than binary.
OUTPUT: Maxima object
Note that other's parent should already be Maxima since this should be called after coercion has been performed.
If other is a ``MaximaFunction``, then we convert ``self`` to a ``MaximaFunction`` that takes no arguments, and let the ``MaximaFunction._operation`` code handle everything from there.
EXAMPLES::
sage: f = maxima.cos(x) sage: f._operation("+", f) 2*cos(_SAGE_VAR_x) """
else: except Exception as msg: raise TypeError(msg)
MaximaAbstractFunctionElement = InterfaceFunctionElement MaximaAbstractFunction = InterfaceFunction
class MaximaAbstractElementFunction(MaximaAbstractElement): r""" Create a Maxima function with the parent ``parent``, name ``name``, definition ``defn``, arguments ``args`` and latex representation ``latex``.
INPUT:
- ``parent`` - an instance of a concrete Maxima interface
- ``name`` - string
- ``defn`` - string
- ``args`` - string; comma separated names of arguments
- ``latex`` - string
OUTPUT: Maxima function
EXAMPLES::
sage: maxima.function('x,y','e^cos(x)') e^cos(x) """
def __init__(self, parent, name, defn, args, latex): """ Create a Maxima function. See ``MaximaAbstractElementFunction`` for full documentation.
TESTS::
sage: from sage.interfaces.maxima_abstract import MaximaAbstractElementFunction sage: MaximaAbstractElementFunction == loads(dumps(MaximaAbstractElementFunction)) True sage: f = maxima.function('x,y','sin(x+y)') sage: f == loads(dumps(f)) True """
def __reduce__(self): """ Implement __reduce__ for ``MaximaAbstractElementFunction``.
INPUT: none
OUTPUT:
A couple consisting of:
- the function to call for unpickling
- a tuple of arguments for the function
EXAMPLES::
sage: f = maxima.function('x,y','sin(x+y)') sage: f.__reduce__() (<function reduce_load_MaximaAbstract_function at 0x...>, (Maxima, 'sin(x+y)', 'x,y', None)) """ self.__defn, self.__args, self.__latex)
def __call__(self, *args): """ Return the result of calling this Maxima function with the given arguments.
INPUT:
- ``args`` - a variable number of arguments
OUTPUT: Maxima object
EXAMPLES::
sage: f = maxima.function('x,y','sin(x+y)') sage: f(1,2) sin(3) sage: f(x,x) sin(2*x) """
def _repr_(self): """ Return print representation of this Maxima function.
INPUT: none
OUTPUT: string
EXAMPLES::
sage: f = maxima.function('x,y','sin(x+y)') sage: repr(f) # indirect doctest 'sin(x+y)' """
def _latex_(self): """ Return latex representation of this Maxima function.
INPUT: none
OUTPUT: string
EXAMPLES::
sage: f = maxima.function('x,y','sin(x+y)') sage: latex(f) \mathrm{sin(x+y)} """ else: return self.__latex
def arguments(self, split=True): r""" Returns the arguments of this Maxima function.
INPUT:
- ``split`` - boolean; if True return a tuple of strings, otherwise return a string of comma-separated arguments
OUTPUT:
- a string if ``split`` is False
- a list of strings if ``split`` is True
EXAMPLES::
sage: f = maxima.function('x,y','sin(x+y)') sage: f.arguments() ['x', 'y'] sage: f.arguments(split=False) 'x,y' sage: f = maxima.function('', 'sin(x)') sage: f.arguments() [] """ else:
def definition(self): """ Returns the definition of this Maxima function as a string.
INPUT: none
OUTPUT: string
EXAMPLES::
sage: f = maxima.function('x,y','sin(x+y)') sage: f.definition() 'sin(x+y)' """
def integral(self, var): """ Returns the integral of self with respect to the variable var.
INPUT:
- ``var`` - a variable
OUTPUT: Maxima function
Note that integrate is an alias of integral.
EXAMPLES::
sage: x,y = var('x,y') sage: f = maxima.function('x','sin(x)') sage: f.integral(x) -cos(x) sage: f.integral(y) sin(x)*y """ self.arguments(split=False), var))
integrate = integral
def _operation(self, operation, f=None): r""" This is a utility function which factors out much of the commonality used in the arithmetic operations for ``MaximaAbstractElementFunction``.
INPUT:
- ``operation`` - A string representing the operation being performed. For example, '\*', or '1/'.
- ``f`` - The other operand. If f is ``None``, then the operation is assumed to be unary rather than binary.
EXAMPLES::
sage: f = maxima.function('x,y','sin(x+y)') sage: f._operation("+", f) 2*sin(y+x) sage: f._operation("+", 2) sin(y+x)+2 sage: f._operation('-') -sin(y+x) sage: f._operation('1/') 1/sin(y+x) """ else:
def reduce_load_MaximaAbstract_function(parent, defn, args, latex): r""" Unpickle a Maxima function.
EXAMPLES::
sage: from sage.interfaces.maxima_abstract import reduce_load_MaximaAbstract_function sage: f = maxima.function('x,y','sin(x+y)') sage: _,args = f.__reduce__() sage: g = reduce_load_MaximaAbstract_function(*args) sage: g == f True """
def maxima_version(): """ Return Maxima version.
Currently this calls a new copy of Maxima.
EXAMPLES::
sage: from sage.interfaces.maxima_abstract import maxima_version sage: maxima_version() '5.39.0' """
def maxima_console(): """ Spawn a new Maxima command-line session.
EXAMPLES::
sage: from sage.interfaces.maxima_abstract import maxima_console sage: maxima_console() # not tested Maxima 5.34.1 http://maxima.sourceforge.net ... """ from sage.repl.rich_output.display_manager import get_display_manager if not get_display_manager().is_in_terminal(): raise RuntimeError('Can use the console only in the terminal. Try %%maxima magics instead.') os.system('maxima') |