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,212 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.population import Population
|
|
4
|
+
from pymoo.core.survival import Survival, split_by_feasibility
|
|
5
|
+
from pymoo.operators.survival.rank_and_crowding.metrics import get_crowding_function
|
|
6
|
+
from pymoo.util.nds.non_dominated_sorting import NonDominatedSorting
|
|
7
|
+
from pymoo.util.randomized_argsort import randomized_argsort
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RankAndCrowding(Survival):
|
|
11
|
+
|
|
12
|
+
def __init__(self, nds=None, crowding_func="cd"):
|
|
13
|
+
"""
|
|
14
|
+
A generalization of the NSGA-II survival operator that ranks individuals by dominance criteria
|
|
15
|
+
and sorts the last front by some user-specified crowding metric. The default is NSGA-II's crowding distances
|
|
16
|
+
although others might be more effective.
|
|
17
|
+
|
|
18
|
+
For many-objective problems, try using 'mnn' or '2nn'.
|
|
19
|
+
|
|
20
|
+
For Bi-objective problems, 'pcd' is very effective.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
nds : str or None, optional
|
|
25
|
+
Pymoo type of non-dominated sorting. Defaults to None.
|
|
26
|
+
|
|
27
|
+
crowding_func : str or callable, optional
|
|
28
|
+
Crowding metric. Options are:
|
|
29
|
+
|
|
30
|
+
- 'cd': crowding distances
|
|
31
|
+
- 'pcd' or 'pruning-cd': improved pruning based on crowding distances
|
|
32
|
+
- 'ce': crowding entropy
|
|
33
|
+
- 'mnn': M-Neaest Neighbors
|
|
34
|
+
- '2nn': 2-Neaest Neighbors
|
|
35
|
+
|
|
36
|
+
If callable, it has the form ``fun(F, filter_out_duplicates=None, n_remove=None, **kwargs)``
|
|
37
|
+
in which F (n, m) and must return metrics in a (n,) array.
|
|
38
|
+
|
|
39
|
+
The options 'pcd', 'cd', and 'ce' are recommended for two-objective problems, whereas 'mnn' and '2nn' for many objective.
|
|
40
|
+
When using 'pcd', 'mnn', or '2nn', individuals are already eliminated in a 'single' manner.
|
|
41
|
+
Due to Cython implementation, they are as fast as the corresponding 'cd', 'mnn-fast', or '2nn-fast',
|
|
42
|
+
although they can singnificantly improve diversity of solutions.
|
|
43
|
+
Defaults to 'cd'.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
crowding_func_ = get_crowding_function(crowding_func)
|
|
47
|
+
|
|
48
|
+
super().__init__(filter_infeasible=True)
|
|
49
|
+
self.nds = nds if nds is not None else NonDominatedSorting()
|
|
50
|
+
self.crowding_func = crowding_func_
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _do(self,
|
|
54
|
+
problem,
|
|
55
|
+
pop,
|
|
56
|
+
*args,
|
|
57
|
+
random_state=None,
|
|
58
|
+
n_survive=None,
|
|
59
|
+
**kwargs):
|
|
60
|
+
|
|
61
|
+
# get the objective space values and objects
|
|
62
|
+
F = pop.get("F").astype(float, copy=False)
|
|
63
|
+
|
|
64
|
+
# the final indices of surviving individuals
|
|
65
|
+
survivors = []
|
|
66
|
+
|
|
67
|
+
# do the non-dominated sorting until splitting front
|
|
68
|
+
fronts = self.nds.do(F, n_stop_if_ranked=n_survive)
|
|
69
|
+
|
|
70
|
+
for k, front in enumerate(fronts):
|
|
71
|
+
|
|
72
|
+
I = np.arange(len(front))
|
|
73
|
+
|
|
74
|
+
# current front sorted by crowding distance if splitting
|
|
75
|
+
if len(survivors) + len(I) > n_survive:
|
|
76
|
+
|
|
77
|
+
# Define how many will be removed
|
|
78
|
+
n_remove = len(survivors) + len(front) - n_survive
|
|
79
|
+
|
|
80
|
+
# re-calculate the crowding distance of the front
|
|
81
|
+
crowding_of_front = \
|
|
82
|
+
self.crowding_func.do(
|
|
83
|
+
F[front, :],
|
|
84
|
+
n_remove=n_remove
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
I = randomized_argsort(crowding_of_front, order='descending', method='numpy', random_state=random_state)
|
|
88
|
+
I = I[:-n_remove]
|
|
89
|
+
|
|
90
|
+
# otherwise take the whole front unsorted
|
|
91
|
+
else:
|
|
92
|
+
# calculate the crowding distance of the front
|
|
93
|
+
crowding_of_front = \
|
|
94
|
+
self.crowding_func.do(
|
|
95
|
+
F[front, :],
|
|
96
|
+
n_remove=0
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# save rank and crowding in the individual class
|
|
100
|
+
for j, i in enumerate(front):
|
|
101
|
+
pop[i].set("rank", k)
|
|
102
|
+
pop[i].set("crowding", crowding_of_front[j])
|
|
103
|
+
|
|
104
|
+
# extend the survivors by all or selected individuals
|
|
105
|
+
survivors.extend(front[I])
|
|
106
|
+
|
|
107
|
+
return pop[survivors]
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class ConstrRankAndCrowding(Survival):
|
|
111
|
+
|
|
112
|
+
def __init__(self, nds=None, crowding_func="cd"):
|
|
113
|
+
"""
|
|
114
|
+
The Rank and Crowding survival approach for handling constraints proposed on
|
|
115
|
+
GDE3 by Kukkonen, S. & Lampinen, J. (2005).
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
nds : str or None, optional
|
|
120
|
+
Pymoo type of non-dominated sorting. Defaults to None.
|
|
121
|
+
|
|
122
|
+
crowding_func : str or callable, optional
|
|
123
|
+
Crowding metric. Options are:
|
|
124
|
+
|
|
125
|
+
- 'cd': crowding distances
|
|
126
|
+
- 'pcd' or 'pruning-cd': improved pruning based on crowding distances
|
|
127
|
+
- 'ce': crowding entropy
|
|
128
|
+
- 'mnn': M-Neaest Neighbors
|
|
129
|
+
- '2nn': 2-Neaest Neighbors
|
|
130
|
+
|
|
131
|
+
If callable, it has the form ``fun(F, filter_out_duplicates=None, n_remove=None, **kwargs)``
|
|
132
|
+
in which F (n, m) and must return metrics in a (n,) array.
|
|
133
|
+
|
|
134
|
+
The options 'pcd', 'cd', and 'ce' are recommended for two-objective problems, whereas 'mnn' and '2nn' for many objective.
|
|
135
|
+
When using 'pcd', 'mnn', or '2nn', individuals are already eliminated in a 'single' manner.
|
|
136
|
+
Due to Cython implementation, they are as fast as the corresponding 'cd', 'mnn-fast', or '2nn-fast',
|
|
137
|
+
although they can singnificantly improve diversity of solutions.
|
|
138
|
+
Defaults to 'cd'.
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
super().__init__(filter_infeasible=False)
|
|
142
|
+
self.nds = nds if nds is not None else NonDominatedSorting()
|
|
143
|
+
self.ranking = RankAndCrowding(nds=nds, crowding_func=crowding_func)
|
|
144
|
+
|
|
145
|
+
def _do(self,
|
|
146
|
+
problem,
|
|
147
|
+
pop,
|
|
148
|
+
*args,
|
|
149
|
+
n_survive=None,
|
|
150
|
+
**kwargs):
|
|
151
|
+
|
|
152
|
+
if n_survive is None:
|
|
153
|
+
n_survive = len(pop)
|
|
154
|
+
|
|
155
|
+
n_survive = min(n_survive, len(pop))
|
|
156
|
+
|
|
157
|
+
# If the split should be done beforehand
|
|
158
|
+
if problem.n_constr > 0:
|
|
159
|
+
|
|
160
|
+
# Split by feasibility
|
|
161
|
+
feas, infeas = split_by_feasibility(pop, sort_infeas_by_cv=True, sort_feas_by_obj=False, return_pop=False)
|
|
162
|
+
|
|
163
|
+
# Obtain len of feasible
|
|
164
|
+
n_feas = len(feas)
|
|
165
|
+
|
|
166
|
+
# Assure there is at least_one survivor
|
|
167
|
+
if n_feas == 0:
|
|
168
|
+
survivors = Population()
|
|
169
|
+
else:
|
|
170
|
+
survivors = self.ranking.do(problem, pop[feas], *args, n_survive=min(len(feas), n_survive), **kwargs)
|
|
171
|
+
|
|
172
|
+
# Calculate how many individuals are still remaining to be filled up with infeasible ones
|
|
173
|
+
n_remaining = n_survive - len(survivors)
|
|
174
|
+
|
|
175
|
+
# If infeasible solutions need to be added
|
|
176
|
+
if n_remaining > 0:
|
|
177
|
+
|
|
178
|
+
# Constraints to new ranking
|
|
179
|
+
G = pop[infeas].get("G")
|
|
180
|
+
G = np.maximum(G, 0)
|
|
181
|
+
H = pop[infeas].get("H")
|
|
182
|
+
H = np.absolute(H)
|
|
183
|
+
C = np.column_stack((G, H))
|
|
184
|
+
|
|
185
|
+
# Fronts in infeasible population
|
|
186
|
+
infeas_fronts = self.nds.do(C, n_stop_if_ranked=n_remaining)
|
|
187
|
+
|
|
188
|
+
# Iterate over fronts
|
|
189
|
+
for k, front in enumerate(infeas_fronts):
|
|
190
|
+
|
|
191
|
+
# Save ranks
|
|
192
|
+
pop[infeas][front].set("cv_rank", k)
|
|
193
|
+
|
|
194
|
+
# Current front sorted by CV
|
|
195
|
+
if len(survivors) + len(front) > n_survive:
|
|
196
|
+
|
|
197
|
+
# Obtain CV of front
|
|
198
|
+
CV = pop[infeas][front].get("CV").flatten()
|
|
199
|
+
I = randomized_argsort(CV, order='ascending', method='numpy')
|
|
200
|
+
I = I[:(n_survive - len(survivors))]
|
|
201
|
+
|
|
202
|
+
# Otherwise take the whole front unsorted
|
|
203
|
+
else:
|
|
204
|
+
I = np.arange(len(front))
|
|
205
|
+
|
|
206
|
+
# extend the survivors by all or selected individuals
|
|
207
|
+
survivors = Population.merge(survivors, pop[infeas][front[I]])
|
|
208
|
+
|
|
209
|
+
else:
|
|
210
|
+
survivors = self.ranking.do(problem, pop, *args, n_survive=n_survive, **kwargs)
|
|
211
|
+
|
|
212
|
+
return survivors
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from scipy.spatial.distance import pdist, squareform
|
|
3
|
+
from pymoo.util.misc import find_duplicates
|
|
4
|
+
from pymoo.functions import load_function
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_crowding_function(label):
|
|
8
|
+
|
|
9
|
+
if label == "cd":
|
|
10
|
+
fun = FunctionalDiversity(calc_crowding_distance, filter_out_duplicates=False)
|
|
11
|
+
elif (label == "pcd") or (label == "pruning-cd"):
|
|
12
|
+
fun = FunctionalDiversity(load_function("calc_pcd"), filter_out_duplicates=True)
|
|
13
|
+
elif label == "ce":
|
|
14
|
+
fun = FunctionalDiversity(calc_crowding_entropy, filter_out_duplicates=True)
|
|
15
|
+
elif label == "mnn":
|
|
16
|
+
fun = FuncionalDiversityMNN(load_function("calc_mnn"), filter_out_duplicates=True)
|
|
17
|
+
elif label == "2nn":
|
|
18
|
+
fun = FuncionalDiversityMNN(load_function("calc_2nn"), filter_out_duplicates=True)
|
|
19
|
+
elif hasattr(label, "__call__"):
|
|
20
|
+
fun = FunctionalDiversity(label, filter_out_duplicates=True)
|
|
21
|
+
elif isinstance(label, CrowdingDiversity):
|
|
22
|
+
fun = label
|
|
23
|
+
else:
|
|
24
|
+
raise KeyError("Crowding function not defined")
|
|
25
|
+
return fun
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class CrowdingDiversity:
|
|
29
|
+
|
|
30
|
+
def do(self, F, n_remove=0):
|
|
31
|
+
# Converting types Python int to Cython int would fail in some cases converting to long instead
|
|
32
|
+
n_remove = np.intc(n_remove)
|
|
33
|
+
F = np.array(F, dtype=np.double)
|
|
34
|
+
return self._do(F, n_remove=n_remove)
|
|
35
|
+
|
|
36
|
+
def _do(self, F, n_remove=None):
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class FunctionalDiversity(CrowdingDiversity):
|
|
41
|
+
|
|
42
|
+
def __init__(self, function=None, filter_out_duplicates=True):
|
|
43
|
+
self.function = function
|
|
44
|
+
self.filter_out_duplicates = filter_out_duplicates
|
|
45
|
+
super().__init__()
|
|
46
|
+
|
|
47
|
+
def _do(self, F, **kwargs):
|
|
48
|
+
|
|
49
|
+
n_points, n_obj = F.shape
|
|
50
|
+
|
|
51
|
+
if n_points <= 2:
|
|
52
|
+
return np.full(n_points, np.inf)
|
|
53
|
+
|
|
54
|
+
else:
|
|
55
|
+
|
|
56
|
+
if self.filter_out_duplicates:
|
|
57
|
+
# filter out solutions which are duplicates - duplicates get a zero finally
|
|
58
|
+
is_unique = np.where(np.logical_not(find_duplicates(F, epsilon=1e-32)))[0]
|
|
59
|
+
else:
|
|
60
|
+
# set every point to be unique without checking it
|
|
61
|
+
is_unique = np.arange(n_points)
|
|
62
|
+
|
|
63
|
+
# index the unique points of the array
|
|
64
|
+
_F = F[is_unique]
|
|
65
|
+
|
|
66
|
+
_d = self.function(_F, **kwargs)
|
|
67
|
+
|
|
68
|
+
d = np.zeros(n_points)
|
|
69
|
+
d[is_unique] = _d
|
|
70
|
+
|
|
71
|
+
return d
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class FuncionalDiversityMNN(FunctionalDiversity):
|
|
75
|
+
|
|
76
|
+
def _do(self, F, **kwargs):
|
|
77
|
+
|
|
78
|
+
n_points, n_obj = F.shape
|
|
79
|
+
|
|
80
|
+
if n_points <= n_obj:
|
|
81
|
+
return np.full(n_points, np.inf)
|
|
82
|
+
|
|
83
|
+
else:
|
|
84
|
+
return super()._do(F, **kwargs)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def calc_crowding_distance(F, **kwargs):
|
|
88
|
+
n_points, n_obj = F.shape
|
|
89
|
+
|
|
90
|
+
# sort each column and get index
|
|
91
|
+
I = np.argsort(F, axis=0, kind='mergesort')
|
|
92
|
+
|
|
93
|
+
# sort the objective space values for the whole matrix
|
|
94
|
+
F = F[I, np.arange(n_obj)]
|
|
95
|
+
|
|
96
|
+
# calculate the distance from each point to the last and next
|
|
97
|
+
dist = np.vstack([F, np.full(n_obj, np.inf)]) - np.vstack([np.full(n_obj, -np.inf), F])
|
|
98
|
+
|
|
99
|
+
# calculate the norm for each objective - set to NaN if all values are equal
|
|
100
|
+
norm = np.max(F, axis=0) - np.min(F, axis=0)
|
|
101
|
+
norm[norm == 0] = np.nan
|
|
102
|
+
|
|
103
|
+
# prepare the distance to last and next vectors
|
|
104
|
+
dist_to_last, dist_to_next = dist, np.copy(dist)
|
|
105
|
+
dist_to_last, dist_to_next = dist_to_last[:-1] / norm, dist_to_next[1:] / norm
|
|
106
|
+
|
|
107
|
+
# if we divide by zero because all values in one columns are equal replace by none
|
|
108
|
+
dist_to_last[np.isnan(dist_to_last)] = 0.0
|
|
109
|
+
dist_to_next[np.isnan(dist_to_next)] = 0.0
|
|
110
|
+
|
|
111
|
+
# sum up the distance to next and last and norm by objectives - also reorder from sorted list
|
|
112
|
+
J = np.argsort(I, axis=0)
|
|
113
|
+
cd = np.sum(dist_to_last[J, np.arange(n_obj)] + dist_to_next[J, np.arange(n_obj)], axis=1) / n_obj
|
|
114
|
+
|
|
115
|
+
return cd
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def calc_crowding_entropy(F, **kwargs):
|
|
119
|
+
"""Wang, Y.-N., Wu, L.-H. & Yuan, X.-F., 2010. Multi-objective self-adaptive differential
|
|
120
|
+
evolution with elitist archive and crowding entropy-based diversity measure.
|
|
121
|
+
Soft Comput., 14(3), pp. 193-209.
|
|
122
|
+
|
|
123
|
+
Parameters
|
|
124
|
+
----------
|
|
125
|
+
F : 2d array like
|
|
126
|
+
Objective functions.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
ce : 1d array
|
|
131
|
+
Crowding Entropies
|
|
132
|
+
"""
|
|
133
|
+
n_points, n_obj = F.shape
|
|
134
|
+
|
|
135
|
+
# sort each column and get index
|
|
136
|
+
I = np.argsort(F, axis=0, kind='mergesort')
|
|
137
|
+
|
|
138
|
+
# sort the objective space values for the whole matrix
|
|
139
|
+
F = F[I, np.arange(n_obj)]
|
|
140
|
+
|
|
141
|
+
# calculate the distance from each point to the last and next
|
|
142
|
+
dist = np.vstack([F, np.full(n_obj, np.inf)]) - np.vstack([np.full(n_obj, -np.inf), F])
|
|
143
|
+
|
|
144
|
+
# calculate the norm for each objective - set to NaN if all values are equal
|
|
145
|
+
norm = np.max(F, axis=0) - np.min(F, axis=0)
|
|
146
|
+
norm[norm == 0] = np.nan
|
|
147
|
+
|
|
148
|
+
# prepare the distance to last and next vectors
|
|
149
|
+
dl = dist.copy()[:-1]
|
|
150
|
+
du = dist.copy()[1:]
|
|
151
|
+
|
|
152
|
+
# Fix nan
|
|
153
|
+
dl[np.isnan(dl)] = 0.0
|
|
154
|
+
du[np.isnan(du)] = 0.0
|
|
155
|
+
|
|
156
|
+
# Total distance
|
|
157
|
+
cd = dl + du
|
|
158
|
+
|
|
159
|
+
# Get relative positions
|
|
160
|
+
pl = (dl[1:-1] / cd[1:-1])
|
|
161
|
+
pu = (du[1:-1] / cd[1:-1])
|
|
162
|
+
|
|
163
|
+
# Entropy
|
|
164
|
+
entropy = np.vstack([np.full(n_obj, np.inf),
|
|
165
|
+
-(pl * np.log2(pl) + pu * np.log2(pu)),
|
|
166
|
+
np.full(n_obj, np.inf)])
|
|
167
|
+
|
|
168
|
+
# Crowding entropy
|
|
169
|
+
J = np.argsort(I, axis=0)
|
|
170
|
+
_cej = cd[J, np.arange(n_obj)] * entropy[J, np.arange(n_obj)] / norm
|
|
171
|
+
_cej[np.isnan(_cej)] = 0.0
|
|
172
|
+
ce = _cej.sum(axis=1)
|
|
173
|
+
|
|
174
|
+
return ce
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def calc_mnn_fast(F, **kwargs):
|
|
178
|
+
return _calc_mnn_fast(F, F.shape[1], **kwargs)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def calc_2nn_fast(F, **kwargs):
|
|
182
|
+
return _calc_mnn_fast(F, 2, **kwargs)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _calc_mnn_fast(F, n_neighbors, **kwargs):
|
|
186
|
+
|
|
187
|
+
# calculate the norm for each objective - set to NaN if all values are equal
|
|
188
|
+
norm = np.max(F, axis=0) - np.min(F, axis=0)
|
|
189
|
+
norm[norm == 0] = 1.0
|
|
190
|
+
|
|
191
|
+
# F normalized
|
|
192
|
+
F = (F - F.min(axis=0)) / norm
|
|
193
|
+
|
|
194
|
+
# Distances pairwise (Inefficient)
|
|
195
|
+
D = squareform(pdist(F, metric="sqeuclidean"))
|
|
196
|
+
|
|
197
|
+
# M neighbors
|
|
198
|
+
M = F.shape[1]
|
|
199
|
+
_D = np.partition(D, range(1, M+1), axis=1)[:, 1:M+1]
|
|
200
|
+
|
|
201
|
+
# Metric d
|
|
202
|
+
d = np.prod(_D, axis=1)
|
|
203
|
+
|
|
204
|
+
# Set top performers as np.inf
|
|
205
|
+
_extremes = np.concatenate((np.argmin(F, axis=0), np.argmax(F, axis=0)))
|
|
206
|
+
d[_extremes] = np.inf
|
|
207
|
+
|
|
208
|
+
return d
|
pymoo/optimize.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def minimize(problem, algorithm, termination=None, copy_algorithm=True, copy_termination=True, **kwargs):
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
Minimization of function of one or more variables, objectives and constraints.
|
|
8
|
+
|
|
9
|
+
This is used as a convenience function to execute several algorithms with default settings which turned
|
|
10
|
+
out to work for a test single. However, evolutionary computations utilizes the idea of customizing a
|
|
11
|
+
meta-algorithm. Customizing the algorithm using the object-oriented interface is recommended to improve the
|
|
12
|
+
convergence.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
|
|
17
|
+
problem : :class:`~pymoo.core.problem.Problem`
|
|
18
|
+
A problem object which is defined using pymoo.
|
|
19
|
+
|
|
20
|
+
algorithm : :class:`~pymoo.core.algorithm.Algorithm`
|
|
21
|
+
The algorithm object that should be used for the optimization.
|
|
22
|
+
|
|
23
|
+
termination : :class:`~pymoo.core.termination.Termination` or tuple
|
|
24
|
+
The termination criterion that is used to stop the algorithm.
|
|
25
|
+
|
|
26
|
+
seed : integer
|
|
27
|
+
The random seed to be used.
|
|
28
|
+
|
|
29
|
+
verbose : bool
|
|
30
|
+
Whether output should be printed or not.
|
|
31
|
+
|
|
32
|
+
display : :class:`~pymoo.util.display.Display`
|
|
33
|
+
Each algorithm has a default display object for printouts. However, it can be overwritten if desired.
|
|
34
|
+
|
|
35
|
+
callback : :class:`~pymoo.core.callback.Callback`
|
|
36
|
+
A callback object which is called each iteration of the algorithm.
|
|
37
|
+
|
|
38
|
+
save_history : bool
|
|
39
|
+
Whether the history should be stored or not.
|
|
40
|
+
|
|
41
|
+
copy_algorithm : bool
|
|
42
|
+
Whether the algorithm object should be copied before optimization.
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
res : :class:`~pymoo.core.result.Result`
|
|
47
|
+
The optimization result represented as an object.
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
# create a copy of the algorithm object to ensure no side effects
|
|
52
|
+
if copy_algorithm:
|
|
53
|
+
algorithm = copy.deepcopy(algorithm)
|
|
54
|
+
|
|
55
|
+
# initialize the algorithm object given a problem - if not set already
|
|
56
|
+
if algorithm.problem is None:
|
|
57
|
+
if termination is not None:
|
|
58
|
+
|
|
59
|
+
if copy_termination:
|
|
60
|
+
termination = copy.deepcopy(termination)
|
|
61
|
+
|
|
62
|
+
kwargs["termination"] = termination
|
|
63
|
+
|
|
64
|
+
algorithm.setup(problem, **kwargs)
|
|
65
|
+
|
|
66
|
+
# actually execute the algorithm
|
|
67
|
+
res = algorithm.run()
|
|
68
|
+
|
|
69
|
+
# store the deep copied algorithm in the result object
|
|
70
|
+
res.algorithm = algorithm
|
|
71
|
+
|
|
72
|
+
return res
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Parallelization utilities for pymoo.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .starmap import StarmapParallelization
|
|
6
|
+
from .dask import DaskParallelization
|
|
7
|
+
from .joblib import JoblibParallelization
|
|
8
|
+
from .ray import RayParallelization
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
'StarmapParallelization',
|
|
12
|
+
'DaskParallelization',
|
|
13
|
+
'JoblibParallelization',
|
|
14
|
+
'RayParallelization'
|
|
15
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Dask-based parallelization for pymoo.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DaskParallelization:
|
|
7
|
+
"""Parallelization using Dask distributed client.
|
|
8
|
+
|
|
9
|
+
Parameters
|
|
10
|
+
----------
|
|
11
|
+
client : dask.distributed.Client
|
|
12
|
+
Dask client for distributed computing
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, client):
|
|
16
|
+
self.client = client
|
|
17
|
+
|
|
18
|
+
def __call__(self, f, X):
|
|
19
|
+
jobs = [self.client.submit(f, x) for x in X]
|
|
20
|
+
return [job.result() for job in jobs]
|
|
21
|
+
|
|
22
|
+
def __getstate__(self):
|
|
23
|
+
state = self.__dict__.copy()
|
|
24
|
+
state.pop("client", None)
|
|
25
|
+
return state
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
class JoblibParallelization:
|
|
3
|
+
"""Parallelization using joblib.
|
|
4
|
+
|
|
5
|
+
Parameters
|
|
6
|
+
----------
|
|
7
|
+
n_jobs : int, default=-1
|
|
8
|
+
Number of parallel jobs. -1 uses all available cores.
|
|
9
|
+
**kwargs
|
|
10
|
+
Additional arguments passed to joblib.Parallel
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def __init__(self, n_jobs=-1, **kwargs):
|
|
14
|
+
try:
|
|
15
|
+
import joblib
|
|
16
|
+
except ImportError:
|
|
17
|
+
raise ImportError("joblib must be installed: pip install joblib")
|
|
18
|
+
|
|
19
|
+
self.joblib = joblib
|
|
20
|
+
self.n_jobs = n_jobs
|
|
21
|
+
self.kwargs = kwargs
|
|
22
|
+
|
|
23
|
+
def __call__(self, f, X):
|
|
24
|
+
with self.joblib.Parallel(n_jobs=self.n_jobs, **self.kwargs) as parallel:
|
|
25
|
+
return parallel(self.joblib.delayed(f)(x) for x in X)
|
|
26
|
+
|
|
27
|
+
def __getstate__(self):
|
|
28
|
+
return self.__dict__.copy()
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Ray-based parallelization for pymoo.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RayParallelization:
|
|
7
|
+
"""Parallelization using Ray.
|
|
8
|
+
|
|
9
|
+
Parameters
|
|
10
|
+
----------
|
|
11
|
+
job_resources : dict, default={'num_cpus': 1}
|
|
12
|
+
Ray resource requirements per job
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, job_resources={'num_cpus': 1}):
|
|
16
|
+
try:
|
|
17
|
+
import ray
|
|
18
|
+
except ImportError:
|
|
19
|
+
raise ImportError("Ray must be installed: pip install ray")
|
|
20
|
+
|
|
21
|
+
self.ray = ray
|
|
22
|
+
self.job_resources = job_resources
|
|
23
|
+
|
|
24
|
+
def __call__(self, f, X):
|
|
25
|
+
runnable = self.ray.remote(f.__call__.__func__)
|
|
26
|
+
runnable = runnable.options(**self.job_resources)
|
|
27
|
+
futures = [runnable.remote(f, x) for x in X]
|
|
28
|
+
return self.ray.get(futures)
|
|
29
|
+
|
|
30
|
+
def __getstate__(self):
|
|
31
|
+
return self.__dict__.copy()
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Starmap-based parallelization for pymoo.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class StarmapParallelization:
|
|
7
|
+
"""Parallelization using a starmap function.
|
|
8
|
+
|
|
9
|
+
Parameters
|
|
10
|
+
----------
|
|
11
|
+
starmap : callable
|
|
12
|
+
A starmap function like multiprocessing.Pool.starmap
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, starmap):
|
|
16
|
+
self.starmap = starmap
|
|
17
|
+
|
|
18
|
+
def __call__(self, f, X):
|
|
19
|
+
return list(self.starmap(f, [[x] for x in X]))
|
|
20
|
+
|
|
21
|
+
def __getstate__(self):
|
|
22
|
+
state = self.__dict__.copy()
|
|
23
|
+
state.pop("starmap", None)
|
|
24
|
+
return state
|