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/astro.py
CHANGED
|
@@ -8,33 +8,27 @@ import math
|
|
|
8
8
|
import os
|
|
9
9
|
import ctypes as ct
|
|
10
10
|
from scipy.optimize import Bounds
|
|
11
|
+
from fcmaes.decpp import libcmalib
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"messengerfullC": libgtoplib.messengerfullC,
|
|
27
|
-
"messengerC": libgtoplib.messengerC,
|
|
28
|
-
"gtoc1C": libgtoplib.gtoc1C,
|
|
29
|
-
"cassini1C": libgtoplib.cassini1C,
|
|
30
|
-
"cassini1minlpC": libgtoplib.cassini1minlpC,
|
|
31
|
-
"cassini2C": libgtoplib.cassini2C,
|
|
32
|
-
"rosettaC": libgtoplib.rosettaC,
|
|
33
|
-
"sagasC": libgtoplib.sagasC,
|
|
34
|
-
"tandemC": libgtoplib.tandemC,
|
|
35
|
-
"tandemCu": libgtoplib.tandemCu
|
|
13
|
+
if not libcmalib is None:
|
|
14
|
+
|
|
15
|
+
astro_map = {
|
|
16
|
+
"messengerfullC": libcmalib.messengerfullC,
|
|
17
|
+
"messengerC": libcmalib.messengerC,
|
|
18
|
+
"gtoc1C": libcmalib.gtoc1C,
|
|
19
|
+
"cassini1C": libcmalib.cassini1C,
|
|
20
|
+
"cassini1minlpC": libcmalib.cassini1minlpC,
|
|
21
|
+
"cassini2C": libcmalib.cassini2C,
|
|
22
|
+
"rosettaC": libcmalib.rosettaC,
|
|
23
|
+
"sagasC": libcmalib.sagasC,
|
|
24
|
+
"tandemC": libcmalib.tandemC,
|
|
25
|
+
"tandemCu": libcmalib.tandemCu,
|
|
26
|
+
"cassini2minlpC": libcmalib.cassini2minlpC,
|
|
36
27
|
}
|
|
37
28
|
|
|
29
|
+
freemem = libcmalib.free_mem
|
|
30
|
+
freemem.argtypes = [ct.POINTER(ct.c_double)]
|
|
31
|
+
|
|
38
32
|
class Astrofun(object):
|
|
39
33
|
"""Provides access to ESAs GTOP optimization test functions."""
|
|
40
34
|
def __init__(self, name, fun_c, lower, upper):
|
|
@@ -191,18 +185,33 @@ class Cassini1multi(object):
|
|
|
191
185
|
class Cassini1minlp(object):
|
|
192
186
|
""" see https://www.esa.int/gsp/ACT/projects/gtop/cassini1/ """
|
|
193
187
|
|
|
194
|
-
def __init__(self,
|
|
195
|
-
Astrofun.__init__(self, '
|
|
196
|
-
[-1000.,30.,100.,30.,400.,1000
|
|
197
|
-
[0.,400.,470.,400.,2000.,6000
|
|
188
|
+
def __init__(self, planets = [2,2,3,5]):
|
|
189
|
+
Astrofun.__init__(self, 'Cassini1', "cassini1C",
|
|
190
|
+
[-1000.,30.,100.,30.,400.,1000.],
|
|
191
|
+
[0.,400.,470.,400.,2000.,6000.]
|
|
198
192
|
)
|
|
199
|
-
self.fun = self.
|
|
200
|
-
self.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
193
|
+
self.fun = self.cassini1
|
|
194
|
+
self.planets = planets
|
|
195
|
+
|
|
196
|
+
def cassini1(self, x):
|
|
197
|
+
return cassini1minlp(list(x) + self.planets)
|
|
198
|
+
|
|
199
|
+
def cassini1minlp(x):
|
|
200
|
+
n = len(x)
|
|
201
|
+
array_type = ct.c_double * n
|
|
202
|
+
fun_c = astro_map["cassini1minlpC"]
|
|
203
|
+
fun_c.argtypes = [ct.c_int, ct.POINTER(ct.c_double)]
|
|
204
|
+
fun_c.restype = ct.POINTER(ct.c_double)
|
|
205
|
+
try: # function is only defined inside bounds
|
|
206
|
+
res = fun_c(n, array_type(*x))
|
|
207
|
+
dv = res[0]
|
|
208
|
+
freemem(res)
|
|
209
|
+
if not math.isfinite(dv):
|
|
210
|
+
dv = 1E10
|
|
211
|
+
except Exception as ex:
|
|
212
|
+
print(ex)
|
|
213
|
+
dv = 1E10
|
|
214
|
+
return dv
|
|
206
215
|
|
|
207
216
|
def cassini1multi(x):
|
|
208
217
|
n = len(x)
|
|
@@ -218,13 +227,28 @@ def cassini1multi(x):
|
|
|
218
227
|
if not math.isfinite(dv):
|
|
219
228
|
dv = 1E10
|
|
220
229
|
except Exception as ex:
|
|
230
|
+
print(ex)
|
|
221
231
|
dv = 1E10
|
|
222
232
|
launch_dv = 1E10
|
|
223
|
-
tof = x[1]
|
|
233
|
+
tof = sum(x[1:6])
|
|
224
234
|
launch_time = x[0]
|
|
225
|
-
return [dv, tof, launch_time
|
|
235
|
+
return [dv, tof, launch_time]
|
|
226
236
|
|
|
227
|
-
|
|
237
|
+
def cassini2multi(x):
|
|
238
|
+
n = len(x)
|
|
239
|
+
array_type = ct.c_double * n
|
|
240
|
+
fun_c = astro_map["cassini2minlpC"]
|
|
241
|
+
fun_c.argtypes = [ct.c_int, ct.POINTER(ct.c_double)]
|
|
242
|
+
fun_c.restype = ct.c_double
|
|
243
|
+
try: # function is only defined inside bounds
|
|
244
|
+
dv = fun_c(n, array_type(*x))
|
|
245
|
+
except Exception as ex:
|
|
246
|
+
print(ex)
|
|
247
|
+
dv = 1E99
|
|
248
|
+
tof = sum(x[4:9])
|
|
249
|
+
launch_time = x[0]
|
|
250
|
+
return [dv, tof, launch_time]
|
|
251
|
+
|
|
228
252
|
class python_fun(object):
|
|
229
253
|
|
|
230
254
|
def __init__(self, cfun, bounds):
|
|
@@ -242,5 +266,5 @@ class python_fun(object):
|
|
|
242
266
|
val = 1E10
|
|
243
267
|
except Exception as ex:
|
|
244
268
|
val = 1E10
|
|
245
|
-
return val
|
|
246
|
-
|
|
269
|
+
return val
|
|
270
|
+
|
fcmaes/bitecpp.py
CHANGED
|
@@ -13,23 +13,25 @@ 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.
|
|
19
|
-
|
|
20
|
-
from
|
|
16
|
+
from numpy.random import PCG64DXSM, Generator
|
|
17
|
+
from scipy.optimize import OptimizeResult, Bounds
|
|
18
|
+
from fcmaes.evaluator import _check_bounds, mo_call_back_type, callback_so, libcmalib
|
|
19
|
+
|
|
20
|
+
from typing import Optional, Callable
|
|
21
|
+
from numpy.typing import ArrayLike
|
|
21
22
|
|
|
22
23
|
os.environ['MKL_DEBUG_CPU_TYPE'] = '5'
|
|
23
24
|
|
|
24
|
-
def minimize(fun,
|
|
25
|
-
bounds=None,
|
|
26
|
-
x0=None,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
def minimize(fun: Callable[[ArrayLike], float],
|
|
26
|
+
bounds: Optional[Bounds] = None,
|
|
27
|
+
x0: Optional[ArrayLike] = None,
|
|
28
|
+
max_evaluations: Optional[int] = 100000,
|
|
29
|
+
stop_fitness: Optional[float] = -np.inf,
|
|
30
|
+
M: Optional[int] = 1,
|
|
31
|
+
popsize: Optional[int] = 0,
|
|
32
|
+
stall_criterion: Optional[int] = 0,
|
|
33
|
+
rg: Optional[Generator] = Generator(PCG64DXSM()),
|
|
34
|
+
runid: Optional[int] = 0) -> OptimizeResult:
|
|
33
35
|
"""Minimization of a scalar function of one or more variables using a
|
|
34
36
|
C++ SCMA implementation called via ctypes.
|
|
35
37
|
|
|
@@ -37,10 +39,8 @@ def minimize(fun,
|
|
|
37
39
|
----------
|
|
38
40
|
fun : callable
|
|
39
41
|
The objective function to be minimized.
|
|
40
|
-
``fun(x
|
|
41
|
-
where ``x`` is an 1-D array with shape (dim,)
|
|
42
|
-
is a tuple of the fixed parameters needed to completely
|
|
43
|
-
specify the function.
|
|
42
|
+
``fun(x) -> float``
|
|
43
|
+
where ``x`` is an 1-D array with shape (dim,)
|
|
44
44
|
bounds : sequence or `Bounds`, optional
|
|
45
45
|
Bounds on variables. There are two ways to specify the bounds:
|
|
46
46
|
1. Instance of the `scipy.Bounds` class.
|
|
@@ -49,14 +49,16 @@ def minimize(fun,
|
|
|
49
49
|
x0 : ndarray, shape (dim,)
|
|
50
50
|
Initial guess. Array of real elements of size (dim,),
|
|
51
51
|
where 'dim' is the number of independent variables.
|
|
52
|
-
popsize = int, optional
|
|
53
|
-
CMA-ES population size.
|
|
54
52
|
max_evaluations : int, optional
|
|
55
53
|
Forced termination after ``max_evaluations`` function evaluations.
|
|
56
54
|
stop_fitness : float, optional
|
|
57
55
|
Limit for fitness value. If reached minimize terminates.
|
|
58
56
|
M : int, optional
|
|
59
57
|
Depth to use, 1 for plain CBiteOpt algorithm, >1 for CBiteOptDeep. Expected range is [1; 36].
|
|
58
|
+
popsize = int, optional
|
|
59
|
+
initial population size.
|
|
60
|
+
stall_criterion : int, optional
|
|
61
|
+
Terminate if stall_criterion*128*evaluations stalled, Not used if <= 0
|
|
60
62
|
rg = numpy.random.Generator, optional
|
|
61
63
|
Random generator for creating random guesses.
|
|
62
64
|
runid : int, optional
|
|
@@ -75,19 +77,16 @@ def minimize(fun,
|
|
|
75
77
|
|
|
76
78
|
lower, upper, guess = _check_bounds(bounds, x0, rg)
|
|
77
79
|
dim = guess.size
|
|
78
|
-
if lower is None:
|
|
79
|
-
lower = [0]*dim
|
|
80
|
-
upper = [0]*dim
|
|
81
|
-
if stop_fitness is None:
|
|
82
|
-
stop_fitness = -math.inf
|
|
83
80
|
array_type = ct.c_double * dim
|
|
84
|
-
c_callback = mo_call_back_type(
|
|
81
|
+
c_callback = mo_call_back_type(callback_so(fun, dim))
|
|
85
82
|
res = np.empty(dim+4)
|
|
86
83
|
res_p = res.ctypes.data_as(ct.POINTER(ct.c_double))
|
|
87
84
|
try:
|
|
88
85
|
optimizeBite_C(runid, c_callback, dim, int(rg.uniform(0, 2**32 - 1)),
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
None if x0 is None else array_type(*guess),
|
|
87
|
+
None if lower is None else array_type(*lower),
|
|
88
|
+
None if upper is None else array_type(*upper),
|
|
89
|
+
max_evaluations, stop_fitness, M, popsize, stall_criterion, res_p)
|
|
91
90
|
x = res[:dim]
|
|
92
91
|
val = res[dim]
|
|
93
92
|
evals = int(res[dim+1])
|
|
@@ -97,10 +96,12 @@ def minimize(fun,
|
|
|
97
96
|
except Exception as ex:
|
|
98
97
|
return OptimizeResult(x=None, fun=sys.float_info.max, nfev=0, nit=0, status=-1, success=False)
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
if not libcmalib is None:
|
|
100
|
+
|
|
101
|
+
optimizeBite_C = libcmalib.optimizeBite_C
|
|
102
|
+
optimizeBite_C.argtypes = [ct.c_long, mo_call_back_type, ct.c_int, ct.c_int, \
|
|
103
|
+
ct.POINTER(ct.c_double), ct.POINTER(ct.c_double), ct.POINTER(ct.c_double), \
|
|
104
|
+
ct.c_int, ct.c_double, ct.c_int, ct.c_int, ct.c_int, ct.POINTER(ct.c_double)]
|
|
104
105
|
|
|
105
106
|
|
|
106
107
|
|
fcmaes/cmaes.py
CHANGED
|
@@ -16,38 +16,39 @@ from time import time
|
|
|
16
16
|
import ctypes as ct
|
|
17
17
|
import multiprocessing as mp
|
|
18
18
|
from scipy import linalg
|
|
19
|
-
from scipy.optimize import OptimizeResult
|
|
20
|
-
from numpy.random import
|
|
21
|
-
from fcmaes.evaluator import Evaluator
|
|
19
|
+
from scipy.optimize import OptimizeResult, Bounds
|
|
20
|
+
from numpy.random import PCG64DXSM, Generator
|
|
21
|
+
from fcmaes.evaluator import Evaluator, serial, _check_bounds, _fitness, is_debug_active
|
|
22
|
+
|
|
23
|
+
from loguru import logger
|
|
24
|
+
from typing import Optional, Callable, Union
|
|
25
|
+
from numpy.typing import ArrayLike
|
|
22
26
|
|
|
23
27
|
os.environ['MKL_DEBUG_CPU_TYPE'] = '5'
|
|
24
28
|
|
|
25
|
-
def minimize(fun,
|
|
26
|
-
bounds=None,
|
|
27
|
-
x0=None,
|
|
28
|
-
input_sigma = 0.3,
|
|
29
|
-
popsize = 31,
|
|
30
|
-
max_evaluations = 100000,
|
|
31
|
-
max_iterations = 100000,
|
|
32
|
-
workers = 1,
|
|
33
|
-
accuracy = 1.0,
|
|
34
|
-
stop_fitness = np.
|
|
35
|
-
is_terminate = None,
|
|
36
|
-
rg = Generator(
|
|
37
|
-
runid=0,
|
|
38
|
-
normalize = True,
|
|
39
|
-
update_gap = None
|
|
40
|
-
logger = None):
|
|
29
|
+
def minimize(fun: Callable[[ArrayLike], float],
|
|
30
|
+
bounds: Optional[Bounds] = None,
|
|
31
|
+
x0: Optional[ArrayLike] = None,
|
|
32
|
+
input_sigma: Optional[Union[float, ArrayLike, Callable]] = 0.3,
|
|
33
|
+
popsize: Optional[int] = 31,
|
|
34
|
+
max_evaluations: Optional[int] = 100000,
|
|
35
|
+
max_iterations: Optional[int] = 100000,
|
|
36
|
+
workers: Optional[int] = 1,
|
|
37
|
+
accuracy: Optional[float] = 1.0,
|
|
38
|
+
stop_fitness: Optional[float] = -np.inf,
|
|
39
|
+
is_terminate: Optional[Callable[[ArrayLike, float], bool]] = None,
|
|
40
|
+
rg: Optional[Generator] = Generator(PCG64DXSM()),
|
|
41
|
+
runid: Optional[int] = 0,
|
|
42
|
+
normalize: Optional[bool] = True,
|
|
43
|
+
update_gap: Optional[int] = None) -> OptimizeResult:
|
|
41
44
|
"""Minimization of a scalar function of one or more variables using CMA-ES.
|
|
42
45
|
|
|
43
46
|
Parameters
|
|
44
47
|
----------
|
|
45
48
|
fun : callable
|
|
46
49
|
The objective function to be minimized.
|
|
47
|
-
``fun(x
|
|
48
|
-
where ``x`` is an 1-D array with shape (n,)
|
|
49
|
-
is a tuple of the fixed parameters needed to completely
|
|
50
|
-
specify the function.
|
|
50
|
+
``fun(x) -> float``
|
|
51
|
+
where ``x`` is an 1-D array with shape (n,)
|
|
51
52
|
bounds : sequence or `Bounds`, optional
|
|
52
53
|
Bounds on variables. There are two ways to specify the bounds:
|
|
53
54
|
1. Instance of the `scipy.Bounds` class.
|
|
@@ -82,10 +83,6 @@ def minimize(fun,
|
|
|
82
83
|
pheno -> if true geno transformation maps arguments to interval [-1,1]
|
|
83
84
|
update_gap : int, optional
|
|
84
85
|
number of iterations without distribution update
|
|
85
|
-
logger : logger, optional
|
|
86
|
-
logger for log output for tell_one, If None, logging
|
|
87
|
-
is switched off. Default is a logger which logs both to stdout and
|
|
88
|
-
appends to a file ``optimizer.log``.
|
|
89
86
|
|
|
90
87
|
Returns
|
|
91
88
|
-------
|
|
@@ -103,7 +100,7 @@ def minimize(fun,
|
|
|
103
100
|
max_evaluations, max_iterations,
|
|
104
101
|
accuracy, stop_fitness,
|
|
105
102
|
is_terminate, rg, np.random.randn, runid, normalize,
|
|
106
|
-
update_gap, fun
|
|
103
|
+
update_gap, fun)
|
|
107
104
|
if workers and workers > 1:
|
|
108
105
|
x, val, evals, iterations, stop = cmaes.do_optimize_delayed_update(fun, workers=workers)
|
|
109
106
|
else:
|
|
@@ -114,22 +111,21 @@ def minimize(fun,
|
|
|
114
111
|
class Cmaes(object):
|
|
115
112
|
"""Implements the cma-es ask/tell interactive interface."""
|
|
116
113
|
|
|
117
|
-
def __init__(self, bounds=None,
|
|
118
|
-
x0=None,
|
|
119
|
-
input_sigma = 0.3,
|
|
120
|
-
popsize = 31,
|
|
121
|
-
max_evaluations = 100000,
|
|
122
|
-
max_iterations = 100000,
|
|
123
|
-
accuracy = 1.0,
|
|
124
|
-
stop_fitness = np.
|
|
125
|
-
is_terminate = None,
|
|
126
|
-
rg = Generator(
|
|
127
|
-
randn = np.random.randn, # used for random offspring
|
|
128
|
-
runid=0,
|
|
129
|
-
normalize =
|
|
130
|
-
update_gap = None,
|
|
131
|
-
fun = None
|
|
132
|
-
logger = None
|
|
114
|
+
def __init__(self, bounds: Optional[Bounds] = None,
|
|
115
|
+
x0: Optional[ArrayLike] = None,
|
|
116
|
+
input_sigma: Optional[Union[float, ArrayLike, Callable]] = 0.3,
|
|
117
|
+
popsize: Optional[int] = 31,
|
|
118
|
+
max_evaluations: Optional[int] = 100000,
|
|
119
|
+
max_iterations: Optional[int] = 100000,
|
|
120
|
+
accuracy: Optional[int] = 1.0,
|
|
121
|
+
stop_fitness: Optional[float] = -np.inf,
|
|
122
|
+
is_terminate: Optional[bool] = None,
|
|
123
|
+
rg: Optional[Generator] = Generator(PCG64DXSM()), # used if x0 is undefined
|
|
124
|
+
randn: Optional[Callable] = np.random.randn, # used for random offspring
|
|
125
|
+
runid: Optional[int] = 0,
|
|
126
|
+
normalize: Optional[bool] = True,
|
|
127
|
+
update_gap: Optional[int] = None,
|
|
128
|
+
fun: Optional[Callable[[ArrayLike], float]] = None
|
|
133
129
|
):
|
|
134
130
|
|
|
135
131
|
# runid used in is_terminate callback to identify a specific run at different iteration
|
|
@@ -187,9 +183,8 @@ class Cmaes(object):
|
|
|
187
183
|
# selection strategy parameters
|
|
188
184
|
# Number of parents/points for recombination.
|
|
189
185
|
self.mu = int(self.popsize/2)
|
|
190
|
-
#
|
|
191
|
-
if
|
|
192
|
-
self.logger = logger
|
|
186
|
+
# timing / global best value
|
|
187
|
+
if is_debug_active():
|
|
193
188
|
self.best_y = mp.RawValue(ct.c_double, 1E99)
|
|
194
189
|
self.n_evals = mp.RawValue(ct.c_long, 0)
|
|
195
190
|
self.time_0 = time()
|
|
@@ -257,7 +252,7 @@ class Cmaes(object):
|
|
|
257
252
|
self.arz = None
|
|
258
253
|
self.fitness = None
|
|
259
254
|
|
|
260
|
-
def ask(self):
|
|
255
|
+
def ask(self) -> np.array:
|
|
261
256
|
"""ask for popsize new argument vectors.
|
|
262
257
|
|
|
263
258
|
Returns
|
|
@@ -265,9 +260,11 @@ class Cmaes(object):
|
|
|
265
260
|
xs : popsize sized list of dim sized argument lists."""
|
|
266
261
|
|
|
267
262
|
self.newArgs()
|
|
268
|
-
return [self.fitfun.decode(x) for x in self.arx]
|
|
263
|
+
return np.array([self.fitfun.decode(x) for x in self.arx])
|
|
269
264
|
|
|
270
|
-
def tell(self,
|
|
265
|
+
def tell(self,
|
|
266
|
+
ys: np.ndarray,
|
|
267
|
+
xs: Optional[np.ndarray] = None) -> int:
|
|
271
268
|
"""tell function values for the argument lists retrieved by ask().
|
|
272
269
|
|
|
273
270
|
Parameters
|
|
@@ -297,8 +294,16 @@ class Cmaes(object):
|
|
|
297
294
|
self.updateCMA()
|
|
298
295
|
self.arz = None
|
|
299
296
|
return self.stop
|
|
300
|
-
|
|
301
|
-
def
|
|
297
|
+
|
|
298
|
+
def population(self) -> np.array:
|
|
299
|
+
return self.fitfun.decode(self.arx)
|
|
300
|
+
|
|
301
|
+
def result(self) -> OptimizeResult:
|
|
302
|
+
return OptimizeResult(x=self.best_x, fun=self.best_value,
|
|
303
|
+
nfev=self.fitfun.evaluation_counter,
|
|
304
|
+
nit=self.iterations, status=self.stop, success=True)
|
|
305
|
+
|
|
306
|
+
def ask_one(self) -> np.array:
|
|
302
307
|
"""ask for one new argument vector.
|
|
303
308
|
|
|
304
309
|
Returns
|
|
@@ -309,7 +314,9 @@ class Cmaes(object):
|
|
|
309
314
|
arx = self.fitfun.closestFeasible(self.xmean + delta.transpose())
|
|
310
315
|
return self.fitfun.decode(arx)
|
|
311
316
|
|
|
312
|
-
def tell_one(self,
|
|
317
|
+
def tell_one(self,
|
|
318
|
+
y: float,
|
|
319
|
+
x: np.array) -> int:
|
|
313
320
|
"""tell function value for a argument list retrieved by ask_one().
|
|
314
321
|
|
|
315
322
|
Parameters
|
|
@@ -341,7 +348,7 @@ class Cmaes(object):
|
|
|
341
348
|
self.arx = []
|
|
342
349
|
self.fitness = []
|
|
343
350
|
|
|
344
|
-
if
|
|
351
|
+
if is_debug_active():
|
|
345
352
|
self.n_evals.value += 1
|
|
346
353
|
if y < self.best_y.value or self.n_evals.value % 1000 == 999:
|
|
347
354
|
if y < self.best_y.value: self.best_y.value = y
|
|
@@ -349,12 +356,10 @@ class Cmaes(object):
|
|
|
349
356
|
c = self.n_evals.value
|
|
350
357
|
message = '"c/t={0:.2f} c={1:d} t={2:.2f} y={3:.5f} yb={4:.5f} x={5!s}'.format(
|
|
351
358
|
c/t, c, t, y, self.best_y.value, x)
|
|
352
|
-
|
|
359
|
+
logger.debug(message)
|
|
353
360
|
return self.stop
|
|
354
361
|
|
|
355
362
|
def newArgs(self):
|
|
356
|
-
self.xmean = self.fitfun.closestFeasible(self.xmean)
|
|
357
|
-
self.fitness = np.full(self.popsize, math.inf)
|
|
358
363
|
# generate random offspring
|
|
359
364
|
self.arz = self.randn(self.popsize, self.dim)
|
|
360
365
|
delta = (self.BD @ self.arz.transpose()) * self.sigma
|
|
@@ -397,10 +402,9 @@ class Cmaes(object):
|
|
|
397
402
|
self.iterations += 1
|
|
398
403
|
if self.fitfun.evaluation_counter > self.max_evaluations:
|
|
399
404
|
break
|
|
400
|
-
|
|
401
|
-
self.
|
|
402
|
-
self.
|
|
403
|
-
self.updateCMA()
|
|
405
|
+
xs = self.ask()
|
|
406
|
+
ys = self.fitfun.values(xs)
|
|
407
|
+
self.tell(ys, xs)
|
|
404
408
|
if self.stop != 0:
|
|
405
409
|
break
|
|
406
410
|
return self.best_x, self.best_value, self.fitfun.evaluation_counter, self.iterations, self.stop
|
|
@@ -416,10 +420,9 @@ class Cmaes(object):
|
|
|
416
420
|
if self.best_value > best_fitness:
|
|
417
421
|
self.best_value = best_fitness
|
|
418
422
|
self.best_x = self.fitfun.decode(self.arx[arindex[0]])
|
|
419
|
-
if self.stop_fitness
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
return
|
|
423
|
+
if best_fitness < self.stop_fitness:
|
|
424
|
+
self.stop = 1
|
|
425
|
+
return
|
|
423
426
|
|
|
424
427
|
# Calculate new xmean, this is selection and recombination
|
|
425
428
|
xold = self.xmean # for speed up of Eq. (2) and (3)
|
|
@@ -591,80 +594,4 @@ class Cmaes(object):
|
|
|
591
594
|
self.diagD = np.sqrt(self.diagD) # diagD contains standard deviations now
|
|
592
595
|
|
|
593
596
|
self.BD = self.B * self.diagD # O(n^2)
|
|
594
|
-
|
|
595
|
-
def serial(fun):
|
|
596
|
-
"""Convert an objective function for serial execution for cmaes.minimize.
|
|
597
|
-
|
|
598
|
-
Parameters
|
|
599
|
-
----------
|
|
600
|
-
fun : objective function mapping a list of float arguments to a float value
|
|
601
|
-
|
|
602
|
-
Returns
|
|
603
|
-
-------
|
|
604
|
-
out : function
|
|
605
|
-
A function mapping a list of lists of float arguments to a list of float values
|
|
606
|
-
by applying the input function in a loop."""
|
|
607
|
-
|
|
608
|
-
return lambda xs : [_tryfun(fun, x) for x in xs]
|
|
609
|
-
|
|
610
|
-
def _func_serial(fun, num, pid, xs, ys):
|
|
611
|
-
for i in range(pid, len(xs), num):
|
|
612
|
-
ys[i] = _tryfun(fun, xs[i])
|
|
613
|
-
|
|
614
|
-
def _tryfun(fun, x):
|
|
615
|
-
try:
|
|
616
|
-
fit = fun(x)
|
|
617
|
-
return fit if math.isfinite(fit) else sys.float_info.max
|
|
618
|
-
except Exception:
|
|
619
|
-
return sys.float_info.max
|
|
620
|
-
|
|
621
|
-
def _check_bounds(bounds, guess, rg):
|
|
622
|
-
if bounds is None and guess is None:
|
|
623
|
-
raise ValueError('either guess or bounds need to be defined')
|
|
624
|
-
if bounds is None:
|
|
625
|
-
return None, None, np.asarray(guess)
|
|
626
|
-
if guess is None:
|
|
627
|
-
guess = rg.uniform(bounds.lb, bounds.ub)
|
|
628
|
-
return np.asarray(bounds.lb), np.asarray(bounds.ub), np.asarray(guess)
|
|
629
|
-
|
|
630
|
-
class _fitness(object):
|
|
631
|
-
"""wrapper around the objective function, scales relative to boundaries."""
|
|
632
|
-
|
|
633
|
-
def __init__(self, fun, lower, upper, normalize = None):
|
|
634
|
-
self.fun = fun
|
|
635
|
-
self.evaluation_counter = 0
|
|
636
|
-
self.lower = lower
|
|
637
|
-
self.normalize = False
|
|
638
|
-
if not (lower is None or normalize is None):
|
|
639
|
-
self.normalize = normalize
|
|
640
|
-
if not lower is None:
|
|
641
|
-
self.upper = upper
|
|
642
|
-
self.scale = 0.5 * (upper - lower)
|
|
643
|
-
self.typx = 0.5 * (upper + lower)
|
|
644
|
-
|
|
645
|
-
def values(self, Xs): #enables parallel evaluation
|
|
646
|
-
values = self.fun([self.decode(X) for X in Xs])
|
|
647
|
-
self.evaluation_counter += len(Xs)
|
|
648
|
-
return np.array(values)
|
|
649
|
-
|
|
650
|
-
def closestFeasible(self, X):
|
|
651
|
-
if self.lower is None:
|
|
652
|
-
return X
|
|
653
|
-
else:
|
|
654
|
-
if self.normalize:
|
|
655
|
-
return np.maximum(np.minimum(X, 1.0), -1.0)
|
|
656
|
-
else:
|
|
657
|
-
return np.maximum(np.minimum(X, self.upper), self.lower)
|
|
658
|
-
|
|
659
|
-
def encode(self, X):
|
|
660
|
-
if self.normalize:
|
|
661
|
-
return (X - self.typx) / self.scale
|
|
662
|
-
else:
|
|
663
|
-
return X
|
|
664
|
-
|
|
665
|
-
def decode(self, X):
|
|
666
|
-
if self.normalize:
|
|
667
|
-
return (X * self.scale) + self.typx
|
|
668
|
-
else:
|
|
669
|
-
return X
|
|
670
|
-
|
|
597
|
+
|