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/modecpp.py
ADDED
|
@@ -0,0 +1,470 @@
|
|
|
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
|
+
"""Eigen based implementation of multi objective
|
|
7
|
+
Differential Evolution using the DE/pareto/1 strategy.
|
|
8
|
+
Derived and adapted for MO from its C++ counterpart
|
|
9
|
+
https://github.com/dietmarwo/fast-cma-es/blob/master/_fcmaescpp/deoptimizer.cpp
|
|
10
|
+
|
|
11
|
+
Can switch to NSGA-II like population update via parameter 'nsga_update'.
|
|
12
|
+
Then it works essentially like NSGA-II but instead of the tournament selection
|
|
13
|
+
the whole population is sorted and the best individuals survive. To do this
|
|
14
|
+
efficiently the crowd distance ordering is slightly inaccurate.
|
|
15
|
+
|
|
16
|
+
Supports parallel fitness function evaluation.
|
|
17
|
+
|
|
18
|
+
Features enhanced multiple constraint ranking (https://www.jstage.jst.go.jp/article/tjpnsec/11/2/11_18/_article/-char/en/)
|
|
19
|
+
improving its performance in handling constraints for engineering design optimization.
|
|
20
|
+
|
|
21
|
+
Enables the comparison of DE and NSGA-II population update mechanism with everything else
|
|
22
|
+
kept completely identical.
|
|
23
|
+
|
|
24
|
+
Requires python 3.5 or higher.
|
|
25
|
+
|
|
26
|
+
Uses the following deviation from the standard DE algorithm:
|
|
27
|
+
a) oscillating CR/F parameters.
|
|
28
|
+
|
|
29
|
+
You may keep parameters F and CR at their defaults since this implementation works well with the given settings for most problems,
|
|
30
|
+
since the algorithm oscillates between different F and CR settings.
|
|
31
|
+
|
|
32
|
+
For expensive objective functions (e.g. machine learning parameter optimization) use the workers
|
|
33
|
+
parameter to parallelize objective function evaluation. This causes delayed population update.
|
|
34
|
+
It is usually preferrable if popsize > workers and workers = mp.cpu_count() to improve CPU utilization.
|
|
35
|
+
|
|
36
|
+
The ints parameter is a boolean array indicating which parameters are discrete integer values. This
|
|
37
|
+
parameter was introduced after observing non optimal DE-results for the ESP2 benchmark problem:
|
|
38
|
+
https://github.com/AlgTUDelft/ExpensiveOptimBenchmark/blob/master/expensiveoptimbenchmark/problems/DockerCFDBenchmark.py
|
|
39
|
+
If defined it causes a "special treatment" for discrete variables: They are rounded to the next integer value and
|
|
40
|
+
there is an additional mutation to avoid getting stuck to local minima.
|
|
41
|
+
|
|
42
|
+
See https://github.com/dietmarwo/fast-cma-es/blob/master/tutorials/MODE.adoc for a detailed description.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
import os
|
|
46
|
+
import time
|
|
47
|
+
import threadpoolctl
|
|
48
|
+
import ctypes as ct
|
|
49
|
+
import multiprocessing as mp
|
|
50
|
+
from multiprocessing import Process
|
|
51
|
+
import numpy as np
|
|
52
|
+
from scipy.optimize import Bounds
|
|
53
|
+
from fcmaes import mode, moretry
|
|
54
|
+
from fcmaes.mode import _filter, store
|
|
55
|
+
from numpy.random import Generator, PCG64DXSM, SeedSequence
|
|
56
|
+
from fcmaes.optimizer import dtime
|
|
57
|
+
from fcmaes.evaluator import mo_call_back_type, callback_mo, parallel_mo, libcmalib
|
|
58
|
+
from fcmaes.de import _check_bounds
|
|
59
|
+
from fcmaes.evaluator import is_debug_active
|
|
60
|
+
from loguru import logger
|
|
61
|
+
from typing import Optional, Callable, Tuple
|
|
62
|
+
from numpy.typing import ArrayLike
|
|
63
|
+
|
|
64
|
+
os.environ['MKL_DEBUG_CPU_TYPE'] = '5'
|
|
65
|
+
|
|
66
|
+
def minimize(mofun: Callable[[ArrayLike], ArrayLike],
|
|
67
|
+
nobj: int,
|
|
68
|
+
ncon: int,
|
|
69
|
+
bounds: Bounds,
|
|
70
|
+
guess: Optional[np.ndarray] = None,
|
|
71
|
+
popsize: Optional[int] = 64,
|
|
72
|
+
max_evaluations: Optional[int] = 100000,
|
|
73
|
+
workers: Optional[int] = 1,
|
|
74
|
+
f: Optional[float] = 0.5,
|
|
75
|
+
cr: Optional[float] = 0.9,
|
|
76
|
+
pro_c: Optional[float] = 0.5,
|
|
77
|
+
dis_c: Optional[float] = 15.0,
|
|
78
|
+
pro_m: Optional[float] = 0.9,
|
|
79
|
+
dis_m: Optional[float] = 20.0,
|
|
80
|
+
nsga_update: Optional[bool] = True,
|
|
81
|
+
pareto_update: Optional[int] = 0,
|
|
82
|
+
ints: Optional[ArrayLike] = None,
|
|
83
|
+
min_mutate: Optional[float] = 0.1,
|
|
84
|
+
max_mutate: Optional[float] = 0.5,
|
|
85
|
+
rg: Optional[Generator] = Generator(PCG64DXSM()),
|
|
86
|
+
store: Optional[store] = None,
|
|
87
|
+
runid: Optional[int] = 0) -> Tuple[np.ndarray, np.ndarray]:
|
|
88
|
+
|
|
89
|
+
"""Minimization of a multi objjective function of one or more variables using
|
|
90
|
+
Differential Evolution.
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
mofun : callable
|
|
95
|
+
The objective function to be minimized.
|
|
96
|
+
``mofun(x) -> ndarray(float)``
|
|
97
|
+
where ``x`` is an 1-D array with shape (n,)
|
|
98
|
+
nobj : int
|
|
99
|
+
number of objectives
|
|
100
|
+
ncon : int
|
|
101
|
+
number of constraints, default is 0.
|
|
102
|
+
The objective function needs to return vectors of size nobj + ncon
|
|
103
|
+
bounds : sequence or `Bounds`
|
|
104
|
+
Bounds on variables. There are two ways to specify the bounds:
|
|
105
|
+
1. Instance of the `scipy.Bounds` class.
|
|
106
|
+
2. Sequence of ``(min, max)`` pairs for each element in `x`. None
|
|
107
|
+
is used to specify no bound.
|
|
108
|
+
guess : ndarray, shape (popsize,dim) or Tuple
|
|
109
|
+
Initial guess.
|
|
110
|
+
popsize : int, optional
|
|
111
|
+
Population size.
|
|
112
|
+
max_evaluations : int, optional
|
|
113
|
+
Forced termination after ``max_evaluations`` function evaluations.
|
|
114
|
+
workers : int or None, optional
|
|
115
|
+
if workers > 1, function evaluation is performed in parallel for the whole population.
|
|
116
|
+
Useful for costly objective functions
|
|
117
|
+
f = float, optional
|
|
118
|
+
The mutation constant. In the literature this is also known as differential weight,
|
|
119
|
+
being denoted by F. Should be in the range [0, 2], usually leave at default.
|
|
120
|
+
cr = float, optional
|
|
121
|
+
The recombination constant. Should be in the range [0, 1].
|
|
122
|
+
In the literature this is also known as the crossover probability, usually leave at default.
|
|
123
|
+
pro_c, dis_c, pro_m, dis_m = float, optional
|
|
124
|
+
NSGA population update parameters, usually leave at default.
|
|
125
|
+
nsga_update = boolean, optional
|
|
126
|
+
Use of NSGA-II/SBX or DE population update. Default is True
|
|
127
|
+
pareto_update = float, optional
|
|
128
|
+
Only applied if nsga_update = False. Favor better solutions for sample generation. Default 0 -
|
|
129
|
+
use all population members with the same probability.
|
|
130
|
+
ints = list or array of bool, optional
|
|
131
|
+
indicating which parameters are discrete integer values. If defined these parameters will be
|
|
132
|
+
rounded to the next integer and some additional mutation of discrete parameters are performed.
|
|
133
|
+
min_mutate = float, optional
|
|
134
|
+
Determines the minimal mutation rate for discrete integer parameters.
|
|
135
|
+
max_mutate = float, optional
|
|
136
|
+
Determines the maximal mutation rate for discrete integer parameters.
|
|
137
|
+
rg = numpy.random.Generator, optional
|
|
138
|
+
Random generator for creating random guesses.
|
|
139
|
+
store : result store, optional
|
|
140
|
+
if defined the optimization results are added to the result store.
|
|
141
|
+
|
|
142
|
+
runid : int, optional
|
|
143
|
+
id used to identify the run for debugging / logging.
|
|
144
|
+
|
|
145
|
+
Returns
|
|
146
|
+
-------
|
|
147
|
+
x, y: list of argument vectors and corresponding value vectors of the optimization results. """
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
mode = MODE_C(nobj, ncon, bounds, popsize, f, cr, pro_c, dis_c, pro_m, dis_m,
|
|
151
|
+
nsga_update, pareto_update, ints, min_mutate, max_mutate, rg, runid)
|
|
152
|
+
mode.set_guess(guess, mofun, rg)
|
|
153
|
+
if workers <= 1:
|
|
154
|
+
x, y = mode.minimize_ser(mofun, max_evaluations)
|
|
155
|
+
else:
|
|
156
|
+
x, y = mode.minimize_par(mofun, max_evaluations, workers)
|
|
157
|
+
if not store is None:
|
|
158
|
+
store.create_views()
|
|
159
|
+
store.add_results(x, y)
|
|
160
|
+
return x, y
|
|
161
|
+
except Exception as ex:
|
|
162
|
+
print(str(ex))
|
|
163
|
+
return None, None
|
|
164
|
+
|
|
165
|
+
def retry(mofun: Callable[[ArrayLike], ArrayLike],
|
|
166
|
+
nobj: int,
|
|
167
|
+
ncon: int,
|
|
168
|
+
bounds: Bounds,
|
|
169
|
+
guess: Optional[np.ndarray] = None,
|
|
170
|
+
num_retries: Optional[int] = 64,
|
|
171
|
+
popsize: Optional[int] = 64,
|
|
172
|
+
max_evaluations: Optional[int] = 100000,
|
|
173
|
+
workers: Optional[int] = mp.cpu_count(),
|
|
174
|
+
nsga_update: Optional[bool] = False,
|
|
175
|
+
pareto_update: Optional[int] = 0,
|
|
176
|
+
ints: Optional[ArrayLike] = None,
|
|
177
|
+
capacity: Optional[int] = None):
|
|
178
|
+
|
|
179
|
+
"""Minimization of a multi objjective function of one or more variables using parallel
|
|
180
|
+
optimization retry.
|
|
181
|
+
|
|
182
|
+
Parameters
|
|
183
|
+
----------
|
|
184
|
+
mofun : callable
|
|
185
|
+
The objective function to be minimized.
|
|
186
|
+
``mofun(x, *args) -> ndarray(float)``
|
|
187
|
+
where ``x`` is an 1-D array with shape (n,) and ``args``
|
|
188
|
+
is a tuple of the fixed parameters needed to completely
|
|
189
|
+
specify the function.
|
|
190
|
+
nobj : int
|
|
191
|
+
number of objectives
|
|
192
|
+
ncon : int
|
|
193
|
+
number of constraints, default is 0.
|
|
194
|
+
The objective function needs to return vectors of size nobj + ncon
|
|
195
|
+
bounds : sequence or `Bounds`
|
|
196
|
+
Bounds on variables. There are two ways to specify the bounds:
|
|
197
|
+
1. Instance of the `scipy.Bounds` class.
|
|
198
|
+
2. Sequence of ``(min, max)`` pairs for each element in `x`. None
|
|
199
|
+
is used to specify no bound.
|
|
200
|
+
guess : ndarray, shape (popsize,dim) or Tuple
|
|
201
|
+
Initial guess.
|
|
202
|
+
num_retries : int, optional
|
|
203
|
+
Number of optimization retries.
|
|
204
|
+
popsize : int, optional
|
|
205
|
+
Population size.
|
|
206
|
+
max_evaluations : int, optional
|
|
207
|
+
Forced termination after ``max_evaluations`` function evaluations.
|
|
208
|
+
workers : int or None, optional
|
|
209
|
+
If not workers is None, optimization is performed in parallel.
|
|
210
|
+
nsga_update = boolean, optional
|
|
211
|
+
Use of NSGA-II/SBX or DE population update. Default is False
|
|
212
|
+
pareto_update = float, optional
|
|
213
|
+
Only applied if nsga_update = False. Favor better solutions for sample generation. Default 0 -
|
|
214
|
+
use all population members with the same probability.
|
|
215
|
+
ints = list or array of bool, optional
|
|
216
|
+
indicating which parameters are discrete integer values. If defined these parameters will be
|
|
217
|
+
rounded to the next integer and some additional mutation of discrete parameters are performed.
|
|
218
|
+
capacity : int or None, optional
|
|
219
|
+
capacity of the store collecting all solutions. If full, its content is replaced by its
|
|
220
|
+
pareto front """
|
|
221
|
+
|
|
222
|
+
dim, _, _ = _check_bounds(bounds, None)
|
|
223
|
+
if capacity is None:
|
|
224
|
+
capacity = 2048*popsize
|
|
225
|
+
store = mode.store(dim, nobj + ncon, capacity)
|
|
226
|
+
sg = SeedSequence()
|
|
227
|
+
rgs = [Generator(PCG64DXSM(s)) for s in sg.spawn(workers)]
|
|
228
|
+
proc=[Process(target=_retry_loop,
|
|
229
|
+
args=(num_retries, pid, rgs, mofun, nobj, ncon, bounds, guess, popsize,
|
|
230
|
+
max_evaluations, workers, nsga_update, pareto_update,
|
|
231
|
+
store, ints))
|
|
232
|
+
for pid in range(workers)]
|
|
233
|
+
[p.start() for p in proc]
|
|
234
|
+
[p.join() for p in proc]
|
|
235
|
+
xs, ys = store.get_front()
|
|
236
|
+
return xs, ys
|
|
237
|
+
|
|
238
|
+
def _retry_loop(num_retries, pid, rgs, mofun, nobj, ncon, bounds, guess, popsize,
|
|
239
|
+
max_evaluations, workers, nsga_update, pareto_update,
|
|
240
|
+
store, ints):
|
|
241
|
+
store.create_views()
|
|
242
|
+
t0 = time.perf_counter()
|
|
243
|
+
num = max(1, num_retries - workers)
|
|
244
|
+
with threadpoolctl.threadpool_limits(limits=1, user_api="blas"):
|
|
245
|
+
while store.num_added.value < num:
|
|
246
|
+
minimize(mofun, nobj, ncon, bounds, guess, popsize,
|
|
247
|
+
max_evaluations = max_evaluations,
|
|
248
|
+
nsga_update=nsga_update, pareto_update=pareto_update,
|
|
249
|
+
rg = rgs[pid], store = store, ints=ints)
|
|
250
|
+
if is_debug_active():
|
|
251
|
+
logger.debug("retries = {0}: time = {1:.1f} i = {2}"
|
|
252
|
+
.format(store.num_added.value, dtime(t0), store.num_stored.value))
|
|
253
|
+
|
|
254
|
+
class MODE_C:
|
|
255
|
+
|
|
256
|
+
def __init__(self,
|
|
257
|
+
nobj: int,
|
|
258
|
+
ncon: int,
|
|
259
|
+
bounds: Bounds,
|
|
260
|
+
popsize: Optional[int] = 64,
|
|
261
|
+
f: Optional[float] = 0.5,
|
|
262
|
+
cr: Optional[float] = 0.9,
|
|
263
|
+
pro_c: Optional[float] = 0.5,
|
|
264
|
+
dis_c: Optional[float] = 15.0,
|
|
265
|
+
pro_m: Optional[float] = 0.9,
|
|
266
|
+
dis_m: Optional[float] = 20.0,
|
|
267
|
+
nsga_update: Optional[bool] = True,
|
|
268
|
+
pareto_update: Optional[int] = 0,
|
|
269
|
+
ints: Optional[ArrayLike] = None,
|
|
270
|
+
min_mutate: Optional[float] = 0.1,
|
|
271
|
+
max_mutate: Optional[float] = 0.5,
|
|
272
|
+
rg: Optional[Generator] = Generator(PCG64DXSM()),
|
|
273
|
+
runid: Optional[int] = 0):
|
|
274
|
+
|
|
275
|
+
""" Parameters
|
|
276
|
+
----------
|
|
277
|
+
nobj : int
|
|
278
|
+
number of objectives
|
|
279
|
+
ncon : int
|
|
280
|
+
number of constraints, default is 0.
|
|
281
|
+
The objective function needs to return vectors of size nobj + ncon
|
|
282
|
+
bounds : sequence or `Bounds`
|
|
283
|
+
Bounds on variables. There are two ways to specify the bounds:
|
|
284
|
+
1. Instance of the `scipy.Bounds` class.
|
|
285
|
+
2. Sequence of ``(min, max)`` pairs for each element in `x`. None
|
|
286
|
+
is used to specify no bound.
|
|
287
|
+
popsize : int, optional
|
|
288
|
+
Population size.
|
|
289
|
+
f = float, optional
|
|
290
|
+
The mutation constant. In the literature this is also known as differential weight,
|
|
291
|
+
being denoted by F. Should be in the range [0, 2], usually leave at default.
|
|
292
|
+
cr = float, optional
|
|
293
|
+
The recombination constant. Should be in the range [0, 1].
|
|
294
|
+
In the literature this is also known as the crossover probability, usually leave at default.
|
|
295
|
+
pro_c, dis_c, pro_m, dis_m = float, optional
|
|
296
|
+
NSGA population update parameters, usually leave at default.
|
|
297
|
+
nsga_update = boolean, optional
|
|
298
|
+
Use of NSGA-II or DE population update. Default is True
|
|
299
|
+
pareto_update = float, optional
|
|
300
|
+
Only applied if nsga_update = False. Favor better solutions for sample generation. Default 0 -
|
|
301
|
+
use all population members with the same probability.
|
|
302
|
+
ints = list or array of bool, optional
|
|
303
|
+
indicating which parameters are discrete integer values. If defined these parameters will be
|
|
304
|
+
rounded to the next integer and some additional mutation of discrete parameters are performed.
|
|
305
|
+
min_mutate = float, optional
|
|
306
|
+
Determines the minimal mutation rate for discrete integer parameters.
|
|
307
|
+
max_mutate = float, optional
|
|
308
|
+
Determines the maximal mutation rate for discrete integer parameters.
|
|
309
|
+
rg = numpy.random.Generator, optional
|
|
310
|
+
Random generator for creating random guesses.
|
|
311
|
+
runid : int, optional
|
|
312
|
+
id used to identify the run for debugging / logging."""
|
|
313
|
+
|
|
314
|
+
dim, lower, upper = _check_bounds(bounds, None)
|
|
315
|
+
if popsize is None:
|
|
316
|
+
popsize = 64
|
|
317
|
+
if popsize % 2 == 1 and nsga_update: # nsga update requires even popsize
|
|
318
|
+
popsize += 1
|
|
319
|
+
if lower is None:
|
|
320
|
+
lower = [0]*dim
|
|
321
|
+
upper = [0]*dim
|
|
322
|
+
if ints is None or nsga_update: # nsga update doesn't support mixed integer
|
|
323
|
+
ints = [False]*dim
|
|
324
|
+
array_type = ct.c_double * dim
|
|
325
|
+
bool_array_type = ct.c_bool * dim
|
|
326
|
+
seed = int(rg.uniform(0, 2**32 - 1))
|
|
327
|
+
try:
|
|
328
|
+
self.ptr = initMODE_C(runid, dim, nobj, ncon, seed,
|
|
329
|
+
array_type(*lower), array_type(*upper), bool_array_type(*ints),
|
|
330
|
+
popsize, f, cr,
|
|
331
|
+
pro_c, dis_c, pro_m, dis_m,
|
|
332
|
+
nsga_update, pareto_update, min_mutate, max_mutate)
|
|
333
|
+
self.popsize = popsize
|
|
334
|
+
self.dim = dim
|
|
335
|
+
self.nobj = nobj
|
|
336
|
+
self.ncon = ncon
|
|
337
|
+
self.bounds = bounds
|
|
338
|
+
except Exception as ex:
|
|
339
|
+
print (str(ex))
|
|
340
|
+
pass
|
|
341
|
+
|
|
342
|
+
def __del__(self):
|
|
343
|
+
destroyMODE_C(self.ptr)
|
|
344
|
+
|
|
345
|
+
def set_guess(self, guess, mofun, rg = None):
|
|
346
|
+
if not guess is None:
|
|
347
|
+
if isinstance(guess, np.ndarray):
|
|
348
|
+
ys = np.array([mofun(x) for x in guess])
|
|
349
|
+
else:
|
|
350
|
+
guess, ys = guess
|
|
351
|
+
if rg is None:
|
|
352
|
+
rg = Generator(PCG64DXSM())
|
|
353
|
+
choice = rg.choice(len(ys), self.popsize,
|
|
354
|
+
replace = (len(ys) < self.popsize))
|
|
355
|
+
self.tell(ys[choice], guess[choice])
|
|
356
|
+
|
|
357
|
+
def ask(self) -> np.ndarray:
|
|
358
|
+
try:
|
|
359
|
+
popsize = self.popsize
|
|
360
|
+
n = self.dim
|
|
361
|
+
res = np.empty(popsize*n)
|
|
362
|
+
res_p = res.ctypes.data_as(ct.POINTER(ct.c_double))
|
|
363
|
+
askMODE_C(self.ptr, res_p)
|
|
364
|
+
xs = np.empty((popsize, n))
|
|
365
|
+
for p in range(popsize):
|
|
366
|
+
xs[p,:] = res[p*n : (p+1)*n]
|
|
367
|
+
return xs
|
|
368
|
+
except Exception as ex:
|
|
369
|
+
print (str(ex))
|
|
370
|
+
return None
|
|
371
|
+
|
|
372
|
+
def tell(self, ys: np.ndarray, xs: Optional[np.ndarray] = None) -> int:
|
|
373
|
+
try:
|
|
374
|
+
flat_ys = ys.flatten()
|
|
375
|
+
array_type_ys = ct.c_double * len(flat_ys)
|
|
376
|
+
if xs is None:
|
|
377
|
+
return tellMODE_C(self.ptr, array_type_ys(*flat_ys))
|
|
378
|
+
else:
|
|
379
|
+
flat_xs = xs.flatten()
|
|
380
|
+
array_type_xs = ct.c_double * len(flat_xs)
|
|
381
|
+
return setPopulationMODE_C(self.ptr, len(ys),
|
|
382
|
+
array_type_xs(*flat_xs), array_type_ys(*flat_ys))
|
|
383
|
+
except Exception as ex:
|
|
384
|
+
print (str(ex))
|
|
385
|
+
return -1
|
|
386
|
+
|
|
387
|
+
def tell_switch(self, ys: np.ndarray,
|
|
388
|
+
nsga_update: Optional[bool] = True,
|
|
389
|
+
pareto_update: Optional[int] = 0) -> int:
|
|
390
|
+
try:
|
|
391
|
+
flat_ys = ys.flatten()
|
|
392
|
+
array_type_ys = ct.c_double * len(flat_ys)
|
|
393
|
+
return tellMODE_switchC(self.ptr, array_type_ys(*flat_ys), nsga_update, pareto_update)
|
|
394
|
+
except Exception as ex:
|
|
395
|
+
print (ex)
|
|
396
|
+
return -1
|
|
397
|
+
|
|
398
|
+
def population(self) -> np.ndarray:
|
|
399
|
+
try:
|
|
400
|
+
popsize = self.popsize
|
|
401
|
+
n = self.dim
|
|
402
|
+
res = np.empty(popsize*n)
|
|
403
|
+
res_p = res.ctypes.data_as(ct.POINTER(ct.c_double))
|
|
404
|
+
populationMODE_C(self.ptr, res_p)
|
|
405
|
+
xs = np.empty((popsize, n))
|
|
406
|
+
for p in range(popsize):
|
|
407
|
+
xs[p,:] = res[p*n : (p+1)*n]
|
|
408
|
+
return xs
|
|
409
|
+
except Exception as ex:
|
|
410
|
+
print (str(ex))
|
|
411
|
+
return None
|
|
412
|
+
|
|
413
|
+
def minimize_ser(self,
|
|
414
|
+
fun: Callable[[ArrayLike], ArrayLike],
|
|
415
|
+
max_evaluations: Optional[int] = 100000) -> Tuple[np.ndarray, np.ndarray]:
|
|
416
|
+
evals = 0
|
|
417
|
+
stop = 0
|
|
418
|
+
while stop == 0 and evals < max_evaluations:
|
|
419
|
+
xs = self.ask()
|
|
420
|
+
ys = np.array([fun(x) for x in xs])
|
|
421
|
+
stop = self.tell(ys)
|
|
422
|
+
evals += self.popsize
|
|
423
|
+
return xs, ys
|
|
424
|
+
|
|
425
|
+
def minimize_par(self,
|
|
426
|
+
fun: Callable[[ArrayLike], ArrayLike],
|
|
427
|
+
max_evaluations: Optional[int] = 100000,
|
|
428
|
+
workers: Optional[int] = mp.cpu_count()) -> Tuple[np.ndarray, np.ndarray]:
|
|
429
|
+
fit = parallel_mo(fun, self.nobj + self.ncon, workers)
|
|
430
|
+
evals = 0
|
|
431
|
+
stop = 0
|
|
432
|
+
while stop == 0 and evals < max_evaluations:
|
|
433
|
+
xs = self.ask()
|
|
434
|
+
ys = fit(xs)
|
|
435
|
+
stop = self.tell(ys)
|
|
436
|
+
evals += self.popsize
|
|
437
|
+
fit.stop()
|
|
438
|
+
return xs, ys
|
|
439
|
+
|
|
440
|
+
if not libcmalib is None:
|
|
441
|
+
|
|
442
|
+
initMODE_C = libcmalib.initMODE_C
|
|
443
|
+
initMODE_C.argtypes = [ct.c_long, ct.c_int, ct.c_int, \
|
|
444
|
+
ct.c_int, ct.c_int, ct.POINTER(ct.c_double), ct.POINTER(ct.c_double), ct.POINTER(ct.c_bool), \
|
|
445
|
+
ct.c_int, ct.c_double, ct.c_double, ct.c_double, ct.c_double, ct.c_double, ct.c_double,
|
|
446
|
+
ct.c_bool, ct.c_double, ct.c_double, ct.c_double]
|
|
447
|
+
|
|
448
|
+
initMODE_C.restype = ct.c_void_p
|
|
449
|
+
|
|
450
|
+
destroyMODE_C = libcmalib.destroyMODE_C
|
|
451
|
+
destroyMODE_C.argtypes = [ct.c_void_p]
|
|
452
|
+
|
|
453
|
+
askMODE_C = libcmalib.askMODE_C
|
|
454
|
+
askMODE_C.argtypes = [ct.c_void_p, ct.POINTER(ct.c_double)]
|
|
455
|
+
|
|
456
|
+
tellMODE_C = libcmalib.tellMODE_C
|
|
457
|
+
tellMODE_C.argtypes = [ct.c_void_p, ct.POINTER(ct.c_double)]
|
|
458
|
+
tellMODE_C.restype = ct.c_int
|
|
459
|
+
|
|
460
|
+
tellMODE_switchC = libcmalib.tellMODE_switchC
|
|
461
|
+
tellMODE_switchC.argtypes = [ct.c_void_p, ct.POINTER(ct.c_double), ct.c_bool, ct.c_double]
|
|
462
|
+
tellMODE_switchC.restype = ct.c_int
|
|
463
|
+
|
|
464
|
+
populationMODE_C = libcmalib.populationMODE_C
|
|
465
|
+
populationMODE_C.argtypes = [ct.c_void_p, ct.POINTER(ct.c_double)]
|
|
466
|
+
|
|
467
|
+
setPopulationMODE_C = libcmalib.setPopulationMODE_C
|
|
468
|
+
setPopulationMODE_C.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(ct.c_double), ct.POINTER(ct.c_double)]
|
|
469
|
+
setPopulationMODE_C.restype = ct.c_int
|
|
470
|
+
|