Econ
Econ

Reputation: 1145

ForwardDiff.jl and ReverseDiff.jl error message related to ::getfield()

I am attempting to use the ForwardDiff.jl and / or ReverseDiff.jl libraries for computing the gradient in an optimization problem.

Both of these packages give me an error message related to ::getfield().

ReverseDiff gives me a LoadError:

 MethodError: no method matching (::getfield(CalibrationModule, Symbol("#f#4"))
 {AlgorithmParameters,ModelParameters,Guess,Array{Float64,1}})
 (::ReverseDiff.TrackedArray{Float64,Float64,1,Array{Float64,1},Array{Float64,1}})

ForwardDiff gives me a LoadError:

 MethodError: no method matching (::getfield(CalibrationModule, Symbol("#f#10"))
 {AlgorithmParameters,ModelParameters,Guess,Array{Float64,1}})
 (::Array{ForwardDiff.Dual{ForwardDiff.Tag{getfield(CalibrationModule,
 Symbol("#f#10"))     
 {AlgorithmParameters,ModelParameters,Guess,Array{Float64,1}},Float64},Float64,6},1})

I have no idea how to make sense of this error message. My code is too complicated to post here, but as far as I can tell I am not using any libraries not written in Julia. I do extensively use custom data types (mutable structs) throughout, but I don't see why this would cause a problem...

Upvotes: 1

Views: 972

Answers (2)

mbauman
mbauman

Reputation: 31362

Really hard to say without code, but:

A printout like (::getfield(CalibrationModule, Symbol(...)){...}(...) is how Julia displays anonymous functions and closures. You're getting a method error that this anonymous function or closure doesn't support a signature that takes an Array with either Dual or Tracked numbers. You probably have a function along the lines of:

function main()
    ...
    f(A::Array{Float64}) = # ... some closure
    ...
    f(...)
end

But the both ForwardDiff and ReverseDiff require running your program with dual or tracked numbers — which aren't Float64. So you're getting a method error that your closure named f doesn't accept arrays of these dual or tracked numbers.

Reduce the specificity of your f closure to the widest thing it can support — likely something like f(A::AbstractArray{<:Number}) = .... Note that the two libraries do this slightly differently — ForwardDiff creates an array of Duals whereas ReverseDiff creates a tracked array of floating point numbers. Thus you want both ::AbstractArray to support more than just Arrays (you should almost always do this unless you're calling C) and you want to loosen the element type to be any subtype of Number. I'd recommend going even further and not care about the element type — you often don't need to care about it.

Upvotes: 2

0xm4r
0xm4r

Reputation: 548

From the Julia docs, the MethodError: no method matching is thrown when there is no method with a matching type signature to the one you are calling. Julia has a dynamic type system but allows for type annotations that throw an exception if a value is not of the expected type. Since you are extensively using custom data types, it may be the case that you are passing in a value of custom data type to a method in ForwardDiff/ReverseDiff that expects a different type - hard to confirm without seeing the code but that's where I'd start looking.

Upvotes: 1

Related Questions