Introduction

Build Status

FastDifferentiation (FD) is a package for generating efficient executables to evaluate derivatives of Julia functions. It can also generate efficient true symbolic derivatives for symbolic analysis. Unlike forward and reverse mode automatic differentiation FD automatically generates efficient derivatives for arbitrary function types: ℝ¹->ℝ¹, ℝ¹->ℝᵐ, ℝⁿ->ℝ¹, and ℝⁿ->ℝᵐ.

For f:ℝⁿ->ℝᵐ with n,m large FD may have better performance than conventional AD algorithms because the FD algorithm finds expressions shared between partials and computes them only once. In some cases FD derivatives can be as efficient as manually coded derivatives (see the Lagrangian dynamics example in the D* paper or the Benchmarks section of the documentation for another example).

FD may take much less time to compute symbolic derivatives than Symbolics.jl even in the ℝ¹->ℝ¹ case. The executables generated by FD may also be much faster (see Symbolic Processing).

As of version 0.4.0 FD allows you to create expressions with conditionals:


julia> @variables x y
y

julia> f = ifelse(x<y,x,y)
(ifelse  (x < y) x y)

julia> a = make_function([f],[x,y])

julia> a(1.0,2.0)
1-element Vector{Float64}:
 1.0

julia> a(2.0,1.0)
1-element Vector{Float64}:
 2.0

Howver, you cannot yet compute derivatives of expressions that contain conditionals:

julia> jacobian([f],[x,y])
ERROR: Your expression contained ifelse. FastDifferentiation does not yet support differentiation through ifelse or any of these conditionals (max, min, copysign, &, |, xor, <, >, <=, >=, !=, ==, signbit, isreal, iszero, isfinite, isnan, isinf, isinteger, !)

This may be a breaking change for some users. In previous versions x==y returned a Bool whereas in 0.4.0 and up it returns an FD expression. Some data structures, such as Dict use == by default to determine if two entries are the same. This will no longer work since x==y will not return a Bool. Use an IDict instead since this uses ===.

A future PR will add support for differentiating through conditionals.

You should consider using FastDifferentiation when you need:

  • a fast executable for evaluating the derivative of a function and the overhead of the preprocessing/compilation time is swamped by evaluation time.
  • to do additional symbolic processing on your derivative. FD can generate a true symbolic derivative to be processed further in Symbolics.jl or another computer algebra system.

This is the FD feature set:

Dense JacobianSparse JacobianDense HessianSparse HessianHigher order derivativesJᵀvHv
Compiled function
Symbolic expression

Jᵀv and Jv compute the Jacobian transpose times a vector and the Jacobian times a vector, without explicitly forming the Jacobian matrix. For applications see this paper.

Hv computes the Hessian times a vector without explicitly forming the Hessian matrix. This can be useful when the Hessian matrix is large and sparse.

If you use FD in your work please share the functions you differentiate with me. I'll add them to the benchmarks. The more functions available to test the easier it is for others to determine if FD will help with their problem.

Notes about special derivatives

The derivative of |u| is u/|u| which is NaN when u==0. This is not a bug. The derivative of the absolute value function is undefined at 0 and the way FD signals this is by returning NaN.