Skip to content

Commit ed397e8

Browse files
Vaibhavdixit02ChrisRackauckas
authored andcommitted
Add GalacticOptimJL
1 parent 2caa5de commit ed397e8

File tree

4 files changed

+213
-97
lines changed

4 files changed

+213
-97
lines changed

GalacticOptimJL/Project.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name = "GalacticOptimJL"
2+
uuid = "9d3c5eb1-403b-401b-8c0f-c11105342e6b"
3+
authors = ["Vaibhav Dixit <[email protected]> and contributors"]
4+
version = "0.1.0"
5+
6+
[deps]
7+
GalacticOptim = "a75be94c-b780-496d-a8a9-0878b188d577"
8+
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
9+
10+
[compat]
11+
julia = "1"
12+
13+
[extras]
14+
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
15+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
16+
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
17+
18+
[targets]
19+
test = ["Test"]
Lines changed: 101 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
1+
module GalacticOptimJL
2+
3+
using Optim, GalacticOptim, GalacticOptim.SciMLBase
4+
15
decompose_trace(trace::Optim.OptimizationTrace) = last(trace)
6+
decompose_trace(trace::Optim.OptimizationState) = trace
27

3-
function __map_optimizer_args(prob::OptimizationProblem, opt::Union{Optim.AbstractOptimizer, Optim.Fminbox,Optim.SAMIN, Optim.ConstrainedOptimizer};
8+
function __map_optimizer_args(prob::OptimizationProblem, opt::Union{Optim.AbstractOptimizer,Optim.Fminbox,Optim.SAMIN,Optim.ConstrainedOptimizer};
49
cb=nothing,
5-
maxiters::Union{Number, Nothing}=nothing,
6-
maxtime::Union{Number, Nothing}=nothing,
7-
abstol::Union{Number, Nothing}=nothing,
8-
reltol::Union{Number, Nothing}=nothing,
10+
maxiters::Union{Number,Nothing}=nothing,
11+
maxtime::Union{Number,Nothing}=nothing,
12+
abstol::Union{Number,Nothing}=nothing,
13+
reltol::Union{Number,Nothing}=nothing,
914
kwargs...)
1015
if !isnothing(abstol)
1116
@warn "common abstol is currently not used by $(opt)"
1217
end
1318

14-
mapped_args = (;extended_trace=true, kwargs...)
15-
19+
mapped_args = (; extended_trace=true, kwargs...)
20+
1621
if !isnothing(cb)
17-
mapped_args = (; mapped_args..., callback = cb)
22+
mapped_args = (; mapped_args..., callback=cb)
1823
end
1924

2025
if !isnothing(maxiters)
@@ -28,16 +33,18 @@ function __map_optimizer_args(prob::OptimizationProblem, opt::Union{Optim.Abstra
2833
if !isnothing(reltol)
2934
mapped_args = (; mapped_args..., f_tol=reltol)
3035
end
31-
32-
return Optim.Options(;mapped_args...)
36+
37+
return Optim.Options(; mapped_args...)
3338
end
3439

35-
function __solve(prob::OptimizationProblem, opt::Optim.AbstractOptimizer, data = DEFAULT_DATA;
40+
function SciMLBase.__solve(prob::OptimizationProblem,
41+
opt::Optim.AbstractOptimizer,
42+
data=GalacticOptim.DEFAULT_DATA;
3643
kwargs...)
3744
if !isnothing(prob.lb) | !isnothing(prob.ub)
38-
if !(opt isa Union{Optim.Fminbox, Optim.SAMIN, Optim.AbstractConstrainedOptimizer})
45+
if !(opt isa Union{Optim.Fminbox,Optim.SAMIN,Optim.AbstractConstrainedOptimizer})
3946
if opt isa Optim.ParticleSwarm
40-
opt = Optim.ParticleSwarm(;lower=prob.lb, upper=prob.ub, n_particles=opt.n_particles)
47+
opt = Optim.ParticleSwarm(; lower=prob.lb, upper=prob.ub, n_particles=opt.n_particles)
4148
elseif opt isa Optim.SimulatedAnnealing
4249
@warn "$(opt) can currently not be wrapped in Fminbox(). The lower and upper bounds thus will be ignored. Consider using a different optimizer or open an issue with Optim.jl"
4350
else
@@ -50,147 +57,147 @@ function __solve(prob::OptimizationProblem, opt::Optim.AbstractOptimizer, data =
5057
end
5158

5259
function ___solve(prob::OptimizationProblem, opt::Optim.AbstractOptimizer,
53-
data = DEFAULT_DATA;
54-
cb = (args...) -> (false),
55-
maxiters::Union{Number, Nothing} = nothing,
56-
maxtime::Union{Number, Nothing} = nothing,
57-
abstol::Union{Number, Nothing}=nothing,
58-
reltol::Union{Number, Nothing}=nothing,
59-
progress = false,
60-
kwargs...)
60+
data=GalacticOptim.DEFAULT_DATA;
61+
cb=(args...) -> (false),
62+
maxiters::Union{Number,Nothing}=nothing,
63+
maxtime::Union{Number,Nothing}=nothing,
64+
abstol::Union{Number,Nothing}=nothing,
65+
reltol::Union{Number,Nothing}=nothing,
66+
progress=false,
67+
kwargs...)
6168
local x, cur, state
6269

63-
if data != DEFAULT_DATA
70+
if data != GalacticOptim.DEFAULT_DATA
6471
maxiters = length(data)
6572
end
6673

6774
cur, state = iterate(data)
6875

6976
function _cb(trace)
70-
cb_call = opt == Optim.NelderMead() ? cb(decompose_trace(trace).metadata["centroid"],x...) : cb(decompose_trace(trace).metadata["x"],x...)
77+
cb_call = opt == Optim.NelderMead() ? cb(decompose_trace(trace).metadata["centroid"], x...) : cb(decompose_trace(trace).metadata["x"], x...)
7178
if !(typeof(cb_call) <: Bool)
7279
error("The callback should return a boolean `halt` for whether to stop the optimization process.")
7380
end
7481
cur, state = iterate(data, state)
7582
cb_call
7683
end
7784

78-
maxiters = _check_and_convert_maxiters(maxiters)
79-
maxtime = _check_and_convert_maxtime(maxtime)
85+
maxiters = GalacticOptim._check_and_convert_maxiters(maxiters)
86+
maxtime = GalacticOptim._check_and_convert_maxtime(maxtime)
8087

81-
f = instantiate_function(prob.f,prob.u0,prob.f.adtype,prob.p)
88+
f = GalacticOptim.instantiate_function(prob.f, prob.u0, prob.f.adtype, prob.p)
8289

8390
!(opt isa Optim.ZerothOrderOptimizer) && f.grad === nothing && error("Use OptimizationFunction to pass the derivatives or automatically generate them with one of the autodiff backends")
8491

85-
_loss = function(θ)
92+
_loss = function (θ)
8693
x = f.f(θ, prob.p, cur...)
8794
__x = first(x)
88-
return prob.sense === MaxSense ? -__x : __x
95+
return prob.sense === GalacticOptim.MaxSense ? -__x : __x
8996
end
9097

91-
fg! = function (G,θ)
98+
fg! = function (G, θ)
9299
if G !== nothing
93100
f.grad(G, θ, cur...)
94-
if prob.sense === MaxSense
101+
if prob.sense === GalacticOptim.MaxSense
95102
G .*= false
96103
end
97104
end
98105
return _loss(θ)
99106
end
100107

101108
if opt isa Optim.KrylovTrustRegion
102-
hv = function (H,θ,v)
103-
f.hv(H,θ,v,cur...)
104-
if prob.sense === MaxSense
109+
hv = function (H, θ, v)
110+
f.hv(H, θ, v, cur...)
111+
if prob.sense === GalacticOptim.MaxSense
105112
H .*= false
106113
end
107114
end
108115
optim_f = Optim.TwiceDifferentiableHV(_loss, fg!, hv, prob.u0)
109116
else
110117
gg = function (G, θ)
111118
f.grad(G, θ, cur...)
112-
if prob.sense === MaxSense
119+
if prob.sense === GalacticOptim.MaxSense
113120
G .*= false
114121
end
115122
end
116-
117-
hh = function (H,θ)
118-
f.hess(H,θ,cur...)
119-
if prob.sense === MaxSense
123+
124+
hh = function (H, θ)
125+
f.hess(H, θ, cur...)
126+
if prob.sense === GalacticOptim.MaxSense
120127
H .*= false
121128
end
122129
end
123130
optim_f = Optim.TwiceDifferentiable(_loss, gg, fg!, hh, prob.u0)
124131
end
125132

126-
opt_args = _map_optimizer_args(prob, opt, cb=_cb, maxiters=maxiters, maxtime=maxtime,abstol=abstol, reltol=reltol; kwargs...)
133+
opt_args = __map_optimizer_args(prob, opt, cb=_cb, maxiters=maxiters, maxtime=maxtime, abstol=abstol, reltol=reltol; kwargs...)
127134

128135
t0 = time()
129136
opt_res = Optim.optimize(optim_f, prob.u0, opt, opt_args)
130137
t1 = time()
131138
opt_ret = Symbol(Optim.converged(opt_res))
132139

133-
SciMLBase.build_solution(prob, opt, opt_res.minimizer, prob.sense === MaxSense ? -opt_res.minimum : opt_res.minimum; original=opt_res, retcode=opt_ret)
140+
SciMLBase.build_solution(prob, opt, opt_res.minimizer, prob.sense === GalacticOptim.MaxSense ? -opt_res.minimum : opt_res.minimum; original=opt_res, retcode=opt_ret)
134141
end
135142

136143
function ___solve(prob::OptimizationProblem, opt::Union{Optim.Fminbox,Optim.SAMIN},
137-
data = DEFAULT_DATA;
138-
cb = (args...) -> (false),
139-
maxiters::Union{Number, Nothing} = nothing,
140-
maxtime::Union{Number, Nothing} = nothing,
141-
abstol::Union{Number, Nothing}=nothing,
142-
reltol::Union{Number, Nothing}=nothing,
143-
progress = false,
144-
kwargs...)
144+
data=GalacticOptim.DEFAULT_DATA;
145+
cb=(args...) -> (false),
146+
maxiters::Union{Number,Nothing}=nothing,
147+
maxtime::Union{Number,Nothing}=nothing,
148+
abstol::Union{Number,Nothing}=nothing,
149+
reltol::Union{Number,Nothing}=nothing,
150+
progress=false,
151+
kwargs...)
145152

146153
local x, cur, state
147154

148-
if data != DEFAULT_DATA
155+
if data != GalacticOptim.DEFAULT_DATA
149156
maxiters = length(data)
150157
end
151158

152159
cur, state = iterate(data)
153160

154161
function _cb(trace)
155-
cb_call = !(opt isa Optim.SAMIN) && opt.method == Optim.NelderMead() ? cb(decompose_trace(trace).metadata["centroid"],x...) : cb(decompose_trace(trace).metadata["x"],x...)
162+
cb_call = !(opt isa Optim.SAMIN) && opt.method == Optim.NelderMead() ? cb(decompose_trace(trace).metadata["centroid"], x...) : cb(decompose_trace(trace).metadata["x"], x...)
156163
if !(typeof(cb_call) <: Bool)
157164
error("The callback should return a boolean `halt` for whether to stop the optimization process.")
158165
end
159166
cur, state = iterate(data, state)
160167
cb_call
161168
end
162169

163-
maxiters = _check_and_convert_maxiters(maxiters)
164-
maxtime = _check_and_convert_maxtime(maxtime)
170+
maxiters = GalacticOptim._check_and_convert_maxiters(maxiters)
171+
maxtime = GalacticOptim._check_and_convert_maxtime(maxtime)
165172

166-
f = instantiate_function(prob.f,prob.u0,prob.f.adtype,prob.p)
173+
f = GalacticOptim.instantiate_function(prob.f, prob.u0, prob.f.adtype, prob.p)
167174

168175
!(opt isa Optim.ZerothOrderOptimizer) && f.grad === nothing && error("Use OptimizationFunction to pass the derivatives or automatically generate them with one of the autodiff backends")
169176

170-
_loss = function(θ)
177+
_loss = function (θ)
171178
x = f.f(θ, prob.p, cur...)
172179
__x = first(x)
173-
return prob.sense === MaxSense ? -__x : __x
180+
return prob.sense === GalacticOptim.MaxSense ? -__x : __x
174181
end
175-
fg! = function (G,θ)
182+
fg! = function (G, θ)
176183
if G !== nothing
177184
f.grad(G, θ, cur...)
178-
if prob.sense === MaxSense
185+
if prob.sense === GalacticOptim.MaxSense
179186
G .*= false
180187
end
181188
end
182189
return _loss(θ)
183190
end
184-
191+
185192
gg = function (G, θ)
186193
f.grad(G, θ, cur...)
187-
if prob.sense === MaxSense
194+
if prob.sense === GalacticOptim.MaxSense
188195
G .*= false
189196
end
190197
end
191198
optim_f = Optim.OnceDifferentiable(_loss, gg, fg!, prob.u0)
192199

193-
opt_args = _map_optimizer_args(prob, opt, cb=_cb, maxiters=maxiters, maxtime=maxtime,abstol=abstol, reltol=reltol; kwargs...)
200+
opt_args = __map_optimizer_args(prob, opt, cb=_cb, maxiters=maxiters, maxtime=maxtime, abstol=abstol, reltol=reltol; kwargs...)
194201

195202
t0 = time()
196203
opt_res = Optim.optimize(optim_f, prob.lb, prob.ub, prob.u0, opt, opt_args)
@@ -202,87 +209,87 @@ end
202209

203210

204211
function ___solve(prob::OptimizationProblem, opt::Optim.ConstrainedOptimizer,
205-
data = DEFAULT_DATA;
206-
cb = (args...) -> (false),
207-
maxiters::Union{Number, Nothing} = nothing,
208-
maxtime::Union{Number, Nothing} = nothing,
209-
abstol::Union{Number, Nothing}=nothing,
210-
reltol::Union{Number, Nothing}=nothing,
211-
progress = false,
212-
kwargs...)
212+
data=GalacticOptim.DEFAULT_DATA;
213+
cb=(args...) -> (false),
214+
maxiters::Union{Number,Nothing}=nothing,
215+
maxtime::Union{Number,Nothing}=nothing,
216+
abstol::Union{Number,Nothing}=nothing,
217+
reltol::Union{Number,Nothing}=nothing,
218+
progress=false,
219+
kwargs...)
213220

214221
local x, cur, state
215222

216-
if data != DEFAULT_DATA
223+
if data != GalacticOptim.DEFAULT_DATA
217224
maxiters = length(data)
218225
end
219226

220227
cur, state = iterate(data)
221228

222-
function _cb(trace)
223-
cb_call = cb(decompose_trace(trace).metadata["x"],x...)
224-
if !(typeof(cb_call) <: Bool)
225-
error("The callback should return a boolean `halt` for whether to stop the optimization process.")
226-
end
227-
cur, state = iterate(data, state)
228-
cb_call
229+
function _cb(trace)
230+
cb_call = cb(decompose_trace(trace).metadata["x"], x...)
231+
if !(typeof(cb_call) <: Bool)
232+
error("The callback should return a boolean `halt` for whether to stop the optimization process.")
233+
end
234+
cur, state = iterate(data, state)
235+
cb_call
229236
end
230237

231-
maxiters = _check_and_convert_maxiters(maxiters)
232-
maxtime = _check_and_convert_maxtime(maxtime)
238+
maxiters = GalacticOptim._check_and_convert_maxiters(maxiters)
239+
maxtime = GalacticOptim._check_and_convert_maxtime(maxtime)
233240

234-
f = instantiate_function(prob.f,prob.u0,prob.f.adtype,prob.p,prob.ucons === nothing ? 0 : length(prob.ucons))
241+
f = GalacticOptim.instantiate_function(prob.f, prob.u0, prob.f.adtype, prob.p, prob.ucons === nothing ? 0 : length(prob.ucons))
235242

236-
f.cons_j ===nothing && error("This optimizer requires derivative definitions for nonlinear constraints. If the problem does not have nonlinear constraints, choose a different optimizer. Otherwise define the derivative for cons using OptimizationFunction either directly or automatically generate them with one of the autodiff backends")
243+
f.cons_j === nothing && error("This optimizer requires derivative definitions for nonlinear constraints. If the problem does not have nonlinear constraints, choose a different optimizer. Otherwise define the derivative for cons using OptimizationFunction either directly or automatically generate them with one of the autodiff backends")
237244

238-
_loss = function(θ)
245+
_loss = function (θ)
239246
x = f.f(θ, prob.p, cur...)
240247
__x = first(x)
241-
return prob.sense === MaxSense ? -__x : __x
248+
return prob.sense === GalacticOptim.MaxSense ? -__x : __x
242249
end
243-
fg! = function (G,θ)
250+
fg! = function (G, θ)
244251
if G !== nothing
245252
f.grad(G, θ, cur...)
246-
if prob.sense === MaxSense
253+
if prob.sense === GalacticOptim.MaxSense
247254
G .*= false
248255
end
249256
end
250257
return _loss(θ)
251258
end
252259
gg = function (G, θ)
253260
f.grad(G, θ, cur...)
254-
if prob.sense === MaxSense
261+
if prob.sense === GalacticOptim.MaxSense
255262
G .*= false
256263
end
257264
end
258-
259-
hh = function (H,θ)
260-
f.hess(H,θ,cur...)
261-
if prob.sense === MaxSense
265+
266+
hh = function (H, θ)
267+
f.hess(H, θ, cur...)
268+
if prob.sense === GalacticOptim.MaxSense
262269
H .*= false
263270
end
264271
end
265272
optim_f = Optim.TwiceDifferentiable(_loss, gg, fg!, hh, prob.u0)
266273

267-
cons! = (res, θ) -> res .= f.cons(θ);
274+
cons! = (res, θ) -> res .= f.cons(θ)
268275

269-
cons_j! = function(J, x)
276+
cons_j! = function (J, x)
270277
f.cons_j(J, x)
271278
end
272279

273280
cons_hl! = function (h, θ, λ)
274281
res = [similar(h) for i in 1:length(λ)]
275282
f.cons_h(res, θ)
276283
for i in 1:length(λ)
277-
h .+= λ[i]*res[i]
284+
h .+= λ[i] * res[i]
278285
end
279286
end
280287

281288
lb = prob.lb === nothing ? [] : prob.lb
282289
ub = prob.ub === nothing ? [] : prob.ub
283290
optim_fc = Optim.TwiceDifferentiableConstraints(cons!, cons_j!, cons_hl!, lb, ub, prob.lcons, prob.ucons)
284291

285-
opt_args = _map_optimizer_args(prob, opt, cb=_cb, maxiters=maxiters, maxtime=maxtime,abstol=abstol, reltol=reltol; kwargs...)
292+
opt_args = __map_optimizer_args(prob, opt, cb=_cb, maxiters=maxiters, maxtime=maxtime, abstol=abstol, reltol=reltol; kwargs...)
286293

287294
t0 = time()
288295
opt_res = Optim.optimize(optim_f, optim_fc, prob.u0, opt, opt_args)
@@ -293,4 +300,4 @@ function ___solve(prob::OptimizationProblem, opt::Optim.ConstrainedOptimizer,
293300
end
294301

295302

296-
303+
end

0 commit comments

Comments
 (0)