I am trying to use ReverseDiff.jl and ForwardDiff.jl as a mixed mode AD approach to computing a Hessian vector product. I am using the following function:

import ForwardDiff as fdiff
import ReverseDiff as rdiff
function _hvp(f::F, x::S, v::S) where {F, S<:AbstractVector{<:AbstractFloat}}
dual = fdiff.Dual.(x,v)
return fdiff.partials.(rdiff.gradient(f, dual), 1)
end

but this is not giving me the expected output. See below for a simple example.

A = randn(2,2)
f(x) = x'*A*x
x = randn(2)
v = randn(2)
_hvp(f,x,v) â (A+A')*v #returns false

What is the correct way to compose these two packages?

The code you posted works for me (assuming Dual, gradient, and partials all come from ForwardDiff.jl):

julia> using ForwardDiff: Dual, gradient, partials
julia> function _hvp(f::F, x::S, v::S) where {F, S<:AbstractVector{<:AbstractFloat}}
dual = Dual.(x, v)
return partials.(gradient(f, dual), 1)
end
_hvp (generic function with 1 method)
julia> A = randn(2, 2); x = randn(2); v = randn(2);
julia> f(x) = x' * A * x
f (generic function with 1 method)
julia> _hvp(f, x, v) â (A + A') * v
true

Itâs not clear from your post where the interplay between ForwardDiff.jl and ReverseDiff.jl comes in. Could you elaborate?

Thanks, in my reading of this thread it only seems related in that both the ForwardDiff.jl and ReverseDiff.jl packages are being used, but there is nothing dealing with the composition of them. I think there is perhaps an ambiguity in the term âmixed modeâ. In the referenced thread, the poster just wants to obtain the gradient by combining two different modes, whereas I want higher order derivatives using mixed-mode AD. If I am missing something feel free to point it out.

Ah, yes, apologies for the ambiguity. I updated the question to clarify, but I want to use ReverseDiff.gradient. The goal is to have a forward-over-back approach, where ReverseDiff.jl is handling the backward mode. If I were to use Zygote.gradient instead, then the posted code would work.