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/cmaescpp.py
CHANGED
|
@@ -13,24 +13,32 @@ import os
|
|
|
13
13
|
import math
|
|
14
14
|
import ctypes as ct
|
|
15
15
|
import numpy as np
|
|
16
|
-
from numpy.random import
|
|
17
|
-
from scipy.optimize import OptimizeResult
|
|
18
|
-
from fcmaes.
|
|
16
|
+
from numpy.random import PCG64DXSM, Generator
|
|
17
|
+
from scipy.optimize import OptimizeResult, Bounds
|
|
18
|
+
from fcmaes.evaluator import _check_bounds, _get_bounds, mo_call_back_type, callback_so, callback_par, call_back_par, parallel, libcmalib
|
|
19
|
+
|
|
20
|
+
from typing import Optional, Callable, Union
|
|
21
|
+
from numpy.typing import ArrayLike
|
|
19
22
|
|
|
20
23
|
os.environ['MKL_DEBUG_CPU_TYPE'] = '5'
|
|
21
24
|
|
|
22
|
-
def minimize(fun,
|
|
23
|
-
bounds=None,
|
|
24
|
-
x0=None,
|
|
25
|
-
input_sigma = 0.3,
|
|
26
|
-
popsize = 31,
|
|
27
|
-
max_evaluations = 100000,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
def minimize(fun: Callable[[ArrayLike], float],
|
|
26
|
+
bounds: Optional[Bounds] = None,
|
|
27
|
+
x0: Optional[ArrayLike] = None,
|
|
28
|
+
input_sigma: Optional[Union[float, ArrayLike, Callable]] = 0.3,
|
|
29
|
+
popsize: Optional[int] = 31,
|
|
30
|
+
max_evaluations: Optional[int] = 100000,
|
|
31
|
+
accuracy: Optional[float] = 1.0,
|
|
32
|
+
stop_fitness: Optional[float] = -np.inf,
|
|
33
|
+
stop_hist: Optional[float] = -1,
|
|
34
|
+
rg: Optional[Generator] = Generator(PCG64DXSM()),
|
|
35
|
+
runid: Optional[int] = 0,
|
|
36
|
+
workers: Optional[int] = 1,
|
|
37
|
+
normalize: Optional[bool] = True,
|
|
38
|
+
delayed_update: Optional[bool] = True,
|
|
39
|
+
update_gap: Optional[int] = None
|
|
40
|
+
) -> OptimizeResult:
|
|
41
|
+
|
|
34
42
|
"""Minimization of a scalar function of one or more variables using a
|
|
35
43
|
C++ CMA-ES implementation called via ctypes.
|
|
36
44
|
|
|
@@ -38,38 +46,43 @@ def minimize(fun,
|
|
|
38
46
|
----------
|
|
39
47
|
fun : callable
|
|
40
48
|
The objective function to be minimized.
|
|
41
|
-
``fun(x
|
|
42
|
-
where ``x`` is an 1-D array with shape (
|
|
43
|
-
is a tuple of the fixed parameters needed to completely
|
|
44
|
-
specify the function.
|
|
49
|
+
``fun(x) -> float``
|
|
50
|
+
where ``x`` is an 1-D array with shape (dim,)
|
|
45
51
|
bounds : sequence or `Bounds`, optional
|
|
46
52
|
Bounds on variables. There are two ways to specify the bounds:
|
|
47
53
|
1. Instance of the `scipy.Bounds` class.
|
|
48
54
|
2. Sequence of ``(min, max)`` pairs for each element in `x`. None
|
|
49
55
|
is used to specify no bound.
|
|
50
|
-
x0 : ndarray, shape (
|
|
51
|
-
Initial guess. Array of real elements of size (
|
|
52
|
-
where '
|
|
53
|
-
input_sigma : ndarray, shape (
|
|
56
|
+
x0 : ndarray, shape (dim,)
|
|
57
|
+
Initial guess. Array of real elements of size (dim,),
|
|
58
|
+
where 'dim' is the number of independent variables.
|
|
59
|
+
input_sigma : ndarray, shape (dim,) or scalar
|
|
54
60
|
Initial step size for each dimension.
|
|
55
61
|
popsize = int, optional
|
|
56
62
|
CMA-ES population size.
|
|
57
63
|
max_evaluations : int, optional
|
|
58
64
|
Forced termination after ``max_evaluations`` function evaluations.
|
|
59
|
-
max_iterations : int, optional
|
|
60
|
-
Forced termination after ``max_iterations`` iterations.
|
|
61
65
|
accuracy : float, optional
|
|
62
66
|
values > 1.0 reduce the accuracy.
|
|
63
|
-
|
|
67
|
+
stop_fitness : float, optional
|
|
64
68
|
Limit for fitness value. If reached minimize terminates.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
stop_hist : float, optional
|
|
70
|
+
Set to 0 if you want to prevent premature termination because
|
|
71
|
+
there is no progress
|
|
68
72
|
rg = numpy.random.Generator, optional
|
|
69
73
|
Random generator for creating random guesses.
|
|
70
74
|
runid : int, optional
|
|
71
75
|
id used by the is_terminate callback to identify the CMA-ES run.
|
|
72
|
-
|
|
76
|
+
workers : int or None, optional
|
|
77
|
+
If not workers is None, function evaluation is performed in parallel for the whole population.
|
|
78
|
+
Useful for costly objective functions but is deactivated for parallel retry.
|
|
79
|
+
normalize : boolean, optional
|
|
80
|
+
if true pheno -> geno transformation maps arguments to interval [-1,1]
|
|
81
|
+
delayed_update : boolean, optional
|
|
82
|
+
if true uses delayed update / C++ parallelism, i false uses Python multithreading
|
|
83
|
+
update_gap : int, optional
|
|
84
|
+
number of iterations without distribution update
|
|
85
|
+
|
|
73
86
|
Returns
|
|
74
87
|
-------
|
|
75
88
|
res : scipy.OptimizeResult
|
|
@@ -82,72 +95,225 @@ def minimize(fun,
|
|
|
82
95
|
``success`` a Boolean flag indicating if the optimizer exited successfully. """
|
|
83
96
|
|
|
84
97
|
lower, upper, guess = _check_bounds(bounds, x0, rg)
|
|
85
|
-
|
|
86
|
-
if
|
|
87
|
-
|
|
88
|
-
upper = [0]*n
|
|
98
|
+
dim = guess.size
|
|
99
|
+
if workers is None:
|
|
100
|
+
workers = 0
|
|
89
101
|
mu = int(popsize/2)
|
|
102
|
+
if callable(input_sigma):
|
|
103
|
+
input_sigma=input_sigma()
|
|
90
104
|
if np.ndim(input_sigma) == 0:
|
|
91
|
-
input_sigma = [input_sigma] *
|
|
92
|
-
if
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
c_callback = call_back_type(callback(fun))
|
|
101
|
-
c_is_terminate = is_terminate_type(is_terminate)
|
|
105
|
+
input_sigma = [input_sigma] * dim
|
|
106
|
+
if stop_hist is None:
|
|
107
|
+
stop_hist = -1;
|
|
108
|
+
array_type = ct.c_double * dim
|
|
109
|
+
c_callback = mo_call_back_type(callback_so(fun, dim))
|
|
110
|
+
parfun = None if delayed_update == True or workers is None or workers <= 1 else parallel(fun, workers)
|
|
111
|
+
c_callback_par = call_back_par(callback_par(fun, parfun))
|
|
112
|
+
res = np.empty(dim+4)
|
|
113
|
+
res_p = res.ctypes.data_as(ct.POINTER(ct.c_double))
|
|
102
114
|
try:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
115
|
+
optimizeACMA_C(runid, c_callback, c_callback_par,
|
|
116
|
+
dim, array_type(*guess),
|
|
117
|
+
None if lower is None else array_type(*lower),
|
|
118
|
+
None if upper is None else array_type(*upper),
|
|
119
|
+
array_type(*input_sigma), max_evaluations, stop_fitness, stop_hist, mu,
|
|
120
|
+
popsize, accuracy, int(rg.uniform(0, 2**32 - 1)),
|
|
121
|
+
normalize, delayed_update, -1 if update_gap is None else update_gap,
|
|
122
|
+
workers, res_p)
|
|
123
|
+
x = res[:dim]
|
|
124
|
+
val = res[dim]
|
|
125
|
+
evals = int(res[dim+1])
|
|
126
|
+
iterations = int(res[dim+2])
|
|
127
|
+
stop = int(res[dim+3])
|
|
128
|
+
res = OptimizeResult(x=x, fun=val, nfev=evals, nit=iterations, status=stop, success=True)
|
|
114
129
|
except Exception as ex:
|
|
115
|
-
|
|
130
|
+
res = OptimizeResult(x=None, fun=sys.float_info.max, nfev=0, nit=0, status=-1, success=False)
|
|
131
|
+
if not parfun is None:
|
|
132
|
+
parfun.stop()
|
|
133
|
+
return res
|
|
116
134
|
|
|
117
|
-
class
|
|
118
|
-
|
|
119
|
-
def __init__(self,
|
|
120
|
-
|
|
135
|
+
class ACMA_C:
|
|
136
|
+
|
|
137
|
+
def __init__(self,
|
|
138
|
+
dim,
|
|
139
|
+
bounds: Optional[Bounds] = None,
|
|
140
|
+
x0: Optional[ArrayLike] = None,
|
|
141
|
+
input_sigma: Optional[Union[float, ArrayLike, Callable]] = 0.3,
|
|
142
|
+
popsize: Optional[int] = 31,
|
|
143
|
+
max_evaluations: Optional[int] = 100000,
|
|
144
|
+
accuracy: Optional[float] = 1.0,
|
|
145
|
+
stop_fitness: Optional[float] = -np.inf,
|
|
146
|
+
stop_hist: Optional[float] = -1,
|
|
147
|
+
rg: Optional[Generator] = Generator(PCG64DXSM()),
|
|
148
|
+
runid: Optional[int] = 0,
|
|
149
|
+
normalize: Optional[bool] = True,
|
|
150
|
+
delayed_update: Optional[bool] = True,
|
|
151
|
+
update_gap: Optional[int] = None
|
|
152
|
+
):
|
|
153
|
+
|
|
154
|
+
"""Parameters
|
|
155
|
+
----------
|
|
156
|
+
dim : int
|
|
157
|
+
dimension of the argument of the objective function
|
|
158
|
+
bounds : sequence or `Bounds`, optional
|
|
159
|
+
Bounds on variables. There are two ways to specify the bounds:
|
|
160
|
+
1. Instance of the `scipy.Bounds` class.
|
|
161
|
+
2. Sequence of ``(min, max)`` pairs for each element in `x`. None
|
|
162
|
+
is used to specify no bound.
|
|
163
|
+
x0 : ndarray, shape (dim,)
|
|
164
|
+
Initial guess. Array of real elements of size (dim,),
|
|
165
|
+
where 'dim' is the number of independent variables.
|
|
166
|
+
input_sigma : ndarray, shape (dim,) or scalar
|
|
167
|
+
Initial step size for each dimension.
|
|
168
|
+
popsize = int, optional
|
|
169
|
+
CMA-ES population size.
|
|
170
|
+
max_evaluations : int, optional
|
|
171
|
+
Forced termination after ``max_evaluations`` function evaluations.
|
|
172
|
+
accuracy : float, optional
|
|
173
|
+
values > 1.0 reduce the accuracy.
|
|
174
|
+
stop_fitness : float, optional
|
|
175
|
+
Limit for fitness value. If reached minimize terminates.
|
|
176
|
+
stop_hist : float, optional
|
|
177
|
+
Set to 0 if you want to prevent premature termination because
|
|
178
|
+
there is no progress
|
|
179
|
+
rg = numpy.random.Generator, optional
|
|
180
|
+
Random generator for creating random guesses.
|
|
181
|
+
runid : int, optional
|
|
182
|
+
id used by the is_terminate callback to identify the CMA-ES run.
|
|
183
|
+
normalize : boolean, optional
|
|
184
|
+
if true pheno -> geno transformation maps arguments to interval [-1,1]
|
|
185
|
+
delayed_update : boolean, optional
|
|
186
|
+
if true uses delayed update / C++ parallelism, i false uses Python multithreading
|
|
187
|
+
update_gap : int, optional
|
|
188
|
+
number of iterations without distribution update"""
|
|
189
|
+
|
|
190
|
+
lower, upper, guess = _get_bounds(dim, bounds, x0, rg)
|
|
191
|
+
if lower is None:
|
|
192
|
+
lower = [0]*dim
|
|
193
|
+
upper = [0]*dim
|
|
194
|
+
mu = int(popsize/2)
|
|
195
|
+
if callable(input_sigma):
|
|
196
|
+
input_sigma=input_sigma()
|
|
197
|
+
if np.ndim(input_sigma) == 0:
|
|
198
|
+
input_sigma = [input_sigma] * dim
|
|
199
|
+
if stop_hist is None:
|
|
200
|
+
stop_hist = -1;
|
|
201
|
+
array_type = ct.c_double * dim
|
|
202
|
+
try:
|
|
203
|
+
self.ptr = initACMA_C(runid,
|
|
204
|
+
dim, array_type(*guess), array_type(*lower), array_type(*upper),
|
|
205
|
+
array_type(*input_sigma), max_evaluations, stop_fitness, stop_hist, mu,
|
|
206
|
+
popsize, accuracy, int(rg.uniform(0, 2**32 - 1)),
|
|
207
|
+
normalize, delayed_update, -1 if update_gap is None else update_gap)
|
|
208
|
+
self.popsize = popsize
|
|
209
|
+
self.dim = dim
|
|
210
|
+
except Exception as ex:
|
|
211
|
+
print (ex)
|
|
212
|
+
pass
|
|
121
213
|
|
|
122
|
-
def
|
|
214
|
+
def __del__(self):
|
|
215
|
+
destroyACMA_C(self.ptr)
|
|
216
|
+
|
|
217
|
+
def ask(self) -> np.array:
|
|
123
218
|
try:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
219
|
+
popsize = self.popsize
|
|
220
|
+
n = self.dim
|
|
221
|
+
res = np.empty(popsize*n)
|
|
222
|
+
res_p = res.ctypes.data_as(ct.POINTER(ct.c_double))
|
|
223
|
+
askACMA_C(self.ptr, res_p)
|
|
224
|
+
xs = np.empty((popsize, n))
|
|
225
|
+
for p in range(popsize):
|
|
226
|
+
xs[p,:] = res[p*n : (p+1)*n]
|
|
227
|
+
return xs
|
|
228
|
+
except Exception as ex:
|
|
229
|
+
print (ex)
|
|
230
|
+
return None
|
|
133
231
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
232
|
+
def tell(self,
|
|
233
|
+
ys: np.ndarray,
|
|
234
|
+
xs: Optional[np.ndarray] = None) -> int:
|
|
235
|
+
if not xs is None:
|
|
236
|
+
return self.tell_x_(ys, xs)
|
|
237
|
+
try:
|
|
238
|
+
array_type_ys = ct.c_double * len(ys)
|
|
239
|
+
return tellACMA_C(self.ptr, array_type_ys(*ys))
|
|
240
|
+
except Exception as ex:
|
|
241
|
+
print (ex)
|
|
242
|
+
return -1
|
|
140
243
|
|
|
141
|
-
|
|
142
|
-
|
|
244
|
+
def tell_x_(self, ys: np.ndarray, xs: np.ndarray):
|
|
245
|
+
try:
|
|
246
|
+
flat_xs = xs.flatten()
|
|
247
|
+
array_type_xs = ct.c_double * len(flat_xs)
|
|
248
|
+
array_type_ys = ct.c_double * len(ys)
|
|
249
|
+
return tellXACMA_C(self.ptr, array_type_ys(*ys), array_type_xs(*flat_xs))
|
|
250
|
+
except Exception as ex:
|
|
251
|
+
print (ex)
|
|
252
|
+
return -1
|
|
253
|
+
|
|
254
|
+
def population(self) -> np.array:
|
|
255
|
+
try:
|
|
256
|
+
popsize = self.popsize
|
|
257
|
+
n = self.dim
|
|
258
|
+
res = np.empty(popsize*n)
|
|
259
|
+
res_p = res.ctypes.data_as(ct.POINTER(ct.c_double))
|
|
260
|
+
populationACMA_C(self.ptr, res_p)
|
|
261
|
+
xs = np.array(popsize, n)
|
|
262
|
+
for p in range(popsize):
|
|
263
|
+
xs[p] = res[p*n : (p+1)*n]
|
|
264
|
+
return xs
|
|
265
|
+
except Exception as ex:
|
|
266
|
+
print (ex)
|
|
267
|
+
return None
|
|
143
268
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
269
|
+
def result(self) -> OptimizeResult:
|
|
270
|
+
res = np.empty(self.dim+4)
|
|
271
|
+
res_p = res.ctypes.data_as(ct.POINTER(ct.c_double))
|
|
272
|
+
try:
|
|
273
|
+
resultACMA_C(self.ptr, res_p)
|
|
274
|
+
x = res[:self.dim]
|
|
275
|
+
val = res[self.dim]
|
|
276
|
+
evals = int(res[self.dim+1])
|
|
277
|
+
iterations = int(res[self.dim+2])
|
|
278
|
+
stop = int(res[self.dim+3])
|
|
279
|
+
res = OptimizeResult(x=x, fun=val, nfev=evals, nit=iterations, status=stop, success=True)
|
|
280
|
+
except Exception as ex:
|
|
281
|
+
res = OptimizeResult(x=None, fun=sys.float_info.max, nfev=0, nit=0, status=-1, success=False)
|
|
282
|
+
return res
|
|
149
283
|
|
|
150
|
-
|
|
284
|
+
if not libcmalib is None:
|
|
151
285
|
|
|
152
|
-
|
|
153
|
-
|
|
286
|
+
optimizeACMA_C = libcmalib.optimizeACMA_C
|
|
287
|
+
optimizeACMA_C.argtypes = [ct.c_long, mo_call_back_type, call_back_par, ct.c_int, \
|
|
288
|
+
ct.POINTER(ct.c_double), ct.POINTER(ct.c_double), ct.POINTER(ct.c_double), \
|
|
289
|
+
ct.POINTER(ct.c_double), ct.c_int, ct.c_double, ct.c_double, ct.c_int, ct.c_int, \
|
|
290
|
+
ct.c_double, ct.c_long, ct.c_bool, ct.c_bool, ct.c_int,
|
|
291
|
+
ct.c_int, ct.POINTER(ct.c_double)]
|
|
292
|
+
|
|
293
|
+
initACMA_C = libcmalib.initACMA_C
|
|
294
|
+
initACMA_C.argtypes = [ct.c_long, ct.c_int, \
|
|
295
|
+
ct.POINTER(ct.c_double), ct.POINTER(ct.c_double), ct.POINTER(ct.c_double), \
|
|
296
|
+
ct.POINTER(ct.c_double), ct.c_int, ct.c_double, ct.c_double, ct.c_int,
|
|
297
|
+
ct.c_int, ct.c_double, ct.c_long, ct.c_bool, ct.c_bool, ct.c_int]
|
|
298
|
+
|
|
299
|
+
initACMA_C.restype = ct.c_void_p
|
|
300
|
+
|
|
301
|
+
destroyACMA_C = libcmalib.destroyACMA_C
|
|
302
|
+
destroyACMA_C.argtypes = [ct.c_void_p]
|
|
303
|
+
|
|
304
|
+
askACMA_C = libcmalib.askACMA_C
|
|
305
|
+
askACMA_C.argtypes = [ct.c_void_p, ct.POINTER(ct.c_double)]
|
|
306
|
+
|
|
307
|
+
tellACMA_C = libcmalib.tellACMA_C
|
|
308
|
+
tellACMA_C.argtypes = [ct.c_void_p, ct.POINTER(ct.c_double)]
|
|
309
|
+
tellACMA_C.restype = ct.c_int
|
|
310
|
+
|
|
311
|
+
tellXACMA_C = libcmalib.tellXACMA_C
|
|
312
|
+
tellXACMA_C.argtypes = [ct.c_void_p, ct.POINTER(ct.c_double), ct.POINTER(ct.c_double)]
|
|
313
|
+
tellXACMA_C.restype = ct.c_int
|
|
314
|
+
|
|
315
|
+
populationACMA_C = libcmalib.populationACMA_C
|
|
316
|
+
populationACMA_C.argtypes = [ct.c_void_p, ct.POINTER(ct.c_double)]
|
|
317
|
+
|
|
318
|
+
resultACMA_C = libcmalib.resultACMA_C
|
|
319
|
+
resultACMA_C.argtypes = [ct.c_void_p, ct.POINTER(ct.c_double)]
|