Directional derivative with automatic differentiation

Hello,

I would like to compute the directional derivative of a vector-valued function f at a point x along the direction v, i.e. \nabla f(x) \cdot v using ForwardDiff.jl.
From what I understood, it is possible to compute this with a single Dual vector whose field value is to x and whose dual values are set to v.

Can someone walk me through this implementation with Dual numbers? I am getting the good result, but I still end up summing the entries of the Jacobian (hence forming the Jacobian =( ). What is a better way to implement this directional derivative?

using ForwardDiff
import ForwardDiff: seed!

function f(x)
    @show "call"
    return [2.0*x[1] + x[2]^3 + x[3]^2; 3.0*x[2] + x[3]^2]  
end

x = rand(10)
v = rand(10)
y = zero(x)

cfg = ForwardDiff.GradientConfig(f, x)
xdual = cfg.duals
# Create seeds along the direction v
seeds = ntuple(j -> ForwardDiff.Partials(ntuple(i-> i==j ? v[i] : 0.0, N)), N)

seed!(xdual, x, seeds)

ydual = f(xdual)

Jv = ForwardDiff.jacobian(f, x)*v

@show norm(Jv[1] - sum(ydual[1].partials))
@show norm(Jv[2] - sum(ydual[2].partials))
2 Likes

See SparseDiffTools.jl/jaches_products.jl at master · JuliaDiff/SparseDiffTools.jl · GitHub

1 Like

Thank you Chris for your answer!

The directional derivative at x along d is also just:

ForwardDiff.derivative(t -> f(x + t * d), 0.0)
4 Likes

Also, FWIW: Directional derivatives · Issue #428 · JuliaDiff/ForwardDiff.jl · GitHub