Skip to content

Commit bbf7379

Browse files
authored
Remove support for autodiff::Symbol, autodiff::Bool, and chunk keyword arguments (#164)
* Remove support for `autodiff::Symbol`, `autodiff::Bool`, and `chunk` keyword arguments * Use `DI.Cache`
1 parent f3b1773 commit bbf7379

File tree

10 files changed

+148
-194
lines changed

10 files changed

+148
-194
lines changed

Project.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
name = "NLSolversBase"
22
uuid = "d41bc354-129a-5804-8e4c-c37616107c6c"
3-
version = "7.11.0"
3+
version = "8.0.0-dev"
44

55
[deps]
66
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
77
DifferentiationInterface = "a0c0ee7d-e4b9-4e03-894e-1c5f64a51d63"
88
FiniteDiff = "6a86dc24-6348-571c-b903-95158fe2bd41"
9-
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
109
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1110

1211
[compat]
@@ -31,6 +30,7 @@ julia = "1.10"
3130
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
3231
ComponentArrays = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66"
3332
ExplicitImports = "7d51a73a-1435-4ff3-83d9-f097790105c7"
33+
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
3434
JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b"
3535
OptimTestProblems = "cec144fc-5a64-5bc6-99fb-dde8f63e154c"
3636
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
@@ -40,4 +40,4 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
4040
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
4141

4242
[targets]
43-
test = ["Aqua", "ComponentArrays", "ExplicitImports", "JET", "OptimTestProblems", "Random", "RecursiveArrayTools", "SparseArrays", "StaticArrays", "Test"]
43+
test = ["Aqua", "ComponentArrays", "ExplicitImports", "ForwardDiff", "JET", "OptimTestProblems", "Random", "RecursiveArrayTools", "SparseArrays", "StaticArrays", "Test"]

README.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,7 @@ The words in front of `Differentiable` in the type names (`Non`, `Once`, `Twice`
2929
## Automatic differentiation
3030

3131
Some constructors for `OnceDifferentiable`, `TwiceDifferentiable`, `OnceDifferentiableConstraints` and `TwiceDifferentiableConstraints` accept a positional argument called `autodiff`.
32-
This argument can be either:
33-
34-
- An object subtyping `AbstractADType`, defined by [ADTypes.jl](https://github.com/SciML/ADTypes.jl) and supported by [DifferentiationInterface.jl](https://github.com/JuliaDiff/DifferentiationInterface.jl).
35-
- A `Symbol` like `:finite` (and variants thereof) or `:forward`, which fall back on `ADTypes.AutoFiniteDiff` and `ADTypes.AutoForwardDiff` respectively.
36-
- A `Bool`, namely `true`, which falls back on `ADTypes.AutoForwardDiff`.
37-
38-
When the positional argument `chunk` is passed, it is used to configure chunk size in `ADTypes.AutoForwardDiff`, but _only_ if `autodiff in (:forward, true)`.
39-
Indeed, if `autodiff isa ADTypes.AutoForwardDiff`, we assume that the user already selected the appropriate chunk size and so `chunk` is ignored.
32+
This argument an instance of an `AbstractADType`, defined by [ADTypes.jl](https://github.com/SciML/ADTypes.jl) and supported by [DifferentiationInterface.jl](https://github.com/JuliaDiff/DifferentiationInterface.jl).
4033

4134
## Examples
4235
#### Optimization

src/NLSolversBase.jl

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
module NLSolversBase
22

3-
using ADTypes: AbstractADType, AutoForwardDiff, AutoFiniteDiff
3+
using ADTypes: AbstractADType, AutoFiniteDiff
44
import DifferentiationInterface as DI
55
using FiniteDiff: FiniteDiff
6-
using ForwardDiff: ForwardDiff
76
using LinearAlgebra: LinearAlgebra
87

98
export AbstractObjective,
@@ -45,36 +44,6 @@ export AbstractObjective,
4544
export AbstractConstraints, OnceDifferentiableConstraints,
4645
TwiceDifferentiableConstraints, ConstraintBounds
4746

48-
function finitediff_fdtype(autodiff)
49-
if autodiff == :finiteforward
50-
return Val{:forward}
51-
elseif autodiff == :finitecomplex
52-
return Val{:complex}
53-
elseif autodiff == :finite || autodiff == :central || autodiff == :finitecentral
54-
return Val{:central}
55-
else
56-
throw(ArgumentError(LazyString("The autodiff value `", repr(autodiff), "` is not supported. Use `:finite` or `:forward`.")))
57-
end
58-
end
59-
60-
forwarddiff_chunksize(::Nothing) = nothing
61-
forwarddiff_chunksize(::ForwardDiff.Chunk{C}) where {C} = C
62-
63-
is_finitediff(autodiff) = autodiff (:central, :finite, :finiteforward, :finitecomplex)
64-
is_forwarddiff(autodiff) = autodiff (:forward, :forwarddiff, true)
65-
66-
get_adtype(autodiff::AbstractADType, chunk=nothing) = autodiff
67-
68-
function get_adtype(autodiff::Union{Symbol,Bool}, chunk=nothing)
69-
if is_finitediff(autodiff)
70-
return AutoFiniteDiff(; fdtype=finitediff_fdtype(autodiff)())
71-
elseif is_forwarddiff(autodiff)
72-
return AutoForwardDiff(; chunksize=forwarddiff_chunksize(chunk))
73-
else
74-
throw(ArgumentError(LazyString("The autodiff value `", repr(autodiff), "` is not supported. Use `:finite` or `:forward`.")))
75-
end
76-
end
77-
7847
x_of_nans(x::AbstractArray, ::Type{Tf}=float(eltype(x))) where {Tf} = fill!(similar(x, Tf), NaN)
7948

8049
include("objective_types/inplace_factory.jl")

src/objective_types/constraints.jl

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -119,18 +119,17 @@ function OnceDifferentiableConstraints(bounds::ConstraintBounds)
119119
OnceDifferentiableConstraints(c!, J!, bounds)
120120
end
121121

122-
function checked_chunk(lx)
122+
function check_autodiff(lx::AbstractVector)
123123
if isempty(lx)
124124
throw(ArgumentError("autodiff on constraints require the full lower bound vector `lx`."))
125125
end
126-
ForwardDiff.Chunk(lx)
127126
end
128127

129128
function OnceDifferentiableConstraints(c!, lx::AbstractVector, ux::AbstractVector,
130129
lc::AbstractVector, uc::AbstractVector,
131-
autodiff::Symbol = :central,
132-
chunk::ForwardDiff.Chunk = checked_chunk(lx))
133-
130+
autodiff::AbstractADType = AutoFiniteDiff(; fdtype = Val(:central)))
131+
132+
check_autodiff(lx)
134133
bounds = ConstraintBounds(lx, ux, lc, uc)
135134
T = eltype(bounds)
136135
sizex = size(lx)
@@ -139,11 +138,12 @@ function OnceDifferentiableConstraints(c!, lx::AbstractVector, ux::AbstractVecto
139138
xcache = zeros(T, sizex)
140139
ccache = zeros(T, sizec)
141140

142-
backend = get_adtype(autodiff, chunk)
143-
jac_prep = DI.prepare_jacobian(c!, ccache, backend, xcache)
144-
function j!(_j, _x)
145-
DI.jacobian!(c!, ccache, _j, jac_prep, backend, _x)
146-
return _j
141+
jac_prep = DI.prepare_jacobian(c!, ccache, autodiff, xcache)
142+
j! = let c! = c!, ccache = ccache, jac_prep = jac_prep, autodiff = autodiff
143+
function (_j, _x)
144+
DI.jacobian!(c!, ccache, _j, jac_prep, autodiff, _x)
145+
return _j
146+
end
147147
end
148148
return OnceDifferentiableConstraints(c!, j!, bounds)
149149
end
@@ -163,48 +163,45 @@ end
163163

164164
function TwiceDifferentiableConstraints(c!, lx::AbstractVector, ux::AbstractVector,
165165
lc::AbstractVector, uc::AbstractVector,
166-
autodiff::Symbol = :central,
167-
chunk::ForwardDiff.Chunk = checked_chunk(lx))
166+
autodiff::AbstractADType = AutoFiniteDiff(; fdtype = Val(:central)))
167+
check_autodiff(lx)
168168
bounds = ConstraintBounds(lx, ux, lc, uc)
169169
T = eltype(bounds)
170170
nc = length(lc)
171171
nx = length(lx)
172172
x_example = zeros(T, nx)
173173
λ_example = zeros(T, nc)
174174
ccache = zeros(T, nc)
175-
176-
function sum_constraints(_x, _λ)
177-
# TODO: get rid of this allocation with DI.Cache
178-
ccache_righttype = zeros(promote_type(T, eltype(_x)), nc)
179-
c!(ccache_righttype, _x)
180-
return LinearAlgebra.dot(_λ, ccache_righttype)
181-
end
182-
183-
backend = get_adtype(autodiff, chunk)
184-
185175

186-
jac_prep = DI.prepare_jacobian(c!, ccache, backend, x_example)
187-
function con_jac!(_j, _x)
188-
DI.jacobian!(c!, ccache, _j, jac_prep, backend, _x)
189-
return _j
176+
jac_prep = DI.prepare_jacobian(c!, ccache, autodiff, x_example)
177+
con_jac! = let c! = c!, ccache = ccache, jac_prep = jac_prep, autodiff = autodiff
178+
function (_j, _x)
179+
DI.jacobian!(c!, ccache, _j, jac_prep, autodiff, _x)
180+
return _j
181+
end
190182
end
191-
192-
hess_prep = DI.prepare_hessian(sum_constraints, backend, x_example, DI.Constant(λ_example))
193-
function con_hess!(_h, _x, _λ)
194-
DI.hessian!(sum_constraints, _h, hess_prep, backend, _x, DI.Constant(_λ))
195-
return _h
183+
184+
function sum_constraints(_x, _λ, _ccache)
185+
c!(_ccache, _x)
186+
return LinearAlgebra.dot(_λ, _ccache)
187+
end
188+
hess_prep = DI.prepare_hessian(sum_constraints, autodiff, x_example, DI.Constant(λ_example), DI.Cache(ccache))
189+
con_hess! = let sum_constraints = sum_constraints, hess_prep = hess_prep, autodiff = autodiff, ccache = ccache
190+
function (_h, _x, _λ)
191+
DI.hessian!(sum_constraints, _h, hess_prep, autodiff, _x, DI.Constant(_λ), DI.Cache(ccache))
192+
return _h
193+
end
196194
end
197195

198196
return TwiceDifferentiableConstraints(c!, con_jac!, con_hess!, bounds)
199197
end
200198

201199
function TwiceDifferentiableConstraints(c!, con_jac!,lx::AbstractVector, ux::AbstractVector,
202200
lc::AbstractVector, uc::AbstractVector,
203-
autodiff::Symbol = :central,
204-
chunk::ForwardDiff.Chunk = checked_chunk(lx))
201+
autodiff::AbstractADType = AutoFiniteDiff(; fdtype = Val(:central)),)
205202
# TODO: is con_jac! still useful? we ignore it here
206203

207-
return TwiceDifferentiableConstraints(c!, lx, ux, lc, uc, autodiff, chunk)
204+
return TwiceDifferentiableConstraints(c!, lx, ux, lc, uc, autodiff)
208205
end
209206

210207

src/objective_types/oncedifferentiable.jl

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,26 @@ end
1313

1414
### Only the objective
1515
# Ambiguity
16-
OnceDifferentiable(f, x::AbstractArray,
16+
function OnceDifferentiable(f, x::AbstractArray,
1717
F::Real = real(zero(eltype(x))),
18-
DF::AbstractArray = alloc_DF(x, F); inplace::Bool = true, autodiff::Union{AbstractADType,Symbol,Bool} = :finite,
19-
chunk::ForwardDiff.Chunk = ForwardDiff.Chunk(x)) =
20-
OnceDifferentiable(f, x, F, DF, autodiff, chunk)
21-
#OnceDifferentiable(f, x::AbstractArray, F::AbstractArray; autodiff = :finite) =
22-
# OnceDifferentiable(f, x::AbstractArray, F::AbstractArray, alloc_DF(x, F))
18+
DF::AbstractArray = alloc_DF(x, F);
19+
inplace::Bool = true,
20+
autodiff::AbstractADType = AutoFiniteDiff(; fdtype = Val(:central)))
21+
OnceDifferentiable(f, x, F, DF, autodiff)
22+
end
2323
function OnceDifferentiable(f, x::AbstractArray,
2424
F::AbstractArray, DF::AbstractArray = alloc_DF(x, F);
25-
inplace::Bool = true, autodiff::Union{AbstractADType,Symbol,Bool} = :finite)
25+
inplace::Bool = true,
26+
autodiff::AbstractADType = AutoFiniteDiff(; fdtype = Val(:central)))
2627
f! = f!_from_f(f, F, inplace)
27-
2828
OnceDifferentiable(f!, x, F, DF, autodiff)
2929
end
3030

3131

3232
function OnceDifferentiable(f, x_seed::AbstractArray,
3333
F::Real,
3434
DF::AbstractArray,
35-
autodiff::Union{AbstractADType,Symbol,Bool}, chunk::ForwardDiff.Chunk)
35+
autodiff::AbstractADType)
3636
# When here, at the constructor with positional autodiff, it should already
3737
# be the case, that f is inplace.
3838
if f isa Union{InplaceObjective, NotInplaceObjective}
@@ -43,51 +43,48 @@ function OnceDifferentiable(f, x_seed::AbstractArray,
4343

4444
return OnceDifferentiable(fF, dfF, fdfF, x_seed, F, DF)
4545
else
46-
backend = get_adtype(autodiff, chunk)
47-
grad_prep = DI.prepare_gradient(f, backend, x_seed)
48-
function g!(_g, _x)
49-
DI.gradient!(f, _g, grad_prep, backend, _x)
50-
return nothing
46+
grad_prep = DI.prepare_gradient(f, autodiff, x_seed)
47+
g! = let f = f, grad_prep = grad_prep, autodiff = autodiff
48+
function (_g, _x)
49+
DI.gradient!(f, _g, grad_prep, autodiff, _x)
50+
return nothing
51+
end
5152
end
52-
function fg!(_g, _x)
53-
y, _ = DI.value_and_gradient!(f, _g, grad_prep, backend, _x)
54-
return y
53+
fg! = let f = f, grad_prep = grad_prep, autodiff = autodiff
54+
function (_g, _x)
55+
y, _ = DI.value_and_gradient!(f, _g, grad_prep, autodiff, _x)
56+
return y
57+
end
5558
end
5659
return OnceDifferentiable(f, g!, fg!, x_seed, F, DF)
5760
end
5861
end
5962

60-
has_not_dep_symbol_in_ad = Ref{Bool}(true)
61-
OnceDifferentiable(f, x::AbstractArray, F::AbstractArray, autodiff::Symbol, chunk::ForwardDiff.Chunk = ForwardDiff.Chunk(x)) =
62-
OnceDifferentiable(f, x, F, alloc_DF(x, F), autodiff, chunk)
63-
function OnceDifferentiable(f, x::AbstractArray, F::AbstractArray,
64-
autodiff::Bool, chunk::ForwardDiff.Chunk = ForwardDiff.Chunk(x))
65-
if autodiff == false
66-
throw(ErrorException("It is not possible to set the `autodiff` keyword to `false` when constructing a OnceDifferentiable instance from only one function. Pass in the (partial) derivative or specify a valid `autodiff` symbol."))
67-
elseif has_not_dep_symbol_in_ad[]
68-
@warn("Setting the `autodiff` keyword to `true` is deprecated. Please use a valid symbol instead.")
69-
has_not_dep_symbol_in_ad[] = false
70-
end
71-
OnceDifferentiable(f, x, F, alloc_DF(x, F), :forward, chunk)
72-
end
73-
function OnceDifferentiable(f, x_seed::AbstractArray, F::AbstractArray, DF::AbstractArray,
74-
autodiff::Union{AbstractADType,Symbol,Bool}, chunk::ForwardDiff.Chunk = ForwardDiff.Chunk(x_seed))
75-
if f isa Union{InplaceObjective, NotInplaceObjective}
63+
OnceDifferentiable(f, x::AbstractArray, F::AbstractArray, autodiff::AbstractADType) =
64+
OnceDifferentiable(f, x, F, alloc_DF(x, F), autodiff)
65+
function OnceDifferentiable(f, x_seed::AbstractArray,
66+
F::AbstractArray,
67+
DF::AbstractArray,
68+
autodiff::AbstractADType)
69+
if f isa Union{InplaceObjective, NotInplaceObjective}
7670
fF = make_f(f, x_seed, F)
7771
dfF = make_df(f, x_seed, F)
7872
fdfF = make_fdf(f, x_seed, F)
7973
return OnceDifferentiable(fF, dfF, fdfF, x_seed, F, DF)
8074
else
8175
F2 = similar(F)
82-
backend = get_adtype(autodiff, chunk)
83-
jac_prep = DI.prepare_jacobian(f, F2, backend, x_seed)
84-
function j!(_j, _x)
85-
DI.jacobian!(f, F2, _j, jac_prep, backend, _x)
86-
return _j
76+
jac_prep = DI.prepare_jacobian(f, F2, autodiff, x_seed)
77+
j! = let f = f, F2 = F2, jac_prep = jac_prep, autodiff = autodiff
78+
function (_j, _x)
79+
DI.jacobian!(f, F2, _j, jac_prep, autodiff, _x)
80+
return _j
81+
end
8782
end
88-
function fj!(_y, _j, _x)
89-
y, _ = DI.value_and_jacobian!(f, _y, _j, jac_prep, backend, _x)
90-
return y
83+
fj! = let f = f, jac_prep = jac_prep, autodiff = autodiff
84+
function (_y, _j, _x)
85+
y, _ = DI.value_and_jacobian!(f, _y, _j, jac_prep, autodiff, _x)
86+
return y
87+
end
9188
end
9289
return OnceDifferentiable(f, j!, fj!, x_seed, F, DF)
9390
end

0 commit comments

Comments
 (0)