Best Practices for converting a Mathematica expression to Julia

Are there suggestions how to convert a rather long Mathematica expression to Julia?

With Matlab I use http://library.wolfram.com/infocenter/MathSource/577/

I also would appreciate suggestions for the same problem with Sage Math

The closest thing to it is this

Use SymPy.jl. SymPy can parse Mathematica expressions, and SymPy.jl can convert SymPy expressions to Julia expressions. For example, if we define:

using SymPy
const sympy_parsing_mathematica = SymPy.PyCall.pyimport("sympy.parsing.mathematica")
mathematica2julia(s::AbstractString, substitutions::Pair{<:AbstractString,<:AbstractString}...) =
    SymPy.lambdify_expr(sympy_parsing_mathematica["mathematica"](s, Dict(substitutions...))).args[2]

then we get:

julia> mathematica2julia("Log[Log[x]]")
:(log(log(x)))

julia> mathematica2julia("Exp[Log3[x]]", "Log3[x]"=>"log(x,3)")
:(x ^ (log(3) ^ -1))

Works charmingly well… thank you!

SymataSyntax has not been upgraded for v1.0.

Ah, this stops working now for SymPy v1.0.10.

The updated code should be:

using SymPy
const sympy_parsing_mathematica = SymPy.PyCall.pyimport("sympy.parsing.mathematica")
mathematica2julia(s::AbstractString, substitutions::Pair{<:AbstractString,<:AbstractString}...) =
           SymPy.walk_expression(sympy_parsing_mathematica."mathematica"(s, Dict(substitutions...)))

You may also find https://github.com/JuliaInterop/MathLink.jl helpful.

How to replace the unknown function?Naively the following code does not work.

mathematica2julia("(Sqrt[Pi])/(2*Gamma[23/10])","Gamma"=>"gamma")

PyError ($(Expr(:escape, :(ccall(#= /Users/gangchen/.julia/packages/PyCall/ttONZ/src/pyfncall.jl:44 =# @pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, pyargsptr, kw))))) <class ‘ValueError’>
ValueError(“‘Gamma’ function form is invalid.”)
File “/Users/gangchen/.julia/conda/3/lib/python3.7/site-packages/sympy/parsing/mathematica.py”, line 17, in mathematica
parser = MathematicaParser(additional_translations)
File “/Users/gangchen/.julia/conda/3/lib/python3.7/site-packages/sympy/parsing/mathematica.py”, line 154, in init
d = self._compile_dictionary(additional_translations)
File “/Users/gangchen/.julia/conda/3/lib/python3.7/site-packages/sympy/parsing/mathematica.py”, line 187, in _compile_dictionary
raise ValueError(err)

The dictionary has to map a Mathematica function-call expression to a Python/SymPy function call:

julia> mathematica2julia("(Sqrt[Pi])/(2*Gamma[23/10])","Gamma[x]"=>"gamma(x)")
:(__prod__(1 / 2, pi ^ (1 / 2), gamma(23//10) ^ -1))

See the documentation for the sympy.parsing.mathematica.mathematica function that is being called here.

Thanks. That works well

I got a Julia expression if I do this. How to turn expression that I get into a function?

you can use SyntaxTree.jl. The genfun is useful. You can also see the examples in my UseMathLink.jl

I eventually ended up using sage and copy paste to Julia since the syntax are quite similar. The only problem I found so far is that sage convert Exp(2) from Mathematica to e^2. But I often want it written as exp(2).

I am trying to run this now, but I got some errors. I tried to fix it and I got this function

using SymPy
const sympy_parsing_mathematica = SymPy.PyCall.pyimport("sympy.parsing.mathematica")
mathematica2julia(s::AbstractString, substitutions::Pair{<:AbstractString,<:AbstractString}...) =
           SymPy.walk_expression(sympy_parsing_mathematica."parse_mathematica"(s))

When I now try, I get

mathematica2julia("(Sqrt[Pi])/(2*EllipticE[m])","EllipticE[x]"=>"elliptic_e(x)")
# :((1 / 2) * SymPy.__POW__(pi, 1 / 2) * SymPy.__POW__(EllipticE(m), -1))

My goal is to get

sqrt(pi) / (2*elliptic_e(m))

How can I get this?

You don’t really need the walk expression part, but you need to add the EllipticE function to help sympy out. This seems to work:

sympy_parsing_mathematica.mathematica(s, Dict("EllipticE[x]"=>"elliptic_e(x)"))

Thanks, but I don’t understand the suggestion.
Following what you wrote I tried to run:

sympy_parsing_mathematica.mathematica("(Sqrt[Pi])/(2*EllipticE[m])", Dict("EllipticE[x]"=>"elliptic_e(x)"))

I get a latex expression. But I actually want to get an expression I then can copy into a julia function like

Do you know how to do that?

Okay, the “POW” you are seeing was removed somewhat recently, and ^ should be used in the returned expression. You can update SymPy, or try passing in a dictionary holding the conversion, like SymPy.walk_expression(out, fns=Dict("Pow"=>:^)).

Thanks again!
But I think the substitutions do not work anyway. In this example

mathematica2julia("(Sqrt[Pi])/(2*EllipticE[m])", "EllipticE[x]"=>"elliptic_e(x)")
# :((1 / 2) * SymPy.__POW__(pi, 1 / 2) * SymPy.__POW__(EllipticE(m), -1))

I get that EllipticE[m] is not substituted by elliptic_e(m).

Github Copilot is quite good for these kind of tasks. I use it to convert from latex to Julia.