fcmaes 1.3.17__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 +5 -4
- fcmaes/advretry.py +135 -141
- fcmaes/astro.py +64 -40
- fcmaes/bitecpp.py +33 -32
- fcmaes/cmaes.py +69 -142
- fcmaes/cmaescpp.py +231 -39
- fcmaes/crfmnes.py +339 -0
- fcmaes/crfmnescpp.py +273 -0
- fcmaes/dacpp.py +26 -27
- fcmaes/de.py +163 -56
- fcmaes/decpp.py +188 -179
- fcmaes/diversifier.py +357 -0
- fcmaes/evaluator.py +279 -6
- 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/mapelites.py +737 -0
- fcmaes/mode.py +399 -256
- fcmaes/modecpp.py +326 -149
- fcmaes/moretry.py +107 -77
- fcmaes/multiretry.py +37 -30
- fcmaes/optimizer.py +695 -271
- fcmaes/pgpecpp.py +340 -0
- fcmaes/pygmoretry.py +8 -17
- fcmaes/retry.py +161 -139
- fcmaes/test_cma.py +45 -25
- fcmaes-1.6.9.dist-info/METADATA +47 -0
- fcmaes-1.6.9.dist-info/RECORD +36 -0
- {fcmaes-1.3.17.dist-info → fcmaes-1.6.9.dist-info}/WHEEL +1 -1
- fcmaes/csmacpp.py +0 -108
- fcmaes/gcldecpp.py +0 -148
- fcmaes/lcldecpp.py +0 -138
- fcmaes/ldecpp.py +0 -172
- fcmaes/lib/libgcc_s_seh-1.dll +0 -0
- fcmaes/lib/libgtoplib.dll +0 -0
- fcmaes/lib/libgtoplib.so +0 -0
- fcmaes/lib/libstdc++-6.dll +0 -0
- fcmaes/lib/libwinpthread-1.dll +0 -0
- fcmaes-1.3.17.dist-info/METADATA +0 -55
- fcmaes-1.3.17.dist-info/RECORD +0 -37
- {fcmaes-1.3.17.dist-info → fcmaes-1.6.9.dist-info}/LICENSE +0 -0
- {fcmaes-1.3.17.dist-info → fcmaes-1.6.9.dist-info}/top_level.txt +0 -0
fcmaes/modecpp.py
CHANGED
|
@@ -33,47 +33,58 @@
|
|
|
33
33
|
parameter to parallelize objective function evaluation. This causes delayed population update.
|
|
34
34
|
It is usually preferrable if popsize > workers and workers = mp.cpu_count() to improve CPU utilization.
|
|
35
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
|
+
|
|
36
42
|
See https://github.com/dietmarwo/fast-cma-es/blob/master/tutorials/MODE.adoc for a detailed description.
|
|
37
43
|
"""
|
|
38
44
|
|
|
39
|
-
import sys
|
|
40
45
|
import os
|
|
41
|
-
import math
|
|
42
46
|
import time
|
|
47
|
+
import threadpoolctl
|
|
43
48
|
import ctypes as ct
|
|
44
49
|
import multiprocessing as mp
|
|
45
50
|
from multiprocessing import Process
|
|
46
51
|
import numpy as np
|
|
47
|
-
from
|
|
48
|
-
from fcmaes
|
|
49
|
-
from fcmaes import
|
|
50
|
-
from
|
|
51
|
-
from numpy.random import Generator, MT19937, SeedSequence
|
|
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
|
|
52
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
|
|
53
63
|
|
|
54
64
|
os.environ['MKL_DEBUG_CPU_TYPE'] = '5'
|
|
55
65
|
|
|
56
|
-
def minimize(mofun,
|
|
57
|
-
nobj,
|
|
58
|
-
ncon,
|
|
59
|
-
bounds,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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]:
|
|
77
88
|
|
|
78
89
|
"""Minimization of a multi objjective function of one or more variables using
|
|
79
90
|
Differential Evolution.
|
|
@@ -82,10 +93,8 @@ def minimize(mofun,
|
|
|
82
93
|
----------
|
|
83
94
|
mofun : callable
|
|
84
95
|
The objective function to be minimized.
|
|
85
|
-
``mofun(x
|
|
86
|
-
where ``x`` is an 1-D array with shape (n,)
|
|
87
|
-
is a tuple of the fixed parameters needed to completely
|
|
88
|
-
specify the function.
|
|
96
|
+
``mofun(x) -> ndarray(float)``
|
|
97
|
+
where ``x`` is an 1-D array with shape (n,)
|
|
89
98
|
nobj : int
|
|
90
99
|
number of objectives
|
|
91
100
|
ncon : int
|
|
@@ -96,12 +105,14 @@ def minimize(mofun,
|
|
|
96
105
|
1. Instance of the `scipy.Bounds` class.
|
|
97
106
|
2. Sequence of ``(min, max)`` pairs for each element in `x`. None
|
|
98
107
|
is used to specify no bound.
|
|
108
|
+
guess : ndarray, shape (popsize,dim) or Tuple
|
|
109
|
+
Initial guess.
|
|
99
110
|
popsize : int, optional
|
|
100
111
|
Population size.
|
|
101
112
|
max_evaluations : int, optional
|
|
102
|
-
Forced termination after ``max_evaluations`` function evaluations.
|
|
113
|
+
Forced termination after ``max_evaluations`` function evaluations.
|
|
103
114
|
workers : int or None, optional
|
|
104
|
-
|
|
115
|
+
if workers > 1, function evaluation is performed in parallel for the whole population.
|
|
105
116
|
Useful for costly objective functions
|
|
106
117
|
f = float, optional
|
|
107
118
|
The mutation constant. In the literature this is also known as differential weight,
|
|
@@ -112,24 +123,22 @@ def minimize(mofun,
|
|
|
112
123
|
pro_c, dis_c, pro_m, dis_m = float, optional
|
|
113
124
|
NSGA population update parameters, usually leave at default.
|
|
114
125
|
nsga_update = boolean, optional
|
|
115
|
-
Use of NSGA-II or DE population update. Default is
|
|
126
|
+
Use of NSGA-II/SBX or DE population update. Default is True
|
|
116
127
|
pareto_update = float, optional
|
|
117
|
-
Only applied if nsga_update = False.
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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.
|
|
122
137
|
rg = numpy.random.Generator, optional
|
|
123
138
|
Random generator for creating random guesses.
|
|
124
|
-
logger : logger, optional
|
|
125
|
-
logger for log output for tell_one, If None, logging
|
|
126
|
-
is switched off. Default is a logger which logs both to stdout and
|
|
127
|
-
appends to a file ``optimizer.log``.
|
|
128
139
|
store : result store, optional
|
|
129
|
-
if defined the optimization results are added to the result store.
|
|
130
|
-
|
|
131
|
-
is_terminate : callable, optional
|
|
132
|
-
Callback to be used if the caller of minimize wants to decide when to terminate.
|
|
140
|
+
if defined the optimization results are added to the result store.
|
|
141
|
+
|
|
133
142
|
runid : int, optional
|
|
134
143
|
id used to identify the run for debugging / logging.
|
|
135
144
|
|
|
@@ -137,50 +146,36 @@ def minimize(mofun,
|
|
|
137
146
|
-------
|
|
138
147
|
x, y: list of argument vectors and corresponding value vectors of the optimization results. """
|
|
139
148
|
|
|
140
|
-
dim, lower, upper = de._check_bounds(bounds, None)
|
|
141
|
-
if popsize is None:
|
|
142
|
-
popsize = 64
|
|
143
|
-
if popsize % 2 == 1 and nsga_update: # nsga update requires even popsize
|
|
144
|
-
popsize += 1
|
|
145
|
-
if lower is None:
|
|
146
|
-
lower = [0]*dim
|
|
147
|
-
upper = [0]*dim
|
|
148
|
-
if workers is None:
|
|
149
|
-
workers = 0
|
|
150
|
-
array_type = ct.c_double * dim
|
|
151
|
-
c_callback = mo_call_back_type(callback_mo(mofun, dim, nobj + ncon, is_terminate))
|
|
152
|
-
c_log = mo_call_back_type(log_mo(plot_name, dim, nobj, ncon))
|
|
153
|
-
seed = int(rg.uniform(0, 2**32 - 1))
|
|
154
|
-
res = np.empty(2*dim*popsize) # stores the resulting pareto front parameters
|
|
155
|
-
res_p = res.ctypes.data_as(ct.POINTER(ct.c_double))
|
|
156
149
|
try:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
x[p] = res[p*dim : (p+1)*dim]
|
|
165
|
-
y = np.array([mofun(xi) for xi in x])
|
|
166
|
-
x, y = filter(x, y)
|
|
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)
|
|
167
157
|
if not store is None:
|
|
158
|
+
store.create_views()
|
|
168
159
|
store.add_results(x, y)
|
|
169
160
|
return x, y
|
|
170
161
|
except Exception as ex:
|
|
162
|
+
print(str(ex))
|
|
171
163
|
return None, None
|
|
172
164
|
|
|
173
|
-
def retry(mofun,
|
|
174
|
-
nobj,
|
|
175
|
-
ncon,
|
|
176
|
-
bounds,
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
+
|
|
184
179
|
"""Minimization of a multi objjective function of one or more variables using parallel
|
|
185
180
|
optimization retry.
|
|
186
181
|
|
|
@@ -188,7 +183,7 @@ def retry(mofun,
|
|
|
188
183
|
----------
|
|
189
184
|
mofun : callable
|
|
190
185
|
The objective function to be minimized.
|
|
191
|
-
``mofun(x, *args) ->
|
|
186
|
+
``mofun(x, *args) -> ndarray(float)``
|
|
192
187
|
where ``x`` is an 1-D array with shape (n,) and ``args``
|
|
193
188
|
is a tuple of the fixed parameters needed to completely
|
|
194
189
|
specify the function.
|
|
@@ -202,6 +197,8 @@ def retry(mofun,
|
|
|
202
197
|
1. Instance of the `scipy.Bounds` class.
|
|
203
198
|
2. Sequence of ``(min, max)`` pairs for each element in `x`. None
|
|
204
199
|
is used to specify no bound.
|
|
200
|
+
guess : ndarray, shape (popsize,dim) or Tuple
|
|
201
|
+
Initial guess.
|
|
205
202
|
num_retries : int, optional
|
|
206
203
|
Number of optimization retries.
|
|
207
204
|
popsize : int, optional
|
|
@@ -211,83 +208,263 @@ def retry(mofun,
|
|
|
211
208
|
workers : int or None, optional
|
|
212
209
|
If not workers is None, optimization is performed in parallel.
|
|
213
210
|
nsga_update = boolean, optional
|
|
214
|
-
Use of NSGA-II or DE population update. Default is
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
221
|
|
|
222
|
-
dim, _, _ =
|
|
223
|
-
|
|
222
|
+
dim, _, _ = _check_bounds(bounds, None)
|
|
223
|
+
if capacity is None:
|
|
224
|
+
capacity = 2048*popsize
|
|
225
|
+
store = mode.store(dim, nobj + ncon, capacity)
|
|
224
226
|
sg = SeedSequence()
|
|
225
|
-
rgs = [Generator(
|
|
227
|
+
rgs = [Generator(PCG64DXSM(s)) for s in sg.spawn(workers)]
|
|
226
228
|
proc=[Process(target=_retry_loop,
|
|
227
|
-
args=(num_retries, pid, rgs, mofun, nobj, ncon, bounds, popsize,
|
|
228
|
-
max_evaluations, workers, nsga_update,
|
|
229
|
+
args=(num_retries, pid, rgs, mofun, nobj, ncon, bounds, guess, popsize,
|
|
230
|
+
max_evaluations, workers, nsga_update, pareto_update,
|
|
231
|
+
store, ints))
|
|
229
232
|
for pid in range(workers)]
|
|
230
233
|
[p.start() for p in proc]
|
|
231
234
|
[p.join() for p in proc]
|
|
232
|
-
xs, ys = store.get_front()
|
|
233
|
-
if not logger is None:
|
|
234
|
-
logger.info(str([tuple(y) for y in ys]))
|
|
235
|
+
xs, ys = store.get_front()
|
|
235
236
|
return xs, ys
|
|
236
237
|
|
|
237
|
-
def _retry_loop(num_retries, pid, rgs, mofun, nobj, ncon, bounds, popsize,
|
|
238
|
-
max_evaluations, workers, nsga_update,
|
|
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()
|
|
239
242
|
t0 = time.perf_counter()
|
|
240
243
|
num = max(1, num_retries - workers)
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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))
|
|
250
253
|
|
|
251
|
-
class
|
|
252
|
-
|
|
253
|
-
def __init__(self,
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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
|
|
259
386
|
|
|
260
|
-
def
|
|
387
|
+
def tell_switch(self, ys: np.ndarray,
|
|
388
|
+
nsga_update: Optional[bool] = True,
|
|
389
|
+
pareto_update: Optional[int] = 0) -> int:
|
|
261
390
|
try:
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
arrTypeY = ct.c_double*(self.nobj*n)
|
|
266
|
-
xaddr = ct.addressof(x.contents)
|
|
267
|
-
yaddr = ct.addressof(y.contents)
|
|
268
|
-
xbuf = np.frombuffer(arrTypeX.from_address(xaddr))
|
|
269
|
-
ybuf = np.frombuffer(arrTypeY.from_address(yaddr))
|
|
270
|
-
xs = []; ys = []
|
|
271
|
-
for p in range(n):
|
|
272
|
-
x = xbuf[p*self.dim : (p+1)*self.dim]
|
|
273
|
-
xs.append(x)
|
|
274
|
-
y = ybuf[p*self.nobj : (p+1)*self.nobj]
|
|
275
|
-
ys.append(y)
|
|
276
|
-
xs = np.array(xs)
|
|
277
|
-
ys = np.array(ys)
|
|
278
|
-
print("callback", np.min(ys[:,0]), np.min(ys[:,1]))
|
|
279
|
-
name = self.name + '_' + str(self.calls)
|
|
280
|
-
np.savez_compressed(name, xs=xs, ys=ys)
|
|
281
|
-
moretry.plot(name, self.ncon, xs, ys)
|
|
282
|
-
return False # don't terminate optimization
|
|
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)
|
|
283
394
|
except Exception as ex:
|
|
284
395
|
print (ex)
|
|
285
|
-
return
|
|
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)]
|
|
286
466
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
ct.c_int, ct.c_int, ct.c_int,\
|
|
291
|
-
ct.c_double, ct.c_double, ct.c_double, ct.c_double, ct.c_double, ct.c_double,
|
|
292
|
-
ct.c_bool, ct.c_double, ct.c_int, ct.POINTER(ct.c_double)]
|
|
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
|
|
293
470
|
|