forked from SciML/Optimization.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOptimizationCMAEvolutionStrategy.jl
More file actions
141 lines (120 loc) · 4.4 KB
/
Copy pathOptimizationCMAEvolutionStrategy.jl
File metadata and controls
141 lines (120 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
module OptimizationCMAEvolutionStrategy
using Reexport
@reexport using OptimizationBase
using CMAEvolutionStrategy
using OptimizationBase: SciMLBase
export CMAEvolutionStrategyOpt
struct CMAEvolutionStrategyOpt end
SciMLBase.allowscallback(opt::CMAEvolutionStrategyOpt) = true
SciMLBase.allowsbounds(::CMAEvolutionStrategyOpt) = true
SciMLBase.has_init(opt::CMAEvolutionStrategyOpt) = true
SciMLBase.requiresgradient(::CMAEvolutionStrategyOpt) = false
SciMLBase.requireshessian(::CMAEvolutionStrategyOpt) = false
SciMLBase.requiresconsjac(::CMAEvolutionStrategyOpt) = false
SciMLBase.requiresconshess(::CMAEvolutionStrategyOpt) = false
# Map `CMAEvolutionStrategy.Stop.reason` to a `SciMLBase.ReturnCode.T`. The
# reasons come from `CMAEvolutionStrategy/src/stop.jl` — the full set is
# `:maxiter`, `:maxtime`, `:maxfevals`, `:ftarget`, `:xtol`, `:ftol`, `:stagnation`
# (plus `:none` for the pre-termination state).
function _cma_retcode(reason::Symbol)
if reason === :ftarget || reason === :xtol || reason === :ftol
return SciMLBase.ReturnCode.Success
elseif reason === :maxiter || reason === :maxfevals
return SciMLBase.ReturnCode.MaxIters
elseif reason === :maxtime
return SciMLBase.ReturnCode.MaxTime
elseif reason === :stagnation
return SciMLBase.ReturnCode.Stalled
else
return SciMLBase.ReturnCode.Default
end
end
function __map_optimizer_args(
prob::OptimizationBase.OptimizationCache, opt::CMAEvolutionStrategyOpt;
callback = nothing,
maxiters::Union{Number, Nothing} = nothing,
maxtime::Union{Number, Nothing} = nothing,
abstol::Union{Number, Nothing} = nothing,
reltol::Union{Number, Nothing} = nothing,
verbose::Bool = false,
# `sigma0` is the initial step size; it is the positional `s0` argument of
# `CMAEvolutionStrategy.minimize`, so it is handled in `__solve` and only
# captured here to keep it out of the forwarded `kwargs`.
sigma0 = nothing,
kwargs...
)
if !isnothing(reltol)
@SciMLMessage(
lazy"common reltol is currently not used by $(opt)",
prob.verbose, :unsupported_kwargs
)
end
mapped_args = (; kwargs...)
mapped_args = (;
mapped_args...,
lower = prob.lb,
upper = prob.ub,
logger = CMAEvolutionStrategy.BasicLogger(
prob.u0;
verbosity = verbose ? 1 : 0,
callback = callback
),
)
if !isnothing(maxiters)
mapped_args = (; mapped_args..., maxiter = maxiters)
end
if !isnothing(maxtime)
mapped_args = (; mapped_args..., maxtime = maxtime)
end
if !isnothing(abstol)
mapped_args = (; mapped_args..., ftol = abstol)
end
return mapped_args
end
function SciMLBase.__solve(cache::OptimizationCache{O}) where {O <: CMAEvolutionStrategyOpt}
local x, cur, state
function _cb(opt, y, fvals, perm)
curr_u = xbest(opt)
opt_state = OptimizationBase.OptimizationState(;
iter = length(opt.logger.fmedian),
u = curr_u,
p = cache.p,
objective = fbest(opt),
original = opt.logger
)
cb_call = cache.callback(opt_state, x...)
if !(cb_call isa Bool)
error("The callback should return a boolean `halt` for whether to stop the optimization process.")
end
return cb_call
end
maxiters = OptimizationBase._check_and_convert_maxiters(cache.solver_args.maxiters)
maxtime = OptimizationBase._check_and_convert_maxtime(cache.solver_args.maxtime)
_loss = function (θ)
x = cache.f(θ, cache.p)
return first(x)
end
opt_args = __map_optimizer_args(
cache, cache.opt; callback = _cb, cache.solver_args...,
maxiters = maxiters,
maxtime = maxtime
)
sigma0 = get(cache.solver_args, :sigma0, 0.1)
t0 = time()
opt_res = CMAEvolutionStrategy.minimize(_loss, cache.u0, sigma0; opt_args...)
t1 = time()
opt_ret = _cma_retcode(opt_res.stop.reason)
stats = OptimizationBase.OptimizationStats(;
iterations = length(opt_res.logger.fmedian),
time = t1 - t0,
fevals = length(opt_res.logger.fmedian)
)
return SciMLBase.build_solution(
cache, cache.opt,
xbest(opt_res),
fbest(opt_res); original = opt_res,
retcode = opt_ret,
stats = stats
)
end
end