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,94 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.algorithms.soo.nonconvex.ga import FitnessSurvival
|
|
4
|
+
from pymoo.core.algorithm import LoopwiseAlgorithm
|
|
5
|
+
from pymoo.core.initialization import Initialization
|
|
6
|
+
from pymoo.core.population import Population
|
|
7
|
+
from pymoo.core.repair import NoRepair
|
|
8
|
+
from pymoo.core.replacement import is_better
|
|
9
|
+
from pymoo.core.variable import Real, Integer, get
|
|
10
|
+
from pymoo.docs import parse_doc_string
|
|
11
|
+
from pymoo.operators.crossover.pcx import PCX
|
|
12
|
+
from pymoo.operators.mutation.pm import PM
|
|
13
|
+
from pymoo.operators.sampling.rnd import FloatRandomSampling
|
|
14
|
+
from pymoo.operators.selection.rnd import fast_fill_random
|
|
15
|
+
from pymoo.util.display.single import SingleObjectiveOutput
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# =========================================================================================================
|
|
19
|
+
# Implementation
|
|
20
|
+
# =========================================================================================================
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class G3PCX(LoopwiseAlgorithm):
|
|
24
|
+
|
|
25
|
+
def __init__(self,
|
|
26
|
+
pop_size=100,
|
|
27
|
+
sampling=FloatRandomSampling(),
|
|
28
|
+
n_offsprings=2,
|
|
29
|
+
n_parents=3,
|
|
30
|
+
family_size=2,
|
|
31
|
+
repair=NoRepair(),
|
|
32
|
+
output=SingleObjectiveOutput(),
|
|
33
|
+
**kwargs):
|
|
34
|
+
|
|
35
|
+
super().__init__(output=output, **kwargs)
|
|
36
|
+
|
|
37
|
+
self.pop_size = Integer(pop_size, bounds=(20, 200))
|
|
38
|
+
self.repair = repair
|
|
39
|
+
|
|
40
|
+
self.initialization = Initialization(sampling, repair=self.repair, eliminate_duplicates=False)
|
|
41
|
+
|
|
42
|
+
self.n_offsprings = Integer(n_offsprings, bounds=(1, 10))
|
|
43
|
+
self.n_parents = Integer(n_parents, bounds=(3, 10))
|
|
44
|
+
self.family_size = Integer(family_size, bounds=(1, 10))
|
|
45
|
+
|
|
46
|
+
self.crossover = PCX()
|
|
47
|
+
self.crossover.prob = 1.0
|
|
48
|
+
|
|
49
|
+
self.mutation = PM()
|
|
50
|
+
self.mutation.prob = Real(0.25, bounds=(0.0, 1.0))
|
|
51
|
+
|
|
52
|
+
def _initialize_infill(self):
|
|
53
|
+
return self.initialization.do(self.problem, get(self.pop_size), algorithm=self, random_state=self.random_state)
|
|
54
|
+
|
|
55
|
+
def _initialize_advance(self, infills=None, **kwargs):
|
|
56
|
+
self.pop = FitnessSurvival().do(self.problem, infills, n_survive=len(infills), algorithm=self, **kwargs)
|
|
57
|
+
|
|
58
|
+
def _next(self, **kwargs):
|
|
59
|
+
pop_size, n_offsprings, n_parents = get(self.pop_size, self.n_offsprings, self.n_parents)
|
|
60
|
+
|
|
61
|
+
# how many loops shall be iterated until one iteration has ended
|
|
62
|
+
loops_per_iter = pop_size // n_offsprings
|
|
63
|
+
|
|
64
|
+
for _ in range(loops_per_iter):
|
|
65
|
+
|
|
66
|
+
S = np.zeros((n_offsprings, n_parents), dtype=int)
|
|
67
|
+
S[:, 0] = 0
|
|
68
|
+
fast_fill_random(S, len(self.pop), columns=range(1, n_parents), random_state=self.random_state)
|
|
69
|
+
|
|
70
|
+
off = self.crossover(self.problem, self.pop, parents=S, algorithm=self, random_state=self.random_state)
|
|
71
|
+
|
|
72
|
+
off = self.mutation(self.problem, off, algorithm=self, random_state=self.random_state)
|
|
73
|
+
|
|
74
|
+
self.repair(self.problem, off, algorithm=self)
|
|
75
|
+
|
|
76
|
+
off = yield off
|
|
77
|
+
|
|
78
|
+
pop, family_size = self.pop, get(self.family_size)
|
|
79
|
+
|
|
80
|
+
rnd = self.random_state.choice(np.arange(len(pop)), size=family_size, replace=False)
|
|
81
|
+
family = Population.merge(pop[rnd], off)
|
|
82
|
+
pop[rnd] = FitnessSurvival().do(self.problem, family, n_survive=family_size)
|
|
83
|
+
|
|
84
|
+
for i in rnd:
|
|
85
|
+
if is_better(pop[i], pop[0]):
|
|
86
|
+
tmp = pop[0]
|
|
87
|
+
pop[0] = pop[i]
|
|
88
|
+
pop[i] = tmp
|
|
89
|
+
|
|
90
|
+
def _set_optimum(self, **kwargs):
|
|
91
|
+
self.opt = self.pop[[0]]
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
parse_doc_string(G3PCX.__init__)
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.algorithms.base.genetic import GeneticAlgorithm
|
|
4
|
+
from pymoo.core.survival import Survival
|
|
5
|
+
from pymoo.docs import parse_doc_string
|
|
6
|
+
from pymoo.operators.crossover.sbx import SBX
|
|
7
|
+
from pymoo.operators.crossover.spx import SPX
|
|
8
|
+
from pymoo.operators.mutation.bitflip import BitflipMutation
|
|
9
|
+
from pymoo.operators.mutation.pm import PM
|
|
10
|
+
from pymoo.operators.sampling.rnd import BinaryRandomSampling
|
|
11
|
+
from pymoo.operators.sampling.rnd import FloatRandomSampling
|
|
12
|
+
from pymoo.operators.selection.tournament import compare, TournamentSelection
|
|
13
|
+
from pymoo.termination.default import DefaultSingleObjectiveTermination
|
|
14
|
+
from pymoo.util import default_random_state
|
|
15
|
+
from pymoo.util.display.single import SingleObjectiveOutput
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# =========================================================================================================
|
|
19
|
+
# Survival
|
|
20
|
+
# =========================================================================================================
|
|
21
|
+
|
|
22
|
+
class FitnessSurvival(Survival):
|
|
23
|
+
|
|
24
|
+
def __init__(self) -> None:
|
|
25
|
+
super().__init__(filter_infeasible=False)
|
|
26
|
+
|
|
27
|
+
def _do(self, problem, pop, n_survive=None, **kwargs):
|
|
28
|
+
F, cv = pop.get("F", "cv")
|
|
29
|
+
assert F.shape[1] == 1, "FitnessSurvival can only used for single objective single!"
|
|
30
|
+
S = np.lexsort([F[:, 0], cv])
|
|
31
|
+
pop.set("rank", np.argsort(S))
|
|
32
|
+
return pop[S[:n_survive]]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# =========================================================================================================
|
|
36
|
+
# Implementation
|
|
37
|
+
# =========================================================================================================
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@default_random_state
|
|
41
|
+
def comp_by_cv_and_fitness(pop, P, random_state=None, **kwargs):
|
|
42
|
+
S = np.full(P.shape[0], np.nan)
|
|
43
|
+
|
|
44
|
+
for i in range(P.shape[0]):
|
|
45
|
+
a, b = P[i, 0], P[i, 1]
|
|
46
|
+
|
|
47
|
+
# if at least one solution is infeasible
|
|
48
|
+
if pop[a].CV > 0.0 or pop[b].CV > 0.0:
|
|
49
|
+
S[i] = compare(a, pop[a].CV, b, pop[b].CV, method='smaller_is_better', return_random_if_equal=True, random_state=random_state)
|
|
50
|
+
|
|
51
|
+
# both solutions are feasible just set random
|
|
52
|
+
else:
|
|
53
|
+
S[i] = compare(a, pop[a].F, b, pop[b].F, method='smaller_is_better', return_random_if_equal=True, random_state=random_state)
|
|
54
|
+
|
|
55
|
+
return S[:, None].astype(int)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class GA(GeneticAlgorithm):
|
|
59
|
+
|
|
60
|
+
def __init__(self,
|
|
61
|
+
pop_size=100,
|
|
62
|
+
sampling=FloatRandomSampling(),
|
|
63
|
+
selection=TournamentSelection(func_comp=comp_by_cv_and_fitness),
|
|
64
|
+
crossover=SBX(),
|
|
65
|
+
mutation=PM(),
|
|
66
|
+
survival=FitnessSurvival(),
|
|
67
|
+
eliminate_duplicates=True,
|
|
68
|
+
n_offsprings=None,
|
|
69
|
+
output=SingleObjectiveOutput(),
|
|
70
|
+
**kwargs):
|
|
71
|
+
super().__init__(pop_size=pop_size,
|
|
72
|
+
sampling=sampling,
|
|
73
|
+
selection=selection,
|
|
74
|
+
crossover=crossover,
|
|
75
|
+
mutation=mutation,
|
|
76
|
+
survival=survival,
|
|
77
|
+
eliminate_duplicates=eliminate_duplicates,
|
|
78
|
+
n_offsprings=n_offsprings,
|
|
79
|
+
output=output,
|
|
80
|
+
**kwargs)
|
|
81
|
+
|
|
82
|
+
self.termination = DefaultSingleObjectiveTermination()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class BGA(GA):
|
|
86
|
+
|
|
87
|
+
def __init__(self,
|
|
88
|
+
sampling=BinaryRandomSampling(),
|
|
89
|
+
crossover=SPX(),
|
|
90
|
+
mutation=BitflipMutation(),
|
|
91
|
+
**kwargs):
|
|
92
|
+
super().__init__(sampling=sampling, crossover=crossover, mutation=mutation, **kwargs)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
parse_doc_string(GA.__init__)
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.algorithms.soo.nonconvex.ga import FitnessSurvival, GA
|
|
4
|
+
from pymoo.core.survival import Survival
|
|
5
|
+
from pymoo.docs import parse_doc_string
|
|
6
|
+
from pymoo.operators.selection.tournament import compare, TournamentSelection
|
|
7
|
+
from pymoo.termination.cv import ConstraintViolationTermination
|
|
8
|
+
from pymoo.termination.default import DefaultSingleObjectiveTermination, DefaultTermination
|
|
9
|
+
from pymoo.termination.ftol import SingleObjectiveSpaceTermination
|
|
10
|
+
from pymoo.termination.robust import RobustTermination
|
|
11
|
+
from pymoo.termination.xtol import DesignSpaceTermination
|
|
12
|
+
from pymoo.util.clearing import EpsilonClearing
|
|
13
|
+
from pymoo.util.display.column import Column
|
|
14
|
+
from pymoo.util.display.single import SingleObjectiveOutput
|
|
15
|
+
from pymoo.util.misc import norm_eucl_dist
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# =========================================================================================================
|
|
19
|
+
# Display
|
|
20
|
+
# =========================================================================================================
|
|
21
|
+
|
|
22
|
+
class NicheOutput(SingleObjectiveOutput):
|
|
23
|
+
|
|
24
|
+
def __init__(self):
|
|
25
|
+
super().__init__()
|
|
26
|
+
self.n_niches = Column("n_niches", width=10, func=lambda algorithm: len(algorithm.opt))
|
|
27
|
+
self.columns += [self.n_niches]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# =========================================================================================================
|
|
31
|
+
# Termination
|
|
32
|
+
# =========================================================================================================
|
|
33
|
+
|
|
34
|
+
class NicheSingleObjectiveSpaceToleranceTermination(SingleObjectiveSpaceTermination):
|
|
35
|
+
|
|
36
|
+
def _data(self, algorithm):
|
|
37
|
+
return algorithm.opt.get("F").mean()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class NicheTermination(DefaultTermination):
|
|
41
|
+
|
|
42
|
+
def __init__(self,
|
|
43
|
+
x_tol=1e-32,
|
|
44
|
+
cv_tol=1e-6,
|
|
45
|
+
f_tol=1e-6,
|
|
46
|
+
period=20,
|
|
47
|
+
**kwargs) -> None:
|
|
48
|
+
super().__init__(RobustTermination(DesignSpaceTermination(tol=x_tol), period=period),
|
|
49
|
+
RobustTermination(ConstraintViolationTermination(tol=cv_tol), period=period),
|
|
50
|
+
RobustTermination(NicheSingleObjectiveSpaceToleranceTermination(tol=f_tol, n_skip=5),
|
|
51
|
+
period=period),
|
|
52
|
+
**kwargs)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# =========================================================================================================
|
|
56
|
+
# Selection
|
|
57
|
+
# =========================================================================================================
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def comp_by_cv_and_clearing_fitness(pop, P, **kwargs):
|
|
61
|
+
S = np.full(P.shape[0], np.nan)
|
|
62
|
+
|
|
63
|
+
for i in range(P.shape[0]):
|
|
64
|
+
a, b = P[i, 0], P[i, 1]
|
|
65
|
+
|
|
66
|
+
# if at least one solution is infeasible
|
|
67
|
+
if pop[a].CV[0] > 0.0 or pop[b].CV[0] > 0.0:
|
|
68
|
+
S[i] = compare(a, pop[a].CV, b, pop[b].CV,
|
|
69
|
+
method='smaller_is_better',
|
|
70
|
+
return_random_if_equal=True)
|
|
71
|
+
|
|
72
|
+
# first compare by the round the individual was selected
|
|
73
|
+
else:
|
|
74
|
+
S[i] = compare(a, pop[a].get("iter"), b, pop[b].get("iter"), method='smaller_is_better')
|
|
75
|
+
|
|
76
|
+
# if it was the same round - then use the rank of the fitness directly
|
|
77
|
+
if np.isnan(S[i]):
|
|
78
|
+
S[i] = compare(a, pop[a].get("rank"), b, pop[b].get("rank"),
|
|
79
|
+
method='smaller_is_better', return_random_if_equal=True)
|
|
80
|
+
|
|
81
|
+
return S[:, None].astype(int)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# =========================================================================================================
|
|
85
|
+
# Survival
|
|
86
|
+
# =========================================================================================================
|
|
87
|
+
|
|
88
|
+
class EpsilonClearingSurvival(Survival):
|
|
89
|
+
|
|
90
|
+
def __init__(self, epsilon, n_max_each_iter=None, norm_by_dim=False) -> None:
|
|
91
|
+
super().__init__(False)
|
|
92
|
+
self.epsilon = epsilon
|
|
93
|
+
self.n_max_each_iter = n_max_each_iter
|
|
94
|
+
self.norm_by_dim = norm_by_dim
|
|
95
|
+
|
|
96
|
+
def _do(self, problem, pop, n_survive=None, out=None, **kwargs):
|
|
97
|
+
F = pop.get("F")
|
|
98
|
+
|
|
99
|
+
if F.shape[1] != 1:
|
|
100
|
+
raise ValueError("FitnessSurvival can only used for single objective single!")
|
|
101
|
+
|
|
102
|
+
# this basically sorts the population by constraint and objective value
|
|
103
|
+
pop = FitnessSurvival().do(problem, pop, n_survive=len(pop))
|
|
104
|
+
|
|
105
|
+
# calculate the distance from each individual to another - pre-processing for the clearing
|
|
106
|
+
# NOTE: the distance is normalized by the maximum distance possible
|
|
107
|
+
X = pop.get("X").astype(float)
|
|
108
|
+
D = norm_eucl_dist(problem, X, X)
|
|
109
|
+
if self.norm_by_dim:
|
|
110
|
+
D = D / (problem.n_var ** 0.5)
|
|
111
|
+
|
|
112
|
+
# initialize the clearing strategy
|
|
113
|
+
clearing = EpsilonClearing(D, self.epsilon)
|
|
114
|
+
|
|
115
|
+
# initialize the iteration and rank i the beginning
|
|
116
|
+
iter, rank = 1, 1
|
|
117
|
+
|
|
118
|
+
# also solutions that have been found in the first iteration
|
|
119
|
+
iter_one = None
|
|
120
|
+
|
|
121
|
+
# until the number of selected individuals are less than expected survivors
|
|
122
|
+
while len(clearing.selected()) < n_survive:
|
|
123
|
+
|
|
124
|
+
# get all the remaining indices
|
|
125
|
+
remaining = clearing.remaining()
|
|
126
|
+
|
|
127
|
+
# if no individuals are left because of clearing - perform a reset
|
|
128
|
+
if len(remaining) == 0 or (self.n_max_each_iter is not None and rank > self.n_max_each_iter):
|
|
129
|
+
# reset and retrieve the newly available indices
|
|
130
|
+
clearing.reset()
|
|
131
|
+
remaining = clearing.remaining()
|
|
132
|
+
|
|
133
|
+
# increase the iteration counter and start over from rank 1
|
|
134
|
+
iter += 1
|
|
135
|
+
rank = 1
|
|
136
|
+
|
|
137
|
+
# get the individual of the first iteration - needed for niche assignment
|
|
138
|
+
iter_one = np.where(pop.get("iter") == 1)[0] if iter_one is None else iter_one
|
|
139
|
+
|
|
140
|
+
# since the population is ordered by F and CV it is always the first index
|
|
141
|
+
k = remaining[0]
|
|
142
|
+
|
|
143
|
+
# set the attribute to the selected individual
|
|
144
|
+
pop[k].set("iter", iter)
|
|
145
|
+
pop[k].set("rank", rank)
|
|
146
|
+
|
|
147
|
+
# in the first iteration set the niche counter for each solution equal to rank
|
|
148
|
+
if iter == 1:
|
|
149
|
+
pop[k].set("niche", rank)
|
|
150
|
+
else:
|
|
151
|
+
closest_iter_one = iter_one[D[k][iter_one].argmin()]
|
|
152
|
+
niche = pop[closest_iter_one].get("niche")
|
|
153
|
+
pop[k].set("niche", niche)
|
|
154
|
+
|
|
155
|
+
clearing.select(k)
|
|
156
|
+
rank += 1
|
|
157
|
+
|
|
158
|
+
# retrieve all individuals being selected
|
|
159
|
+
S = clearing.selected()
|
|
160
|
+
|
|
161
|
+
return pop[S]
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# =========================================================================================================
|
|
165
|
+
# Algorithm
|
|
166
|
+
# =========================================================================================================
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class NicheGA(GA):
|
|
170
|
+
|
|
171
|
+
def __init__(self,
|
|
172
|
+
pop_size=100,
|
|
173
|
+
norm_niche_size=0.05,
|
|
174
|
+
norm_by_dim=False,
|
|
175
|
+
return_all_opt=True,
|
|
176
|
+
output=NicheOutput(),
|
|
177
|
+
survival=None,
|
|
178
|
+
selection=None,
|
|
179
|
+
**kwargs):
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
Parameters
|
|
183
|
+
----------
|
|
184
|
+
norm_niche_size : float
|
|
185
|
+
The radius in which the clearing shall be performed. The clearing is performed in the normalized design
|
|
186
|
+
space, e.g. 0.05 corresponds to clear all solutions which have less norm euclidean distance than 5%.
|
|
187
|
+
pop_size : {pop_size}
|
|
188
|
+
sampling : {sampling}
|
|
189
|
+
selection : {selection}
|
|
190
|
+
crossover : {crossover}
|
|
191
|
+
mutation : {mutation}
|
|
192
|
+
eliminate_duplicates : {eliminate_duplicates}
|
|
193
|
+
n_offsprings : {n_offsprings}
|
|
194
|
+
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
if survival is None:
|
|
198
|
+
survival = EpsilonClearingSurvival(norm_niche_size, n_max_each_iter=None, norm_by_dim=norm_by_dim)
|
|
199
|
+
|
|
200
|
+
if selection is None:
|
|
201
|
+
selection = TournamentSelection(comp_by_cv_and_clearing_fitness)
|
|
202
|
+
|
|
203
|
+
super().__init__(pop_size=pop_size,
|
|
204
|
+
selection=selection,
|
|
205
|
+
survival=survival,
|
|
206
|
+
output=output,
|
|
207
|
+
advance_after_initial_infill=True,
|
|
208
|
+
**kwargs)
|
|
209
|
+
|
|
210
|
+
# self.termination = NicheTermination()
|
|
211
|
+
self.termination = DefaultSingleObjectiveTermination()
|
|
212
|
+
|
|
213
|
+
# whether with rank one after clearing or just the best should be considered as optimal
|
|
214
|
+
self.return_all_opt = return_all_opt
|
|
215
|
+
|
|
216
|
+
def _set_optimum(self, **kwargs):
|
|
217
|
+
if self.return_all_opt:
|
|
218
|
+
self.opt = self.pop[self.pop.get("iter") == 1]
|
|
219
|
+
else:
|
|
220
|
+
super()._set_optimum()
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
parse_doc_string(NicheGA.__init__)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from math import sqrt, log, exp
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from pymoo.algorithms.soo.nonconvex.es import es_sigma, es_mut_repair
|
|
6
|
+
from pymoo.algorithms.soo.nonconvex.sres import SRES
|
|
7
|
+
from pymoo.core.population import Population
|
|
8
|
+
from pymoo.docs import parse_doc_string
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ISRES(SRES):
|
|
12
|
+
|
|
13
|
+
def __init__(self, gamma=0.85, alpha=0.2, **kwargs):
|
|
14
|
+
"""
|
|
15
|
+
Improved Stochastic Ranking Evolutionary Strategy (SRES)
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
alpha : float
|
|
20
|
+
Length scale of the differentials during mutation.
|
|
21
|
+
PF: float
|
|
22
|
+
The stochastic ranking weight for choosing a random decision while doing the modified bubble sort.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
super().__init__(**kwargs)
|
|
26
|
+
self.gamma = gamma
|
|
27
|
+
self.alpha = alpha
|
|
28
|
+
|
|
29
|
+
def _setup(self, problem, **kwargs):
|
|
30
|
+
super()._setup(problem, **kwargs)
|
|
31
|
+
n = problem.n_var
|
|
32
|
+
|
|
33
|
+
chi = (1 / (2 * n) + 1 / (2 * (n ** 0.5)))
|
|
34
|
+
varphi = sqrt((2 / chi) * log((1 / self.alpha) * (exp(self.phi ** 2 * chi / 2) - (1 - self.alpha))))
|
|
35
|
+
|
|
36
|
+
self.taup = varphi / ((2 * n) ** 0.5)
|
|
37
|
+
self.tau = varphi / ((2 * (n ** 0.5)) ** 0.5)
|
|
38
|
+
|
|
39
|
+
def _infill(self):
|
|
40
|
+
pop, mu, _lambda = self.pop, self.pop_size, self.n_offsprings
|
|
41
|
+
xl, xu = self.problem.bounds()
|
|
42
|
+
X, sigma = pop.get("X", "sigma")
|
|
43
|
+
|
|
44
|
+
# cycle through the elites individuals for create the solutions
|
|
45
|
+
I = np.arange(_lambda) % min(mu, len(X))
|
|
46
|
+
|
|
47
|
+
# transform X and sigma to the shape of number of offsprings
|
|
48
|
+
X, sigma = X[I], sigma[I]
|
|
49
|
+
|
|
50
|
+
# copy the original sigma to sigma prime to be modified
|
|
51
|
+
Xp, sigmap = np.copy(X), np.copy(sigma)
|
|
52
|
+
|
|
53
|
+
# for the best individuals do differential variation to provide a direction to search in
|
|
54
|
+
Xp[:mu - 1] = X[:mu - 1] + self.gamma * (X[0] - X[1:mu])
|
|
55
|
+
|
|
56
|
+
# update the sigma values for elite and non-elite individuals
|
|
57
|
+
sigmap[mu - 1:] = np.minimum(self.sigma_max, es_sigma(sigma[mu - 1:], self.tau, self.taup, random_state=self.random_state))
|
|
58
|
+
|
|
59
|
+
# execute the evolutionary strategy to calculate the offspring solutions
|
|
60
|
+
Xp[mu - 1:] = X[mu - 1:] + sigmap[mu - 1:] * self.random_state.normal(size=sigmap[mu - 1:].shape)
|
|
61
|
+
|
|
62
|
+
# repair the individuals which are not feasible by sampling from sigma again
|
|
63
|
+
Xp = es_mut_repair(Xp, X, sigmap, xl, xu, 10, random_state=self.random_state)
|
|
64
|
+
|
|
65
|
+
# now update the sigma values of the non-elites only
|
|
66
|
+
sigmap[mu:] = sigma[mu:] + self.alpha * (sigmap[mu:] - sigma[mu:])
|
|
67
|
+
|
|
68
|
+
# create the population to proceed further
|
|
69
|
+
off = Population.new(X=Xp, sigma=sigmap)
|
|
70
|
+
|
|
71
|
+
return off
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
parse_doc_string(ISRES.__init__)
|