On Apr 28, 2016 7:15 AM, "Ben Lauwens" <[email protected]> wrote: > > Hi > > I like to create automatically functions that evaluates the total derivative of a function with respect to time, eg. > given f(t, x1, x2) = t^2+x1*x2, I want to obtain df/dt(t,x1,x2,dx1/dt,dx2/dt) = 2t+x1*dx2/dt+x2*dx1/dt, d2f/dt2(t,x1,x2,dx1/dt,dx2/dt,d2x1/dt2,d2x2/dt) = 2+2dx1/dt*dx2/dt+x1*d2x2/dt2+x2*d2x1/dt2, and so on. > The initial function is specified as a string as are the arguments. > The following code using the Calculus package works nicely: > using Calculus > > function total_derivatives_with_respect_to_time(f::AbstractString, order::Int, names::AbstractString...) > derivs = Array(Function, order) > n = length(names) > args = AbstractString["t", names...] > derivs[1] = eval(parse("($(reduce((a,b)->"$a,$b",args)))->$f")) > if order > 1 > fun = f > for o = 2:order > ∇fun = differentiate(fun, args) > dfun = AbstractString["$(∇fun[1])"] > for i = 1:n > push!(args, "d$(o-1)_$(names[i])") > end > for j = 2:(o-1)*n+1 > push!(dfun, "($(∇fun[j])) * $(args[j+n])") > end > fun = reduce((a,b)->"$a + $b", dfun) > derivs[o] = eval(parse("($(reduce((a,b)->"$a,$b",args)))->$fun")) > end > end > return derivs > end > > derivs = total_derivatives_with_respect_to_time("t^2+x1*x2", 3, "x1", "x2") > println(derivs[1](1.0, 2.0, 3.0)) > println(derivs[2](1.0, 2.0, 3.0, 4.0, 5.0)) > println(derivs[3](1.0, 2.0, 3.0, 4.0, 5.0, -1.0, -2.0))
For calculating derivatives there may be better ways (forwarddiff and other packages). In general, generating functions with eval is fine as long as you dont do that in the performance critical part. However, you should never use parse and should construct the AST directly. > I have however the feeling that I am abusing the sequence of eval and parse to automatically generate anonymous function. Is there a way to do this more elegantly? Performance wise the code runs fine in Julia v0.5. > > Ben
