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/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 numpy.random import MT19937, Generator
48
- from fcmaes.decpp import mo_call_back_type, callback_mo, libcmalib
49
- from fcmaes import de, mode, moretry
50
- from fcmaes.mode import filter
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
- popsize = 64,
61
- max_evaluations = 100000,
62
- workers = 1,
63
- f = 0.5,
64
- cr = 0.9,
65
- pro_c = 1.0,
66
- dis_c = 20.0,
67
- pro_m = 1.0,
68
- dis_m = 20.0,
69
- nsga_update = False,
70
- pareto_update = 0,
71
- log_period = sys.maxsize,
72
- rg = Generator(MT19937()),
73
- plot_name = None,
74
- store = None,
75
- is_terminate = None,
76
- runid=0):
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, *args) -> list(float)``
86
- where ``x`` is an 1-D array with shape (n,) and ``args``
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
- If not workers is None, function evaluation is performed in parallel for the whole population.
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 False
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. Use the pareto front for population update
118
- with probability pareto_update, else use the whole population. Default 0 - use always
119
- the whole population.
120
- log_period = int, optional
121
- The log callback is called each log_period iterations. As default the callback is never called.
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. For multi threaded execution.
130
- use workers=1 if you call minimize from multiple threads
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
- optimizeMODE_C(runid, c_callback, c_log, dim, nobj, ncon, seed,
158
- array_type(*lower), array_type(*upper),
159
- max_evaluations, popsize, workers, f, cr,
160
- pro_c, dis_c, pro_m, dis_m,
161
- nsga_update, pareto_update, log_period, res_p)
162
- x = np.empty((2*popsize,dim))
163
- for p in range(2*popsize):
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
- num_retries = 64,
178
- popsize = 64,
179
- max_evaluations = 100000,
180
- workers = mp.cpu_count(),
181
- nsga_update = True,
182
- logger = None,
183
- is_terminate = None):
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) -> list(float)``
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 True
215
- logger : logger, optional
216
- logger for log output for tell_one, If None, logging
217
- is switched off. Default is a logger which logs both to stdout and
218
- appends to a file ``optimizer.log``.
219
- is_terminate : callable, optional
220
- Callback to be used if the caller of minimize wants to decide when to terminate. """
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, _, _ = de._check_bounds(bounds, None)
223
- store = mode.store(dim, nobj + ncon, 100*popsize*2)
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(MT19937(s)) for s in sg.spawn(workers)]
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, is_terminate, store, logger))
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, is_terminate, store, logger):
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
- while store.num_added.value < num:
242
- if not is_terminate is None and hasattr(is_terminate, 'reinit'):
243
- is_terminate.reinit()
244
- minimize(mofun, nobj, ncon, bounds, popsize,
245
- max_evaluations = max_evaluations, nsga_update=nsga_update,
246
- workers = 1, rg = rgs[pid], store = store, is_terminate=is_terminate)
247
- if not logger is None:
248
- logger.info("retries = {0}: time = {1:.1f} i = {2}"
249
- .format(store.num_added.value, dtime(t0), store.num_stored.value))
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 log_mo(object):
252
-
253
- def __init__(self, name, dim, nobj, ncon):
254
- self.name = name
255
- self.dim = dim
256
- self.nobj = nobj + ncon
257
- self.ncon = ncon
258
- self.calls = 0
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 __call__(self, n, x, y):
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
- if not self.name is None:
263
- self.calls += 1
264
- arrTypeX = ct.c_double*(self.dim*n)
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 False
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
- optimizeMODE_C = libcmalib.optimizeMODE_C
288
- optimizeMODE_C.argtypes = [ct.c_long, mo_call_back_type, mo_call_back_type, ct.c_int, ct.c_int, \
289
- ct.c_int, ct.c_int, ct.POINTER(ct.c_double), ct.POINTER(ct.c_double), \
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