fcmaes 1.1.3__py3-none-any.whl → 1.6.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fcmaes/__init__.py +12 -2
- fcmaes/advretry.py +217 -159
- fcmaes/astro.py +143 -27
- fcmaes/bitecpp.py +107 -0
- fcmaes/cmaes.py +204 -173
- fcmaes/cmaescpp.py +253 -87
- fcmaes/crfmnes.py +339 -0
- fcmaes/crfmnescpp.py +273 -0
- fcmaes/dacpp.py +39 -51
- fcmaes/de.py +472 -0
- fcmaes/decpp.py +222 -64
- fcmaes/diversifier.py +357 -0
- fcmaes/evaluator.py +297 -14
- fcmaes/lib/libacmalib.dll +0 -0
- fcmaes/lib/libacmalib.dylib +0 -0
- fcmaes/lib/libacmalib.so +0 -0
- fcmaes/lib/libhbv.so +0 -0
- fcmaes/lib/liblrgv.so +0 -0
- fcmaes/lib/librw_top_trumps.dll +0 -0
- fcmaes/lib/librw_top_trumps.so +0 -0
- fcmaes/mapelites.py +737 -0
- fcmaes/mode.py +719 -0
- fcmaes/modecpp.py +470 -0
- fcmaes/moretry.py +270 -0
- fcmaes/multiretry.py +195 -0
- fcmaes/optimizer.py +883 -112
- fcmaes/pgpecpp.py +340 -0
- fcmaes/pygmoretry.py +10 -19
- fcmaes/retry.py +248 -121
- fcmaes/test_cma.py +207 -30
- fcmaes/testfun.py +38 -1
- {fcmaes-1.1.3.dist-info → fcmaes-1.6.9.dist-info}/METADATA +22 -12
- fcmaes-1.6.9.dist-info/RECORD +36 -0
- {fcmaes-1.1.3.dist-info → fcmaes-1.6.9.dist-info}/WHEEL +1 -1
- fcmaes/hhcpp.py +0 -114
- fcmaes/lib/libgtoplib.dll +0 -0
- fcmaes/lib/libgtoplib.so +0 -0
- fcmaes-1.1.3.dist-info/RECORD +0 -23
- {fcmaes-1.1.3.dist-info → fcmaes-1.6.9.dist-info}/LICENSE +0 -0
- {fcmaes-1.1.3.dist-info → fcmaes-1.6.9.dist-info}/top_level.txt +0 -0
fcmaes/moretry.py
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# Copyright (c) Dietmar Wolz.
|
|
2
|
+
#
|
|
3
|
+
# This source code is licensed under the MIT license found in the
|
|
4
|
+
# LICENSE file in the root directory.
|
|
5
|
+
|
|
6
|
+
# parallel optimization retry of a multi-objective problem.
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import math, sys, time, warnings, threadpoolctl
|
|
10
|
+
import multiprocessing as mp
|
|
11
|
+
from multiprocessing import Process
|
|
12
|
+
from scipy.optimize import Bounds
|
|
13
|
+
from numpy.random import Generator, PCG64DXSM, SeedSequence
|
|
14
|
+
from fcmaes.optimizer import de_cma, dtime, Optimizer
|
|
15
|
+
from fcmaes import retry, advretry
|
|
16
|
+
from loguru import logger
|
|
17
|
+
|
|
18
|
+
from typing import Optional, Callable, Tuple
|
|
19
|
+
from numpy.typing import ArrayLike
|
|
20
|
+
|
|
21
|
+
def minimize(fun: Callable[[ArrayLike], float],
|
|
22
|
+
bounds: Bounds,
|
|
23
|
+
weight_bounds: Bounds,
|
|
24
|
+
ncon: Optional[int] = 0,
|
|
25
|
+
value_exp: Optional[float] = 2.0,
|
|
26
|
+
value_limits: Optional[ArrayLike] = None,
|
|
27
|
+
num_retries: Optional[int] = 1024,
|
|
28
|
+
workers: Optional[int] = mp.cpu_count(),
|
|
29
|
+
popsize: Optional[int] = 31,
|
|
30
|
+
max_evaluations: Optional[int] = 50000,
|
|
31
|
+
capacity: Optional[int] = None,
|
|
32
|
+
optimizer: Optional[Optimizer] = None,
|
|
33
|
+
statistic_num: Optional[int] = 0,
|
|
34
|
+
plot_name: Optional[str] = None
|
|
35
|
+
) -> Tuple[np.ndarray, np.ndarray]:
|
|
36
|
+
"""Minimization of a multi objective function of one or more variables using parallel
|
|
37
|
+
optimization retry.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
fun : callable
|
|
42
|
+
The objective function to be minimized.
|
|
43
|
+
``fun(x) -> float``
|
|
44
|
+
where ``x`` is an 1-D array with shape (n,)
|
|
45
|
+
bounds : sequence or `Bounds`, optional
|
|
46
|
+
Bounds on variables. There are two ways to specify the bounds:
|
|
47
|
+
1. Instance of the `scipy.Bounds` class.
|
|
48
|
+
2. Sequence of ``(min, max)`` pairs for each element in `x`. None
|
|
49
|
+
is used to specify no bound.
|
|
50
|
+
weight_bounds : `Bounds`, optional
|
|
51
|
+
Bounds on objective weights.
|
|
52
|
+
ncon : int, optional
|
|
53
|
+
number of constraints
|
|
54
|
+
value_exp : float, optional
|
|
55
|
+
exponent applied to the objective values for the weighted sum.
|
|
56
|
+
value_limits : sequence of floats, optional
|
|
57
|
+
Upper limit for optimized objective values to be stored.
|
|
58
|
+
num_retries : int, optional
|
|
59
|
+
Number of optimization retries.
|
|
60
|
+
workers : int, optional
|
|
61
|
+
number of parallel processes used. Default is mp.cpu_count()
|
|
62
|
+
popsize = int, optional
|
|
63
|
+
CMA-ES population size used for all CMA-ES runs.
|
|
64
|
+
Not used for differential evolution.
|
|
65
|
+
Ignored if parameter optimizer is defined.
|
|
66
|
+
max_evaluations : int, optional
|
|
67
|
+
Forced termination of all optimization runs after ``max_evaluations``
|
|
68
|
+
function evaluations. Only used if optimizer is undefined, otherwise
|
|
69
|
+
this setting is defined in the optimizer.
|
|
70
|
+
capacity : int, optional
|
|
71
|
+
capacity of the evaluation store.
|
|
72
|
+
optimizer : optimizer.Optimizer, optional
|
|
73
|
+
optimizer to use. Default is a sequence of differential evolution and CMA-ES.
|
|
74
|
+
plot_name : plot_name, optional
|
|
75
|
+
if defined the pareto front is plotted during the optimization to monitor progress
|
|
76
|
+
|
|
77
|
+
Returns
|
|
78
|
+
-------
|
|
79
|
+
xs, ys: list of argument vectors and corresponding value vectors of the optimization results. """
|
|
80
|
+
|
|
81
|
+
if optimizer is None:
|
|
82
|
+
optimizer = de_cma(max_evaluations, popsize)
|
|
83
|
+
if capacity is None:
|
|
84
|
+
capacity = num_retries
|
|
85
|
+
store = retry.Store(fun, bounds, capacity = capacity,
|
|
86
|
+
statistic_num = statistic_num)
|
|
87
|
+
store.plot_name = plot_name
|
|
88
|
+
xs = np.array(mo_retry(fun, weight_bounds, ncon, value_exp,
|
|
89
|
+
store, optimizer.minimize, num_retries, value_limits, workers))
|
|
90
|
+
ys = np.array([fun(x) for x in xs])
|
|
91
|
+
return xs, ys
|
|
92
|
+
|
|
93
|
+
def mo_retry(fun: Callable[[ArrayLike], float],
|
|
94
|
+
weight_bounds: Bounds,
|
|
95
|
+
ncon: int,
|
|
96
|
+
y_exp: float,
|
|
97
|
+
store,
|
|
98
|
+
optimize: Callable,
|
|
99
|
+
num_retries: int,
|
|
100
|
+
value_limits: ArrayLike,
|
|
101
|
+
workers: Optional[int] = mp.cpu_count()):
|
|
102
|
+
|
|
103
|
+
sg = SeedSequence()
|
|
104
|
+
rgs = [Generator(PCG64DXSM(s)) for s in sg.spawn(workers)]
|
|
105
|
+
proc=[Process(target=_retry_loop,
|
|
106
|
+
args=(pid, rgs, fun, weight_bounds, ncon, y_exp,
|
|
107
|
+
store, optimize, num_retries, value_limits)) for pid in range(workers)]
|
|
108
|
+
[p.start() for p in proc]
|
|
109
|
+
[p.join() for p in proc]
|
|
110
|
+
store.sort()
|
|
111
|
+
store.dump()
|
|
112
|
+
return store.xs_view
|
|
113
|
+
|
|
114
|
+
def _retry_loop(pid, rgs, fun, weight_bounds, ncon, y_exp,
|
|
115
|
+
store, optimize, num_retries, value_limits):
|
|
116
|
+
|
|
117
|
+
store.create_xs_view()
|
|
118
|
+
lower = store.lower
|
|
119
|
+
wlb = np.array(weight_bounds.lb)
|
|
120
|
+
wub = np.array(weight_bounds.ub)
|
|
121
|
+
with threadpoolctl.threadpool_limits(limits=1, user_api="blas"):
|
|
122
|
+
while store.get_runs_compare_incr(num_retries):
|
|
123
|
+
try:
|
|
124
|
+
rg = rgs[pid]
|
|
125
|
+
w = rg.uniform(size=len(wub))
|
|
126
|
+
w /= _avg_exp(w, y_exp) # correct scaling
|
|
127
|
+
w = wlb + w * (wub - wlb)
|
|
128
|
+
wrapper = mo_wrapper(fun, w, ncon, y_exp)
|
|
129
|
+
x, y, evals = optimize(wrapper.eval, Bounds(store.lower, store.upper), None,
|
|
130
|
+
[rg.uniform(0.05, 0.1)]*len(lower), rg, store)
|
|
131
|
+
objs = wrapper.mo_eval(x) # retrieve the objective values
|
|
132
|
+
if value_limits is None or all([objs[i] < value_limits[i] for i in range(len(w))]):
|
|
133
|
+
store.add_result(y, x, evals, np.inf)
|
|
134
|
+
if not store.plot_name is None:
|
|
135
|
+
name = store.plot_name + "_moretry_" + str(store.get_count_evals())
|
|
136
|
+
xs = np.array(store.get_xs())
|
|
137
|
+
ys = np.array([fun(x) for x in xs])
|
|
138
|
+
np.savez_compressed(name, xs=xs, ys=ys)
|
|
139
|
+
plot(name, ncon, xs, ys)
|
|
140
|
+
except Exception as ex:
|
|
141
|
+
print(str(ex))
|
|
142
|
+
|
|
143
|
+
def pareto(xs: np.ndarray, ys: np.ndarray):
|
|
144
|
+
"""pareto front for argument vectors and corresponding function value vectors."""
|
|
145
|
+
par = _pareto(ys)
|
|
146
|
+
xp = xs[par]
|
|
147
|
+
yp = ys[par]
|
|
148
|
+
ya = np.argsort(yp.T[0])
|
|
149
|
+
return xp[ya], yp[ya]
|
|
150
|
+
|
|
151
|
+
class mo_wrapper(object):
|
|
152
|
+
"""wrapper for multi objective functions applying the weighted sum approach."""
|
|
153
|
+
|
|
154
|
+
def __init__(self, fun, weights, ncon, y_exp=2):
|
|
155
|
+
self.fun = fun
|
|
156
|
+
self.weights = weights
|
|
157
|
+
self.ny = len(weights)
|
|
158
|
+
self.nobj = self.ny - ncon
|
|
159
|
+
self.ncon = ncon
|
|
160
|
+
self.y_exp = y_exp
|
|
161
|
+
|
|
162
|
+
def eval(self, x):
|
|
163
|
+
y = self.fun(np.array(x))
|
|
164
|
+
weighted = _avg_exp(self.weights*y, self.y_exp)
|
|
165
|
+
if self.ncon > 0: # check constraint violations
|
|
166
|
+
violations = np.fromiter((i for i in range(self.nobj, self.ny) if y[i] > 0), dtype=int)
|
|
167
|
+
if len(violations) > 0:
|
|
168
|
+
weighted += sum(self.weights[violations])
|
|
169
|
+
return weighted
|
|
170
|
+
|
|
171
|
+
def mo_eval(self, x):
|
|
172
|
+
return self.fun(np.array(x))
|
|
173
|
+
|
|
174
|
+
def minimize_plot(name: str,
|
|
175
|
+
optimizer: Optimizer,
|
|
176
|
+
fun: Callable[[ArrayLike], float],
|
|
177
|
+
bounds: Bounds,
|
|
178
|
+
weight_bounds,
|
|
179
|
+
ncon: Optional[int] = 0,
|
|
180
|
+
value_limits: Optional[ArrayLike] = None,
|
|
181
|
+
num_retries: Optional[int] = 1024,
|
|
182
|
+
exp: Optional[float] = 2.0,
|
|
183
|
+
workers: Optional[int] = mp.cpu_count(),
|
|
184
|
+
statistic_num = 0, plot_name = None):
|
|
185
|
+
|
|
186
|
+
time0 = time.perf_counter() # optimization start time
|
|
187
|
+
name += '_' + optimizer.name
|
|
188
|
+
logger.info('optimize ' + name)
|
|
189
|
+
xs, ys = minimize(fun, bounds, weight_bounds, ncon,
|
|
190
|
+
value_exp = exp,
|
|
191
|
+
value_limits = value_limits,
|
|
192
|
+
num_retries = num_retries,
|
|
193
|
+
optimizer = optimizer,
|
|
194
|
+
workers = workers,
|
|
195
|
+
statistic_num = statistic_num, plot_name = plot_name)
|
|
196
|
+
logger.info(name + ' time ' + str(dtime(time0)))
|
|
197
|
+
np.savez_compressed(name, xs=xs, ys=ys)
|
|
198
|
+
plot(name, ncon, xs, ys)
|
|
199
|
+
|
|
200
|
+
def plot(name, ncon, xs, ys, eps = 1E-2, all=True, interp=False, plot3d=False):
|
|
201
|
+
try:
|
|
202
|
+
if ncon > 0: # select feasible
|
|
203
|
+
ycon = np.array([np.maximum(y[-ncon:], 0) for y in ys])
|
|
204
|
+
con = np.sum(ycon, axis=1)
|
|
205
|
+
nobj = len(ys[0]) - ncon
|
|
206
|
+
feasible = np.fromiter((i for i in range(len(ys)) if con[i] < eps), dtype=int)
|
|
207
|
+
if len(feasible) > 0:
|
|
208
|
+
xs, ys = xs[feasible], np.array([y[:nobj] for y in ys[feasible]])
|
|
209
|
+
else:
|
|
210
|
+
print("no feasible")
|
|
211
|
+
return
|
|
212
|
+
if all:
|
|
213
|
+
retry.plot(ys, 'all_' + name + '.png', interp=False)
|
|
214
|
+
xs, ys = pareto(xs, ys)
|
|
215
|
+
for x, y in zip(xs, ys):
|
|
216
|
+
print(str(list(y)) + ' ' + str([round(xi,5) for xi in x]))
|
|
217
|
+
retry.plot(ys, 'front_' + name + '.png', interp=interp, plot3d=plot3d)
|
|
218
|
+
except Exception as ex:
|
|
219
|
+
print(str(ex))
|
|
220
|
+
|
|
221
|
+
def adv_minimize_plot(name: str,
|
|
222
|
+
optimizer: Optimizer,
|
|
223
|
+
fun: Callable[[ArrayLike], float],
|
|
224
|
+
bounds: Optional[Bounds],
|
|
225
|
+
value_limit: Optional[float] = np.inf,
|
|
226
|
+
num_retries: Optional[int] = 1024,
|
|
227
|
+
statistic_num: Optional[int] = 0):
|
|
228
|
+
|
|
229
|
+
time0 = time.perf_counter() # optimization start time
|
|
230
|
+
name += '_smart_' + optimizer.name
|
|
231
|
+
logger.info('smart optimize ' + name)
|
|
232
|
+
store = advretry.Store(lambda x:fun(x)[0], bounds, capacity=5000,
|
|
233
|
+
num_retries=num_retries, statistic_num = statistic_num)
|
|
234
|
+
advretry.retry(store, optimizer.minimize, value_limit)
|
|
235
|
+
xs = np.array(store.get_xs())
|
|
236
|
+
ys = np.fromiter((fun(x) for x in xs), dtype=float)
|
|
237
|
+
retry.plot(ys, '_all_' + name + '.png', interp=False)
|
|
238
|
+
np.savez_compressed(name , xs=xs, ys=ys)
|
|
239
|
+
xs, front = pareto(xs, ys)
|
|
240
|
+
logger.info(name+ ' time ' + str(dtime(time0)))
|
|
241
|
+
retry.plot(front, '_front_' + name + '.png')
|
|
242
|
+
|
|
243
|
+
def _avg_exp(y, y_exp):
|
|
244
|
+
with warnings.catch_warnings():
|
|
245
|
+
warnings.simplefilter("ignore")
|
|
246
|
+
weighted = sum([y[i]**y_exp for i in range(len(y))])**(1.0/y_exp)
|
|
247
|
+
return weighted
|
|
248
|
+
|
|
249
|
+
def _pareto_values(ys):
|
|
250
|
+
ys = ys[ys.sum(1).argsort()[::-1]]
|
|
251
|
+
undominated = np.ones(ys.shape[0], dtype=bool)
|
|
252
|
+
for i in range(ys.shape[0]):
|
|
253
|
+
n = ys.shape[0]
|
|
254
|
+
if i >= n:
|
|
255
|
+
break
|
|
256
|
+
undominated[i+1:n] = (ys[i+1:] >= ys[i]).any(1)
|
|
257
|
+
ys = ys[undominated[:n]]
|
|
258
|
+
return ys
|
|
259
|
+
|
|
260
|
+
def _pareto(ys):
|
|
261
|
+
pareto = np.arange(ys.shape[0])
|
|
262
|
+
index = 0 # Next index to search for
|
|
263
|
+
while index < len(ys):
|
|
264
|
+
mask = np.any(ys < ys[index], axis=1)
|
|
265
|
+
mask[index] = True
|
|
266
|
+
pareto = pareto[mask] # Remove dominated points
|
|
267
|
+
ys = ys[mask]
|
|
268
|
+
index = np.sum(mask[:index])+1
|
|
269
|
+
return pareto
|
|
270
|
+
|
fcmaes/multiretry.py
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Copyright (c) Dietmar Wolz.
|
|
2
|
+
#
|
|
3
|
+
# This source code is licensed under the MIT license found in the
|
|
4
|
+
# LICENSE file in the root directory.
|
|
5
|
+
|
|
6
|
+
# parallel optimization retry of a list of problems.
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import _pickle as cPickle
|
|
10
|
+
import bz2
|
|
11
|
+
import multiprocessing as mp
|
|
12
|
+
from scipy.optimize import OptimizeResult, Bounds
|
|
13
|
+
from fcmaes.optimizer import de_cma, eprint, Optimizer
|
|
14
|
+
from fcmaes import advretry
|
|
15
|
+
|
|
16
|
+
from fcmaes.evaluator import is_debug_active
|
|
17
|
+
from loguru import logger
|
|
18
|
+
from typing import Optional, Callable, Tuple, List
|
|
19
|
+
from numpy.typing import ArrayLike
|
|
20
|
+
|
|
21
|
+
def minimize(problems: ArrayLike,
|
|
22
|
+
ids: Optional[ArrayLike] = None,
|
|
23
|
+
retries_inc: Optional[int] = min(256, 8*mp.cpu_count()),
|
|
24
|
+
num_retries: Optional[int] = 10000,
|
|
25
|
+
keep: Optional[float] = 0.7,
|
|
26
|
+
optimizer: Optional[Optimizer] = de_cma(1500),
|
|
27
|
+
datafile = None) -> List:
|
|
28
|
+
|
|
29
|
+
"""Minimization of a list of optimization problems by first applying parallel retry
|
|
30
|
+
to filter the best ones and then applying coordinated retry to evaluate these further.
|
|
31
|
+
Can replace mixed integer optimization if the integer variables are narrowly bound.
|
|
32
|
+
In this case all combinations of these integer values can be enumerated to generate a
|
|
33
|
+
list of problem instances each representing one combination. See for instance
|
|
34
|
+
https://www.esa.int/gsp/ACT/projects/gtop/tandem where there is a problem instance for each
|
|
35
|
+
planet sequence.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
|
|
40
|
+
problems: list
|
|
41
|
+
list of objects providing name, fun and bounds attributes like fcmaes.astro.Astrofun
|
|
42
|
+
|
|
43
|
+
ids: list, optional
|
|
44
|
+
list of objects corresponding to the list of problems used in logging to identify the
|
|
45
|
+
problem variant currently logged. If None, the index of the problem
|
|
46
|
+
variant is used instead.
|
|
47
|
+
|
|
48
|
+
retries_inc: int, optional
|
|
49
|
+
number of coordinated retries applied in the problem filter for each problem
|
|
50
|
+
in each iteration.
|
|
51
|
+
|
|
52
|
+
num_retries: int, optional
|
|
53
|
+
number of coordinated retries applied in the problem filter for the winner problem.
|
|
54
|
+
|
|
55
|
+
keep: float, optional
|
|
56
|
+
rate of the problems kept after each iteration. 100*(1 - keep) % will be deleted.
|
|
57
|
+
|
|
58
|
+
optimizer: optimizer.Optimizer, optional
|
|
59
|
+
optimizer to use for the problem filter.
|
|
60
|
+
|
|
61
|
+
datafile, optional
|
|
62
|
+
file to persist / retrieve the internal state of the optimizations.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
dictionary( optimizer -> ret): scipy.OptimizeResult
|
|
67
|
+
The optimization result is represented as an ``OptimizeResult`` object.
|
|
68
|
+
Important attributes are: ``x`` the solution array,
|
|
69
|
+
``fun`` the best function value, ``nfev`` the number of function evaluations,
|
|
70
|
+
``success`` a Boolean flag indicating if the optimizer exited successfully. """
|
|
71
|
+
|
|
72
|
+
solver = multiretry()
|
|
73
|
+
n = len(problems)
|
|
74
|
+
|
|
75
|
+
for i in range(n):
|
|
76
|
+
id = str(i+1) if ids is None else ids[i]
|
|
77
|
+
solver.add(problem_stats(problems[i], id, i, retries_inc, num_retries))
|
|
78
|
+
|
|
79
|
+
if not datafile is None:
|
|
80
|
+
solver.load(datafile)
|
|
81
|
+
|
|
82
|
+
while solver.size() > 1:
|
|
83
|
+
solver.retry(optimizer)
|
|
84
|
+
to_remove = int(round((1.0 - keep) * solver.size()))
|
|
85
|
+
if to_remove == 0 and keep < 1.0:
|
|
86
|
+
to_remove = 1
|
|
87
|
+
solver.remove_worst(to_remove)
|
|
88
|
+
solver.dump()
|
|
89
|
+
if not datafile is None:
|
|
90
|
+
solver.save(datafile)
|
|
91
|
+
|
|
92
|
+
idx = solver.values_all().argsort()
|
|
93
|
+
return list(np.asarray(solver.all_stats)[idx])
|
|
94
|
+
|
|
95
|
+
class problem_stats:
|
|
96
|
+
|
|
97
|
+
def __init__(self, prob, id, index, retries_inc = 64, num_retries = 10000):
|
|
98
|
+
self.store = advretry.Store(prob.fun, prob.bounds, num_retries=num_retries)
|
|
99
|
+
self.prob = prob
|
|
100
|
+
self.name = prob.name
|
|
101
|
+
self.fun = prob.fun
|
|
102
|
+
self.retries_inc = retries_inc
|
|
103
|
+
self.value = 0
|
|
104
|
+
self.id = id
|
|
105
|
+
self.index = index
|
|
106
|
+
self.ret = None
|
|
107
|
+
self.store.num_retries = self.retries_inc
|
|
108
|
+
|
|
109
|
+
def retry(self, optimizer):
|
|
110
|
+
self.store.num_retries += self.retries_inc
|
|
111
|
+
self.ret = advretry.retry(self.store, optimizer.minimize)
|
|
112
|
+
self.value = self.store.get_y_best()
|
|
113
|
+
|
|
114
|
+
class multiretry:
|
|
115
|
+
|
|
116
|
+
def __init__(self):
|
|
117
|
+
self.problem_stats = []
|
|
118
|
+
self.all_stats = []
|
|
119
|
+
|
|
120
|
+
def add(self, stats):
|
|
121
|
+
self.problem_stats.append(stats)
|
|
122
|
+
self.all_stats.append(stats)
|
|
123
|
+
|
|
124
|
+
def retry(self, optimizer):
|
|
125
|
+
for ps in self.problem_stats:
|
|
126
|
+
if is_debug_active():
|
|
127
|
+
logger.debug("problem " + ps.prob.name + ' ' + str(ps.id))
|
|
128
|
+
ps.retry(optimizer)
|
|
129
|
+
|
|
130
|
+
def values(self):
|
|
131
|
+
return np.fromiter((ps.value for ps in self.problem_stats), dtype=float)
|
|
132
|
+
|
|
133
|
+
def remove_worst(self, n = 1):
|
|
134
|
+
idx = self.values().argsort()
|
|
135
|
+
self.problem_stats = list(np.asarray(self.problem_stats)[idx])
|
|
136
|
+
for _ in range(n):
|
|
137
|
+
self.problem_stats.pop(-1)
|
|
138
|
+
|
|
139
|
+
def size(self):
|
|
140
|
+
return len(self.problem_stats)
|
|
141
|
+
|
|
142
|
+
def dump(self):
|
|
143
|
+
if is_debug_active():
|
|
144
|
+
for i in range(self.size()):
|
|
145
|
+
ps = self.problem_stats[i]
|
|
146
|
+
logger.debug(str(ps.id) + ' ' + str(ps.value))
|
|
147
|
+
|
|
148
|
+
def dump_all(self):
|
|
149
|
+
if is_debug_active():
|
|
150
|
+
idx = self.values_all().argsort()
|
|
151
|
+
self.all_stats = list(np.asarray(self.all_stats)[idx])
|
|
152
|
+
for i in range(len(self.all_stats)):
|
|
153
|
+
ps = self.all_stats[i]
|
|
154
|
+
logger.debug(str(ps.id) + ' ' + str(ps.value))
|
|
155
|
+
|
|
156
|
+
def values_all(self):
|
|
157
|
+
return np.fromiter((ps.value for ps in self.all_stats), dtype=float)
|
|
158
|
+
|
|
159
|
+
def result(self):
|
|
160
|
+
idx = self.values_all().argsort()
|
|
161
|
+
self.all_stats = list(np.asarray(self.all_stats)[idx])
|
|
162
|
+
ret = []
|
|
163
|
+
for i in range(len(self.all_stats)):
|
|
164
|
+
problem = self.all_stats[i].prob
|
|
165
|
+
store = self.all_stats[i].store
|
|
166
|
+
ret.append([problem,
|
|
167
|
+
OptimizeResult(x=store.get_x_best(), fun=store.get_y_best(),
|
|
168
|
+
nfev=store.get_count_evals(), success=True)])
|
|
169
|
+
|
|
170
|
+
# persist all stats
|
|
171
|
+
def save(self, name):
|
|
172
|
+
try:
|
|
173
|
+
with bz2.BZ2File(name + '.pbz2', 'w') as f:
|
|
174
|
+
cPickle.dump(self.get_data(), f)
|
|
175
|
+
except Exception as ex:
|
|
176
|
+
eprint('error writing data file ' + name + '.pbz2 ' + str(ex))
|
|
177
|
+
|
|
178
|
+
def load(self, name):
|
|
179
|
+
try:
|
|
180
|
+
data = cPickle.load(bz2.BZ2File(name + '.pbz2', 'rb'))
|
|
181
|
+
self.set_data(data)
|
|
182
|
+
except Exception as ex:
|
|
183
|
+
eprint('error reading data file ' + name + '.pbz2 ' + str(ex))
|
|
184
|
+
|
|
185
|
+
def get_data(self):
|
|
186
|
+
data = []
|
|
187
|
+
for stats in self.all_stats:
|
|
188
|
+
data.append(stats.store.get_data())
|
|
189
|
+
return data
|
|
190
|
+
|
|
191
|
+
def set_data(self, data):
|
|
192
|
+
for i in range(len(data)):
|
|
193
|
+
self.all_stats[i].store.set_data(data[i])
|
|
194
|
+
|
|
195
|
+
|