JuliaDiff / JuliaDiff/ForwardDiff.jl

hessian!(::ImmutableDiffResult, f, ::StaticArray) errors when f does not depend on its argument

Open
#846 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Julia
Stars
1k
Forks
160
PR merge metrics
No merged PRs in 30d

Description

hessian!(::ImmutableDiffResult, f, ::StaticArray) errors outright whenever f returns no Dual of its own tag.

using ForwardDiff, StaticArrays, DiffResults
sx = SVector(1.0, 2.0, 3.0)

# (a) constant `f`
ForwardDiff.hessian!(DiffResults.HessianResult(sx), z -> 2.0, sx)
# ERROR: DimensionMismatch: No precise constructor for SMatrix{3, 3, Float64, 9} found.
#        Size of input was (0, 3).

# (b) `f` constant in `z` but carrying an enclosing tag
ForwardDiff.derivative(1.0) do a
    r = ForwardDiff.hessian!(DiffResults.HessianResult(sx), z -> a * 2.0, sx)
    DiffResults.value(r)
end
# ERROR: MethodError: no method matching extract_jacobian(::Type{Tag{…}}, ::Dual{…}, ::SVector{3, Float64})

Every other path handles both fine — hessian(f, sx), hessian!(::Matrix, f, sx) and hessian(f, ::Vector) all return a 3×3 zero Hessian, and the nested forms of those return 0.0.

Cause

The method extracts with extract_jacobian(T, partials(T, fd2), x), and extract_jacobian(::Type{T}, ydual::Union{StaticArray,Partials}, x) assumes partials(T, fd2) has one entry per input. It does not when f returns no Dual{T}:

  • a constant gives Partials{0}, so the result is built at size (0, N) and the SMatrix constructor rejects it;
  • a Dual{S} with S ≺ T gives zero(d), a bare Dual, which matches no method at all.

Suggested fix

Dispatch on the result rather than on its partials, returning a zero length(x) × length(x) Hessian when there is no differentiated layer to read — a constant f, an empty x, and a result that carries only an enclosing tag all fall under the same rule.

Version: ForwardDiff master (v1.4.5), Julia 1.12.7, StaticArrays 1.9.19.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the hessian! implementation path that calls extract_jacobian(T, partials(T, fd2), x), then trace how constant results and enclosing-tag Dual results are handled. Add regression coverage for both examples, including the empty-input case, and verify that each produces the expected zero Hessian or nested scalar result.

Written by the indexing model from the issue text.

Assessment

Tech stack
julia
Domain
backend-api-design
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.