Jacobians

The supertype Jacobian comprises different ways of taking Jacobians:

We first start by showing JacobianAutodiff:

# the input and output dimensions of this function are the same
F(y::AbstractArray, x::AbstractArray, params) = y .= tanh.(x)
dim = 3
x = rand(dim)
jac = JacobianAutodiff{eltype(x)}(F, dim)
JacobianAutodiff{Float64, typeof(Main.F), ForwardDiff.JacobianConfig{Nothing, Float64, 3, Tuple{Vector{ForwardDiff.Dual{Nothing, Float64, 3}}, Vector{ForwardDiff.Dual{Nothing, Float64, 3}}}}, Vector{Float64}}(Main.F, ForwardDiff.JacobianConfig{Nothing, Float64, 3, Tuple{Vector{ForwardDiff.Dual{Nothing, Float64, 3}}, Vector{ForwardDiff.Dual{Nothing, Float64, 3}}}}((Partials(1.0, 0.0, 0.0), Partials(0.0, 1.0, 0.0), Partials(0.0, 0.0, 1.0)), (ForwardDiff.Dual{Nothing, Float64, 3}[Dual{Nothing}(6.93188590959606e-310,6.93188586060886e-310,6.9318859204663e-310,6.93188586842063e-310), Dual{Nothing}(6.9318858690665e-310,6.93188592200146e-310,6.9318859220236e-310,6.9318858682993e-310), Dual{Nothing}(6.9318858569919e-310,6.9318858597385e-310,6.93188586221833e-310,6.93188592108606e-310)], ForwardDiff.Dual{Nothing, Float64, 3}[Dual{Nothing}(6.9318858577567e-310,6.9318858569773e-310,6.93188585697333e-310,6.93188585696543e-310), Dual{Nothing}(6.93188585696147e-310,6.93188585695713e-310,6.93188585698124e-310,6.9318858569413e-310), Dual{Nothing}(6.931885856933e-310,6.93188585692827e-310,6.9318858569093e-310,6.93188585692353e-310)])), [0.0, 0.0, 0.0])

Instead of calling JacobianAutodiff(f, x) we can equivalently do:

jac = Jacobian{eltype(x)}(F, dim; mode = :autodiff)
JacobianAutodiff{Float64, typeof(Main.F), ForwardDiff.JacobianConfig{Nothing, Float64, 3, Tuple{Vector{ForwardDiff.Dual{Nothing, Float64, 3}}, Vector{ForwardDiff.Dual{Nothing, Float64, 3}}}}, Vector{Float64}}(Main.F, ForwardDiff.JacobianConfig{Nothing, Float64, 3, Tuple{Vector{ForwardDiff.Dual{Nothing, Float64, 3}}, Vector{ForwardDiff.Dual{Nothing, Float64, 3}}}}((Partials(1.0, 0.0, 0.0), Partials(0.0, 1.0, 0.0), Partials(0.0, 0.0, 1.0)), (ForwardDiff.Dual{Nothing, Float64, 3}[Dual{Nothing}(6.9318858577567e-310,6.9318858569773e-310,6.93188585697333e-310,6.93188585696543e-310), Dual{Nothing}(6.93188585696147e-310,6.93188585695713e-310,6.93188585698124e-310,6.9318858569413e-310), Dual{Nothing}(6.931885856933e-310,6.93188585692827e-310,6.9318858569093e-310,6.93188585692353e-310)], ForwardDiff.Dual{Nothing, Float64, 3}[Dual{Nothing}(6.93188586009345e-310,6.93188585732313e-310,6.9318858578492e-310,6.93188585783854e-310), Dual{Nothing}(6.9318858827264e-310,6.93188585999543e-310,6.93188583160444e-310,6.9318858608899e-310), Dual{Nothing}(6.93188587294983e-310,6.93188586976924e-310,6.93188587824187e-310,6.931885882709e-310)])), [0.0, 0.0, 0.0])

When calling an instance of Jacobian we can use the function [compute_jacobian!]:

params = nothing
j = zeros(dim, dim)
compute_jacobian!(j, x, jac, params)
3×3 Matrix{Float64}:
 0.770907  0.0       0.0
 0.0       0.721643  0.0
 0.0       0.0       0.493302

This is equivalent to calling:

jac(j, x, params)
3×3 Matrix{Float64}:
 0.770907  0.0       0.0
 0.0       0.721643  0.0
 0.0       0.0       0.493302