How it works
FD is a domain specific language (DSL) embedded in Julia. FD defines a custom Number
type and nd overloads all the mathematical operators in Base to apply to this new number type. You create FD numbers using either @variables
or make_variables
.
Mathematical operations on FD numbers create a graph representing the mathematical expression rather than immediately returning a floating point value. For example, in this code fragment
@variables x y
f(a,b)= cos(a)*sin(b)
myexpr = f(x,y)
myexpr
contains a graph representation of the cos(x)*sin(y)
where x,y
are FD numbers.
For the most part there is no difference between using FD numbers and the base number types, Float64
, Int64
, etc. You define your Julia function as you normally world and then call it with FD numbers as inputs; the return value will be a graph representing the expression your Julia function computes.
The FD differentiation functions, jacobian
, hessian
, etc., take FD expression graphs as inputs and return FD expression graphs. To turn this into executable Julia code you pass an FD expression graph as an argument to make_function
.
All the FD differntiation functions use derivative graph factorization[2] to compute derivatives. The FD differentiation algorithm is related to the D* algorithm but is asymptotically faster so it works on much larger expression graphs. The new algorithms used in FD will be described in a soon to be written paper. FD automatic differentiaion is fundamentally different from forward and reverse automatic differentiation.
The efficiency of FD comes from analysis of the graph structure of the function rather than sophisticated algebraic simplification rules. By default FD applies only these algebraic simplications[1] to expressions:
x×0=>0
x×1=>x
x/1=>x
x+0=>x
c₁×c₂=>c₃
forc₁,c₂,c₃
constantsc₁+c₂=>c₃
forc₁,c₂,c₃
constantsc₁×(c₂×x)
=>(c₁×c₂)×x
forc₁,c₂
constants
These rules are generally safe in the sense of obeying IEEE floating point arithmetic rules. However if the runtime value of x
happens to be NaN or Inf the FD expression x*0
will identically return 0, because it will have been rewritten to 0 by the simplification rules. The expected IEEE result is NaN.