"""
Mathematica code printer
"""
from __future__ import print_function, division
from sympy.printing.codeprinter import CodePrinter
from sympy.printing.precedence import precedence
from sympy.printing.str import StrPrinter
# Used in MCodePrinter._print_Function(self)
known_functions = {
"exp": [(lambda x: True, "Exp")],
"log": [(lambda x: True, "Log")],
"sin": [(lambda x: True, "Sin")],
"cos": [(lambda x: True, "Cos")],
"tan": [(lambda x: True, "Tan")],
"cot": [(lambda x: True, "Cot")],
"asin": [(lambda x: True, "ArcSin")],
"acos": [(lambda x: True, "ArcCos")],
"atan": [(lambda x: True, "ArcTan")],
"sinh": [(lambda x: True, "Sinh")],
"cosh": [(lambda x: True, "Cosh")],
"tanh": [(lambda x: True, "Tanh")],
"coth": [(lambda x: True, "Coth")],
"sech": [(lambda x: True, "Sech")],
"csch": [(lambda x: True, "Csch")],
"asinh": [(lambda x: True, "ArcSinh")],
"acosh": [(lambda x: True, "ArcCosh")],
"atanh": [(lambda x: True, "ArcTanh")],
"acoth": [(lambda x: True, "ArcCoth")],
"asech": [(lambda x: True, "ArcSech")],
"acsch": [(lambda x: True, "ArcCsch")],
"conjugate": [(lambda x: True, "Conjugate")],
"Max": [(lambda *x: True, "Max")],
"Min": [(lambda *x: True, "Min")],
}
[docs]class MCodePrinter(CodePrinter):
"""A printer to convert python expressions to
strings of the Wolfram's Mathematica code
"""
printmethod = "_mcode"
language = "Wolfram Language"
_default_settings = {
'order': None,
'full_prec': 'auto',
'precision': 15,
'user_functions': {},
'human': True,
'allow_unknown_functions': False,
}
_number_symbols = set()
_not_supported = set()
def __init__(self, settings={}):
"""Register function mappings supplied by user"""
CodePrinter.__init__(self, settings)
self.known_functions = dict(known_functions)
userfuncs = settings.get('user_functions', {}).copy()
for k, v in userfuncs.items():
if not isinstance(v, list):
userfuncs[k] = [(lambda *x: True, v)]
self.known_functions.update(userfuncs)
def _format_code(self, lines):
return lines
def _print_Pow(self, expr):
PREC = precedence(expr)
return '%s^%s' % (self.parenthesize(expr.base, PREC),
self.parenthesize(expr.exp, PREC))
def _print_Mul(self, expr):
PREC = precedence(expr)
c, nc = expr.args_cnc()
res = super(MCodePrinter, self)._print_Mul(expr.func(*c))
if nc:
res += '*'
res += '**'.join(self.parenthesize(a, PREC) for a in nc)
return res
# Primitive numbers
def _print_Zero(self, expr):
return '0'
def _print_One(self, expr):
return '1'
def _print_NegativeOne(self, expr):
return '-1'
def _print_half(self, expr):
return '1/2'
def _print_ImaginaryUnit(self, expr):
return 'I'
# Infinity and invalid numbers
def _print_Infinity(self, expr):
return 'Infinity'
def _print_NegativeInfinity(self, expr):
return '-Infinity'
def _print_ComplexInfinity(self, expr):
return 'ComplexInfinity'
def _print_NaN(self, expr):
return 'Indeterminate'
# Mathematical constants
def _print_Exp1(self, expr):
return 'E'
def _print_Pi(self, expr):
return 'Pi'
def _print_GoldenRatio(self, expr):
return 'GoldenRatio'
def _print_TribonacciConstant(self, expr):
return self.doprint(expr._eval_expand_func())
def _print_EulerGamma(self, expr):
return 'EulerGamma'
def _print_Catalan(self, expr):
return 'Catalan'
def _print_list(self, expr):
return '{' + ', '.join(self.doprint(a) for a in expr) + '}'
_print_tuple = _print_list
_print_Tuple = _print_list
def _print_ImmutableDenseMatrix(self, expr):
return self.doprint(expr.tolist())
def _print_ImmutableSparseMatrix(self, expr):
from sympy.core.compatibility import default_sort_key
def print_rule(pos, val):
return '{} -> {}'.format(
self.doprint((pos[0]+1, pos[1]+1)), self.doprint(val))
def print_data():
items = sorted(expr._smat.items(), key=default_sort_key)
return '{' + \
', '.join(print_rule(k, v) for k, v in items) + \
'}'
def print_dims():
return self.doprint(expr.shape)
return 'SparseArray[{}, {}]'.format(print_data(), print_dims())
def _print_ImmutableDenseNDimArray(self, expr):
return self.doprint(expr.tolist())
def _print_ImmutableSparseNDimArray(self, expr):
def print_string_list(string_list):
return '{' + ', '.join(a for a in string_list) + '}'
def to_mathematica_index(*args):
"""Helper function to change Python style indexing to
Pathematica indexing.
Python indexing (0, 1 ... n-1)
-> Mathematica indexing (1, 2 ... n)
"""
return tuple(i + 1 for i in args)
def print_rule(pos, val):
"""Helper function to print a rule of Mathematica"""
return '{} -> {}'.format(self.doprint(pos), self.doprint(val))
def print_data():
"""Helper function to print data part of Mathematica
sparse array.
It uses the fourth notation ``SparseArray[data,{d1,d2,...}]``
from
https://reference.wolfram.com/language/ref/SparseArray.html
``data`` must be formatted with rule.
"""
return print_string_list(
[print_rule(
to_mathematica_index(*(expr._get_tuple_index(key))),
value)
for key, value in sorted(expr._sparse_array.items())]
)
def print_dims():
"""Helper function to print dimensions part of Mathematica
sparse array.
It uses the fourth notation ``SparseArray[data,{d1,d2,...}]``
from
https://reference.wolfram.com/language/ref/SparseArray.html
"""
return self.doprint(expr.shape)
return 'SparseArray[{}, {}]'.format(print_data(), print_dims())
def _print_Function(self, expr):
if expr.func.__name__ in self.known_functions:
cond_mfunc = self.known_functions[expr.func.__name__]
for cond, mfunc in cond_mfunc:
if cond(*expr.args):
return "%s[%s]" % (mfunc, self.stringify(expr.args, ", "))
return expr.func.__name__ + "[%s]" % self.stringify(expr.args, ", ")
_print_MinMaxBase = _print_Function
def _print_Integral(self, expr):
if len(expr.variables) == 1 and not expr.limits[0][1:]:
args = [expr.args[0], expr.variables[0]]
else:
args = expr.args
return "Hold[Integrate[" + ', '.join(self.doprint(a) for a in args) + "]]"
def _print_Sum(self, expr):
return "Hold[Sum[" + ', '.join(self.doprint(a) for a in expr.args) + "]]"
def _print_Derivative(self, expr):
dexpr = expr.expr
dvars = [i[0] if i[1] == 1 else i for i in expr.variable_count]
return "Hold[D[" + ', '.join(self.doprint(a) for a in [dexpr] + dvars) + "]]"
def _get_comment(self, text):
return "(* {} *)".format(text)
[docs]def mathematica_code(expr, **settings):
r"""Converts an expr to a string of the Wolfram Mathematica code
Examples
========
>>> from sympy import mathematica_code as mcode, symbols, sin
>>> x = symbols('x')
>>> mcode(sin(x).series(x).removeO())
'(1/120)*x^5 - 1/6*x^3 + x'
"""
return MCodePrinter(settings).doprint(expr)