Open wesselb opened 6 years ago
Did you an API for this in mind?
Given we have grad(fdm, f, x::Vector)
for scalar function f(x::Vector)
https://github.com/JuliaDiff/FiniteDifferences.jl/blob/287a26186bc58cfba3f7d5a977bbb759b74cf871/src/grad.jl#L8
we could have
function grad(fdm, f, x::Vector{T}, i::Integer) where T<:Real
v = zeros(T, size(x))
v[i] = one(T)
dx = fdm(ϵ -> f(x .+ ϵ .* v), zero(T))
return dx
end
this is obviously better than computing all the partials then selecting the one you want... but maybe you had something nicer in mind?
julia> f(x) = x[1]^2 * x[2] + x[3];
julia> xs = randn(3);
julia> h = [1e-6, 0.0, 0.0];
julia> _fdm = central_fdm(3, 1);
julia> @btime ($f($xs + $h) - $f($xs - $h)) / (2 * $h[1])
73.728 ns (2 allocations: 224 bytes)
-0.1254986907728295
julia> @btime grad($_fdm, $f, $xs)[1]
12.084 μs (237 allocations: 7.41 KiB)
-0.12549869079279574
julia> @btime grad($_fdm, $f, $xs, 1)
3.693 μs (87 allocations: 3.34 KiB)
-0.12549869079279574
Your proposed interface looks good and like what I had in mind. We can allow multiple integers to specify mixed derivatives; e.g., grad(fdm, f, x, 1, 2)
would estimate d^2 f / dx[1] dx[2]
. The main challenge here is to generalise the algorithm that automatically determines the weights and step size for a given order, but I think we should be able to resolve that without too much trouble.
An alternative iterface would be to return a tuple of ChainRulesCore.Thunk
s.
Nice thing is these are just anonfunctions so you call the one you want, which would do the work.
and if there is common setup it can happen before them.
And ChainRules.extern
(or just calling them) would evaluate them.
Add support for partial derivatives.