ForwardDiff failing on simple polynomial


#1

Hello everybody,

I am trying to use ForwardDiff for a project, but I am having problems getting it to work even for a simple case. Please see screen scrape below. It’s entirely possible I don’t know exactly how to use ForwardDiff, so I am appealing for help in case I am doing something wrong.

Note that I have played around for a while with different types just in case something fiddly is happening, but I haven’t found a magic set of Float64s and Ints which appease the gradient method.

Is it possible that when I installed ForwardDiff, I got an obsolete version of the package?

Thanks for your insights,
Stuart

julia> using ForwardDiff

julia> g = x::Vector -> 1 + 2.0x + 3.0x.^2.0
(::#1) (generic function with 1 method)

julia> phi = x -> ForwardDiff.gradient(g, x)
(::#3) (generic function with 1 method)

julia> y = [2.0, 3.0, 4.0]
3-element Array{Float64,1}:
2.0
3.0
4.0

julia> g(y)
3-element Array{Float64,1}:
17.0
34.0
57.0

julia> phi(y)
ERROR: MethodError: no method matching extract_gradient!(::Array{Array{ForwardDiff.Dual{3,Float64},1},1}, ::Array{ForwardDiff.Dual{3,Float64},1})
Closest candidates are:
extract_gradient!(::AbstractArray{T,N}, ::ForwardDiff.Dual{N,T<:Real}) at /home/sbrorson/.julia/v0.5/ForwardDiff/src/gradient.jl:40
extract_gradient!(::AbstractArray{T,N}, ::Real) at /home/sbrorson/.julia/v0.5/ForwardDiff/src/gradient.jl:39
in vector_mode_gradient(::##1#2, ::Array{Float64,1}, ::ForwardDiff.GradientConfig{3,Float64,Array{ForwardDiff.Dual{3,Float64},1}}) at /home/sbrorson/.julia/v0.5/ForwardDiff/src/gradient.jl:62
in gradient(::##1#2, ::Array{Float64,1}, ::ForwardDiff.GradientConfig{3,Float64,Array{ForwardDiff.Dual{3,Float64},1}}) at /home/sbrorson/.julia/v0.5/ForwardDiff/src/gradient.jl:7
in gradient(::##1#2, ::Array{Float64,1}) at /home/sbrorson/.julia/v0.5/ForwardDiff/src/gradient.jl:6
in (::##3#4)(::Array{Float64,1}) at ./REPL[3]:1

julia> versioninfo()
Julia Version 0.5.0-rc4+0
Commit 9c76c3e* (2016-09-09 01:43 UTC)
Platform Info:
System: Linux (x86_64-redhat-linux)
CPU: Intel® Core™ i5-3320M CPU @ 2.60GHz
WORD_SIZE: 64
BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Sandybridge)
LAPACK: libopenblas64_
LIBM: libopenlibm
LLVM: libLLVM-3.7.1 (ORCJIT, ivybridge)


#2

The answer is in the documentation for gradient: (type ? into the repl to access the documentation)

help?> ForwardDiff.gradient
  ForwardDiff.gradient(f, x::AbstractArray, cfg::GradientConfig = GradientConfig(f, x))

  Return ∇f evaluated at x, assuming f is called as f(x).

  This method assumes that isa(f(x), Real).

The method assumes the return of g is a Real. The gradient operator is most commonly used to represent the differential of a function of the form: f: \mathbb R^n \to \mathbb R .

Your g returns a vector- try instead using the jacobian function:

julia> g = x::Vector -> 1 + 2.0x + 3.0x.^2.0
(::#1) (generic function with 1 method)

julia> phi = x-> ForwardDiff.jacobian(g,x)
(::#5) (generic function with 1 method)

julia> y = [2.0, 3.0, 4.0]
3-element Array{Float64,1}:
 2.0
 3.0
 4.0

julia> phi(y)
3×3 Array{Float64,2}:
 14.0   0.0   0.0
  0.0  20.0   0.0
  0.0   0.0  26.0