pymoo 0.6.1.5.dev0__cp313-cp313-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.
Potentially problematic release.
This version of pymoo might be problematic. Click here for more details.
- 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 +109 -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 +89 -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/ctaea.py +298 -0
- pymoo/algorithms/moo/dnsga2.py +76 -0
- pymoo/algorithms/moo/kgb.py +446 -0
- pymoo/algorithms/moo/moead.py +183 -0
- pymoo/algorithms/moo/nsga2.py +113 -0
- pymoo/algorithms/moo/nsga3.py +358 -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 +195 -0
- pymoo/algorithms/moo/spea2.py +190 -0
- pymoo/algorithms/moo/unsga3.py +47 -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 +161 -0
- pymoo/algorithms/soo/nonconvex/cmaes.py +554 -0
- pymoo/algorithms/soo/nonconvex/de.py +279 -0
- pymoo/algorithms/soo/nonconvex/direct.py +149 -0
- pymoo/algorithms/soo/nonconvex/es.py +203 -0
- pymoo/algorithms/soo/nonconvex/g3pcx.py +94 -0
- pymoo/algorithms/soo/nonconvex/ga.py +93 -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/optuna.py +80 -0
- pymoo/algorithms/soo/nonconvex/pattern.py +183 -0
- pymoo/algorithms/soo/nonconvex/pso.py +399 -0
- pymoo/algorithms/soo/nonconvex/pso_ep.py +297 -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/backtracking.py +59 -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 +62 -0
- pymoo/constraints/as_obj.py +56 -0
- pymoo/constraints/as_penalty.py +41 -0
- pymoo/constraints/eps.py +26 -0
- pymoo/constraints/from_bounds.py +36 -0
- pymoo/core/__init__.py +0 -0
- pymoo/core/algorithm.py +394 -0
- pymoo/core/callback.py +38 -0
- pymoo/core/crossover.py +77 -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 +64 -0
- pymoo/core/initialization.py +42 -0
- pymoo/core/mating.py +39 -0
- pymoo/core/meta.py +21 -0
- pymoo/core/mixed.py +165 -0
- pymoo/core/mutation.py +44 -0
- pymoo/core/operator.py +40 -0
- pymoo/core/parameters.py +134 -0
- pymoo/core/plot.py +210 -0
- pymoo/core/population.py +180 -0
- pymoo/core/problem.py +460 -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 +43 -0
- pymoo/core/selection.py +61 -0
- pymoo/core/solution.py +10 -0
- pymoo/core/survival.py +103 -0
- pymoo/core/termination.py +70 -0
- pymoo/core/variable.py +399 -0
- pymoo/cython/__init__.py +0 -0
- pymoo/cython/calc_perpendicular_distance.cpython-313-darwin.so +0 -0
- pymoo/cython/calc_perpendicular_distance.pyx +67 -0
- pymoo/cython/decomposition.cpython-313-darwin.so +0 -0
- pymoo/cython/decomposition.pyx +165 -0
- pymoo/cython/hv.cpython-313-darwin.so +0 -0
- pymoo/cython/hv.pyx +18 -0
- pymoo/cython/info.cpython-313-darwin.so +0 -0
- pymoo/cython/info.pyx +5 -0
- pymoo/cython/mnn.cpython-313-darwin.so +0 -0
- pymoo/cython/mnn.pyx +273 -0
- pymoo/cython/non_dominated_sorting.cpython-313-darwin.so +0 -0
- pymoo/cython/non_dominated_sorting.pyx +645 -0
- pymoo/cython/pruning_cd.cpython-313-darwin.so +0 -0
- pymoo/cython/pruning_cd.pyx +197 -0
- pymoo/cython/stochastic_ranking.cpython-313-darwin.so +0 -0
- pymoo/cython/stochastic_ranking.pyx +49 -0
- pymoo/cython/utils.pxd +129 -0
- pymoo/cython/vendor/__init__.py +0 -0
- pymoo/cython/vendor/hypervolume.cpp +1621 -0
- pymoo/cython/vendor/hypervolume.h +63 -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/gradient/__init__.py +21 -0
- pymoo/gradient/automatic.py +57 -0
- pymoo/gradient/grad_autograd.py +105 -0
- pymoo/gradient/grad_complex.py +35 -0
- pymoo/gradient/grad_jax.py +51 -0
- pymoo/gradient/toolbox/__init__.py +6 -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 +63 -0
- pymoo/indicators/hv/exact.py +71 -0
- pymoo/indicators/hv/exact_2d.py +102 -0
- pymoo/indicators/hv/monte_carlo.py +74 -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 +187 -0
- pymoo/operators/crossover/__init__.py +0 -0
- pymoo/operators/crossover/binx.py +45 -0
- pymoo/operators/crossover/dex.py +122 -0
- pymoo/operators/crossover/erx.py +162 -0
- pymoo/operators/crossover/expx.py +51 -0
- pymoo/operators/crossover/hux.py +37 -0
- pymoo/operators/crossover/nox.py +13 -0
- pymoo/operators/crossover/ox.py +84 -0
- pymoo/operators/crossover/pcx.py +82 -0
- pymoo/operators/crossover/pntx.py +49 -0
- pymoo/operators/crossover/sbx.py +125 -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 +58 -0
- pymoo/operators/mutation/inversion.py +42 -0
- pymoo/operators/mutation/nom.py +7 -0
- pymoo/operators/mutation/pm.py +94 -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 +95 -0
- pymoo/operators/repair/inverse_penalty.py +89 -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 +73 -0
- pymoo/operators/sampling/rnd.py +50 -0
- pymoo/operators/selection/__init__.py +0 -0
- pymoo/operators/selection/rnd.py +72 -0
- pymoo/operators/selection/tournament.py +76 -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 +209 -0
- pymoo/operators/survival/rank_and_crowding/metrics.py +208 -0
- pymoo/optimize.py +72 -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 +452 -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 +550 -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 +112 -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 +48 -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 +0 -0
- pymoo/util/archive.py +150 -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 +96 -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/function_loader.py +129 -0
- pymoo/util/hv.py +23 -0
- pymoo/util/matlab_engine.py +39 -0
- pymoo/util/misc.py +460 -0
- pymoo/util/mnn.py +70 -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/naive_non_dominated_sort.py +36 -0
- pymoo/util/nds/non_dominated_sorting.py +67 -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/plotting.py +177 -0
- pymoo/util/pruning_cd.py +89 -0
- pymoo/util/randomized_argsort.py +60 -0
- pymoo/util/ref_dirs/__init__.py +24 -0
- pymoo/util/ref_dirs/construction.py +88 -0
- pymoo/util/ref_dirs/das_dennis.py +52 -0
- pymoo/util/ref_dirs/energy.py +319 -0
- pymoo/util/ref_dirs/energy_layer.py +119 -0
- pymoo/util/ref_dirs/genetic_algorithm.py +63 -0
- pymoo/util/ref_dirs/incremental.py +68 -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 +260 -0
- pymoo/util/remote.py +55 -0
- pymoo/util/roulette.py +27 -0
- pymoo/util/running_metric.py +128 -0
- pymoo/util/sliding_window.py +25 -0
- pymoo/util/stochastic_ranking.py +32 -0
- pymoo/util/value_functions.py +719 -0
- pymoo/util/vectors.py +40 -0
- pymoo/util/vf_dominator.py +99 -0
- pymoo/vendor/__init__.py +0 -0
- pymoo/vendor/cec2018.py +398 -0
- pymoo/vendor/gta.py +617 -0
- pymoo/vendor/hv.py +267 -0
- pymoo/vendor/vendor_cmaes.py +412 -0
- pymoo/vendor/vendor_coco.py +81 -0
- pymoo/vendor/vendor_scipy.py +232 -0
- pymoo/version.py +1 -0
- pymoo/visualization/__init__.py +8 -0
- pymoo/visualization/fitness_landscape.py +127 -0
- pymoo/visualization/heatmap.py +123 -0
- pymoo/visualization/pcp.py +120 -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 +123 -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.5.dev0.dist-info/METADATA +187 -0
- pymoo-0.6.1.5.dev0.dist-info/RECORD +328 -0
- pymoo-0.6.1.5.dev0.dist-info/WHEEL +6 -0
- pymoo-0.6.1.5.dev0.dist-info/licenses/LICENSE +191 -0
- pymoo-0.6.1.5.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.algorithms.base.genetic import GeneticAlgorithm
|
|
4
|
+
from pymoo.algorithms.moo.nsga3 import HyperplaneNormalization
|
|
5
|
+
from pymoo.core.survival import Survival
|
|
6
|
+
from pymoo.docs import parse_doc_string
|
|
7
|
+
from pymoo.operators.crossover.sbx import SBX
|
|
8
|
+
from pymoo.operators.mutation.pm import PM
|
|
9
|
+
from pymoo.operators.sampling.rnd import FloatRandomSampling
|
|
10
|
+
from pymoo.operators.selection.tournament import TournamentSelection, compare
|
|
11
|
+
from pymoo.termination.default import DefaultMultiObjectiveTermination
|
|
12
|
+
from pymoo.util.display.multi import MultiObjectiveOutput
|
|
13
|
+
from pymoo.util.dominator import Dominator
|
|
14
|
+
from pymoo.util.misc import vectorized_cdist
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
18
|
+
# Environmental Survival (in the original paper it is referred to as archiving)
|
|
19
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SPEA2Survival(Survival):
|
|
23
|
+
|
|
24
|
+
def __init__(self, normalize=False, filter_infeasible=True):
|
|
25
|
+
super().__init__(filter_infeasible)
|
|
26
|
+
|
|
27
|
+
# whether the survival should considered normalized distance or just raw
|
|
28
|
+
self.normalize = normalize
|
|
29
|
+
|
|
30
|
+
# an object keeping track of normalization points
|
|
31
|
+
self.norm = None
|
|
32
|
+
|
|
33
|
+
def _do(self, problem, pop, *args, n_survive=None, **kwargs):
|
|
34
|
+
|
|
35
|
+
# get the objective space values and objects
|
|
36
|
+
F = pop.get("F").astype(float, copy=False)
|
|
37
|
+
|
|
38
|
+
# the domination matrix to see the relation for each solution to another
|
|
39
|
+
M = Dominator().calc_domination_matrix(F)
|
|
40
|
+
|
|
41
|
+
# the number of solutions each individual dominates
|
|
42
|
+
S = (M == 1).sum(axis=0)
|
|
43
|
+
|
|
44
|
+
# the raw fitness of each solution - strength of its dominators
|
|
45
|
+
R = ((M == -1) * S).sum(axis=1)
|
|
46
|
+
|
|
47
|
+
# determine what k-th nearest neighbor to consider
|
|
48
|
+
k = int(np.sqrt(len(pop)))
|
|
49
|
+
if k >= len(pop):
|
|
50
|
+
k = len(pop) - 1
|
|
51
|
+
|
|
52
|
+
# if normalization is enabled keep track of ideal and nadir
|
|
53
|
+
if self.normalize:
|
|
54
|
+
|
|
55
|
+
# initialize the first time and then always update the boundary points
|
|
56
|
+
if self.norm is None:
|
|
57
|
+
self.norm = HyperplaneNormalization(F.shape[1])
|
|
58
|
+
self.norm.update(F)
|
|
59
|
+
|
|
60
|
+
ideal, nadir = self.norm.ideal_point, self.norm.nadir_point
|
|
61
|
+
|
|
62
|
+
_F = (F - ideal) / (nadir - ideal)
|
|
63
|
+
dists = vectorized_cdist(_F, _F, fill_diag_with_inf=True)
|
|
64
|
+
|
|
65
|
+
# if no normalize is required simply use the F values from the population
|
|
66
|
+
else:
|
|
67
|
+
dists = vectorized_cdist(F, F, fill_diag_with_inf=True)
|
|
68
|
+
|
|
69
|
+
# the distances sorted for each individual
|
|
70
|
+
sdists = np.sort(dists, axis=1)
|
|
71
|
+
|
|
72
|
+
# inverse distance as part of the fitness
|
|
73
|
+
D = 1 / (sdists[:, k] + 2)
|
|
74
|
+
|
|
75
|
+
# the actual fitness value used to determine who survives
|
|
76
|
+
SPEA_F = R + D
|
|
77
|
+
|
|
78
|
+
# set all the attributes to the population
|
|
79
|
+
pop.set(SPEA_F=SPEA_F, SPEA_R=R, SPEA_D=D)
|
|
80
|
+
|
|
81
|
+
# get all the non-dominated solutions
|
|
82
|
+
survivors = list(np.where(np.all(M >= 0, axis=1))[0])
|
|
83
|
+
|
|
84
|
+
# if we normalize give boundary points most importance - give the boundary points in the nds set the lowest fit.
|
|
85
|
+
if self.normalize:
|
|
86
|
+
I = vectorized_cdist(self.norm.extreme_points, F[survivors]).argmin(axis=1)
|
|
87
|
+
pop[survivors][I].set("SPEA_F", -1.0)
|
|
88
|
+
|
|
89
|
+
# identify the remaining individuals to choose from
|
|
90
|
+
H = set(survivors)
|
|
91
|
+
rem = np.array([k for k in range(len(pop)) if k not in H])
|
|
92
|
+
|
|
93
|
+
# if not enough solutions, will up by F
|
|
94
|
+
if len(survivors) < n_survive:
|
|
95
|
+
|
|
96
|
+
# sort them by the fitness values (lower is better) and append them
|
|
97
|
+
rem_by_F = rem[SPEA_F[rem].argsort()]
|
|
98
|
+
survivors.extend(rem_by_F[:n_survive - len(survivors)])
|
|
99
|
+
|
|
100
|
+
# if too many, delete based on distances
|
|
101
|
+
elif len(survivors) > n_survive:
|
|
102
|
+
|
|
103
|
+
# remove one individual per loop, until we hit n_survive
|
|
104
|
+
while len(survivors) > n_survive:
|
|
105
|
+
i = dists[survivors][:, survivors].min(axis=1).argmin()
|
|
106
|
+
survivors = [survivors[j] for j in range(len(survivors)) if j != i]
|
|
107
|
+
|
|
108
|
+
return pop[survivors]
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
112
|
+
# Binary Tournament Selection
|
|
113
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def spea_binary_tournament(pop, P, algorithm, **kwargs):
|
|
117
|
+
n_tournaments, n_parents = P.shape
|
|
118
|
+
|
|
119
|
+
if n_parents != 2:
|
|
120
|
+
raise ValueError("Only implemented for binary tournament!")
|
|
121
|
+
|
|
122
|
+
S = np.full(n_tournaments, np.nan)
|
|
123
|
+
|
|
124
|
+
for i in range(n_tournaments):
|
|
125
|
+
|
|
126
|
+
a, b = P[i, 0], P[i, 1]
|
|
127
|
+
a_cv, a_f, b_cv, b_f, = pop[a].CV[0], pop[a].F, pop[b].CV[0], pop[b].F
|
|
128
|
+
|
|
129
|
+
# if at least one solution is infeasible
|
|
130
|
+
if a_cv > 0.0 or b_cv > 0.0:
|
|
131
|
+
S[i] = compare(a, a_cv, b, b_cv, method='smaller_is_better', return_random_if_equal=True)
|
|
132
|
+
|
|
133
|
+
# both solutions are feasible
|
|
134
|
+
else:
|
|
135
|
+
S[i] = compare(a, pop[a].get("SPEA_F"), b, pop[b].get("SPEA_F"), method='smaller_is_better',
|
|
136
|
+
return_random_if_equal=True)
|
|
137
|
+
|
|
138
|
+
return S[:, None].astype(int, copy=False)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
142
|
+
# Algorithm
|
|
143
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class SPEA2(GeneticAlgorithm):
|
|
147
|
+
|
|
148
|
+
def __init__(self,
|
|
149
|
+
pop_size=100,
|
|
150
|
+
sampling=FloatRandomSampling(),
|
|
151
|
+
selection=TournamentSelection(spea_binary_tournament),
|
|
152
|
+
crossover=SBX(),
|
|
153
|
+
mutation=PM(),
|
|
154
|
+
survival=SPEA2Survival(normalize=True),
|
|
155
|
+
eliminate_duplicates=True,
|
|
156
|
+
n_offsprings=None,
|
|
157
|
+
output=MultiObjectiveOutput(),
|
|
158
|
+
**kwargs):
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
SPEA2 - Strength Pareto EA 2
|
|
162
|
+
|
|
163
|
+
Parameters
|
|
164
|
+
----------
|
|
165
|
+
pop_size : {pop_size}
|
|
166
|
+
sampling : {sampling}
|
|
167
|
+
selection : {selection}
|
|
168
|
+
crossover : {crossover}
|
|
169
|
+
mutation : {mutation}
|
|
170
|
+
eliminate_duplicates : {eliminate_duplicates}
|
|
171
|
+
n_offsprings : {n_offsprings}
|
|
172
|
+
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
super().__init__(pop_size=pop_size,
|
|
176
|
+
sampling=sampling,
|
|
177
|
+
selection=selection,
|
|
178
|
+
crossover=crossover,
|
|
179
|
+
mutation=mutation,
|
|
180
|
+
survival=survival,
|
|
181
|
+
eliminate_duplicates=eliminate_duplicates,
|
|
182
|
+
n_offsprings=n_offsprings,
|
|
183
|
+
output=output,
|
|
184
|
+
advance_after_initial_infill=True,
|
|
185
|
+
**kwargs)
|
|
186
|
+
self.termination = DefaultMultiObjectiveTermination()
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
parse_doc_string(SPEA2.__init__)
|
|
190
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.algorithms.moo.nsga3 import NSGA3
|
|
4
|
+
from pymoo.operators.selection.tournament import compare, TournamentSelection
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# =========================================================================================================
|
|
8
|
+
# Implementation
|
|
9
|
+
# =========================================================================================================
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def comp_by_rank_and_ref_line_dist(pop, P, **kwargs):
|
|
13
|
+
S = np.full(P.shape[0], np.nan)
|
|
14
|
+
|
|
15
|
+
for i in range(P.shape[0]):
|
|
16
|
+
a, b = P[i, 0], P[i, 1]
|
|
17
|
+
|
|
18
|
+
# if at least one solution is infeasible
|
|
19
|
+
if pop[a].CV > 0.0 or pop[b].CV > 0.0:
|
|
20
|
+
S[i] = compare(a, pop[a].CV, b, pop[b].CV, method='smaller_is_better', return_random_if_equal=True)
|
|
21
|
+
|
|
22
|
+
# both solutions are feasible
|
|
23
|
+
else:
|
|
24
|
+
|
|
25
|
+
# if in the same niche select by rank
|
|
26
|
+
if pop[a].get("niche") == pop[b].get("niche"):
|
|
27
|
+
|
|
28
|
+
if pop[a].get("rank") != pop[b].get("rank"):
|
|
29
|
+
S[i] = compare(a, pop[a].get("rank"), b, pop[b].get("rank"), method='smaller_is_better')
|
|
30
|
+
|
|
31
|
+
else:
|
|
32
|
+
S[i] = compare(a, pop[a].get("dist_to_niche"), b, pop[b].get("dist_to_niche"),
|
|
33
|
+
method='smaller_is_better')
|
|
34
|
+
|
|
35
|
+
if np.isnan(S[i]):
|
|
36
|
+
S[i] = np.random.choice([a, b])
|
|
37
|
+
|
|
38
|
+
return S[:, None].astype(int)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class UNSGA3(NSGA3):
|
|
42
|
+
|
|
43
|
+
def __init__(self,
|
|
44
|
+
ref_dirs,
|
|
45
|
+
selection=TournamentSelection(func_comp=comp_by_rank_and_ref_line_dist),
|
|
46
|
+
**kwargs):
|
|
47
|
+
super().__init__(ref_dirs, selection=selection, **kwargs)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.algorithms.base.genetic import GeneticAlgorithm
|
|
4
|
+
from pymoo.algorithms.soo.nonconvex.ga import FitnessSurvival
|
|
5
|
+
from pymoo.core.duplicate import DefaultDuplicateElimination, DuplicateElimination
|
|
6
|
+
from pymoo.core.population import Population
|
|
7
|
+
from pymoo.core.selection import Selection
|
|
8
|
+
from pymoo.core.survival import Survival
|
|
9
|
+
from pymoo.docs import parse_doc_string
|
|
10
|
+
from pymoo.operators.crossover.binx import BinomialCrossover
|
|
11
|
+
from pymoo.operators.mutation.nom import NoMutation
|
|
12
|
+
from pymoo.operators.sampling.rnd import FloatRandomSampling
|
|
13
|
+
from pymoo.termination.default import DefaultSingleObjectiveTermination
|
|
14
|
+
from pymoo.util.display.single import SingleObjectiveOutput
|
|
15
|
+
from pymoo.util.nds.non_dominated_sorting import NonDominatedSorting
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# =========================================================================================================
|
|
19
|
+
# Implementation
|
|
20
|
+
# =========================================================================================================
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class EliteSurvival(Survival):
|
|
24
|
+
|
|
25
|
+
def __init__(self, n_elites, eliminate_duplicates=None):
|
|
26
|
+
super().__init__(False)
|
|
27
|
+
self.n_elites = n_elites
|
|
28
|
+
self.eliminate_duplicates = eliminate_duplicates
|
|
29
|
+
|
|
30
|
+
def _do(self, problem, pop, n_survive=None, algorithm=None, **kwargs):
|
|
31
|
+
|
|
32
|
+
if isinstance(self.eliminate_duplicates, bool) and self.eliminate_duplicates:
|
|
33
|
+
pop = DefaultDuplicateElimination(func=lambda p: p.get("F")).do(pop)
|
|
34
|
+
|
|
35
|
+
elif isinstance(self.eliminate_duplicates, DuplicateElimination):
|
|
36
|
+
_, no_candidates, candidates = DefaultDuplicateElimination(func=lambda pop: pop.get("F")).do(pop,
|
|
37
|
+
return_indices=True)
|
|
38
|
+
_, _, is_duplicate = self.eliminate_duplicates.do(pop[candidates], pop[no_candidates], return_indices=True,
|
|
39
|
+
to_itself=False)
|
|
40
|
+
elim = set(np.array(candidates)[is_duplicate])
|
|
41
|
+
pop = pop[[k for k in range(len(pop)) if k not in elim]]
|
|
42
|
+
|
|
43
|
+
if problem.n_obj == 1:
|
|
44
|
+
pop = FitnessSurvival().do(problem, pop, n_survive=len(pop))
|
|
45
|
+
elites = pop[:self.n_elites]
|
|
46
|
+
non_elites = pop[self.n_elites:]
|
|
47
|
+
else:
|
|
48
|
+
I = NonDominatedSorting().do(pop.get("F"), only_non_dominated_front=True)
|
|
49
|
+
elites = pop[I]
|
|
50
|
+
non_elites = pop[[k for k in range(len(pop)) if k not in I]]
|
|
51
|
+
|
|
52
|
+
elites.set("type", ["elite"] * len(elites))
|
|
53
|
+
non_elites.set("type", ["non_elite"] * len(non_elites))
|
|
54
|
+
|
|
55
|
+
return pop
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class EliteBiasedSelection(Selection):
|
|
59
|
+
|
|
60
|
+
def _do(self, problem, pop, n_select, n_parents, **kwargs):
|
|
61
|
+
_type = pop.get("type")
|
|
62
|
+
elites = np.where(_type == "elite")[0].astype(int)
|
|
63
|
+
non_elites = np.where(_type == "non_elite")[0].astype(int)
|
|
64
|
+
|
|
65
|
+
# if through duplicate elimination no non-elites exist
|
|
66
|
+
if len(non_elites) == 0:
|
|
67
|
+
non_elites = elites
|
|
68
|
+
|
|
69
|
+
# do the mating selection - always one elite and one non-elites
|
|
70
|
+
s_elite = np.random.choice(elites, size=n_select)
|
|
71
|
+
s_non_elite = np.random.choice(non_elites, size=n_select)
|
|
72
|
+
|
|
73
|
+
return np.column_stack([s_elite, s_non_elite])
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class BRKGA(GeneticAlgorithm):
|
|
77
|
+
|
|
78
|
+
def __init__(self,
|
|
79
|
+
n_elites=200,
|
|
80
|
+
n_offsprings=700,
|
|
81
|
+
n_mutants=100,
|
|
82
|
+
bias=0.7,
|
|
83
|
+
sampling=FloatRandomSampling(),
|
|
84
|
+
survival=None,
|
|
85
|
+
output=SingleObjectiveOutput(),
|
|
86
|
+
eliminate_duplicates=False,
|
|
87
|
+
**kwargs
|
|
88
|
+
):
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
|
|
95
|
+
n_elites : int
|
|
96
|
+
Number of elite individuals
|
|
97
|
+
|
|
98
|
+
n_offsprings : int
|
|
99
|
+
Number of offsprings to be generated through mating of an elite and a non-elite individual
|
|
100
|
+
|
|
101
|
+
n_mutants : int
|
|
102
|
+
Number of mutations to be introduced each generation
|
|
103
|
+
|
|
104
|
+
bias : float
|
|
105
|
+
Bias of an offspring inheriting the allele of its elite parent
|
|
106
|
+
|
|
107
|
+
eliminate_duplicates : bool or class
|
|
108
|
+
The duplicate elimination is more important if a decoding is used. The duplicate check has to be
|
|
109
|
+
performed on the decoded variable and not on the real values. Therefore, we recommend passing
|
|
110
|
+
a DuplicateElimination object.
|
|
111
|
+
If eliminate_duplicates is simply set to `True`, then duplicates are filtered out whenever the
|
|
112
|
+
objective values are equal.
|
|
113
|
+
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
if survival is None:
|
|
117
|
+
survival = EliteSurvival(n_elites, eliminate_duplicates=eliminate_duplicates)
|
|
118
|
+
|
|
119
|
+
super().__init__(pop_size=n_elites + n_offsprings + n_mutants,
|
|
120
|
+
n_offsprings=n_offsprings,
|
|
121
|
+
sampling=sampling,
|
|
122
|
+
selection=EliteBiasedSelection(),
|
|
123
|
+
crossover=BinomialCrossover(bias, prob=1.0, n_offsprings=1),
|
|
124
|
+
mutation=NoMutation(),
|
|
125
|
+
survival=survival,
|
|
126
|
+
output=output,
|
|
127
|
+
eliminate_duplicates=True,
|
|
128
|
+
advance_after_initial_infill=True,
|
|
129
|
+
**kwargs)
|
|
130
|
+
|
|
131
|
+
self.n_elites = n_elites
|
|
132
|
+
self.n_mutants = n_mutants
|
|
133
|
+
self.bias = bias
|
|
134
|
+
self.termination = DefaultSingleObjectiveTermination()
|
|
135
|
+
|
|
136
|
+
def _infill(self):
|
|
137
|
+
pop = self.pop
|
|
138
|
+
|
|
139
|
+
# actually do the mating given the elite selection and biased crossover
|
|
140
|
+
off = self.mating.do(self.problem, pop, n_offsprings=self.n_offsprings, algorithm=self)
|
|
141
|
+
|
|
142
|
+
# create the mutants randomly to fill the population with
|
|
143
|
+
mutants = FloatRandomSampling().do(self.problem, self.n_mutants, algorithm=self)
|
|
144
|
+
|
|
145
|
+
# evaluate all the new solutions
|
|
146
|
+
return Population.merge(off, mutants)
|
|
147
|
+
|
|
148
|
+
def _advance(self, infills=None, **kwargs):
|
|
149
|
+
pop = self.pop
|
|
150
|
+
|
|
151
|
+
# get all the elites from the current population
|
|
152
|
+
elites = np.where(pop.get("type") == "elite")[0]
|
|
153
|
+
|
|
154
|
+
# finally merge everything together and sort by fitness
|
|
155
|
+
pop = Population.merge(pop[elites], infills)
|
|
156
|
+
|
|
157
|
+
# the do survival selection - set the elites for the next round
|
|
158
|
+
self.pop = self.survival.do(self.problem, pop, n_survive=len(pop), algorithm=self)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
parse_doc_string(BRKGA.__init__)
|