JuliaDiff / FiniteDiff.jl

Fast non-allocating calculations of gradients, Jacobians, and Hessians with sparsity support
Other
241 stars 39 forks source link

GradientCache method in README doesn't exist #141

Closed DanielVandH closed 1 year ago

DanielVandH commented 1 year ago

The README lists the following method (df should also be fx, actually)

FiniteDiff.GradientCache(
    c1         :: Union{Nothing,AbstractArray{<:Number}},
    c2         :: Union{Nothing,AbstractArray{<:Number}},
    fx         :: Union{Nothing,<:Number,AbstractArray{<:Number}} = nothing,
    fdtype     :: Type{T1} = Val{:central},
    returntype :: Type{T2} = eltype(df),
    inplace    :: Type{Val{T3}} = Val{true})

for a non-allocating gradient cache constructor. I don't think this method exists?:

julia> FiniteDiff.GradientCache(zeros(2), zeros(2), zeros(2), Val(:central), Float64, Val(true))
ERROR: MethodError: no method matching FiniteDiff.GradientCache(::Vector{Float64}, ::Vector{Float64}, ::Vector{Float64}, ::Val{:central}, ::Type{Float64}, ::Val{true})
Closest candidates are:
  FiniteDiff.GradientCache(::Any, ::Any, ::Any, ::Any, ::Any) at C:\Users\licer\.julia\packages\FiniteDiff\KkXlb\src\gradients.jl:8
  FiniteDiff.GradientCache(::Any, ::Any, ::Any, ::Any) at C:\Users\licer\.julia\packages\FiniteDiff\KkXlb\src\gradients.jl:8
  FiniteDiff.GradientCache(::Any, ::Any, ::Any) at C:\Users\licer\.julia\packages\FiniteDiff\KkXlb\src\gradients.jl:8
julia> methods(FiniteDiff.GradientCache)
# 4 methods for type constructor:
[1] FiniteDiff.GradientCache(df, x) in FiniteDiff at C:\Users\licer\.julia\packages\FiniteDiff\KkXlb\src\gradients.jl:8
[2] FiniteDiff.GradientCache(df, x, fdtype) in FiniteDiff at C:\Users\licer\.julia\packages\FiniteDiff\KkXlb\src\gradients.jl:8
[3] FiniteDiff.GradientCache(df, x, fdtype, returntype) in FiniteDiff at C:\Users\licer\.julia\packages\FiniteDiff\KkXlb\src\gradients.jl:8
[4] FiniteDiff.GradientCache(df, x, fdtype, returntype, inplace) in FiniteDiff at C:\Users\licer\.julia\packages\FiniteDiff\KkXlb\src\gradients.jl:8

Is there an alternative method to be using if I want to get a non-allocating cache?

ChrisRackauckas commented 1 year ago

Looks like it's actually missing because https://github.com/JuliaDiff/FiniteDiff.jl/blob/master/src/gradients.jl#L8-L13 is the only constructor other than the default, and the default is a little nasty to use with how it takes in types. Looks like that needs to be added and a test.

We should also convert this whole package to real docs, but that's a bit more.

DanielVandH commented 1 year ago

Yeah, I was just thinking about documentation. It's a bit hard to pick out what each part of the cache is for initially.

If I understand it correctly, is this the type of usage you're expecting from this method (if it existed)?

"""
    GradientCache(c1, c2, fx, fdtype, returntype, inplace)

Non-allocating cache constructor for computing a gradient.

# Arguments 
- `c1, c2`: (Non-aliased) caches for the input vector.
- `fx=nothing`: Cache function call.
- `fdtype=Val(:central)`: Method used for computing the gradient.
- `returntype=eltype(df)`: Element type returned from the function call.
- `inplace=Val(true)`: Indicator of whether the function is computed in-place or not.

For example, the cache for a function `f(x) = x[1]^2 + x[2]` might be defined via 
\```julia
julia> c1, c2 = zeros(2), zeros(2)
julia> fx = f(c1)
julia> cache = GradientCache(c1, c2, fx, Val(:central), Float64, Val(true))
\```
"""
function FiniteDiff.GradientCache(
    c1,
    c2,
    fx=nothing,
    fdtype=Val(:central),
    returntype=eltype(fx),
    inplace=Val(true)) 
    # ... construct the cache ...
end

Maybe I'm misunderstanding the way these caches are used. Also - what is the usage of Val here? I've never used it before working through some of this package.

ChrisRackauckas commented 1 year ago

Yes, I think it also picked up a c3 along the way too, so it needs another in there, but that's correct.

The Val types convert runtime values to type information, allowing compile-time checks. This allows branches for things like :forward to compile away for fast code (only really matters on small arrays).