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,88 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.crossover import Crossover
|
|
4
|
+
from pymoo.util import default_random_state
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@default_random_state
|
|
8
|
+
def random_sequence(n, random_state=None):
|
|
9
|
+
start, end = np.sort(random_state.choice(n, 2, replace=False))
|
|
10
|
+
return tuple([start, end])
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@default_random_state
|
|
14
|
+
def ox(receiver, donor, seq=None, shift=False, random_state=None):
|
|
15
|
+
"""
|
|
16
|
+
The Ordered Crossover (OX) as explained in http://www.dmi.unict.it/mpavone/nc-cs/materiale/moscato89.pdf.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
receiver : numpy.array
|
|
21
|
+
The receiver of the sequence. The array needs to be repaired after the donation took place.
|
|
22
|
+
donor : numpy.array
|
|
23
|
+
The donor of the sequence.
|
|
24
|
+
seq : tuple (optional)
|
|
25
|
+
Tuple with two problems defining the start and the end of the sequence. Please note in our implementation
|
|
26
|
+
the end of the sequence is included. The sequence is randomly chosen if not provided.
|
|
27
|
+
|
|
28
|
+
shift : bool
|
|
29
|
+
Whether during the repair the receiver should be shifted or not. Both version of it can be found in the
|
|
30
|
+
literature.
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
-------
|
|
34
|
+
|
|
35
|
+
y : numpy.array
|
|
36
|
+
The offspring which was created by the ordered crossover.
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
assert len(donor) == len(receiver)
|
|
40
|
+
|
|
41
|
+
# the sequence which shall be use for the crossover
|
|
42
|
+
seq = seq if seq is not None else random_sequence(len(receiver), random_state=random_state)
|
|
43
|
+
start, end = seq
|
|
44
|
+
|
|
45
|
+
# the donation and a set of it to allow a quick lookup
|
|
46
|
+
donation = np.copy(donor[start:end + 1])
|
|
47
|
+
donation_as_set = set(donation)
|
|
48
|
+
|
|
49
|
+
# the final value to be returned
|
|
50
|
+
y = []
|
|
51
|
+
|
|
52
|
+
for k in range(len(receiver)):
|
|
53
|
+
|
|
54
|
+
# do the shift starting from the swapped sequence - as proposed in the paper
|
|
55
|
+
i = k if not shift else (start + k) % len(receiver)
|
|
56
|
+
v = receiver[i]
|
|
57
|
+
|
|
58
|
+
if v not in donation_as_set:
|
|
59
|
+
y.append(v)
|
|
60
|
+
|
|
61
|
+
# now insert the donation at the right place
|
|
62
|
+
y = np.concatenate([y[:start], donation, y[start:]]).astype(copy=False, dtype=int)
|
|
63
|
+
|
|
64
|
+
return y
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class OrderCrossover(Crossover):
|
|
68
|
+
|
|
69
|
+
def __init__(self, shift=False, **kwargs):
|
|
70
|
+
super().__init__(2, 2, **kwargs)
|
|
71
|
+
self.shift = shift
|
|
72
|
+
|
|
73
|
+
@default_random_state
|
|
74
|
+
def _do(self, problem, X, random_state=None, **kwargs):
|
|
75
|
+
_, n_matings, n_var = X.shape
|
|
76
|
+
Y = np.full((self.n_offsprings, n_matings, n_var), -1, dtype=int)
|
|
77
|
+
|
|
78
|
+
for i in range(n_matings):
|
|
79
|
+
a, b = X[:, i, :]
|
|
80
|
+
n = len(a)
|
|
81
|
+
|
|
82
|
+
# define the sequence to be used for crossover
|
|
83
|
+
start, end = random_sequence(n, random_state=random_state)
|
|
84
|
+
|
|
85
|
+
Y[0, i, :] = ox(a, b, seq=(start, end), shift=self.shift, random_state=random_state)
|
|
86
|
+
Y[1, i, :] = ox(b, a, seq=(start, end), shift=self.shift, random_state=random_state)
|
|
87
|
+
|
|
88
|
+
return Y
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.crossover import Crossover
|
|
4
|
+
from pymoo.core.variable import Real, get
|
|
5
|
+
from pymoo.operators.repair.bounds_repair import repair_random_init
|
|
6
|
+
from pymoo.util import default_random_state
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@default_random_state
|
|
10
|
+
def pcx(X, eta, zeta, index, random_state=None):
|
|
11
|
+
eps = 1e-32
|
|
12
|
+
|
|
13
|
+
# the number of parents to be considered
|
|
14
|
+
n_parents, n_matings, n_var = X.shape
|
|
15
|
+
|
|
16
|
+
# calculate the differences from all parents to index parent
|
|
17
|
+
diff_to_index = X - X[index]
|
|
18
|
+
dist_to_index = np.linalg.norm(diff_to_index, axis=-1)
|
|
19
|
+
dist_to_index = np.maximum(eps, dist_to_index)
|
|
20
|
+
|
|
21
|
+
# find the centroid of the parents
|
|
22
|
+
centroid = np.mean(X, axis=0)
|
|
23
|
+
|
|
24
|
+
# calculate the difference between the centroid and the k-th parent
|
|
25
|
+
diff_to_centroid = centroid - X[index]
|
|
26
|
+
|
|
27
|
+
dist_to_centroid = np.linalg.norm(diff_to_centroid, axis=-1)
|
|
28
|
+
dist_to_centroid = np.maximum(eps, dist_to_centroid)
|
|
29
|
+
|
|
30
|
+
# orthogonal directions are computed
|
|
31
|
+
orth_dir = np.zeros_like(dist_to_index)
|
|
32
|
+
|
|
33
|
+
for i in range(n_parents):
|
|
34
|
+
if i != index:
|
|
35
|
+
temp1 = (diff_to_index[i] * diff_to_centroid).sum(axis=-1)
|
|
36
|
+
temp2 = temp1 / (dist_to_index[i] * dist_to_centroid)
|
|
37
|
+
temp3 = np.maximum(0.0, 1.0 - temp2 ** 2)
|
|
38
|
+
orth_dir[i] = dist_to_index[i] * (temp3 ** 0.5)
|
|
39
|
+
|
|
40
|
+
# this is the avg of the perpendicular distances from other parents to the parent k
|
|
41
|
+
D_not = orth_dir.sum(axis=0) / (n_parents - 1)
|
|
42
|
+
|
|
43
|
+
# generating zero-mean normally distributed variables
|
|
44
|
+
sigma = D_not[:, None] * eta.repeat(n_var, axis=1)
|
|
45
|
+
rnd = random_state.normal(loc=0.0, scale=sigma)
|
|
46
|
+
|
|
47
|
+
# implemented just like the c code - generate_new.h file
|
|
48
|
+
inner_prod = np.sum(rnd * diff_to_centroid, axis=-1, keepdims=True)
|
|
49
|
+
noise = rnd - (inner_prod * diff_to_centroid) / dist_to_centroid[:, None] ** 2
|
|
50
|
+
|
|
51
|
+
bias_to_centroid = random_state.normal(0.0, zeta) * diff_to_centroid
|
|
52
|
+
|
|
53
|
+
# the array which is finally returned
|
|
54
|
+
Xp = X[index] + noise + bias_to_centroid
|
|
55
|
+
|
|
56
|
+
return Xp
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ParentCentricCrossover(Crossover):
|
|
60
|
+
def __init__(self,
|
|
61
|
+
eta=0.1,
|
|
62
|
+
zeta=0.1,
|
|
63
|
+
**kwargs):
|
|
64
|
+
|
|
65
|
+
super().__init__(n_parents=3, n_offsprings=1, **kwargs)
|
|
66
|
+
self.eta = Real(eta, bounds=(0.01, 0.3))
|
|
67
|
+
self.zeta = Real(zeta, bounds=(0.01, 0.3))
|
|
68
|
+
|
|
69
|
+
def _do(self, problem, X, params=None, random_state=None, **kwargs):
|
|
70
|
+
n_parents, n_matings, n_var = X.shape
|
|
71
|
+
zeta, eta = get(self.zeta, self.eta, size=(n_matings, 1))
|
|
72
|
+
|
|
73
|
+
index = 0
|
|
74
|
+
|
|
75
|
+
Xp = pcx(X, eta, zeta, index=index, random_state=random_state)
|
|
76
|
+
|
|
77
|
+
if problem.has_bounds():
|
|
78
|
+
Xp = repair_random_init(Xp, X[index], *problem.bounds(), random_state=random_state)
|
|
79
|
+
|
|
80
|
+
return Xp[None, :]
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class PCX(ParentCentricCrossover):
|
|
84
|
+
pass
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.crossover import Crossover
|
|
4
|
+
from pymoo.util.misc import crossover_mask
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class PointCrossover(Crossover):
|
|
8
|
+
|
|
9
|
+
def __init__(self, n_points, **kwargs):
|
|
10
|
+
super().__init__(2, 2, **kwargs)
|
|
11
|
+
self.n_points = n_points
|
|
12
|
+
|
|
13
|
+
def _do(self, _, X, random_state=None, **kwargs):
|
|
14
|
+
|
|
15
|
+
# get the X of parents and count the matings
|
|
16
|
+
_, n_matings, n_var = X.shape
|
|
17
|
+
|
|
18
|
+
# start point of crossover
|
|
19
|
+
r = np.vstack([random_state.permutation(n_var - 1) + 1 for _ in range(n_matings)])[:, :self.n_points]
|
|
20
|
+
r.sort(axis=1)
|
|
21
|
+
r = np.column_stack([r, np.full(n_matings, n_var)])
|
|
22
|
+
|
|
23
|
+
# the mask do to the crossover
|
|
24
|
+
M = np.full((n_matings, n_var), False)
|
|
25
|
+
|
|
26
|
+
# create for each individual the crossover range
|
|
27
|
+
for i in range(n_matings):
|
|
28
|
+
|
|
29
|
+
j = 0
|
|
30
|
+
while j < r.shape[1] - 1:
|
|
31
|
+
a, b = r[i, j], r[i, j + 1]
|
|
32
|
+
M[i, a:b] = True
|
|
33
|
+
j += 2
|
|
34
|
+
|
|
35
|
+
Xp = crossover_mask(X, M)
|
|
36
|
+
|
|
37
|
+
return Xp
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class SinglePointCrossover(PointCrossover):
|
|
41
|
+
|
|
42
|
+
def __init__(self, **kwargs):
|
|
43
|
+
super().__init__(n_points=1, **kwargs)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class TwoPointCrossover(PointCrossover):
|
|
47
|
+
|
|
48
|
+
def __init__(self, **kwargs):
|
|
49
|
+
super().__init__(n_points=2, **kwargs)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.crossover import Crossover
|
|
4
|
+
from pymoo.core.variable import Real, get
|
|
5
|
+
from pymoo.operators.repair.bounds_repair import repair_clamp
|
|
6
|
+
from pymoo.util import default_random_state
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
10
|
+
# Function
|
|
11
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@default_random_state
|
|
15
|
+
def cross_sbx(X, xl, xu, eta, prob_var, prob_bin, eps=1.0e-14, random_state=None):
|
|
16
|
+
n_parents, n_matings, n_var = X.shape
|
|
17
|
+
|
|
18
|
+
# the probability of a crossover for each of the variables
|
|
19
|
+
cross = random_state.random((n_matings, n_var)) < prob_var
|
|
20
|
+
|
|
21
|
+
# when solutions are too close -> do not apply sbx crossover
|
|
22
|
+
too_close = np.abs(X[0] - X[1]) <= eps
|
|
23
|
+
|
|
24
|
+
# disable if two individuals are already too close
|
|
25
|
+
cross[too_close] = False
|
|
26
|
+
|
|
27
|
+
# disable crossover when lower and upper bound are identical
|
|
28
|
+
cross[:, xl == xu] = False
|
|
29
|
+
|
|
30
|
+
# preserve parent identity while getting values for SBX calculation
|
|
31
|
+
p1 = X[0][cross]
|
|
32
|
+
p2 = X[1][cross]
|
|
33
|
+
|
|
34
|
+
# assign y1 the smaller and y2 the larger value for SBX calculation
|
|
35
|
+
sm = p1 < p2
|
|
36
|
+
y1 = np.where(sm, p1, p2)
|
|
37
|
+
y2 = np.where(sm, p2, p1)
|
|
38
|
+
|
|
39
|
+
# mask all the values that should be crossovered
|
|
40
|
+
_xl = np.repeat(xl[None, :], n_matings, axis=0)[cross]
|
|
41
|
+
_xu = np.repeat(xu[None, :], n_matings, axis=0)[cross]
|
|
42
|
+
eta = eta.repeat(n_var, axis=1)[cross]
|
|
43
|
+
prob_bin = prob_bin.repeat(n_var, axis=1)[cross]
|
|
44
|
+
|
|
45
|
+
# random values for each individual
|
|
46
|
+
rand = random_state.random(len(eta))
|
|
47
|
+
|
|
48
|
+
def calc_betaq(beta):
|
|
49
|
+
alpha = 2.0 - np.power(beta, -(eta + 1.0))
|
|
50
|
+
|
|
51
|
+
mask, mask_not = (rand <= (1.0 / alpha)), (rand > (1.0 / alpha))
|
|
52
|
+
|
|
53
|
+
betaq = np.zeros(mask.shape)
|
|
54
|
+
betaq[mask] = np.power((rand * alpha), (1.0 / (eta + 1.0)))[mask]
|
|
55
|
+
betaq[mask_not] = np.power((1.0 / (2.0 - rand * alpha)), (1.0 / (eta + 1.0)))[mask_not]
|
|
56
|
+
|
|
57
|
+
return betaq
|
|
58
|
+
|
|
59
|
+
# difference between all variables
|
|
60
|
+
delta = (y2 - y1)
|
|
61
|
+
|
|
62
|
+
beta = 1.0 + (2.0 * (y1 - _xl) / delta)
|
|
63
|
+
betaq = calc_betaq(beta)
|
|
64
|
+
c1 = 0.5 * ((y1 + y2) - betaq * delta)
|
|
65
|
+
|
|
66
|
+
beta = 1.0 + (2.0 * (_xu - y2) / delta)
|
|
67
|
+
betaq = calc_betaq(beta)
|
|
68
|
+
c2 = 0.5 * ((y1 + y2) + betaq * delta)
|
|
69
|
+
|
|
70
|
+
# assign children based on parent position, then apply exchange probability
|
|
71
|
+
child1 = np.where(sm, c1, c2) # child for parent 1
|
|
72
|
+
child2 = np.where(sm, c2, c1) # child for parent 2
|
|
73
|
+
|
|
74
|
+
# exchange children with given probability
|
|
75
|
+
b = np.bitwise_xor(
|
|
76
|
+
random_state.random(len(prob_bin)) < prob_bin,
|
|
77
|
+
X[0, cross] > X[1, cross]
|
|
78
|
+
)
|
|
79
|
+
child1, child2 = np.where(b, (child2, child1), (child1, child2))
|
|
80
|
+
|
|
81
|
+
# first copy the unmodified parents
|
|
82
|
+
Q = np.copy(X)
|
|
83
|
+
|
|
84
|
+
# copy the positions where the crossover was done
|
|
85
|
+
Q[0, cross] = child1
|
|
86
|
+
Q[1, cross] = child2
|
|
87
|
+
|
|
88
|
+
Q[0] = repair_clamp(Q[0], xl, xu)
|
|
89
|
+
Q[1] = repair_clamp(Q[1], xl, xu)
|
|
90
|
+
|
|
91
|
+
return Q
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
95
|
+
# Class
|
|
96
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class SimulatedBinaryCrossover(Crossover):
|
|
100
|
+
|
|
101
|
+
def __init__(self,
|
|
102
|
+
prob_var=0.5,
|
|
103
|
+
eta=15,
|
|
104
|
+
prob_exch=1.0,
|
|
105
|
+
prob_bin=0.5,
|
|
106
|
+
n_offsprings=2,
|
|
107
|
+
**kwargs):
|
|
108
|
+
super().__init__(2, n_offsprings, **kwargs)
|
|
109
|
+
|
|
110
|
+
self.prob_var = Real(prob_var, bounds=(0.1, 0.9))
|
|
111
|
+
self.eta = Real(eta, bounds=(3.0, 30.0), strict=(1.0, None))
|
|
112
|
+
self.prob_exch = Real(prob_exch, bounds=(0.0, 1.0), strict=(0.0, 1.0))
|
|
113
|
+
self.prob_bin = Real(prob_bin, bounds=(0.0, 1.0), strict=(0.0, 1.0))
|
|
114
|
+
|
|
115
|
+
def _do(self, problem, X, *args, random_state=None, **kwargs):
|
|
116
|
+
_, n_matings, _ = X.shape
|
|
117
|
+
|
|
118
|
+
# get the parameters required by SBX
|
|
119
|
+
eta, prob_var, prob_exch, prob_bin = get(self.eta, self.prob_var, self.prob_exch, self.prob_bin,
|
|
120
|
+
size=(n_matings, 1))
|
|
121
|
+
|
|
122
|
+
# set the binomial probability to zero if no exchange between individuals shall happen
|
|
123
|
+
rand = random_state.random((len(prob_bin), 1))
|
|
124
|
+
prob_bin[rand > prob_exch] = 0.0
|
|
125
|
+
|
|
126
|
+
Q = cross_sbx(X.astype(float), problem.xl, problem.xu, eta, prob_var, prob_bin, random_state=random_state)
|
|
127
|
+
|
|
128
|
+
if self.n_offsprings == 1:
|
|
129
|
+
rand = random_state.random(size=n_matings) < 0.5
|
|
130
|
+
Q[0, rand] = Q[1, rand]
|
|
131
|
+
Q = Q[[0]]
|
|
132
|
+
|
|
133
|
+
return Q
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class SBX(SimulatedBinaryCrossover):
|
|
137
|
+
pass
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.crossover import Crossover
|
|
4
|
+
from pymoo.util.misc import crossover_mask
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class UniformCrossover(Crossover):
|
|
8
|
+
|
|
9
|
+
def __init__(self, **kwargs):
|
|
10
|
+
super().__init__(2, 2, **kwargs)
|
|
11
|
+
|
|
12
|
+
def _do(self, _, X, random_state=None, **kwargs):
|
|
13
|
+
_, n_matings, n_var = X.shape
|
|
14
|
+
M = random_state.random((n_matings, n_var)) < 0.5
|
|
15
|
+
_X = crossover_mask(X, M)
|
|
16
|
+
return _X
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class UX(UniformCrossover):
|
|
20
|
+
pass
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.mutation import Mutation
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BitflipMutation(Mutation):
|
|
7
|
+
|
|
8
|
+
def _do(self, problem, X, random_state=None, **kwargs):
|
|
9
|
+
prob_var = self.get_prob_var(problem, size=(len(X), 1))
|
|
10
|
+
Xp = np.copy(X)
|
|
11
|
+
flip = random_state.random(X.shape) < prob_var
|
|
12
|
+
Xp[flip] = ~X[flip]
|
|
13
|
+
return Xp
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BFM(BitflipMutation):
|
|
17
|
+
pass
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.mutation import Mutation
|
|
4
|
+
from pymoo.core.variable import Real, get
|
|
5
|
+
from pymoo.operators.repair.bounds_repair import repair_random_init
|
|
6
|
+
from pymoo.util import default_random_state
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
10
|
+
# Function
|
|
11
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@default_random_state
|
|
15
|
+
def mut_gauss(X, xl, xu, sigma, prob, random_state=None):
|
|
16
|
+
n, n_var = X.shape
|
|
17
|
+
assert len(sigma) == n
|
|
18
|
+
assert len(prob) == n
|
|
19
|
+
|
|
20
|
+
Xp = np.full(X.shape, np.inf)
|
|
21
|
+
|
|
22
|
+
mut = random_state.random(X.shape) < prob[:, None]
|
|
23
|
+
|
|
24
|
+
Xp[:, :] = X
|
|
25
|
+
|
|
26
|
+
_xl = np.repeat(xl[None, :], X.shape[0], axis=0)[mut]
|
|
27
|
+
_xu = np.repeat(xu[None, :], X.shape[0], axis=0)[mut]
|
|
28
|
+
sigma = sigma[:, None].repeat(n_var, axis=1)[mut]
|
|
29
|
+
|
|
30
|
+
Xp[mut] = random_state.normal(X[mut], sigma * (_xu - _xl))
|
|
31
|
+
|
|
32
|
+
Xp = repair_random_init(Xp, X, xl, xu)
|
|
33
|
+
|
|
34
|
+
return Xp
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
38
|
+
# Class
|
|
39
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class GaussianMutation(Mutation):
|
|
43
|
+
|
|
44
|
+
def __init__(self, sigma=0.1, **kwargs):
|
|
45
|
+
super().__init__(**kwargs)
|
|
46
|
+
self.sigma = Real(sigma, bounds=(0.01, 0.25), strict=(0.0, 1.0))
|
|
47
|
+
|
|
48
|
+
def _do(self, problem, X, random_state=None, **kwargs):
|
|
49
|
+
X = X.astype(float)
|
|
50
|
+
|
|
51
|
+
sigma = get(self.sigma, size=len(X))
|
|
52
|
+
prob_var = self.get_prob_var(problem, size=len(X))
|
|
53
|
+
|
|
54
|
+
Xp = mut_gauss(X, problem.xl, problem.xu, sigma, prob_var, random_state=random_state)
|
|
55
|
+
|
|
56
|
+
return Xp
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class GM(GaussianMutation):
|
|
60
|
+
pass
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.mutation import Mutation
|
|
4
|
+
from pymoo.operators.crossover.ox import random_sequence
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def inversion_mutation(y, seq, inplace=True):
|
|
8
|
+
y = y if inplace else np.copy(y)
|
|
9
|
+
|
|
10
|
+
if seq is None:
|
|
11
|
+
seq = random_sequence(len(y))
|
|
12
|
+
start, end = seq
|
|
13
|
+
|
|
14
|
+
y[start:end + 1] = np.flip(y[start:end + 1])
|
|
15
|
+
return y
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class InversionMutation(Mutation):
|
|
19
|
+
|
|
20
|
+
def __init__(self, prob=1.0):
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
This mutation is applied to permutations. It randomly selects a segment of a chromosome and reverse its order.
|
|
24
|
+
For instance, for the permutation `[1, 2, 3, 4, 5]` the segment can be `[2, 3, 4]` which results in `[1, 4, 3, 2, 5]`.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
prob : float
|
|
29
|
+
Probability to apply the mutation to the individual
|
|
30
|
+
|
|
31
|
+
"""
|
|
32
|
+
super().__init__()
|
|
33
|
+
self.prob = prob
|
|
34
|
+
|
|
35
|
+
def _do(self, problem, X, random_state=None, **kwargs):
|
|
36
|
+
Y = X.copy()
|
|
37
|
+
for i, y in enumerate(X):
|
|
38
|
+
if random_state.random() < self.prob:
|
|
39
|
+
seq = random_sequence(len(y), random_state=random_state)
|
|
40
|
+
Y[i] = inversion_mutation(y, seq, inplace=True)
|
|
41
|
+
|
|
42
|
+
return Y
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.mutation import Mutation
|
|
4
|
+
from pymoo.core.variable import get, Real
|
|
5
|
+
from pymoo.operators.crossover.binx import mut_binomial
|
|
6
|
+
from pymoo.operators.repair.to_bound import set_to_bounds_if_outside
|
|
7
|
+
from pymoo.util import default_random_state
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
11
|
+
# Function
|
|
12
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@default_random_state
|
|
16
|
+
def mut_pm(X, xl, xu, eta, prob, at_least_once, random_state=None):
|
|
17
|
+
n, n_var = X.shape
|
|
18
|
+
assert len(eta) == n
|
|
19
|
+
assert len(prob) == n
|
|
20
|
+
|
|
21
|
+
Xp = np.full(X.shape, np.inf)
|
|
22
|
+
|
|
23
|
+
mut = mut_binomial(n, n_var, prob, at_least_once=at_least_once, random_state=random_state)
|
|
24
|
+
mut[:, xl == xu] = False
|
|
25
|
+
|
|
26
|
+
Xp[:, :] = X
|
|
27
|
+
|
|
28
|
+
_xl = np.repeat(xl[None, :], X.shape[0], axis=0)[mut]
|
|
29
|
+
_xu = np.repeat(xu[None, :], X.shape[0], axis=0)[mut]
|
|
30
|
+
|
|
31
|
+
X = X[mut]
|
|
32
|
+
eta = np.tile(eta[:, None], (1, n_var))[mut]
|
|
33
|
+
|
|
34
|
+
delta1 = (X - _xl) / (_xu - _xl)
|
|
35
|
+
delta2 = (_xu - X) / (_xu - _xl)
|
|
36
|
+
|
|
37
|
+
mut_pow = 1.0 / (eta + 1.0)
|
|
38
|
+
|
|
39
|
+
rand = random_state.random(X.shape)
|
|
40
|
+
mask = rand <= 0.5
|
|
41
|
+
mask_not = np.logical_not(mask)
|
|
42
|
+
|
|
43
|
+
deltaq = np.zeros(X.shape)
|
|
44
|
+
|
|
45
|
+
xy = 1.0 - delta1
|
|
46
|
+
val = 2.0 * rand + (1.0 - 2.0 * rand) * (np.power(xy, (eta + 1.0)))
|
|
47
|
+
d = np.power(val, mut_pow) - 1.0
|
|
48
|
+
deltaq[mask] = d[mask]
|
|
49
|
+
|
|
50
|
+
xy = 1.0 - delta2
|
|
51
|
+
val = 2.0 * (1.0 - rand) + 2.0 * (rand - 0.5) * (np.power(xy, (eta + 1.0)))
|
|
52
|
+
d = 1.0 - (np.power(val, mut_pow))
|
|
53
|
+
deltaq[mask_not] = d[mask_not]
|
|
54
|
+
|
|
55
|
+
# mutated values
|
|
56
|
+
_Y = X + deltaq * (_xu - _xl)
|
|
57
|
+
|
|
58
|
+
# back in bounds if necessary (floating point issues)
|
|
59
|
+
_Y[_Y < _xl] = _xl[_Y < _xl]
|
|
60
|
+
_Y[_Y > _xu] = _xu[_Y > _xu]
|
|
61
|
+
|
|
62
|
+
# set the values for output
|
|
63
|
+
Xp[mut] = _Y
|
|
64
|
+
|
|
65
|
+
# in case out of bounds repair (very unlikely)
|
|
66
|
+
Xp = set_to_bounds_if_outside(Xp, xl, xu)
|
|
67
|
+
|
|
68
|
+
return Xp
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
72
|
+
# Class
|
|
73
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class PolynomialMutation(Mutation):
|
|
77
|
+
|
|
78
|
+
def __init__(self, prob=0.9, eta=20, at_least_once=False, **kwargs):
|
|
79
|
+
super().__init__(prob=prob, **kwargs)
|
|
80
|
+
self.at_least_once = at_least_once
|
|
81
|
+
self.eta = Real(eta, bounds=(3.0, 30.0), strict=(1.0, 100.0))
|
|
82
|
+
|
|
83
|
+
def _do(self, problem, X, params=None, *args, random_state=None, **kwargs):
|
|
84
|
+
X = X.astype(float)
|
|
85
|
+
|
|
86
|
+
eta = get(self.eta, size=len(X))
|
|
87
|
+
prob_var = self.get_prob_var(problem, size=len(X))
|
|
88
|
+
|
|
89
|
+
Xp = mut_pm(X, problem.xl, problem.xu, eta, prob_var, at_least_once=self.at_least_once, random_state=random_state)
|
|
90
|
+
|
|
91
|
+
return Xp
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class PM(PolynomialMutation):
|
|
95
|
+
pass
|
|
96
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.mutation import Mutation
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ChoiceRandomMutation(Mutation):
|
|
7
|
+
|
|
8
|
+
def _do(self, problem, X, random_state=None, **kwargs):
|
|
9
|
+
assert problem.vars is not None
|
|
10
|
+
|
|
11
|
+
# ensure the type object (fixed string length <UX can cause issues)
|
|
12
|
+
X = X.astype(object)
|
|
13
|
+
|
|
14
|
+
prob_var = self.get_prob_var(problem, size=len(X))
|
|
15
|
+
|
|
16
|
+
for k, (_, var) in enumerate(problem.vars.items()):
|
|
17
|
+
mut = np.where(random_state.random(len(X)) < prob_var)[0]
|
|
18
|
+
|
|
19
|
+
v = var.sample(len(mut), random_state=random_state)
|
|
20
|
+
X[mut, k] = v
|
|
21
|
+
|
|
22
|
+
return X
|
|
23
|
+
|
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.operators.repair.bounds_repair import BoundsRepair
|
|
4
|
+
from pymoo.util.misc import at_least_2d_array
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def bounce_back(X, xl, xu):
|
|
8
|
+
only_1d = (X.ndim == 1)
|
|
9
|
+
X = at_least_2d_array(X)
|
|
10
|
+
|
|
11
|
+
xl = np.repeat(xl[None, :], X.shape[0], axis=0)
|
|
12
|
+
xu = np.repeat(xu[None, :], X.shape[0], axis=0)
|
|
13
|
+
|
|
14
|
+
# otherwise bounds back into the feasible space
|
|
15
|
+
_range = xu - xl
|
|
16
|
+
X[X < xl] = (xl + np.mod((xl - X), _range))[X < xl]
|
|
17
|
+
X[X > xu] = (xu - np.mod((X - xu), _range))[X > xu]
|
|
18
|
+
|
|
19
|
+
if only_1d:
|
|
20
|
+
return X[0, :]
|
|
21
|
+
else:
|
|
22
|
+
return X
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def bounce_back_by_problem(problem, X):
|
|
26
|
+
return bounce_back(X, problem.xl, problem.xu)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class BounceBackOutOfBoundsRepair(BoundsRepair):
|
|
30
|
+
|
|
31
|
+
def repair_out_of_bounds(self, problem, X, **kwargs):
|
|
32
|
+
return bounce_back_by_problem(problem, X)
|