Search code examples
pythonwolfram-mathematica

How to implement a function with Python(Sympy), realizing the same as ToExpression in Wolfram Mathematica?


In Wolfram Mathematica, I can use ToExpression to convert a string to an expression, and evaluate the expression.

An example:

Reflection[expr_, a_] := expr /. a[l_] -> I*a[-l]
StringA = "Reflection[a[0]b[3],b]"
Output=ToExpression[StringA]

the result is ia[0]b[-3]

However, I don't know how to realize such thing in Python (or Sympy).

import numpy as np
import sympy as sp

a, b, c, d, e, f=map(sp.IndexedBase,['a','b','c','d','e', 'f'])  
l1=map(sp.Wild,['l1'])
imagI=sp.I ## equals to Imaginary

def Reflection(expr, p):
    expr=imagI*expr.replace(p[l1],p[-l1], map=False, simultaneous=True, exact=False)
    return expr

fundict={'Reflection':Reflection}
pdict={'a':a,'b':b,'c':c,'d':d,'e':e,'f':f}  ##A dictionary used for connect the string to existed variable
mydict=dict(fundict,**pdict) ## combine two dictionary

StringA ='Reflection(a(0)b(3),b)'

How to realize the same work as the ToExpression does?

And more complicated case:

Reflection[expr_, a_] := expr /. a[l_] -> I*a[-l]
OAMHolo[expr_, a_, n_] := expr /. a[l_] -> a[l + n]

StringA = "Reflection[OAMHolo[Reflection[a[0]b[3],b],a,3],b]"
Output=ToExpression[StringA]

The output is -a[3]b[3]

For the python cases, I tried exec(), replace() but these don't work. So how to realize this case in Python? Thank you very much!


Solution

  • sympify converts a string into an expression. To use custom objects in sympify, pass them as a dictionary to the second argument.

    Here is your example (I also fixed some minor bugs)

    >>> l1 = Wild('l1')
    >>> StringA = 'Reflection(a[0]*b[3], b)'
    >>> sympify(StringA, mydict)
    I*a[0]*b[-3]
    

    Regarding sympify vs. eval, sympify uses eval internally. It is a littler smarter,

    • sympify('1/2') will produce Rational(1, 2) whereas eval('1/2') produces 0.5.
    • sympify also automatically converts any undefined variables in the expression into Symbol or Function, whereas eval does not.
    • sympify automatically evaluates the expression in the SymPy namespace, so any SymPy function will automatically be defined (with eval you have to either import the name manually or add it to a dictionary as the second argument)
    • In the future sympify may become better than eval in terms of security (see https://github.com/sympy/sympy/pull/12524). For now, both can execute arbitrary code, so they are unsafe to use on untrusted input.

    The performance of either should be negligible. So I would recommend using sympify rather than eval to create SymPy expressions.