ForwardDiff - MethodError: no method matching extract_jacobian

Hello everyone,

I’m struggling with the differentiation of some functions using the ForwardDiff package. Here is a reproducible example :

using StaticArrays
using ForwardDiff

function f_test(x)
       return exp(x[1])*sin(x[2])
end

y = SVector(0.0, 0.0) # or a random SVector

ForwardDiff.jacobian(f_test, y)

Unfortunately I get this error:

ERROR: MethodError: no method matching extract_jacobian(::Type{ForwardDiff.Tag{…}}, ::ForwardDiff.Dual{ForwardDiff.Tag{…}, Float64, 2}, ::SVector{2, Float64})

Closest candidates are:
  extract_jacobian(::Type{T}, ::StaticArray, ::S) where {T, S<:StaticArray}
   @ ForwardDiffStaticArraysExt C:\Users\Adrien VET\.julia\packages\ForwardDiff\UBbGT\ext\ForwardDiffStaticArraysExt.jl:74
  extract_jacobian(::Type{T}, ::AbstractArray, ::StaticArray) where T
   @ ForwardDiffStaticArraysExt C:\Users\Adrien VET\.julia\packages\ForwardDiff\UBbGT\ext\ForwardDiffStaticArraysExt.jl:84

Stacktrace:
 [1] vector_mode_jacobian
   @ C:\Users\Adrien VET\.julia\packages\ForwardDiff\UBbGT\ext\ForwardDiffStaticArraysExt.jl:91 [inlined]
 [2] jacobian(f::typeof(f_test), x::SVector{2, Float64})
   @ ForwardDiffStaticArraysExt C:\Users\Adrien VET\.julia\packages\ForwardDiff\UBbGT\ext\ForwardDiffStaticArraysExt.jl:66
 [3] top-level scope
   @ REPL[99]:1
Some type information was truncated. Use `show(err)` to see complete types.

I don’t get why I have this error. I see in the docstring that the function to differentiate has to take an AbstractArray and output an AbstractArray ; and every SVector is indeed an AbstractArray

Alright, quick response lol. I just figured out my problem by reading this post again. The output HAS to be an abstract vector, and my function output was a Float which is NOT an abstract vector.

To fix the problem you have to output something like (SVector(exp(x[1])*sin(x[2]))) which is a 1-element SVector{1, Float64}.

This topic can be closed

1 Like

Alternatively (as also hinted to in ?ForwardDiff.jacobian), you can get the 1 \times n Jacobian of a scalar-valued function f at an n-D point x via ForwardDiff.gradient(f, x), though the Jacobian will then be represented as a length-n Vector. If you want size(...) == (1, n), you can always just transpose it.

using StaticArrays
using ForwardDiff

function f_test(x)
       return exp(x[1])*sin(x[2])
end

y = SVector(0.0, 0.0) # or a random SVector

ForwardDiff.gradient(f_test, y)'
# 1×2 adjoint(::SVector{2, Float64}) with eltype Float64 with indices SOneTo(1)×SOneTo(2):
#  0.0  1.0
1 Like

ForwardDiff will usually friendly errors when you use the wrong function:

julia> ForwardDiff.jacobian(f_test, [0.0, 0.0])
ERROR: DimensionMismatch: jacobian(f, x) expects that f(x) is an array. Perhaps you meant gradient(f, x)?
...

julia> ForwardDiff.gradient(f_test, [0.0, 0.0])
2-element Vector{Float64}:
 0.0
 1.0

The fact that you get an internal error instead with StaticArrays is arguably a bug, perhaps make an issue?