朱莉娅:我如何将符号表达式转换为函数?

时间:2014-12-08 12:02:48

标签: julia sympy

我使用SymPy包(https://github.com/jverzani/SymPy.jl)创建了一个符号表达式。我想现在使用Roots包(https://github.com/JuliaLang/Roots.jl)找到该表达式的根。但是,我无法弄清楚如何使用fzeros方法来查找根,因为这只能应用于类型为Function而不是Sym的对象,这是类型我的表达。

以下是我尝试做的一个例子。我创建了一个符号"x"和一个符号表达式sin(x)。现在让我们尝试在值-10和10之间找到sin(x)的零:

using SymPy
x = sym"x"
expr = sin(x)
using Roots
fzeros(expr,-10,10)

这是错误:

ERROR: `fzeros` has no method matching fzeros(::Sym, ::Int64, ::Int64)

如何将Sym类型的表达式转换为Function类型,以便找到根?

2 个答案:

答案 0 :(得分:4)

[更新:以下讨论在很多情况下已被最近推出的lambdify功能取代。调用lambdify(expr)创建了一个julia函数,该函数不会回调到SymPy进行评估,因此应该更快。它应该适用于大多数,但肯定不是所有的表达方式。]

这是一个两步过程:

convert(Function, expr)
在您的情况下,

将返回自由变量x的函数。但是,函数值仍然是符号的,不能与fzeros一起使用。可以猜测输入,但返回值的类型是另一个故事。但是,在这种情况下,强制浮动将起作用:

fzeros(x -> float(convert(Function, expr)), -10, 10)

(您也可以使用a -> float(replace(expr, x, a))执行此操作。)

对于这个简单示例,solve(expr)也可以使用,但一般情况下,findroot中的SymPy函数未公开,因此通过SymPy进行数字根求解不是&#39 ;没有最终用户的努力就可以解决问题。

答案 1 :(得分:0)

使用Julia 0.6,这可以直接开箱即用:

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

但它比纯Julia解决方案慢得多。 以下是我使用BenchmarkTools运行的一些基准测试:

天真的解决方案(6.8s):

fzeros(expr, -10, 10)

Pure Julia(1.5ms):

fzeros(x-> sin(x), -10, 10)

半天真(7.6ms):

fzeros(Function(expr), -10, 10)

显式转换(3.8ms):

expr2 = Function(expr)
fzeros(expr2, -10, 10)