I have created a symbolic expression using the SymPy package (https://github.com/jverzani/SymPy.jl). I want to now find the roots of that expression using the Roots package
With Julia 0.6 this works straight out of box:
julia> using SymPy, Roots
julia> x = Sym("x")
x
julia> expr = sin(x)
sin(x)
julia> fzeros(expr, -10, 10)
7-element Array{Float64,1}:
-9.42478
-6.28319
-3.14159
0.0
3.14159
6.28319
9.42478
But it's a lot slower than pure Julia solution.
Here are some benchmarks I ran with BenchmarkTools
:
Naive Solution (6.8s):
fzeros(expr, -10, 10)
Pure Julia (1.5ms):
fzeros(x-> sin(x), -10, 10)
Semi-Naive (7.6ms):
fzeros(Function(expr), -10, 10)
Explicit Conversion (3.8ms):
expr2 = Function(expr)
fzeros(expr2, -10, 10)
[UPDATE: The discussion below has been superseded in many cases by the recently introduced lambdify
function. The call lambdify(expr)
creates a julia function that does not call back into SymPy to evaluate, so should be much faster. It should work for most, but certainly not all, expressions.]
It is a two step process:
convert(Function, expr)
will return a function of the free variables, x
, in your case. However, the function values are still symbolic and can't be used with fzeros
. The inputs can be guessed, but the type of the return value is another story. However, coercing to float will work in this case:
fzeros(x -> float(convert(Function, expr)), -10, 10)
(You could also do this with a -> float(replace(expr, x, a))
.)
For this simple example solve(expr)
will also work, but in general, the findroot
function in SymPy
is not exposed, so numeric root solving via SymPy
isn't a workaround without some effort by the end-users.