pymoo 0.6.1.5.dev0__cp311-cp311-musllinux_1_2_x86_64.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-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/calc_perpendicular_distance.pyx +67 -0
- pymoo/cython/decomposition.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/decomposition.pyx +165 -0
- pymoo/cython/hv.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/hv.pyx +18 -0
- pymoo/cython/info.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/info.pyx +5 -0
- pymoo/cython/mnn.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/mnn.pyx +273 -0
- pymoo/cython/non_dominated_sorting.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/non_dominated_sorting.pyx +645 -0
- pymoo/cython/pruning_cd.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/pruning_cd.pyx +197 -0
- pymoo/cython/stochastic_ranking.cpython-311-x86_64-linux-musl.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 +330 -0
- pymoo-0.6.1.5.dev0.dist-info/WHEEL +5 -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
- pymoo.libs/libgcc_s-2298274a.so.1 +0 -0
- pymoo.libs/libstdc++-08d5c7eb.so.6.0.33 +0 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.crossover import Crossover
|
|
4
|
+
from pymoo.core.population import Population
|
|
5
|
+
from pymoo.operators.crossover.binx import mut_binomial
|
|
6
|
+
from pymoo.operators.crossover.expx import mut_exp
|
|
7
|
+
from pymoo.operators.repair.bounds_repair import is_out_of_bounds_by_problem, repair_random_init
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def de_differential(X, F, dither=None, jitter=True, gamma=0.0001, return_differentials=False):
|
|
11
|
+
n_parents, n_matings, n_var = X.shape
|
|
12
|
+
assert n_parents % 2 == 1, "For the differential an odd number of values need to be provided"
|
|
13
|
+
|
|
14
|
+
# make sure F is a one-dimensional vector
|
|
15
|
+
F = np.ones(n_matings) * F
|
|
16
|
+
|
|
17
|
+
# build the pairs for the differentials
|
|
18
|
+
pairs = (np.arange(n_parents - 1) + 1).reshape(-1, 2)
|
|
19
|
+
|
|
20
|
+
# the differentials from each pair subtraction
|
|
21
|
+
diffs = np.zeros((n_matings, n_var))
|
|
22
|
+
|
|
23
|
+
# for each difference
|
|
24
|
+
for i, j in pairs:
|
|
25
|
+
|
|
26
|
+
if dither == "vector":
|
|
27
|
+
F = (F + np.random.random(n_matings) * (1 - F))
|
|
28
|
+
elif dither == "scalar":
|
|
29
|
+
F = F + np.random.random() * (1 - F)
|
|
30
|
+
|
|
31
|
+
# http://www.cs.ndsu.nodak.edu/~siludwig/Publish/papers/SSCI20141.pdf
|
|
32
|
+
if jitter:
|
|
33
|
+
F = (F * (1 + gamma * (np.random.random(n_matings) - 0.5)))
|
|
34
|
+
|
|
35
|
+
# an add the difference to the first vector
|
|
36
|
+
diffs += F[:, None] * (X[i] - X[j])
|
|
37
|
+
|
|
38
|
+
# now add the differentials to the first parent
|
|
39
|
+
Xp = X[0] + diffs
|
|
40
|
+
|
|
41
|
+
if return_differentials:
|
|
42
|
+
return Xp, diffs
|
|
43
|
+
else:
|
|
44
|
+
return Xp
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class DEX(Crossover):
|
|
48
|
+
|
|
49
|
+
def __init__(self,
|
|
50
|
+
F=None,
|
|
51
|
+
CR=0.7,
|
|
52
|
+
variant="bin",
|
|
53
|
+
dither=None,
|
|
54
|
+
jitter=False,
|
|
55
|
+
n_diffs=1,
|
|
56
|
+
n_iter=1,
|
|
57
|
+
at_least_once=True,
|
|
58
|
+
**kwargs):
|
|
59
|
+
|
|
60
|
+
super().__init__(1 + 2 * n_diffs, 1, **kwargs)
|
|
61
|
+
self.n_diffs = n_diffs
|
|
62
|
+
self.F = F
|
|
63
|
+
self.CR = CR
|
|
64
|
+
self.variant = variant
|
|
65
|
+
self.at_least_once = at_least_once
|
|
66
|
+
self.dither = dither
|
|
67
|
+
self.jitter = jitter
|
|
68
|
+
self.n_iter = n_iter
|
|
69
|
+
|
|
70
|
+
def do(self, problem, pop, parents=None, **kwargs):
|
|
71
|
+
|
|
72
|
+
# if a parents with array with mating indices is provided -> transform the input first
|
|
73
|
+
if parents is not None:
|
|
74
|
+
pop = [pop[mating] for mating in parents]
|
|
75
|
+
|
|
76
|
+
# get the actual values from each of the parents
|
|
77
|
+
X = np.swapaxes(np.array([[parent.get("X") for parent in mating] for mating in pop]), 0, 1).copy()
|
|
78
|
+
|
|
79
|
+
n_parents, n_matings, n_var = X.shape
|
|
80
|
+
|
|
81
|
+
# a mask over matings that need to be repeated
|
|
82
|
+
m = np.arange(n_matings)
|
|
83
|
+
|
|
84
|
+
# if the user provides directly an F value to use
|
|
85
|
+
F = self.F if self.F is not None else rnd_F(m)
|
|
86
|
+
|
|
87
|
+
# prepare the out to be set
|
|
88
|
+
Xp = de_differential(X[:, m], F)
|
|
89
|
+
|
|
90
|
+
# if the problem has boundaries to be considered
|
|
91
|
+
if problem.has_bounds():
|
|
92
|
+
|
|
93
|
+
for k in range(self.n_iter):
|
|
94
|
+
# find the individuals which are still infeasible
|
|
95
|
+
m = is_out_of_bounds_by_problem(problem, Xp)
|
|
96
|
+
|
|
97
|
+
F = rnd_F(m)
|
|
98
|
+
|
|
99
|
+
# actually execute the differential equation
|
|
100
|
+
Xp[m] = de_differential(X[:, m], F)
|
|
101
|
+
|
|
102
|
+
# if still infeasible do a random initialization
|
|
103
|
+
Xp = repair_random_init(Xp, X[0], *problem.bounds())
|
|
104
|
+
|
|
105
|
+
if self.variant == "bin":
|
|
106
|
+
M = mut_binomial(n_matings, n_var, self.CR, at_least_once=self.at_least_once)
|
|
107
|
+
elif self.variant == "exp":
|
|
108
|
+
M = mut_exp(n_matings, n_var, self.CR, at_least_once=self.at_least_once)
|
|
109
|
+
else:
|
|
110
|
+
raise Exception(f"Unknown variant: {self.variant}")
|
|
111
|
+
|
|
112
|
+
# take the first parents (this is already a copy)
|
|
113
|
+
X = X[0]
|
|
114
|
+
|
|
115
|
+
# set the corresponding values from the donor vector
|
|
116
|
+
X[M] = Xp[M]
|
|
117
|
+
|
|
118
|
+
return Population.new("X", X)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def rnd_F(m):
|
|
122
|
+
return 0.5 * (1 + np.random.uniform(size=len(m)))
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.crossover import Crossover
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def remove_from_adj_list(H, val):
|
|
7
|
+
for e in list(H[val]):
|
|
8
|
+
H[e].remove(val)
|
|
9
|
+
del H[val]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def has_duplicates(x):
|
|
13
|
+
H = set()
|
|
14
|
+
for v in x:
|
|
15
|
+
if v in H:
|
|
16
|
+
return True
|
|
17
|
+
H.add(v)
|
|
18
|
+
return False
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def erx(a, b):
|
|
22
|
+
"""
|
|
23
|
+
http://www.rubicite.com/Tutorials/GeneticAlgorithms/CrossoverOperators/EdgeRecombinationCrossoverOperator.aspx
|
|
24
|
+
|
|
25
|
+
Algorithm Pseudo Code:
|
|
26
|
+
|
|
27
|
+
1. X = the first node from a random parent.
|
|
28
|
+
|
|
29
|
+
2. While the CHILD chromo isn't full, Loop:
|
|
30
|
+
- Append X to CHILD
|
|
31
|
+
- Remove X from Neighbor Lists
|
|
32
|
+
|
|
33
|
+
if X's neighbor list is empty:
|
|
34
|
+
- Xp = random node not already in CHILD
|
|
35
|
+
else
|
|
36
|
+
- Determine neighbor of X that has fewest neighbors
|
|
37
|
+
- If there is a tie, randomly choose 1
|
|
38
|
+
- Xp = chosen node
|
|
39
|
+
X = Xp
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
assert len(a) == len(b)
|
|
43
|
+
|
|
44
|
+
# calculate the edge matrix considering both permutation
|
|
45
|
+
H = calc_adjency_matrix(a)
|
|
46
|
+
H = calc_adjency_matrix(b, H=H)
|
|
47
|
+
|
|
48
|
+
# randomly select the first node
|
|
49
|
+
_next = np.random.choice(list(H.keys()))
|
|
50
|
+
|
|
51
|
+
y = []
|
|
52
|
+
while True:
|
|
53
|
+
|
|
54
|
+
# append to the child
|
|
55
|
+
y.append(_next)
|
|
56
|
+
|
|
57
|
+
# break if the child was successfully created.
|
|
58
|
+
if len(y) == len(a):
|
|
59
|
+
break
|
|
60
|
+
|
|
61
|
+
# get the neighbors to consider and remove them from the lists
|
|
62
|
+
neighbors = list(H[_next])
|
|
63
|
+
remove_from_adj_list(H, _next)
|
|
64
|
+
|
|
65
|
+
# if the current node does not have any neighbors
|
|
66
|
+
if len(neighbors) == 0:
|
|
67
|
+
_next = np.random.choice(list(H.keys()))
|
|
68
|
+
|
|
69
|
+
# otherwise search in the neighbors for a node with the fewest neighbors
|
|
70
|
+
else:
|
|
71
|
+
# search for the one with minimum neighbors
|
|
72
|
+
n_neighbors = [len(H[e]) for e in neighbors]
|
|
73
|
+
min_n_neighbors = min(n_neighbors)
|
|
74
|
+
_next = [neighbors[k] for k in range(len(neighbors)) if n_neighbors[k] == min_n_neighbors]
|
|
75
|
+
|
|
76
|
+
# break the tie if they might have the same number of neighbors
|
|
77
|
+
_next = np.random.choice(_next)
|
|
78
|
+
|
|
79
|
+
return y
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class EdgeRecombinationCrossover(Crossover):
|
|
83
|
+
|
|
84
|
+
def __init__(self, **kwargs):
|
|
85
|
+
super().__init__(2, 1, **kwargs)
|
|
86
|
+
|
|
87
|
+
def _do(self, problem, X, **kwargs):
|
|
88
|
+
_, n_matings, n_var = X.shape
|
|
89
|
+
Y = np.full((self.n_offsprings, n_matings, n_var), -1, dtype=int)
|
|
90
|
+
|
|
91
|
+
for i in range(n_matings):
|
|
92
|
+
a, b = X[:, i, :]
|
|
93
|
+
Y[0, i, :] = erx(a, b)
|
|
94
|
+
|
|
95
|
+
return Y
|
|
96
|
+
|
|
97
|
+
class ERX(EdgeRecombinationCrossover):
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
def number_to_letter(n):
|
|
101
|
+
return chr(ord('@') + n)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def numbers_to_letters(numbers):
|
|
105
|
+
return [number_to_letter(n) for n in numbers]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def letter_to_number(char):
|
|
109
|
+
return ord(char.lower()) - 96
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def letters_to_numbers(letters):
|
|
113
|
+
return np.array([letter_to_number(char) for char in letters])
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def calc_adjency_matrix(x, H=None):
|
|
117
|
+
H = {} if H is None else H
|
|
118
|
+
|
|
119
|
+
for k in range(len(x)):
|
|
120
|
+
prev = (k - 1) % len(x)
|
|
121
|
+
succ = (k + 1) % len(x)
|
|
122
|
+
|
|
123
|
+
if x[k] not in H:
|
|
124
|
+
H[x[k]] = set()
|
|
125
|
+
H[x[k]].update([x[prev], x[succ]])
|
|
126
|
+
|
|
127
|
+
return H
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
if __name__ == "__main__":
|
|
131
|
+
a = ['A', 'B', 'F', 'E', 'D', 'G', 'C']
|
|
132
|
+
b = ['G', 'F', 'A', 'B', 'C', 'D', 'E']
|
|
133
|
+
|
|
134
|
+
"""
|
|
135
|
+
A: B C F
|
|
136
|
+
B: A F C
|
|
137
|
+
C: A G B D
|
|
138
|
+
D: E G C E
|
|
139
|
+
E: F D G
|
|
140
|
+
F: B E G A
|
|
141
|
+
G: D C E F
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
H = calc_adjency_matrix(a)
|
|
145
|
+
H = calc_adjency_matrix(b, H=H)
|
|
146
|
+
|
|
147
|
+
assert len(H["A"]) == 3
|
|
148
|
+
assert 'B' in H["A"] and 'C' in H["A"] and 'F' in H["A"]
|
|
149
|
+
assert len(H["B"]) == 3
|
|
150
|
+
assert 'A' in H["B"] and 'F' in H["B"] and 'C' in H["B"]
|
|
151
|
+
assert len(H["C"]) == 4
|
|
152
|
+
assert 'A' in H["C"] and 'G' in H["C"] and 'B' in H["C"] and 'D' in H["C"]
|
|
153
|
+
assert len(H["D"]) == 3
|
|
154
|
+
assert 'E' in H["D"] and 'G' in H["D"] and 'C' in H["D"]
|
|
155
|
+
assert len(H["E"]) == 3
|
|
156
|
+
assert 'F' in H["E"] and 'D' in H["E"] and 'G' in H["E"]
|
|
157
|
+
assert len(H["F"]) == 4
|
|
158
|
+
assert 'B' in H["F"] and 'E' in H["F"] and 'G' in H["F"] and 'A' in H["F"]
|
|
159
|
+
assert len(H["G"]) == 4
|
|
160
|
+
assert 'D' in H["G"] and 'E' in H["G"] and 'E' in H["G"] and 'F' in H["G"]
|
|
161
|
+
|
|
162
|
+
c = erx(a, b)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.crossover import Crossover
|
|
4
|
+
from pymoo.core.variable import get, Real
|
|
5
|
+
from pymoo.util.misc import crossover_mask, row_at_least_once_true
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def mut_exp(n_matings, n_var, prob, at_least_once=True):
|
|
9
|
+
assert len(prob) == n_matings
|
|
10
|
+
|
|
11
|
+
# the mask do to the crossover
|
|
12
|
+
M = np.full((n_matings, n_var), False)
|
|
13
|
+
|
|
14
|
+
# start point of crossover
|
|
15
|
+
s = np.random.randint(0, n_var, size=n_matings)
|
|
16
|
+
|
|
17
|
+
# create for each individual the crossover range
|
|
18
|
+
for i in range(n_matings):
|
|
19
|
+
|
|
20
|
+
# the actual index where we start
|
|
21
|
+
start = s[i]
|
|
22
|
+
for j in range(n_var):
|
|
23
|
+
|
|
24
|
+
# the current position where we are pointing to
|
|
25
|
+
current = (start + j) % n_var
|
|
26
|
+
|
|
27
|
+
# replace only if random value keeps being smaller than CR
|
|
28
|
+
if np.random.random() <= prob[i]:
|
|
29
|
+
M[i, current] = True
|
|
30
|
+
else:
|
|
31
|
+
break
|
|
32
|
+
|
|
33
|
+
if at_least_once:
|
|
34
|
+
M = row_at_least_once_true(M)
|
|
35
|
+
|
|
36
|
+
return M
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ExponentialCrossover(Crossover):
|
|
40
|
+
|
|
41
|
+
def __init__(self, prob_exp=0.75, **kwargs):
|
|
42
|
+
super().__init__(2, 2, **kwargs)
|
|
43
|
+
self.prob_exp = Real(prob_exp, bounds=(0.5, 0.9), strict=(0.0, 1.0))
|
|
44
|
+
|
|
45
|
+
def _do(self, _, X, **kwargs):
|
|
46
|
+
_, n_matings, n_var = X.shape
|
|
47
|
+
prob_exp = get(self.prob_exp, size=n_matings)
|
|
48
|
+
|
|
49
|
+
M = mut_exp(n_matings, n_var, prob_exp, at_least_once=True)
|
|
50
|
+
_X = crossover_mask(X, M)
|
|
51
|
+
return _X
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from pymoo.core.crossover import Crossover
|
|
6
|
+
from pymoo.util.misc import crossover_mask
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class HalfUniformCrossover(Crossover):
|
|
10
|
+
|
|
11
|
+
def __init__(self, prob_hux=0.5, **kwargs):
|
|
12
|
+
super().__init__(2, 2, **kwargs)
|
|
13
|
+
self.prob_hux = prob_hux
|
|
14
|
+
|
|
15
|
+
def _do(self, _, X, **kwargs):
|
|
16
|
+
_, n_matings, n_var = X.shape
|
|
17
|
+
|
|
18
|
+
# the mask do to the crossover
|
|
19
|
+
M = np.full((n_matings, n_var), False)
|
|
20
|
+
|
|
21
|
+
not_equal = X[0] != X[1]
|
|
22
|
+
|
|
23
|
+
# create for each individual the crossover range
|
|
24
|
+
for i in range(n_matings):
|
|
25
|
+
I = np.where(not_equal[i])[0]
|
|
26
|
+
|
|
27
|
+
n = math.ceil(len(I) / 2)
|
|
28
|
+
if n > 0:
|
|
29
|
+
_I = I[np.random.permutation(len(I))[:n]]
|
|
30
|
+
M[i, _I] = True
|
|
31
|
+
|
|
32
|
+
_X = crossover_mask(X, M)
|
|
33
|
+
return _X
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class HUX(HalfUniformCrossover):
|
|
37
|
+
pass
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.crossover import Crossover
|
|
4
|
+
from pymoo.core.population import Population
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class NoCrossover(Crossover):
|
|
8
|
+
|
|
9
|
+
def __init__(self):
|
|
10
|
+
super().__init__(1, 1, 0.0)
|
|
11
|
+
|
|
12
|
+
def do(self, problem, pop, **kwargs):
|
|
13
|
+
return Population.create(*[np.random.choice(parents) for parents in pop])
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.crossover import Crossover
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def random_sequence(n):
|
|
7
|
+
start, end = np.sort(np.random.choice(n, 2, replace=False))
|
|
8
|
+
return tuple([start, end])
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def ox(receiver, donor, seq=None, shift=False):
|
|
12
|
+
"""
|
|
13
|
+
The Ordered Crossover (OX) as explained in http://www.dmi.unict.it/mpavone/nc-cs/materiale/moscato89.pdf.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
receiver : numpy.array
|
|
18
|
+
The receiver of the sequence. The array needs to be repaired after the donation took place.
|
|
19
|
+
donor : numpy.array
|
|
20
|
+
The donor of the sequence.
|
|
21
|
+
seq : tuple (optional)
|
|
22
|
+
Tuple with two problems defining the start and the end of the sequence. Please note in our implementation
|
|
23
|
+
the end of the sequence is included. The sequence is randomly chosen if not provided.
|
|
24
|
+
|
|
25
|
+
shift : bool
|
|
26
|
+
Whether during the repair the receiver should be shifted or not. Both version of it can be found in the
|
|
27
|
+
literature.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
|
|
32
|
+
y : numpy.array
|
|
33
|
+
The offspring which was created by the ordered crossover.
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
assert len(donor) == len(receiver)
|
|
37
|
+
|
|
38
|
+
# the sequence which shall be use for the crossover
|
|
39
|
+
seq = seq if seq is not None else random_sequence(len(receiver))
|
|
40
|
+
start, end = seq
|
|
41
|
+
|
|
42
|
+
# the donation and a set of it to allow a quick lookup
|
|
43
|
+
donation = np.copy(donor[start:end + 1])
|
|
44
|
+
donation_as_set = set(donation)
|
|
45
|
+
|
|
46
|
+
# the final value to be returned
|
|
47
|
+
y = []
|
|
48
|
+
|
|
49
|
+
for k in range(len(receiver)):
|
|
50
|
+
|
|
51
|
+
# do the shift starting from the swapped sequence - as proposed in the paper
|
|
52
|
+
i = k if not shift else (start + k) % len(receiver)
|
|
53
|
+
v = receiver[i]
|
|
54
|
+
|
|
55
|
+
if v not in donation_as_set:
|
|
56
|
+
y.append(v)
|
|
57
|
+
|
|
58
|
+
# now insert the donation at the right place
|
|
59
|
+
y = np.concatenate([y[:start], donation, y[start:]]).astype(copy=False, dtype=int)
|
|
60
|
+
|
|
61
|
+
return y
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class OrderCrossover(Crossover):
|
|
65
|
+
|
|
66
|
+
def __init__(self, shift=False, **kwargs):
|
|
67
|
+
super().__init__(2, 2, **kwargs)
|
|
68
|
+
self.shift = shift
|
|
69
|
+
|
|
70
|
+
def _do(self, problem, X, **kwargs):
|
|
71
|
+
_, n_matings, n_var = X.shape
|
|
72
|
+
Y = np.full((self.n_offsprings, n_matings, n_var), -1, dtype=int)
|
|
73
|
+
|
|
74
|
+
for i in range(n_matings):
|
|
75
|
+
a, b = X[:, i, :]
|
|
76
|
+
n = len(a)
|
|
77
|
+
|
|
78
|
+
# define the sequence to be used for crossover
|
|
79
|
+
start, end = random_sequence(n)
|
|
80
|
+
|
|
81
|
+
Y[0, i, :] = ox(a, b, seq=(start, end), shift=self.shift)
|
|
82
|
+
Y[1, i, :] = ox(b, a, seq=(start, end), shift=self.shift)
|
|
83
|
+
|
|
84
|
+
return Y
|
|
@@ -0,0 +1,82 @@
|
|
|
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
|
+
|
|
7
|
+
|
|
8
|
+
def pcx(X, eta, zeta, index):
|
|
9
|
+
eps = 1e-32
|
|
10
|
+
|
|
11
|
+
# the number of parents to be considered
|
|
12
|
+
n_parents, n_matings, n_var = X.shape
|
|
13
|
+
|
|
14
|
+
# calculate the differences from all parents to index parent
|
|
15
|
+
diff_to_index = X - X[index]
|
|
16
|
+
dist_to_index = np.linalg.norm(diff_to_index, axis=-1)
|
|
17
|
+
dist_to_index = np.maximum(eps, dist_to_index)
|
|
18
|
+
|
|
19
|
+
# find the centroid of the parents
|
|
20
|
+
centroid = np.mean(X, axis=0)
|
|
21
|
+
|
|
22
|
+
# calculate the difference between the centroid and the k-th parent
|
|
23
|
+
diff_to_centroid = centroid - X[index]
|
|
24
|
+
|
|
25
|
+
dist_to_centroid = np.linalg.norm(diff_to_centroid, axis=-1)
|
|
26
|
+
dist_to_centroid = np.maximum(eps, dist_to_centroid)
|
|
27
|
+
|
|
28
|
+
# orthogonal directions are computed
|
|
29
|
+
orth_dir = np.zeros_like(dist_to_index)
|
|
30
|
+
|
|
31
|
+
for i in range(n_parents):
|
|
32
|
+
if i != index:
|
|
33
|
+
temp1 = (diff_to_index[i] * diff_to_centroid).sum(axis=-1)
|
|
34
|
+
temp2 = temp1 / (dist_to_index[i] * dist_to_centroid)
|
|
35
|
+
temp3 = np.maximum(0.0, 1.0 - temp2 ** 2)
|
|
36
|
+
orth_dir[i] = dist_to_index[i] * (temp3 ** 0.5)
|
|
37
|
+
|
|
38
|
+
# this is the avg of the perpendicular distances from other parents to the parent k
|
|
39
|
+
D_not = orth_dir.sum(axis=0) / (n_parents - 1)
|
|
40
|
+
|
|
41
|
+
# generating zero-mean normally distributed variables
|
|
42
|
+
sigma = D_not[:, None] * eta.repeat(n_var, axis=1)
|
|
43
|
+
rnd = np.random.normal(loc=0.0, scale=sigma)
|
|
44
|
+
|
|
45
|
+
# implemented just like the c code - generate_new.h file
|
|
46
|
+
inner_prod = np.sum(rnd * diff_to_centroid, axis=-1, keepdims=True)
|
|
47
|
+
noise = rnd - (inner_prod * diff_to_centroid) / dist_to_centroid[:, None] ** 2
|
|
48
|
+
|
|
49
|
+
bias_to_centroid = np.random.normal(0.0, zeta) * diff_to_centroid
|
|
50
|
+
|
|
51
|
+
# the array which is finally returned
|
|
52
|
+
Xp = X[index] + noise + bias_to_centroid
|
|
53
|
+
|
|
54
|
+
return Xp
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class ParentCentricCrossover(Crossover):
|
|
58
|
+
def __init__(self,
|
|
59
|
+
eta=0.1,
|
|
60
|
+
zeta=0.1,
|
|
61
|
+
**kwargs):
|
|
62
|
+
|
|
63
|
+
super().__init__(n_parents=3, n_offsprings=1, **kwargs)
|
|
64
|
+
self.eta = Real(eta, bounds=(0.01, 0.3))
|
|
65
|
+
self.zeta = Real(zeta, bounds=(0.01, 0.3))
|
|
66
|
+
|
|
67
|
+
def _do(self, problem, X, params=None, **kwargs):
|
|
68
|
+
n_parents, n_matings, n_var = X.shape
|
|
69
|
+
zeta, eta = get(self.zeta, self.eta, size=(n_matings, 1))
|
|
70
|
+
|
|
71
|
+
index = 0
|
|
72
|
+
|
|
73
|
+
Xp = pcx(X, eta, zeta, index=index)
|
|
74
|
+
|
|
75
|
+
if problem.has_bounds():
|
|
76
|
+
Xp = repair_random_init(Xp, X[index], *problem.bounds())
|
|
77
|
+
|
|
78
|
+
return Xp[None, :]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class PCX(ParentCentricCrossover):
|
|
82
|
+
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, **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.row_stack([np.random.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)
|