Derivative of a Symbolic Expression as a Symbol Valued Function

julia> using Symbolics

julia> @variables a3, a2, a1, a0, t
5-element Vector{Num}:
 a3
 a2
 a1
 a0
 t

julia> f0(t) = a3*t^3 + a2*t^2 + a1*t + a0
f0 (generic function with 1 method)

julia> f1Gen = Differential(t)(f0(t))
Differential(t)(a0 + a1*t + a2*(t^2) + a3*(t^3))

julia> f1Exp = expand_derivatives(f1Gen)
a1 + 2a2*t + 3a3*(t^2)

julia> f1 = Symbolics.build_function(f1Exp, t)
:(function (t,)
      #= F:\Users\Redacted\.julia\packages\SymbolicUtils\9iQGH\src\code.jl:282 =#
      #= F:\Users\Redacted\.julia\packages\SymbolicUtils\9iQGH\src\code.jl:283 =#
      (+)(a1, (*)(2, a2, t), (*)(3, a3, (^)(t, 2)))
  end)

julia> eval(f1)(0)
a1

I wanted to take the symbolic derivative of a symbolic expression and then evaluate it at a numerical value of the argument producing a symbolic expression.

This solution seems to work, but violated my expectations (having written a lot of code for other CAS (Computer Algebra Systems)). It feels clunky, but I can imagine that with a little practice it might feel natural. Am I missing some shortcut?

The fact that

julia> f1Not(t) = expand_derivatives(f1Gen)
f1Not (generic function with 1 method)

produces something that looks right

julia> f1Not(t)
a1 + 2a2*t + 3a3*(t^2)

but is wrong

julia> f1Not(0)
a1 + 2a2*t + 3a3*(t^2)

created quite a bit of confusion for me.

The fact that f0 is naturally the right type of expression may have increased my expectation that expand_derivatives could be induced to return the desired function directly.

julia> f0(0)
a0

My desire is to call some sort of “compile” step when creating a numerical valued function from a symbolic expression, because interpretation is too slow. But when producing a symbol valued function it seems that interpretation might be better … Maybe that’s incompatible with the Julia way …

Note that you could have done Symbolics.derivative(f1Exp,t)

Instead of creating a function you can just solve it by interpretation by using substitute and substituting in numerical values.

You created a function that returns a constant.

This provided the desired symmetry to build_funciton.

The user knows which they want, and when … seems like a good system.

Didn’t catch on the first time around, because a type-o, led me to the wrong inference.

No worries, we probably still need a bunch more work on the docs.

  • I’m not complaining, but yea, the documentation assumes too much context.
  • I wish I could write some documentation for you, but I’m still figure things out.
  • Maybe after I actually get some interesting amount of my own code to work.

You should complain about the docs, they need work :laughing:

Perhaps. But I always fear the complaints won’t end up at “The Documentation Department”. :thinking: