Thanks. Never heard of this Github Copilot.
Do you have an example of how you use it? It seems like a powerful thing.
Though it would be nice to find a julia solution…
Thanks. Never heard of this Github Copilot.
Do you have an example of how you use it? It seems like a powerful thing.
Though it would be nice to find a julia solution…
Here is something you can copy and paste to see if it works for you:
using SymPy
const sympy_parsing_mathematica = SymPy.PyCall.pyimport("sympy.parsing.mathematica")
s = "(Sqrt[Pi])/(2*EllipticE[m])"
ex = sympy_parsing_mathematica.mathematica(s, Dict("EllipticE[x]"=>"elliptic_e(x)"))
SymPy.walk_expression(ex) #:((1 / 2) * pi ^ (1 / 2) * elliptic_e(m) ^ -1)
# or
SymPy.convert_expr(ex, use_julia_code=true) # :(sqrt(pi) ./ (2 * elliptic_e(m)))
That is phenomenal!
Some things still do not work as expected, though.
The walk_expression
gives me something different, and I do not know why:
s = "(Sqrt[Pi])/(2*EllipticE[m])"
ex = sympy_parsing_mathematica.mathematica(s, Dict("EllipticE[x]"=>"elliptic_e(x)"))
SymPy.walk_expression(ex) # what I should get :((1 / 2) * pi ^ (1 / 2) * elliptic_e(m) ^ -1)
# what I get is
# :((1 / 2) * SymPy.__POW__(pi, 1 / 2) * SymPy.__POW__(elliptic_e(m), -1))
I can fix it using
SymPy.walk_expression(ex, fns=Dict("Pow"=>:^))
# :((1 / 2) * pi ^ (1 / 2) * elliptic_e(m) ^ -1)
The convert_expr
does not work well.
First, I do not like that it returns all operations with the vectorized dot notion like so
:(sqrt(pi) ./ (2 * elliptic_e(m)))
The more problematic issue is that it does not deal with this expression for some reason
s = "Sqrt[2]/q2 EllipticF[x, 1 - q1^2/q2^2]"
ex = sympy_parsing_mathematica.mathematica(s, Dict("EllipticF[x, y]"=>"elliptic_e(x, y)"))
SymPy.convert_expr(ex, use_julia_code=true)
gives
Base.Meta.ParseError("use \"x^y\" instead of \"x**y\" for exponentiation, and \"x...\" instead of \"**x\" for splatting.")
Stacktrace:
[1] #parse#3
@ ./meta.jl:236 [inlined]
[2] parse
@ ./meta.jl:232 [inlined]
[3] parse(str::String; raise::Bool, depwarn::Bool)
@ Base.Meta ./meta.jl:267
[4] parse(str::String)
@ Base.Meta ./meta.jl:266
[5] convert_expr(ex::Sym; fns::Dict{Any, Any}, values::Dict{Any, Any}, use_julia_code::Bool)
@ SymPy ~/.julia/packages/SymPy/mpN0u/src/lambdify.jl:260
[6] top-level scope
@ In[37]:5
Sorry, convert_expr
has some issues like this, hence the need for walk_expression
. However, I realize I had some unpushed changes that are causing the differences you see with my example with walk_expression
. I just made a PR, which I hope to tag once all the tests pass.
Thanks again!
I see that the walk_expression
does not know how to handle sqrt
and it gives a power of 1/2
instead as can be seen here
Is there a way to get the sqrt
from the walk_expression
?
(The convert_expr
gives sqrt
, but as you said it has some issues).
Let me also mention for completeness that in the first time I run these functions I get the following warning:
sys:1: SymPyDeprecationWarning:
The ``mathematica`` function for the Mathematica parser is now
deprecated. Use ``parse_mathematica`` instead.
The parameter ``additional_translation`` can be replaced by SymPy's
.replace( ) or .subs( ) methods on the output expression instead.
See https://docs.sympy.org/latest/explanation/active-deprecations.html#mathematica-parser-new
for details.
This has been deprecated since SymPy version 1.11. It
will be removed in a future version of SymPy.
Thanks. Looks like a need to update my sympy library!
Anyways, I just registered a fix to lambdify
that should also give back sqrt
, as you wanted.
Great. I saw that the sqrt
was fixed!
Just mentioning that the issue with convert_expr
is still there:
And also, this issue is still thereL
I extended @gangchern’s example to a package (GitHub - musoke/WolframExpr.jl). It’s bare bones, but does the basics of converting algebraic expressions from Mathematica to Julia. You can define mappings for special functions.
Example:
julia> using WolframExpr
julia> f = string_to_function("A[x,y]+y", [:A, :x, :y]);
julia> A(x, y) = x^2 + y^2;
julia> f(A, 1, 2)
7
Running now on Julia 1.9.3, with SymPy v2.0.1
, it does not have convert_expr
and walk_expression
.
Does anyone know what is the alternative to these functions?
They are buried behind another module now. For ex
coming from sympy_parsing_mathematica.mathematica
try:
SymPy.SymPyCore.walk_expression(Sym(ex))
Wonderful! that indeed works! thanks so much!
I have an issue with the //
operation. The expression I get from sympy does not have parenthesis around the numbers, which causes then an error when I copy the expression into a function.
Here is an example:
using SymPy
const sympy_parsing_mathematica = SymPy.PyCall.pyimport("sympy.parsing.mathematica")
s = raw"1/Sqrt[(x+y)^3]"
ex = sympy_parsing_mathematica.mathematica(s)
SymPy.SymPyCore.walk_expression(Sym(ex))
# :(((x + y) ^ 3) ^ -1//2)
# my goal is to take the above output and make a function out of it.
# I want to do it often, so I want to automate it as much as possible.
# defining
ftest(x, y) = (((x + y) ^ 3) ^ -1//2)
# then results in an error
ftest(1, 1)
Here is the error:
MethodError: no method matching //(::Float64, ::Int64)
Closest candidates are:
//(::Integer, ::Integer)
@ Base rational.jl:62
//(::Rational, ::Integer)
@ Base rational.jl:64
//(::Complex, ::Real)
@ Base rational.jl:78
...
Stacktrace:
[1] ftest(x::Int64, y::Int64)
@ Main ./In[58]:1
[2] top-level scope
@ In[59]:1
Putting parenthesis around the //
operation will solve it, but I want to do it automatically in the parsing. Is there a way to do that?
I have found some resolution using @generated
macro:
s = raw"1/Sqrt[(x+y)^3]"
ex = sympy_parsing_mathematica.mathematica(s)
f_expr = SymPy.SymPyCore.walk_expression(Sym(ex))
# :(((x + y) ^ 3) ^ -1//2)
@generated ftest(x,y) = f_expr
ftest(1,0)
# 1.
UPDATE:
Let me mention that SymPyCore is not needed anymore, and one should use f_expr = SymPy.walk_expression(Sym(ex))
in the above code.
Looks like there’s still a long way to go, but MathLink.jl now has W2JuliaExpr
. Its approach looks roughly similar to WolframExpr.jl, which certainly has lighter dependencies, but maybe closer integration with Wolfram could enable more flexible transformations.