| | """ |
| | Maple code printer |
| | |
| | The MapleCodePrinter converts single SymPy expressions into single |
| | Maple expressions, using the functions defined in the Maple objects where possible. |
| | |
| | |
| | FIXME: This module is still under actively developed. Some functions may be not completed. |
| | """ |
| |
|
| | from sympy.core import S |
| | from sympy.core.numbers import Integer, IntegerConstant, equal_valued |
| | from sympy.printing.codeprinter import CodePrinter |
| | from sympy.printing.precedence import precedence, PRECEDENCE |
| |
|
| | import sympy |
| |
|
| | _known_func_same_name = ( |
| | 'sin', 'cos', 'tan', 'sec', 'csc', 'cot', 'sinh', 'cosh', 'tanh', 'sech', |
| | 'csch', 'coth', 'exp', 'floor', 'factorial', 'bernoulli', 'euler', |
| | 'fibonacci', 'gcd', 'lcm', 'conjugate', 'Ci', 'Chi', 'Ei', 'Li', 'Si', 'Shi', |
| | 'erf', 'erfc', 'harmonic', 'LambertW', |
| | 'sqrt', |
| | ) |
| |
|
| | known_functions = { |
| | |
| | 'Abs': 'abs', |
| | 'log': 'ln', |
| | 'asin': 'arcsin', |
| | 'acos': 'arccos', |
| | 'atan': 'arctan', |
| | 'asec': 'arcsec', |
| | 'acsc': 'arccsc', |
| | 'acot': 'arccot', |
| | 'asinh': 'arcsinh', |
| | 'acosh': 'arccosh', |
| | 'atanh': 'arctanh', |
| | 'asech': 'arcsech', |
| | 'acsch': 'arccsch', |
| | 'acoth': 'arccoth', |
| | 'ceiling': 'ceil', |
| | 'Max' : 'max', |
| | 'Min' : 'min', |
| |
|
| | 'factorial2': 'doublefactorial', |
| | 'RisingFactorial': 'pochhammer', |
| | 'besseli': 'BesselI', |
| | 'besselj': 'BesselJ', |
| | 'besselk': 'BesselK', |
| | 'bessely': 'BesselY', |
| | 'hankelh1': 'HankelH1', |
| | 'hankelh2': 'HankelH2', |
| | 'airyai': 'AiryAi', |
| | 'airybi': 'AiryBi', |
| | 'appellf1': 'AppellF1', |
| | 'fresnelc': 'FresnelC', |
| | 'fresnels': 'FresnelS', |
| | 'lerchphi' : 'LerchPhi', |
| | } |
| |
|
| | for _func in _known_func_same_name: |
| | known_functions[_func] = _func |
| |
|
| | number_symbols = { |
| | |
| | S.Pi: 'Pi', |
| | S.Exp1: 'exp(1)', |
| | S.Catalan: 'Catalan', |
| | S.EulerGamma: 'gamma', |
| | S.GoldenRatio: '(1/2 + (1/2)*sqrt(5))' |
| | } |
| |
|
| | spec_relational_ops = { |
| | |
| | '==': '=', |
| | '!=': '<>' |
| | } |
| |
|
| | not_supported_symbol = [ |
| | S.ComplexInfinity |
| | ] |
| |
|
| | class MapleCodePrinter(CodePrinter): |
| | """ |
| | Printer which converts a SymPy expression into a maple code. |
| | """ |
| | printmethod = "_maple" |
| | language = "maple" |
| |
|
| | _operators = { |
| | 'and': 'and', |
| | 'or': 'or', |
| | 'not': 'not ', |
| | } |
| |
|
| | _default_settings = dict(CodePrinter._default_settings, **{ |
| | 'inline': True, |
| | 'allow_unknown_functions': True, |
| | }) |
| |
|
| | def __init__(self, settings=None): |
| | if settings is None: |
| | settings = {} |
| | super().__init__(settings) |
| | self.known_functions = dict(known_functions) |
| | userfuncs = settings.get('user_functions', {}) |
| | self.known_functions.update(userfuncs) |
| |
|
| | def _get_statement(self, codestring): |
| | return "%s;" % codestring |
| |
|
| | def _get_comment(self, text): |
| | return "# {}".format(text) |
| |
|
| | def _declare_number_const(self, name, value): |
| | return "{} := {};".format(name, |
| | value.evalf(self._settings['precision'])) |
| |
|
| | def _format_code(self, lines): |
| | return lines |
| |
|
| | def _print_tuple(self, expr): |
| | return self._print(list(expr)) |
| |
|
| | def _print_Tuple(self, expr): |
| | return self._print(list(expr)) |
| |
|
| | def _print_Assignment(self, expr): |
| | lhs = self._print(expr.lhs) |
| | rhs = self._print(expr.rhs) |
| | return "{lhs} := {rhs}".format(lhs=lhs, rhs=rhs) |
| |
|
| | def _print_Pow(self, expr, **kwargs): |
| | PREC = precedence(expr) |
| | if equal_valued(expr.exp, -1): |
| | return '1/%s' % (self.parenthesize(expr.base, PREC)) |
| | elif equal_valued(expr.exp, 0.5): |
| | return 'sqrt(%s)' % self._print(expr.base) |
| | elif equal_valued(expr.exp, -0.5): |
| | return '1/sqrt(%s)' % self._print(expr.base) |
| | else: |
| | return '{base}^{exp}'.format( |
| | base=self.parenthesize(expr.base, PREC), |
| | exp=self.parenthesize(expr.exp, PREC)) |
| |
|
| | def _print_Piecewise(self, expr): |
| | if (expr.args[-1].cond is not True) and (expr.args[-1].cond != S.BooleanTrue): |
| | |
| | |
| | raise ValueError("All Piecewise expressions must contain an " |
| | "(expr, True) statement to be used as a default " |
| | "condition. Without one, the generated " |
| | "expression may not evaluate to anything under " |
| | "some condition.") |
| | _coup_list = [ |
| | ("{c}, {e}".format(c=self._print(c), |
| | e=self._print(e)) if c is not True and c is not S.BooleanTrue else "{e}".format( |
| | e=self._print(e))) |
| | for e, c in expr.args] |
| | _inbrace = ', '.join(_coup_list) |
| | return 'piecewise({_inbrace})'.format(_inbrace=_inbrace) |
| |
|
| | def _print_Rational(self, expr): |
| | p, q = int(expr.p), int(expr.q) |
| | return "{p}/{q}".format(p=str(p), q=str(q)) |
| |
|
| | def _print_Relational(self, expr): |
| | PREC=precedence(expr) |
| | lhs_code = self.parenthesize(expr.lhs, PREC) |
| | rhs_code = self.parenthesize(expr.rhs, PREC) |
| | op = expr.rel_op |
| | if op in spec_relational_ops: |
| | op = spec_relational_ops[op] |
| | return "{lhs} {rel_op} {rhs}".format(lhs=lhs_code, rel_op=op, rhs=rhs_code) |
| |
|
| | def _print_NumberSymbol(self, expr): |
| | return number_symbols[expr] |
| |
|
| | def _print_NegativeInfinity(self, expr): |
| | return '-infinity' |
| |
|
| | def _print_Infinity(self, expr): |
| | return 'infinity' |
| |
|
| | def _print_BooleanTrue(self, expr): |
| | return "true" |
| |
|
| | def _print_BooleanFalse(self, expr): |
| | return "false" |
| |
|
| | def _print_bool(self, expr): |
| | return 'true' if expr else 'false' |
| |
|
| | def _print_NaN(self, expr): |
| | return 'undefined' |
| |
|
| | def _get_matrix(self, expr, sparse=False): |
| | if S.Zero in expr.shape: |
| | _strM = 'Matrix([], storage = {storage})'.format( |
| | storage='sparse' if sparse else 'rectangular') |
| | else: |
| | _strM = 'Matrix({list}, storage = {storage})'.format( |
| | list=self._print(expr.tolist()), |
| | storage='sparse' if sparse else 'rectangular') |
| | return _strM |
| |
|
| | def _print_MatrixElement(self, expr): |
| | return "{parent}[{i_maple}, {j_maple}]".format( |
| | parent=self.parenthesize(expr.parent, PRECEDENCE["Atom"], strict=True), |
| | i_maple=self._print(expr.i + 1), |
| | j_maple=self._print(expr.j + 1)) |
| |
|
| | def _print_MatrixBase(self, expr): |
| | return self._get_matrix(expr, sparse=False) |
| |
|
| | def _print_SparseRepMatrix(self, expr): |
| | return self._get_matrix(expr, sparse=True) |
| |
|
| | def _print_Identity(self, expr): |
| | if isinstance(expr.rows, (Integer, IntegerConstant)): |
| | return self._print(sympy.SparseMatrix(expr)) |
| | else: |
| | return "Matrix({var_size}, shape = identity)".format(var_size=self._print(expr.rows)) |
| |
|
| | def _print_MatMul(self, expr): |
| | PREC=precedence(expr) |
| | _fact_list = list(expr.args) |
| | _const = None |
| | if not isinstance(_fact_list[0], (sympy.MatrixBase, sympy.MatrixExpr, |
| | sympy.MatrixSlice, sympy.MatrixSymbol)): |
| | _const, _fact_list = _fact_list[0], _fact_list[1:] |
| |
|
| | if _const is None or _const == 1: |
| | return '.'.join(self.parenthesize(_m, PREC) for _m in _fact_list) |
| | else: |
| | return '{c}*{m}'.format(c=_const, m='.'.join(self.parenthesize(_m, PREC) for _m in _fact_list)) |
| |
|
| | def _print_MatPow(self, expr): |
| | |
| | return 'MatrixPower({A}, {n})'.format(A=self._print(expr.base), n=self._print(expr.exp)) |
| |
|
| | def _print_HadamardProduct(self, expr): |
| | PREC = precedence(expr) |
| | _fact_list = list(expr.args) |
| | return '*'.join(self.parenthesize(_m, PREC) for _m in _fact_list) |
| |
|
| | def _print_Derivative(self, expr): |
| | _f, (_var, _order) = expr.args |
| |
|
| | if _order != 1: |
| | _second_arg = '{var}${order}'.format(var=self._print(_var), |
| | order=self._print(_order)) |
| | else: |
| | _second_arg = '{var}'.format(var=self._print(_var)) |
| | return 'diff({func_expr}, {sec_arg})'.format(func_expr=self._print(_f), sec_arg=_second_arg) |
| |
|
| |
|
| | def maple_code(expr, assign_to=None, **settings): |
| | r"""Converts ``expr`` to a string of Maple code. |
| | |
| | Parameters |
| | ========== |
| | |
| | expr : Expr |
| | A SymPy expression to be converted. |
| | assign_to : optional |
| | When given, the argument is used as the name of the variable to which |
| | the expression is assigned. Can be a string, ``Symbol``, |
| | ``MatrixSymbol``, or ``Indexed`` type. This can be helpful for |
| | expressions that generate multi-line statements. |
| | precision : integer, optional |
| | The precision for numbers such as pi [default=16]. |
| | user_functions : dict, optional |
| | A dictionary where keys are ``FunctionClass`` instances and values are |
| | their string representations. Alternatively, the dictionary value can |
| | be a list of tuples i.e. [(argument_test, cfunction_string)]. See |
| | below for examples. |
| | human : bool, optional |
| | If True, the result is a single string that may contain some constant |
| | declarations for the number symbols. If False, the same information is |
| | returned in a tuple of (symbols_to_declare, not_supported_functions, |
| | code_text). [default=True]. |
| | contract: bool, optional |
| | If True, ``Indexed`` instances are assumed to obey tensor contraction |
| | rules and the corresponding nested loops over indices are generated. |
| | Setting contract=False will not generate loops, instead the user is |
| | responsible to provide values for the indices in the code. |
| | [default=True]. |
| | inline: bool, optional |
| | If True, we try to create single-statement code instead of multiple |
| | statements. [default=True]. |
| | |
| | """ |
| | return MapleCodePrinter(settings).doprint(expr, assign_to) |
| |
|
| |
|
| | def print_maple_code(expr, **settings): |
| | """Prints the Maple representation of the given expression. |
| | |
| | See :func:`maple_code` for the meaning of the optional arguments. |
| | |
| | Examples |
| | ======== |
| | |
| | >>> from sympy import print_maple_code, symbols |
| | >>> x, y = symbols('x y') |
| | >>> print_maple_code(x, assign_to=y) |
| | y := x |
| | """ |
| | print(maple_code(expr, **settings)) |
| |
|