Skip to content

Commit 0317dac

Browse files
thchrpkofod
andauthored
add Options(options; kws...) for inheriting from an existing options set (#1172)
* add `Options(options; kws...)` for inheriting from an existing options-set with overrides * bump to v1.13.0 * avoid copying list of arguments * Update Project.toml --------- Co-authored-by: Patrick Kofod Mogensen <[email protected]>
1 parent 99b1bce commit 0317dac

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
name = "Optim"
22
uuid = "429524aa-4258-5aef-a3af-852621145aeb"
3-
version = "1.13.2"
3+
version = "1.14.0"
4+
45

56
[deps]
67
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"

src/types.jl

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ abstract type AbstractOptimizerState end
99
abstract type ZerothOrderState <: AbstractOptimizerState end
1010

1111
"""
12-
Configurable options with defaults (values 0 and NaN indicate unlimited):
12+
Options(; opts...)
13+
14+
Specify configurable optimizer options `opts...`. Unspecified options are set to the default
15+
values below (values 0 and NaN indicate unlimited):
16+
1317
```
1418
x_abstol::Real = 0.0,
1519
x_reltol::Real = 0.0,
@@ -37,7 +41,19 @@ show_every::Int = 1,
3741
callback = nothing,
3842
time_limit = NaN
3943
```
40-
See http://julianlsolvers.github.io/Optim.jl/stable/#user/config/
44+
45+
It is also possible to pass a previously defined `Options` argument as the first argument,
46+
i.e., as:
47+
48+
```jl
49+
Options(inherit_options; opts...)
50+
```
51+
52+
Default values for unspecified `opts` will then be "inherited" from `inherit_options`. This
53+
can be used to modify a subset of options in a previously defined `Options` variable.
54+
55+
For more information on individual options, see the documentaton at
56+
http://julianlsolvers.github.io/Optim.jl/stable/#user/config/.
4157
"""
4258
struct Options{T, TCallback}
4359
x_abstol::T
@@ -172,6 +188,20 @@ function Options(;
172188
)
173189
end
174190

191+
function Options(o::Options; kws...)
192+
fields = fieldnames(typeof(o))
193+
foreach(keys(kws)) do kw
194+
if kw fields
195+
error(lazy"`$kw` is not a valid keyword argument of `Options(opts; kws...)`")
196+
end
197+
end
198+
newargs = ntuple(Val(nfields(o))) do i
199+
field = fields[i]
200+
get(kws, field, getfield(o, field))
201+
end
202+
return Options(newargs...)
203+
end
204+
175205
_show_helper(output, k, v) = output * "$k = $v, "
176206
_show_helper(output, k, ::Nothing) = output
177207

test/general/types.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,14 @@ import Compat.String
4545
io = IOBuffer()
4646
res = show(io, MIME"text/plain"(), Optim.Options(x_abstol = 10.0))
4747
@test String(take!(io)) |> contains("x_abstol = 10.0")
48+
49+
# inheriting update from previously defined `Options`
50+
opts1 = Optim.Options(; x_abstol = 1e-3, f_abstol = 1e-6, iterations = 1000)
51+
opts2 = Optim.Options(opts1; x_abstol = 1e-4, f_calls_limit = 100)
52+
@test opts2.x_abstol == 1e-4 && opts2.x_abstol != opts1.x_abstol
53+
@test opts2.f_calls_limit == 100 && opts2.f_calls_limit != opts1.f_calls_limit
54+
@test opts2.f_abstol == opts1.f_abstol == 1e-6
55+
@test opts2.iterations == opts1.iterations == 1000
56+
@test_throws "not a valid keyword argument" Optim.Options(opts1; invalid_keyword=1)
57+
@test Optim.Options(opts1) == opts1
4858
end

0 commit comments

Comments
 (0)