pymoo 0.6.1.6__cp312-cp312-macosx_10_13_universal2.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.
- pymoo/__init__.py +3 -0
- pymoo/algorithms/__init__.py +0 -0
- pymoo/algorithms/base/__init__.py +0 -0
- pymoo/algorithms/base/bracket.py +38 -0
- pymoo/algorithms/base/genetic.py +110 -0
- pymoo/algorithms/base/line.py +62 -0
- pymoo/algorithms/base/local.py +39 -0
- pymoo/algorithms/base/meta.py +79 -0
- pymoo/algorithms/hyperparameters.py +91 -0
- pymoo/algorithms/moo/__init__.py +0 -0
- pymoo/algorithms/moo/age.py +310 -0
- pymoo/algorithms/moo/age2.py +194 -0
- pymoo/algorithms/moo/cmopso.py +239 -0
- pymoo/algorithms/moo/ctaea.py +305 -0
- pymoo/algorithms/moo/dnsga2.py +80 -0
- pymoo/algorithms/moo/kgb.py +450 -0
- pymoo/algorithms/moo/moead.py +183 -0
- pymoo/algorithms/moo/mopso_cd.py +309 -0
- pymoo/algorithms/moo/nsga2.py +113 -0
- pymoo/algorithms/moo/nsga3.py +361 -0
- pymoo/algorithms/moo/pinsga2.py +370 -0
- pymoo/algorithms/moo/rnsga2.py +188 -0
- pymoo/algorithms/moo/rnsga3.py +246 -0
- pymoo/algorithms/moo/rvea.py +214 -0
- pymoo/algorithms/moo/sms.py +196 -0
- pymoo/algorithms/moo/spea2.py +191 -0
- pymoo/algorithms/moo/unsga3.py +49 -0
- pymoo/algorithms/soo/__init__.py +0 -0
- pymoo/algorithms/soo/convex/__init__.py +0 -0
- pymoo/algorithms/soo/nonconvex/__init__.py +0 -0
- pymoo/algorithms/soo/nonconvex/brkga.py +162 -0
- pymoo/algorithms/soo/nonconvex/cmaes.py +556 -0
- pymoo/algorithms/soo/nonconvex/de.py +283 -0
- pymoo/algorithms/soo/nonconvex/direct.py +148 -0
- pymoo/algorithms/soo/nonconvex/es.py +213 -0
- pymoo/algorithms/soo/nonconvex/g3pcx.py +94 -0
- pymoo/algorithms/soo/nonconvex/ga.py +95 -0
- pymoo/algorithms/soo/nonconvex/ga_niching.py +223 -0
- pymoo/algorithms/soo/nonconvex/isres.py +74 -0
- pymoo/algorithms/soo/nonconvex/nelder.py +251 -0
- pymoo/algorithms/soo/nonconvex/nrbo.py +191 -0
- pymoo/algorithms/soo/nonconvex/optuna.py +80 -0
- pymoo/algorithms/soo/nonconvex/pattern.py +185 -0
- pymoo/algorithms/soo/nonconvex/pso.py +337 -0
- pymoo/algorithms/soo/nonconvex/pso_ep.py +307 -0
- pymoo/algorithms/soo/nonconvex/random_search.py +25 -0
- pymoo/algorithms/soo/nonconvex/sres.py +56 -0
- pymoo/algorithms/soo/univariate/__init__.py +0 -0
- pymoo/algorithms/soo/univariate/exp.py +46 -0
- pymoo/algorithms/soo/univariate/golden.py +65 -0
- pymoo/algorithms/soo/univariate/quadr_interp.py +81 -0
- pymoo/algorithms/soo/univariate/wolfe.py +163 -0
- pymoo/config.py +33 -0
- pymoo/constraints/__init__.py +3 -0
- pymoo/constraints/adaptive.py +66 -0
- pymoo/constraints/as_obj.py +56 -0
- pymoo/constraints/as_penalty.py +41 -0
- pymoo/constraints/eps.py +34 -0
- pymoo/constraints/from_bounds.py +36 -0
- pymoo/core/__init__.py +0 -0
- pymoo/core/algorithm.py +408 -0
- pymoo/core/callback.py +38 -0
- pymoo/core/crossover.py +79 -0
- pymoo/core/decision_making.py +102 -0
- pymoo/core/decomposition.py +76 -0
- pymoo/core/duplicate.py +163 -0
- pymoo/core/evaluator.py +116 -0
- pymoo/core/indicator.py +34 -0
- pymoo/core/individual.py +784 -0
- pymoo/core/infill.py +65 -0
- pymoo/core/initialization.py +44 -0
- pymoo/core/mating.py +39 -0
- pymoo/core/meta.py +21 -0
- pymoo/core/mixed.py +164 -0
- pymoo/core/mutation.py +44 -0
- pymoo/core/operator.py +46 -0
- pymoo/core/parameters.py +134 -0
- pymoo/core/plot.py +208 -0
- pymoo/core/population.py +180 -0
- pymoo/core/problem.py +373 -0
- pymoo/core/recorder.py +99 -0
- pymoo/core/repair.py +23 -0
- pymoo/core/replacement.py +96 -0
- pymoo/core/result.py +52 -0
- pymoo/core/sampling.py +45 -0
- pymoo/core/selection.py +61 -0
- pymoo/core/solution.py +10 -0
- pymoo/core/survival.py +107 -0
- pymoo/core/termination.py +70 -0
- pymoo/core/variable.py +415 -0
- pymoo/decomposition/__init__.py +0 -0
- pymoo/decomposition/aasf.py +24 -0
- pymoo/decomposition/asf.py +10 -0
- pymoo/decomposition/pbi.py +13 -0
- pymoo/decomposition/perp_dist.py +13 -0
- pymoo/decomposition/tchebicheff.py +11 -0
- pymoo/decomposition/util.py +13 -0
- pymoo/decomposition/weighted_sum.py +8 -0
- pymoo/docs.py +187 -0
- pymoo/experimental/__init__.py +0 -0
- pymoo/experimental/algorithms/__init__.py +0 -0
- pymoo/experimental/algorithms/gde3.py +57 -0
- pymoo/functions/__init__.py +135 -0
- pymoo/functions/compiled/__init__.py +0 -0
- pymoo/functions/compiled/calc_perpendicular_distance.cpp +27464 -0
- pymoo/functions/compiled/calc_perpendicular_distance.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/decomposition.cpp +28853 -0
- pymoo/functions/compiled/decomposition.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/info.cpp +7058 -0
- pymoo/functions/compiled/info.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/mnn.cpp +30095 -0
- pymoo/functions/compiled/mnn.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/non_dominated_sorting.cpp +35692 -0
- pymoo/functions/compiled/non_dominated_sorting.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/pruning_cd.cpp +29248 -0
- pymoo/functions/compiled/pruning_cd.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/stochastic_ranking.cpp +28042 -0
- pymoo/functions/compiled/stochastic_ranking.cpython-312-darwin.so +0 -0
- pymoo/functions/standard/__init__.py +1 -0
- pymoo/functions/standard/calc_perpendicular_distance.py +20 -0
- pymoo/functions/standard/decomposition.py +18 -0
- pymoo/functions/standard/hv.py +5 -0
- pymoo/functions/standard/mnn.py +78 -0
- pymoo/functions/standard/non_dominated_sorting.py +474 -0
- pymoo/functions/standard/pruning_cd.py +93 -0
- pymoo/functions/standard/stochastic_ranking.py +42 -0
- pymoo/gradient/__init__.py +24 -0
- pymoo/gradient/automatic.py +85 -0
- pymoo/gradient/grad_autograd.py +105 -0
- pymoo/gradient/grad_complex.py +35 -0
- pymoo/gradient/grad_jax.py +51 -0
- pymoo/gradient/numpy.py +22 -0
- pymoo/gradient/toolbox/__init__.py +19 -0
- pymoo/indicators/__init__.py +0 -0
- pymoo/indicators/distance_indicator.py +55 -0
- pymoo/indicators/gd.py +7 -0
- pymoo/indicators/gd_plus.py +7 -0
- pymoo/indicators/hv/__init__.py +59 -0
- pymoo/indicators/hv/approximate.py +105 -0
- pymoo/indicators/hv/exact.py +68 -0
- pymoo/indicators/hv/exact_2d.py +102 -0
- pymoo/indicators/igd.py +7 -0
- pymoo/indicators/igd_plus.py +7 -0
- pymoo/indicators/kktpm.py +151 -0
- pymoo/indicators/migd.py +55 -0
- pymoo/indicators/rmetric.py +203 -0
- pymoo/indicators/spacing.py +52 -0
- pymoo/mcdm/__init__.py +0 -0
- pymoo/mcdm/compromise_programming.py +19 -0
- pymoo/mcdm/high_tradeoff.py +40 -0
- pymoo/mcdm/pseudo_weights.py +32 -0
- pymoo/operators/__init__.py +0 -0
- pymoo/operators/control.py +190 -0
- pymoo/operators/crossover/__init__.py +0 -0
- pymoo/operators/crossover/binx.py +47 -0
- pymoo/operators/crossover/dex.py +125 -0
- pymoo/operators/crossover/erx.py +164 -0
- pymoo/operators/crossover/expx.py +53 -0
- pymoo/operators/crossover/hux.py +37 -0
- pymoo/operators/crossover/nox.py +25 -0
- pymoo/operators/crossover/ox.py +88 -0
- pymoo/operators/crossover/pcx.py +84 -0
- pymoo/operators/crossover/pntx.py +49 -0
- pymoo/operators/crossover/sbx.py +137 -0
- pymoo/operators/crossover/spx.py +5 -0
- pymoo/operators/crossover/ux.py +20 -0
- pymoo/operators/mutation/__init__.py +0 -0
- pymoo/operators/mutation/bitflip.py +17 -0
- pymoo/operators/mutation/gauss.py +60 -0
- pymoo/operators/mutation/inversion.py +42 -0
- pymoo/operators/mutation/nom.py +7 -0
- pymoo/operators/mutation/pm.py +96 -0
- pymoo/operators/mutation/rm.py +23 -0
- pymoo/operators/repair/__init__.py +0 -0
- pymoo/operators/repair/bounce_back.py +32 -0
- pymoo/operators/repair/bounds_repair.py +97 -0
- pymoo/operators/repair/inverse_penalty.py +91 -0
- pymoo/operators/repair/rounding.py +18 -0
- pymoo/operators/repair/to_bound.py +31 -0
- pymoo/operators/repair/vtype.py +11 -0
- pymoo/operators/sampling/__init__.py +0 -0
- pymoo/operators/sampling/lhs.py +76 -0
- pymoo/operators/sampling/rnd.py +52 -0
- pymoo/operators/selection/__init__.py +0 -0
- pymoo/operators/selection/rnd.py +75 -0
- pymoo/operators/selection/tournament.py +78 -0
- pymoo/operators/survival/__init__.py +0 -0
- pymoo/operators/survival/rank_and_crowding/__init__.py +1 -0
- pymoo/operators/survival/rank_and_crowding/classes.py +212 -0
- pymoo/operators/survival/rank_and_crowding/metrics.py +208 -0
- pymoo/optimize.py +72 -0
- pymoo/parallelization/__init__.py +15 -0
- pymoo/parallelization/dask.py +25 -0
- pymoo/parallelization/joblib.py +28 -0
- pymoo/parallelization/ray.py +31 -0
- pymoo/parallelization/starmap.py +24 -0
- pymoo/problems/__init__.py +157 -0
- pymoo/problems/dyn.py +47 -0
- pymoo/problems/dynamic/__init__.py +0 -0
- pymoo/problems/dynamic/cec2015.py +108 -0
- pymoo/problems/dynamic/df.py +451 -0
- pymoo/problems/dynamic/misc.py +167 -0
- pymoo/problems/functional.py +48 -0
- pymoo/problems/many/__init__.py +5 -0
- pymoo/problems/many/cdtlz.py +159 -0
- pymoo/problems/many/dcdtlz.py +88 -0
- pymoo/problems/many/dtlz.py +264 -0
- pymoo/problems/many/wfg.py +553 -0
- pymoo/problems/multi/__init__.py +14 -0
- pymoo/problems/multi/bnh.py +34 -0
- pymoo/problems/multi/carside.py +48 -0
- pymoo/problems/multi/clutch.py +104 -0
- pymoo/problems/multi/csi.py +55 -0
- pymoo/problems/multi/ctp.py +198 -0
- pymoo/problems/multi/dascmop.py +213 -0
- pymoo/problems/multi/kursawe.py +25 -0
- pymoo/problems/multi/modact.py +68 -0
- pymoo/problems/multi/mw.py +400 -0
- pymoo/problems/multi/omnitest.py +48 -0
- pymoo/problems/multi/osy.py +32 -0
- pymoo/problems/multi/srn.py +28 -0
- pymoo/problems/multi/sympart.py +94 -0
- pymoo/problems/multi/tnk.py +24 -0
- pymoo/problems/multi/truss2d.py +83 -0
- pymoo/problems/multi/welded_beam.py +41 -0
- pymoo/problems/multi/wrm.py +36 -0
- pymoo/problems/multi/zdt.py +151 -0
- pymoo/problems/multi_to_single.py +22 -0
- pymoo/problems/single/__init__.py +12 -0
- pymoo/problems/single/ackley.py +24 -0
- pymoo/problems/single/cantilevered_beam.py +34 -0
- pymoo/problems/single/flowshop_scheduling.py +113 -0
- pymoo/problems/single/g.py +874 -0
- pymoo/problems/single/griewank.py +18 -0
- pymoo/problems/single/himmelblau.py +15 -0
- pymoo/problems/single/knapsack.py +49 -0
- pymoo/problems/single/mopta08.py +26 -0
- pymoo/problems/single/multimodal.py +20 -0
- pymoo/problems/single/pressure_vessel.py +30 -0
- pymoo/problems/single/rastrigin.py +20 -0
- pymoo/problems/single/rosenbrock.py +22 -0
- pymoo/problems/single/schwefel.py +18 -0
- pymoo/problems/single/simple.py +13 -0
- pymoo/problems/single/sphere.py +19 -0
- pymoo/problems/single/traveling_salesman.py +79 -0
- pymoo/problems/single/zakharov.py +19 -0
- pymoo/problems/static.py +14 -0
- pymoo/problems/util.py +42 -0
- pymoo/problems/zero_to_one.py +27 -0
- pymoo/termination/__init__.py +23 -0
- pymoo/termination/collection.py +12 -0
- pymoo/termination/cv.py +48 -0
- pymoo/termination/default.py +45 -0
- pymoo/termination/delta.py +64 -0
- pymoo/termination/fmin.py +16 -0
- pymoo/termination/ftol.py +144 -0
- pymoo/termination/indicator.py +49 -0
- pymoo/termination/max_eval.py +14 -0
- pymoo/termination/max_gen.py +15 -0
- pymoo/termination/max_time.py +20 -0
- pymoo/termination/robust.py +34 -0
- pymoo/termination/xtol.py +33 -0
- pymoo/util/__init__.py +33 -0
- pymoo/util/archive.py +152 -0
- pymoo/util/cache.py +29 -0
- pymoo/util/clearing.py +82 -0
- pymoo/util/display/__init__.py +0 -0
- pymoo/util/display/column.py +52 -0
- pymoo/util/display/display.py +34 -0
- pymoo/util/display/multi.py +100 -0
- pymoo/util/display/output.py +53 -0
- pymoo/util/display/progress.py +54 -0
- pymoo/util/display/single.py +67 -0
- pymoo/util/dominator.py +67 -0
- pymoo/util/hv.py +21 -0
- pymoo/util/matlab_engine.py +39 -0
- pymoo/util/misc.py +447 -0
- pymoo/util/nds/__init__.py +0 -0
- pymoo/util/nds/dominance_degree_non_dominated_sort.py +159 -0
- pymoo/util/nds/efficient_non_dominated_sort.py +152 -0
- pymoo/util/nds/fast_non_dominated_sort.py +70 -0
- pymoo/util/nds/find_non_dominated.py +54 -0
- pymoo/util/nds/naive_non_dominated_sort.py +36 -0
- pymoo/util/nds/non_dominated_sorting.py +94 -0
- pymoo/util/nds/tree_based_non_dominated_sort.py +133 -0
- pymoo/util/normalization.py +312 -0
- pymoo/util/optimum.py +42 -0
- pymoo/util/randomized_argsort.py +63 -0
- pymoo/util/ref_dirs/__init__.py +24 -0
- pymoo/util/ref_dirs/construction.py +89 -0
- pymoo/util/ref_dirs/das_dennis.py +52 -0
- pymoo/util/ref_dirs/energy.py +317 -0
- pymoo/util/ref_dirs/energy_layer.py +119 -0
- pymoo/util/ref_dirs/genetic_algorithm.py +64 -0
- pymoo/util/ref_dirs/incremental.py +69 -0
- pymoo/util/ref_dirs/misc.py +128 -0
- pymoo/util/ref_dirs/optimizer.py +59 -0
- pymoo/util/ref_dirs/performance.py +162 -0
- pymoo/util/ref_dirs/reduction.py +85 -0
- pymoo/util/ref_dirs/sample_and_map.py +24 -0
- pymoo/util/reference_direction.py +258 -0
- pymoo/util/remote.py +55 -0
- pymoo/util/roulette.py +29 -0
- pymoo/util/running_metric.py +128 -0
- pymoo/util/sliding_window.py +25 -0
- pymoo/util/value_functions.py +720 -0
- pymoo/util/vectors.py +40 -0
- pymoo/util/vf_dominator.py +102 -0
- pymoo/vendor/__init__.py +0 -0
- pymoo/vendor/cec2018.py +398 -0
- pymoo/vendor/gta.py +617 -0
- pymoo/vendor/vendor_cmaes.py +421 -0
- pymoo/vendor/vendor_coco.py +81 -0
- pymoo/vendor/vendor_scipy.py +232 -0
- pymoo/version.py +1 -0
- pymoo/visualization/__init__.py +21 -0
- pymoo/visualization/app/__init__.py +0 -0
- pymoo/visualization/app/pso.py +61 -0
- pymoo/visualization/fitness_landscape.py +128 -0
- pymoo/visualization/heatmap.py +123 -0
- pymoo/visualization/matplotlib.py +61 -0
- pymoo/visualization/pcp.py +121 -0
- pymoo/visualization/petal.py +91 -0
- pymoo/visualization/radar.py +108 -0
- pymoo/visualization/radviz.py +68 -0
- pymoo/visualization/scatter.py +150 -0
- pymoo/visualization/star_coordinate.py +75 -0
- pymoo/visualization/util.py +296 -0
- pymoo/visualization/video/__init__.py +0 -0
- pymoo/visualization/video/callback_video.py +82 -0
- pymoo/visualization/video/one_var_one_obj.py +57 -0
- pymoo/visualization/video/two_var_one_obj.py +62 -0
- pymoo-0.6.1.6.dist-info/METADATA +209 -0
- pymoo-0.6.1.6.dist-info/RECORD +337 -0
- pymoo-0.6.1.6.dist-info/WHEEL +6 -0
- pymoo-0.6.1.6.dist-info/licenses/LICENSE +191 -0
- pymoo-0.6.1.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from cma import CMAOptions
|
|
5
|
+
from cma import optimization_tools as ot
|
|
6
|
+
from cma.evolution_strategy import cma_default_options, CMAEvolutionStrategy
|
|
7
|
+
from cma.utilities import utils
|
|
8
|
+
from cma.utilities.math import Mh
|
|
9
|
+
|
|
10
|
+
from pymoo.util import default_random_state
|
|
11
|
+
|
|
12
|
+
all_stoppings = []
|
|
13
|
+
|
|
14
|
+
def void(_):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
@default_random_state
|
|
18
|
+
def my_fmin(x0,
|
|
19
|
+
sigma0,
|
|
20
|
+
objective_function=void,
|
|
21
|
+
options=None,
|
|
22
|
+
args=(),
|
|
23
|
+
gradf=None,
|
|
24
|
+
restarts=0,
|
|
25
|
+
restart_from_best='False',
|
|
26
|
+
incpopsize=2,
|
|
27
|
+
eval_initial_x=False,
|
|
28
|
+
parallel_objective=None,
|
|
29
|
+
noise_handler=None,
|
|
30
|
+
noise_change_sigma_exponent=1,
|
|
31
|
+
noise_kappa_exponent=0, # TODO: add max kappa value as parameter
|
|
32
|
+
bipop=False,
|
|
33
|
+
callback=None,
|
|
34
|
+
random_state=None):
|
|
35
|
+
|
|
36
|
+
if 1 < 3: # try: # pass on KeyboardInterrupt
|
|
37
|
+
if not objective_function and not parallel_objective: # cma.fmin(0, 0, 0)
|
|
38
|
+
return CMAOptions() # these opts are by definition valid
|
|
39
|
+
|
|
40
|
+
fmin_options = locals().copy() # archive original options
|
|
41
|
+
del fmin_options['objective_function']
|
|
42
|
+
del fmin_options['x0']
|
|
43
|
+
del fmin_options['sigma0']
|
|
44
|
+
del fmin_options['options']
|
|
45
|
+
del fmin_options['args']
|
|
46
|
+
|
|
47
|
+
if options is None:
|
|
48
|
+
options = cma_default_options
|
|
49
|
+
CMAOptions().check_attributes(options) # might modify options
|
|
50
|
+
# checked that no options.ftarget =
|
|
51
|
+
opts = CMAOptions(options.copy()).complement()
|
|
52
|
+
|
|
53
|
+
if callback is None:
|
|
54
|
+
callback = []
|
|
55
|
+
elif callable(callback):
|
|
56
|
+
callback = [callback]
|
|
57
|
+
|
|
58
|
+
# BIPOP-related variables:
|
|
59
|
+
runs_with_small = 0
|
|
60
|
+
small_i = []
|
|
61
|
+
large_i = []
|
|
62
|
+
popsize0 = None # to be evaluated after the first iteration
|
|
63
|
+
maxiter0 = None # to be evaluated after the first iteration
|
|
64
|
+
base_evals = 0
|
|
65
|
+
|
|
66
|
+
irun = 0
|
|
67
|
+
best = ot.BestSolution()
|
|
68
|
+
all_stoppings = []
|
|
69
|
+
while True: # restart loop
|
|
70
|
+
sigma_factor = 1
|
|
71
|
+
|
|
72
|
+
# Adjust the population according to BIPOP after a restart.
|
|
73
|
+
if not bipop:
|
|
74
|
+
# BIPOP not in use, simply double the previous population
|
|
75
|
+
# on restart.
|
|
76
|
+
if irun > 0:
|
|
77
|
+
popsize_multiplier = fmin_options['incpopsize'] ** (irun - runs_with_small)
|
|
78
|
+
opts['popsize'] = popsize0 * popsize_multiplier
|
|
79
|
+
|
|
80
|
+
elif irun == 0:
|
|
81
|
+
# Initial run is with "normal" population size; it is
|
|
82
|
+
# the large population before first doubling, but its
|
|
83
|
+
# budget accounting is the same as in case of small
|
|
84
|
+
# population.
|
|
85
|
+
poptype = 'small'
|
|
86
|
+
|
|
87
|
+
elif sum(small_i) < sum(large_i):
|
|
88
|
+
# An interweaved run with small population size
|
|
89
|
+
poptype = 'small'
|
|
90
|
+
if 11 < 3: # not needed when compared to irun - runs_with_small
|
|
91
|
+
restarts += 1 # A small restart doesn't count in the total
|
|
92
|
+
runs_with_small += 1 # _Before_ it's used in popsize_lastlarge
|
|
93
|
+
|
|
94
|
+
sigma_factor = 0.01 ** random_state.uniform() # Local search
|
|
95
|
+
popsize_multiplier = fmin_options['incpopsize'] ** (irun - runs_with_small)
|
|
96
|
+
opts['popsize'] = np.floor(popsize0 * popsize_multiplier ** (random_state.uniform() ** 2))
|
|
97
|
+
opts['maxiter'] = min(maxiter0, 0.5 * sum(large_i) / opts['popsize'])
|
|
98
|
+
# print('small basemul %s --> %s; maxiter %s' % (popsize_multiplier, opts['popsize'], opts['maxiter']))
|
|
99
|
+
|
|
100
|
+
else:
|
|
101
|
+
# A run with large population size; the population
|
|
102
|
+
# doubling is implicit with incpopsize.
|
|
103
|
+
poptype = 'large'
|
|
104
|
+
|
|
105
|
+
popsize_multiplier = fmin_options['incpopsize'] ** (irun - runs_with_small)
|
|
106
|
+
opts['popsize'] = popsize0 * popsize_multiplier
|
|
107
|
+
opts['maxiter'] = maxiter0
|
|
108
|
+
# print('large basemul %s --> %s; maxiter %s' % (popsize_multiplier, opts['popsize'], opts['maxiter']))
|
|
109
|
+
|
|
110
|
+
if not callable(objective_function) and callable(parallel_objective):
|
|
111
|
+
def objective_function(x, *args):
|
|
112
|
+
"""created from `parallel_objective` argument"""
|
|
113
|
+
return parallel_objective([x], *args)[0]
|
|
114
|
+
|
|
115
|
+
# recover from a CMA object
|
|
116
|
+
if irun == 0 and isinstance(x0, MyCMAEvolutionStrategy):
|
|
117
|
+
es = x0
|
|
118
|
+
x0 = es.inputargs['x0'] # for the next restarts
|
|
119
|
+
if np.isscalar(sigma0) and np.isfinite(sigma0) and sigma0 > 0:
|
|
120
|
+
es.sigma = sigma0
|
|
121
|
+
# debatable whether this makes sense:
|
|
122
|
+
sigma0 = es.inputargs['sigma0'] # for the next restarts
|
|
123
|
+
if options is not None:
|
|
124
|
+
es.opts.set(options)
|
|
125
|
+
# ignore further input args and keep original options
|
|
126
|
+
else: # default case
|
|
127
|
+
# Set seed from random_state for deterministic behavior
|
|
128
|
+
if 'seed' not in opts or opts['seed'] is None:
|
|
129
|
+
# Generate a seed from the random_state for CMA-ES
|
|
130
|
+
opts['seed'] = random_state.integers(0, 2**31)
|
|
131
|
+
|
|
132
|
+
if irun and eval(str(fmin_options['restart_from_best'])):
|
|
133
|
+
utils.print_warning('CAVE: restart_from_best is often not useful',
|
|
134
|
+
verbose=opts['verbose'])
|
|
135
|
+
es = MyCMAEvolutionStrategy(best.x, sigma_factor * sigma0, opts)
|
|
136
|
+
else:
|
|
137
|
+
es = MyCMAEvolutionStrategy(x0, sigma_factor * sigma0, opts)
|
|
138
|
+
# return opts, es
|
|
139
|
+
if callable(objective_function) and (
|
|
140
|
+
eval_initial_x
|
|
141
|
+
or es.opts['CMA_elitist'] == 'initial'
|
|
142
|
+
or (es.opts['CMA_elitist'] and
|
|
143
|
+
eval_initial_x is None)):
|
|
144
|
+
x = es.gp.pheno(es.mean,
|
|
145
|
+
into_bounds=es.boundary_handler.repair,
|
|
146
|
+
archive=es.sent_solutions)
|
|
147
|
+
es.f0 = yield x
|
|
148
|
+
es.best.update([x], es.sent_solutions,
|
|
149
|
+
[es.f0], 1)
|
|
150
|
+
es.countevals += 1
|
|
151
|
+
es.objective_function = objective_function # only for the record
|
|
152
|
+
|
|
153
|
+
opts = es.opts # processed options, unambiguous
|
|
154
|
+
# a hack:
|
|
155
|
+
fmin_opts = CMAOptions("unchecked", **fmin_options.copy())
|
|
156
|
+
for k in fmin_opts:
|
|
157
|
+
# locals() cannot be modified directly, exec won't work
|
|
158
|
+
# in 3.x, therefore
|
|
159
|
+
fmin_opts.eval(k, loc={'N': es.N,
|
|
160
|
+
'popsize': opts['popsize']},
|
|
161
|
+
correct_key=False)
|
|
162
|
+
|
|
163
|
+
es.logger.append = opts['verb_append'] or es.countiter > 0 or irun > 0
|
|
164
|
+
# es.logger is "the same" logger, because the "identity"
|
|
165
|
+
# is only determined by the `verb_filenameprefix` option
|
|
166
|
+
logger = es.logger # shortcut
|
|
167
|
+
try:
|
|
168
|
+
logger.persistent_communication_dict.update(
|
|
169
|
+
{'variable_annotations':
|
|
170
|
+
objective_function.variable_annotations})
|
|
171
|
+
except AttributeError:
|
|
172
|
+
pass
|
|
173
|
+
|
|
174
|
+
if 11 < 3:
|
|
175
|
+
if es.countiter == 0 and es.opts['verb_log'] > 0 and \
|
|
176
|
+
not es.opts['verb_append']:
|
|
177
|
+
logger = CMADataLogger(es.opts['verb_filenameprefix']
|
|
178
|
+
).register(es)
|
|
179
|
+
logger.add()
|
|
180
|
+
es.writeOutput() # initial values for sigma etc
|
|
181
|
+
|
|
182
|
+
if noise_handler:
|
|
183
|
+
if isinstance(noise_handler, type):
|
|
184
|
+
noisehandler = noise_handler(es.N)
|
|
185
|
+
else:
|
|
186
|
+
noisehandler = noise_handler
|
|
187
|
+
noise_handling = True
|
|
188
|
+
if fmin_opts['noise_change_sigma_exponent'] > 0:
|
|
189
|
+
es.opts['tolfacupx'] = float('inf')
|
|
190
|
+
else:
|
|
191
|
+
noisehandler = ot.NoiseHandler(es.N, 0) # switched off
|
|
192
|
+
noise_handling = False
|
|
193
|
+
es.noise_handler = noisehandler
|
|
194
|
+
|
|
195
|
+
# the problem: this assumes that good solutions cannot take longer than bad ones:
|
|
196
|
+
# with EvalInParallel(objective_function, 2, is_feasible=opts['is_feasible']) as eval_in_parallel:
|
|
197
|
+
if 1 < 3:
|
|
198
|
+
while not es.stop(): # iteration loop
|
|
199
|
+
# X, fit = eval_in_parallel(lambda: es.ask(1)[0], es.popsize, args, repetitions=noisehandler.evaluations-1)
|
|
200
|
+
X, fit = yield from es.ask_and_eval(parallel_objective or objective_function,
|
|
201
|
+
args, gradf=gradf,
|
|
202
|
+
evaluations=noisehandler.evaluations,
|
|
203
|
+
aggregation=np.median,
|
|
204
|
+
parallel_mode=parallel_objective) # treats NaN with resampling if not parallel_mode
|
|
205
|
+
# TODO: check args and in case use args=(noisehandler.evaluations, )
|
|
206
|
+
|
|
207
|
+
if 11 < 3 and opts['vv']: # inject a solution
|
|
208
|
+
# use option check_point = [0]
|
|
209
|
+
if 0 * random_state.standard_normal() >= 0:
|
|
210
|
+
X[0] = 0 + opts['vv'] * es.sigma ** 0 * random_state.standard_normal(es.N)
|
|
211
|
+
fit[0] = yield X[0]
|
|
212
|
+
# print fit[0]
|
|
213
|
+
if es.opts['verbose'] > 4: # may be undesirable with dynamic fitness (e.g. Augmented Lagrangian)
|
|
214
|
+
if es.countiter < 2 or min(fit) <= es.best.last.f:
|
|
215
|
+
degrading_iterations_count = 0 # comes first to avoid code check complaint
|
|
216
|
+
else: # min(fit) > es.best.last.f:
|
|
217
|
+
degrading_iterations_count += 1
|
|
218
|
+
if degrading_iterations_count > 4:
|
|
219
|
+
utils.print_message('%d f-degrading iterations (set verbose<=4 to suppress)'
|
|
220
|
+
% degrading_iterations_count,
|
|
221
|
+
iteration=es.countiter)
|
|
222
|
+
es.tell(X, fit) # prepare for next iteration
|
|
223
|
+
if noise_handling: # it would be better to also use these f-evaluations in tell
|
|
224
|
+
es.sigma *= noisehandler(X, fit, objective_function, es.ask,
|
|
225
|
+
args=args) ** fmin_opts['noise_change_sigma_exponent']
|
|
226
|
+
|
|
227
|
+
es.countevals += noisehandler.evaluations_just_done # TODO: this is a hack, not important though
|
|
228
|
+
# es.more_to_write.append(noisehandler.evaluations_just_done)
|
|
229
|
+
if noisehandler.maxevals > noisehandler.minevals:
|
|
230
|
+
es.more_to_write.append(noisehandler.evaluations)
|
|
231
|
+
if 1 < 3:
|
|
232
|
+
# If sigma was above multiplied by the same
|
|
233
|
+
# factor cmean is divided by here, this is
|
|
234
|
+
# like only multiplying kappa instead of
|
|
235
|
+
# changing cmean and sigma.
|
|
236
|
+
es.sp.cmean *= np.exp(-noise_kappa_exponent * np.tanh(noisehandler.noiseS))
|
|
237
|
+
es.sp.cmean[es.sp.cmean > 1] = 1.0 # also works with "scalar arrays" like np.array(1.2)
|
|
238
|
+
for f in callback:
|
|
239
|
+
f is None or f(es)
|
|
240
|
+
es.disp()
|
|
241
|
+
logger.add(
|
|
242
|
+
# more_data=[noisehandler.evaluations, 10**noisehandler.noiseS] if noise_handling else [],
|
|
243
|
+
modulo=1 if es.stop() and logger.modulo else None)
|
|
244
|
+
if (opts['verb_log'] and opts['verb_plot'] and
|
|
245
|
+
(es.countiter % max(opts['verb_plot'], opts['verb_log']) == 0 or es.stop())):
|
|
246
|
+
logger.plot(324)
|
|
247
|
+
|
|
248
|
+
# end while not es.stop
|
|
249
|
+
if opts['eval_final_mean'] and callable(objective_function):
|
|
250
|
+
mean_pheno = es.gp.pheno(es.mean,
|
|
251
|
+
into_bounds=es.boundary_handler.repair,
|
|
252
|
+
archive=es.sent_solutions)
|
|
253
|
+
fmean = yield mean_pheno
|
|
254
|
+
es.countevals += 1
|
|
255
|
+
es.best.update([mean_pheno], es.sent_solutions, [fmean], es.countevals)
|
|
256
|
+
|
|
257
|
+
best.update(es.best, es.sent_solutions) # in restarted case
|
|
258
|
+
# es.best.update(best)
|
|
259
|
+
|
|
260
|
+
this_evals = es.countevals - base_evals
|
|
261
|
+
base_evals = es.countevals
|
|
262
|
+
|
|
263
|
+
# BIPOP stats update
|
|
264
|
+
|
|
265
|
+
if irun == 0:
|
|
266
|
+
popsize0 = opts['popsize']
|
|
267
|
+
maxiter0 = opts['maxiter']
|
|
268
|
+
# XXX: This might be a bug? Reproduced from Matlab
|
|
269
|
+
# small_i.append(this_evals)
|
|
270
|
+
|
|
271
|
+
if bipop:
|
|
272
|
+
if poptype == 'small':
|
|
273
|
+
small_i.append(this_evals)
|
|
274
|
+
else: # poptype == 'large'
|
|
275
|
+
large_i.append(this_evals)
|
|
276
|
+
|
|
277
|
+
# final message
|
|
278
|
+
if opts['verb_disp']:
|
|
279
|
+
es.result_pretty(irun, time.asctime(time.localtime()),
|
|
280
|
+
best.f)
|
|
281
|
+
|
|
282
|
+
irun += 1
|
|
283
|
+
# if irun > fmin_opts['restarts'] or 'ftarget' in es.stop() \
|
|
284
|
+
# if irun > restarts or 'ftarget' in es.stop() \
|
|
285
|
+
all_stoppings.append(dict(es.stop(check=False))) # keeping the order
|
|
286
|
+
if irun - runs_with_small > fmin_opts['restarts'] or 'ftarget' in es.stop() \
|
|
287
|
+
or 'maxfevals' in es.stop(check=False) or 'callback' in es.stop(check=False):
|
|
288
|
+
break
|
|
289
|
+
opts['verb_append'] = es.countevals
|
|
290
|
+
opts['popsize'] = fmin_opts['incpopsize'] * es.sp.popsize # TODO: use rather options?
|
|
291
|
+
try:
|
|
292
|
+
opts['seed'] += 1
|
|
293
|
+
except TypeError:
|
|
294
|
+
pass
|
|
295
|
+
|
|
296
|
+
# while irun
|
|
297
|
+
|
|
298
|
+
# es.out['best'] = best # TODO: this is a rather suboptimal type for inspection in the shell
|
|
299
|
+
if irun:
|
|
300
|
+
es.best.update(best)
|
|
301
|
+
# TODO: there should be a better way to communicate the overall best
|
|
302
|
+
return es.result + (es.stop(), es, logger)
|
|
303
|
+
### 4560
|
|
304
|
+
# TODO refine output, can #args be flexible?
|
|
305
|
+
# is this well usable as it is now?
|
|
306
|
+
else: # except KeyboardInterrupt: # Exception as e:
|
|
307
|
+
if eval(safe_str(options['verb_disp'])) > 0:
|
|
308
|
+
print(' in/outcomment ``raise`` in last line of cma.fmin to prevent/restore KeyboardInterrupt exception')
|
|
309
|
+
raise KeyboardInterrupt # cave: swallowing this exception can silently mess up experiments, if ctrl-C is hit
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
class MyCMAEvolutionStrategy(CMAEvolutionStrategy):
|
|
313
|
+
|
|
314
|
+
def ask_and_eval(self, func, args=(), gradf=None, number=None, xmean=None, sigma_fac=1,
|
|
315
|
+
evaluations=1, aggregation=np.median, kappa=1, parallel_mode=False):
|
|
316
|
+
|
|
317
|
+
# initialize
|
|
318
|
+
popsize = self.sp.popsize
|
|
319
|
+
if number is not None:
|
|
320
|
+
popsize = int(number)
|
|
321
|
+
|
|
322
|
+
if self.opts['CMA_mirrormethod'] == 1: # direct selective mirrors
|
|
323
|
+
nmirrors = Mh.sround(self.sp.lam_mirr * popsize / self.sp.popsize)
|
|
324
|
+
self._mirrormethod1_done = self.countiter
|
|
325
|
+
else:
|
|
326
|
+
# method==0 unconditional mirrors are done in ask_geno
|
|
327
|
+
# method==2 delayed selective mirrors are done via injection
|
|
328
|
+
nmirrors = 0
|
|
329
|
+
assert nmirrors <= popsize // 2
|
|
330
|
+
self.mirrors_idx = np.arange(nmirrors) # might never be used
|
|
331
|
+
is_feasible = self.opts['is_feasible']
|
|
332
|
+
|
|
333
|
+
# do the work
|
|
334
|
+
fit = [] # or np.NaN * np.empty(number)
|
|
335
|
+
X_first = self.ask(popsize, xmean=xmean, gradf=gradf, args=args)
|
|
336
|
+
if xmean is None:
|
|
337
|
+
xmean = self.mean # might have changed in self.ask
|
|
338
|
+
X = []
|
|
339
|
+
if parallel_mode:
|
|
340
|
+
if hasattr(func, 'evaluations'):
|
|
341
|
+
evals0 = func.evaluations
|
|
342
|
+
fit_first = yield X_first
|
|
343
|
+
# the rest is only book keeping and warnings spitting
|
|
344
|
+
if hasattr(func, 'evaluations'):
|
|
345
|
+
self.countevals += func.evaluations - evals0 - self.popsize # why not .sp.popsize ?
|
|
346
|
+
if nmirrors and self.opts['CMA_mirrormethod'] > 0 and self.countiter < 2:
|
|
347
|
+
utils.print_warning(
|
|
348
|
+
"selective mirrors will not work in parallel mode",
|
|
349
|
+
"ask_and_eval", "CMAEvolutionStrategy")
|
|
350
|
+
if evaluations > 1 and self.countiter < 2:
|
|
351
|
+
utils.print_warning(
|
|
352
|
+
"aggregating evaluations will not work in parallel mode",
|
|
353
|
+
"ask_and_eval", "CMAEvolutionStrategy")
|
|
354
|
+
else:
|
|
355
|
+
fit_first = len(X_first) * [None]
|
|
356
|
+
for k in range(popsize):
|
|
357
|
+
x, f = X_first.pop(0), fit_first.pop(0)
|
|
358
|
+
rejected = -1
|
|
359
|
+
while f is None or not is_feasible(x, f): # rejection sampling
|
|
360
|
+
if parallel_mode:
|
|
361
|
+
utils.print_warning(
|
|
362
|
+
"rejection sampling will not work in parallel mode"
|
|
363
|
+
" unless the parallel_objective makes a distinction\n"
|
|
364
|
+
"between called with a numpy array vs a list (of"
|
|
365
|
+
" numpy arrays) as first argument.",
|
|
366
|
+
"ask_and_eval", "CMAEvolutionStrategy")
|
|
367
|
+
rejected += 1
|
|
368
|
+
if rejected: # resample
|
|
369
|
+
x = self.ask(1, xmean, sigma_fac)[0]
|
|
370
|
+
elif k >= popsize - nmirrors: # selective mirrors
|
|
371
|
+
if k == popsize - nmirrors:
|
|
372
|
+
self.mirrors_idx = np.argsort(fit)[-1:-1 - nmirrors:-1]
|
|
373
|
+
x = self.get_mirror(X[self.mirrors_idx[popsize - 1 - k]])
|
|
374
|
+
|
|
375
|
+
# constraints handling test hardwired ccccccccccc
|
|
376
|
+
|
|
377
|
+
length_normalizer = 1
|
|
378
|
+
# zzzzzzzzzzzzzzzzzzzzzzzzz
|
|
379
|
+
if 11 < 3:
|
|
380
|
+
# for some unclear reason, this normalization does not work as expected: the step-size
|
|
381
|
+
# becomes sometimes too large and overall the mean might diverge. Is the reason that
|
|
382
|
+
# we observe random fluctuations, because the length is not selection relevant?
|
|
383
|
+
# However sigma-adaptation should mainly work on the correlation, not the length?
|
|
384
|
+
# Or is the reason the deviation of the direction introduced by using the original
|
|
385
|
+
# length, which also can effect the measured correlation?
|
|
386
|
+
# Update: if the length of z in CSA is clipped at chiN+1, it works, but only sometimes?
|
|
387
|
+
length_normalizer = self.N**0.5 / self.mahalanobis_norm(x - xmean) # self.const.chiN < N**0.5, the constant here is irrelevant (absorbed by kappa)
|
|
388
|
+
# print(self.N**0.5 / self.mahalanobis_norm(x - xmean))
|
|
389
|
+
# self.more_to_write += [length_normalizer * 1e-3, length_normalizer * self.mahalanobis_norm(x - xmean) * 1e2]
|
|
390
|
+
if kappa == 1:
|
|
391
|
+
f = yield x
|
|
392
|
+
else:
|
|
393
|
+
f = yield xmean + kappa * length_normalizer * (x - xmean)
|
|
394
|
+
|
|
395
|
+
if is_feasible(x, f) and evaluations > 1:
|
|
396
|
+
if kappa == 1:
|
|
397
|
+
_f = yield x
|
|
398
|
+
f = aggregation([f] + [_f])
|
|
399
|
+
else:
|
|
400
|
+
_f = []
|
|
401
|
+
for _i in range(int(evaluations - 1)):
|
|
402
|
+
v = yield xmean + kappa * length_normalizer * (x - xmean)
|
|
403
|
+
_f.append(v)
|
|
404
|
+
f = aggregation([f] + _f)
|
|
405
|
+
|
|
406
|
+
if (rejected + 1) % 1000 == 0:
|
|
407
|
+
utils.print_warning(' %d solutions rejected (f-value NaN or None) at iteration %d' %
|
|
408
|
+
(rejected, self.countiter))
|
|
409
|
+
fit.append(f)
|
|
410
|
+
X.append(x)
|
|
411
|
+
self.evaluations_per_f_value = int(evaluations)
|
|
412
|
+
if any(f is None or utils.is_nan(f) for f in fit):
|
|
413
|
+
idxs = [i for i in range(len(fit))
|
|
414
|
+
if fit[i] is None or utils.is_nan(fit[i])]
|
|
415
|
+
utils.print_warning("f-values %s contain None or NaN at indices %s"
|
|
416
|
+
% (str(fit[:30]) + ('...' if len(fit) > 30 else ''),
|
|
417
|
+
str(idxs)),
|
|
418
|
+
'ask_and_tell',
|
|
419
|
+
'CMAEvolutionStrategy',
|
|
420
|
+
self.countiter)
|
|
421
|
+
return X, fit
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from pymoo.core.problem import Problem
|
|
6
|
+
from pymoo.util.remote import Remote
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class COCOProblem(Problem):
|
|
10
|
+
|
|
11
|
+
def __init__(self, name, n_var=10, pf_from_file=True, **kwargs):
|
|
12
|
+
self.function, self.instance, self.object = get_bbob(name, n_var)
|
|
13
|
+
self.name = name
|
|
14
|
+
self.pf_from_file = pf_from_file
|
|
15
|
+
|
|
16
|
+
coco = self.object
|
|
17
|
+
n_var, n_obj, n_ieq_constr = coco.number_of_variables, coco.number_of_objectives, coco.number_of_constraints
|
|
18
|
+
xl, xu = coco.lower_bounds, coco.upper_bounds
|
|
19
|
+
|
|
20
|
+
super().__init__(n_var=n_var,
|
|
21
|
+
n_obj=n_obj,
|
|
22
|
+
n_ieq_constr=n_ieq_constr,
|
|
23
|
+
xl=xl,
|
|
24
|
+
xu=xu,
|
|
25
|
+
**kwargs)
|
|
26
|
+
|
|
27
|
+
def _calc_pareto_set(self, *args, **kwargs):
|
|
28
|
+
if self.n_obj == 1:
|
|
29
|
+
fname = '._bbob_problem_best_parameter.txt'
|
|
30
|
+
|
|
31
|
+
self.object._best_parameter(what="print")
|
|
32
|
+
ps = np.loadtxt(fname)
|
|
33
|
+
os.remove(fname)
|
|
34
|
+
|
|
35
|
+
return ps
|
|
36
|
+
|
|
37
|
+
def _calc_pareto_front(self, *args, **kwargs):
|
|
38
|
+
if self.pf_from_file:
|
|
39
|
+
return Remote.get_instance().load("pymoo", "pf", "bbob.pf", to="json")[str(self.function)][str(self.instance)]
|
|
40
|
+
else:
|
|
41
|
+
ps = self.pareto_set()
|
|
42
|
+
if ps is not None:
|
|
43
|
+
return self.evaluate(ps)
|
|
44
|
+
|
|
45
|
+
def _evaluate(self, X, out, *args, **kwargs):
|
|
46
|
+
out["F"] = np.array([self.object(x) for x in X])
|
|
47
|
+
|
|
48
|
+
def __getstate__(self):
|
|
49
|
+
d = self.__dict__.copy()
|
|
50
|
+
d["object"] = None
|
|
51
|
+
return d
|
|
52
|
+
|
|
53
|
+
def __setstate__(self, d):
|
|
54
|
+
self.__dict__.update(d)
|
|
55
|
+
self.object = get_bbob(self.name, self.n_var)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def get_bbob(name, n_var=10, **kwargs):
|
|
59
|
+
try:
|
|
60
|
+
import cocoex as ex
|
|
61
|
+
except:
|
|
62
|
+
raise Exception("COCO test suite not found. \nInstallation Guide: https://github.com/numbbo/coco")
|
|
63
|
+
|
|
64
|
+
args = name.split("-")
|
|
65
|
+
|
|
66
|
+
n_instance = int(args[-1])
|
|
67
|
+
n_function = int(args[-2].replace("f", ""))
|
|
68
|
+
|
|
69
|
+
assert 1 <= n_function <= 24, f"BBOB has 24 different functions to be chosen. {n_function} is out of range."
|
|
70
|
+
|
|
71
|
+
suite_filter_options = f"function_indices: {n_function} " \
|
|
72
|
+
f"instance_indices: {n_instance} " \
|
|
73
|
+
f"dimensions: {n_var}"
|
|
74
|
+
|
|
75
|
+
problems = ex.Suite("bbob", "", suite_filter_options)
|
|
76
|
+
assert len(problems) == 1, "COCO problem not found."
|
|
77
|
+
|
|
78
|
+
coco = problems.next_problem()
|
|
79
|
+
|
|
80
|
+
return n_function, n_instance, coco
|
|
81
|
+
|