Документация Engee

Автоматическое преобразование кода Julia в функции C

Поскольку Symbolics.jl может выполнять трассировку кода Julia в IR Symbolics, который может быть собран и скомпилирован с помощью build_function в C, мы получаем отличный способ автоматической генерации функций C из кода Julia. Чтобы увидеть это в действии, начнем с уравнений Лотки-Вольтерра:

using Symbolics
function lotka_volterra!(du, u, p, t)
  x, y = u
  α, β, δ, γ = p
  du[1] = dx = α*x - β*x*y
  du[2] = dy = -δ*y + γ*x*y
end
lotka_volterra! (generic function with 1 method)

Теперь выполним трассировку в Symbolics:

@variables t du[1:2] u[1:2] p[1:4]
du = collect(du)
lotka_volterra!(du, u, p, t)
du
2-element Vector{Num}:
  p[1]*u[1] - p[2]*u[1]*u[2]
 -p[3]*u[2] + p[4]*u[1]*u[2]

а затем создадим функцию:

build_function(du, u, p, t, target=Symbolics.CTarget())
"#include <math.h>\nvoid diffeqf(double* du, const double* RHS1, const double* RHS2, const double RHS3) {\n  du[0] = RHS2[0] * RHS1[0] + -1 * RHS2[1] * RHS1[0] * RHS1[1];\n  du[1] = -1 * RHS2[2] * RHS1[1] + RHS2[3] * RHS1[0] * RHS1[1];\n}\n"

Чтобы скомпилировать, выполним expression=Val{false}:

f = build_function(du, u, p, t, target=Symbolics.CTarget(), expression=Val{false})
RuntimeGeneratedFunction(#=in Symbolics=#, #=using Symbolics=#, :((du, u, p, t)->begin
          #= /root/.julia/packages/Symbolics/gBKZv/src/build_function.jl:801 =#
          ccall(("diffeqf", "/tmp/jl_0Fw7IP496t"), Cvoid, (Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Float64), du, u, p, t)
      end))

Теперь проверим, что вычисляется то же самое:

du = rand(2); du2 = rand(2)
u = rand(2)
p = rand(4)
t = rand()
f(du, u, p, t)
lotka_volterra!(du2, u, p, t)
du == du2 # верно!
true