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
pymoo/core/infill.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from pymoo.core.duplicate import NoDuplicateElimination
|
|
2
|
+
from pymoo.core.population import Population
|
|
3
|
+
from pymoo.core.repair import NoRepair
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class InfillCriterion:
|
|
7
|
+
|
|
8
|
+
def __init__(self,
|
|
9
|
+
repair=None,
|
|
10
|
+
eliminate_duplicates=None,
|
|
11
|
+
n_max_iterations=100,
|
|
12
|
+
**kwargs):
|
|
13
|
+
|
|
14
|
+
super().__init__()
|
|
15
|
+
self.n_max_iterations = n_max_iterations
|
|
16
|
+
self.eliminate_duplicates = eliminate_duplicates if eliminate_duplicates is not None else NoDuplicateElimination()
|
|
17
|
+
self.repair = repair if repair is not None else NoRepair()
|
|
18
|
+
|
|
19
|
+
def __call__(self, problem, pop, n_offsprings, random_state=None, **kwargs):
|
|
20
|
+
return self.do(problem, pop, n_offsprings, random_state=random_state, **kwargs)
|
|
21
|
+
|
|
22
|
+
def do(self, problem, pop, n_offsprings, random_state=None, n_max_iterations=None, **kwargs):
|
|
23
|
+
if n_max_iterations is None:
|
|
24
|
+
n_max_iterations = self.n_max_iterations
|
|
25
|
+
|
|
26
|
+
# the population object to be used
|
|
27
|
+
off = Population.create()
|
|
28
|
+
|
|
29
|
+
# infill counter - counts how often the mating needs to be done to fill up n_offsprings
|
|
30
|
+
n_infills = 0
|
|
31
|
+
|
|
32
|
+
# iterate until enough offsprings are created
|
|
33
|
+
while len(off) < n_offsprings:
|
|
34
|
+
|
|
35
|
+
# how many offsprings are remaining to be created
|
|
36
|
+
n_remaining = n_offsprings - len(off)
|
|
37
|
+
|
|
38
|
+
# do the mating
|
|
39
|
+
_off = self._do(problem, pop, n_remaining, random_state=random_state, **kwargs)
|
|
40
|
+
|
|
41
|
+
# repair the individuals if necessary - disabled if repair is NoRepair
|
|
42
|
+
_off = self.repair(problem, _off, random_state=random_state, **kwargs)
|
|
43
|
+
|
|
44
|
+
# eliminate the duplicates
|
|
45
|
+
_off = self.eliminate_duplicates.do(_off, pop, off)
|
|
46
|
+
|
|
47
|
+
# if more offsprings than necessary - truncate them randomly
|
|
48
|
+
if len(off) + len(_off) > n_offsprings:
|
|
49
|
+
|
|
50
|
+
# IMPORTANT: Interestingly, this makes a difference in performance for some algorithms
|
|
51
|
+
n_remaining = n_offsprings - len(off)
|
|
52
|
+
_off = _off[:n_remaining]
|
|
53
|
+
|
|
54
|
+
# add to the offsprings and increase the mating counter
|
|
55
|
+
off = Population.merge(off, _off)
|
|
56
|
+
n_infills += 1
|
|
57
|
+
|
|
58
|
+
# if no new offsprings can be generated within a pre-specified number of generations
|
|
59
|
+
if n_infills >= n_max_iterations:
|
|
60
|
+
break
|
|
61
|
+
|
|
62
|
+
return off
|
|
63
|
+
|
|
64
|
+
def _do(self, problem, pop, n_offsprings, random_state=None, **kwargs):
|
|
65
|
+
pass
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.duplicate import NoDuplicateElimination
|
|
4
|
+
from pymoo.core.population import Population
|
|
5
|
+
from pymoo.core.repair import NoRepair
|
|
6
|
+
from pymoo.util import default_random_state
|
|
7
|
+
from pymoo.util.misc import at_least_2d_array
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Initialization:
|
|
11
|
+
|
|
12
|
+
def __init__(self,
|
|
13
|
+
sampling,
|
|
14
|
+
repair=None,
|
|
15
|
+
eliminate_duplicates=None) -> None:
|
|
16
|
+
|
|
17
|
+
super().__init__()
|
|
18
|
+
self.sampling = sampling
|
|
19
|
+
self.eliminate_duplicates = eliminate_duplicates if eliminate_duplicates else NoDuplicateElimination()
|
|
20
|
+
self.repair = repair if repair is not None else NoRepair()
|
|
21
|
+
|
|
22
|
+
@default_random_state
|
|
23
|
+
def do(self, problem, n_samples, random_state=None, **kwargs):
|
|
24
|
+
|
|
25
|
+
# provide a whole population object - (individuals might be already evaluated)
|
|
26
|
+
if isinstance(self.sampling, Population):
|
|
27
|
+
pop = self.sampling
|
|
28
|
+
|
|
29
|
+
else:
|
|
30
|
+
if isinstance(self.sampling, np.ndarray):
|
|
31
|
+
sampling = at_least_2d_array(self.sampling)
|
|
32
|
+
pop = Population.new(X=sampling)
|
|
33
|
+
else:
|
|
34
|
+
pop = self.sampling(problem, n_samples, random_state=random_state, **kwargs)
|
|
35
|
+
|
|
36
|
+
# repair all solutions that are not already evaluated
|
|
37
|
+
not_eval_yet = [k for k in range(len(pop)) if len(pop[k].evaluated) == 0]
|
|
38
|
+
if len(not_eval_yet) > 0:
|
|
39
|
+
pop[not_eval_yet] = self.repair(problem, pop[not_eval_yet], random_state=random_state, **kwargs)
|
|
40
|
+
|
|
41
|
+
# filter duplicate in the population
|
|
42
|
+
pop = self.eliminate_duplicates.do(pop)
|
|
43
|
+
|
|
44
|
+
return pop
|
pymoo/core/mating.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
from pymoo.core.infill import InfillCriterion
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Mating(InfillCriterion):
|
|
7
|
+
|
|
8
|
+
def __init__(self,
|
|
9
|
+
selection,
|
|
10
|
+
crossover,
|
|
11
|
+
mutation,
|
|
12
|
+
**kwargs):
|
|
13
|
+
|
|
14
|
+
super().__init__(**kwargs)
|
|
15
|
+
self.selection = selection
|
|
16
|
+
self.crossover = crossover
|
|
17
|
+
self.mutation = mutation
|
|
18
|
+
|
|
19
|
+
def _do(self, problem, pop, n_offsprings, parents=None, random_state=None, **kwargs):
|
|
20
|
+
|
|
21
|
+
# how many parents need to be select for the mating - depending on number of offsprings remaining
|
|
22
|
+
n_matings = math.ceil(n_offsprings / self.crossover.n_offsprings)
|
|
23
|
+
|
|
24
|
+
# if the parents for the mating are not provided directly - usually selection will be used
|
|
25
|
+
if parents is None:
|
|
26
|
+
|
|
27
|
+
# select the parents for the mating - just an index array
|
|
28
|
+
parents = self.selection(problem, pop, n_matings, n_parents=self.crossover.n_parents, random_state=random_state, **kwargs)
|
|
29
|
+
|
|
30
|
+
# do the crossover using the parents index and the population - additional data provided if necessary
|
|
31
|
+
off = self.crossover(problem, parents, random_state=random_state, **kwargs)
|
|
32
|
+
|
|
33
|
+
# do the mutation on the offsprings created through crossover
|
|
34
|
+
off = self.mutation(problem, off, random_state=random_state, **kwargs)
|
|
35
|
+
|
|
36
|
+
return off
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
pymoo/core/meta.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from copy import deepcopy
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Meta(object):
|
|
5
|
+
|
|
6
|
+
def __init__(self, object, copy=True, clazz=None):
|
|
7
|
+
if clazz is None:
|
|
8
|
+
clazz = self.__class__
|
|
9
|
+
|
|
10
|
+
wrapped = object
|
|
11
|
+
if copy:
|
|
12
|
+
wrapped = deepcopy(wrapped)
|
|
13
|
+
|
|
14
|
+
self.__class__ = type(clazz.__name__,
|
|
15
|
+
tuple([clazz] + wrapped.__class__.mro()),
|
|
16
|
+
{})
|
|
17
|
+
|
|
18
|
+
self.__dict__ = wrapped.__dict__
|
|
19
|
+
self.__object__ = object
|
|
20
|
+
self.__super__ = wrapped
|
|
21
|
+
|
pymoo/core/mixed.py
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from pymoo.algorithms.base.genetic import GeneticAlgorithm
|
|
6
|
+
from pymoo.algorithms.soo.nonconvex.ga import FitnessSurvival
|
|
7
|
+
from pymoo.core.duplicate import ElementwiseDuplicateElimination
|
|
8
|
+
from pymoo.core.individual import Individual
|
|
9
|
+
from pymoo.core.infill import InfillCriterion
|
|
10
|
+
from pymoo.core.population import Population
|
|
11
|
+
from pymoo.core.problem import Problem
|
|
12
|
+
from pymoo.core.sampling import Sampling
|
|
13
|
+
from pymoo.core.variable import Choice, Real, Integer, Binary
|
|
14
|
+
from pymoo.operators.crossover.sbx import SBX
|
|
15
|
+
from pymoo.operators.crossover.ux import UX
|
|
16
|
+
from pymoo.operators.mutation.bitflip import BFM
|
|
17
|
+
from pymoo.operators.mutation.pm import PM
|
|
18
|
+
from pymoo.operators.mutation.rm import ChoiceRandomMutation
|
|
19
|
+
from pymoo.operators.repair.rounding import RoundingRepair
|
|
20
|
+
from pymoo.operators.selection.rnd import RandomSelection
|
|
21
|
+
from pymoo.util.display.single import SingleObjectiveOutput
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class MixedVariableMating(InfillCriterion):
|
|
25
|
+
|
|
26
|
+
def __init__(self,
|
|
27
|
+
selection=RandomSelection(),
|
|
28
|
+
crossover=None,
|
|
29
|
+
mutation=None,
|
|
30
|
+
repair=None,
|
|
31
|
+
eliminate_duplicates=True,
|
|
32
|
+
n_max_iterations=100,
|
|
33
|
+
**kwargs):
|
|
34
|
+
|
|
35
|
+
super().__init__(repair, eliminate_duplicates, n_max_iterations, **kwargs)
|
|
36
|
+
|
|
37
|
+
if crossover is None:
|
|
38
|
+
crossover = {
|
|
39
|
+
Binary: UX(),
|
|
40
|
+
Real: SBX(),
|
|
41
|
+
Integer: SBX(vtype=float, repair=RoundingRepair()),
|
|
42
|
+
Choice: UX(),
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if mutation is None:
|
|
46
|
+
mutation = {
|
|
47
|
+
Binary: BFM(),
|
|
48
|
+
Real: PM(),
|
|
49
|
+
Integer: PM(vtype=float, repair=RoundingRepair()),
|
|
50
|
+
Choice: ChoiceRandomMutation(),
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
self.selection = selection
|
|
54
|
+
self.crossover = crossover
|
|
55
|
+
self.mutation = mutation
|
|
56
|
+
|
|
57
|
+
def _do(self, problem, pop, n_offsprings, parents=False, random_state=None, **kwargs):
|
|
58
|
+
|
|
59
|
+
# So far we assume all crossover need the same amount of parents and create the same number of offsprings
|
|
60
|
+
XOVER_N_PARENTS = 2
|
|
61
|
+
XOVER_N_OFFSPRINGS = 2
|
|
62
|
+
|
|
63
|
+
# the variables with the concrete information
|
|
64
|
+
vars = problem.vars
|
|
65
|
+
|
|
66
|
+
# group all the variables by their types
|
|
67
|
+
vars_by_type = {}
|
|
68
|
+
for k, v in vars.items():
|
|
69
|
+
clazz = type(v)
|
|
70
|
+
|
|
71
|
+
if clazz not in vars_by_type:
|
|
72
|
+
vars_by_type[clazz] = []
|
|
73
|
+
vars_by_type[clazz].append(k)
|
|
74
|
+
|
|
75
|
+
# # all different recombinations (the choices need to be split because of data types)
|
|
76
|
+
recomb = []
|
|
77
|
+
for clazz, list_of_vars in vars_by_type.items():
|
|
78
|
+
if clazz == Choice:
|
|
79
|
+
for e in list_of_vars:
|
|
80
|
+
recomb.append((clazz, [e]))
|
|
81
|
+
else:
|
|
82
|
+
recomb.append((clazz, list_of_vars))
|
|
83
|
+
|
|
84
|
+
# create an empty population that will be set in each iteration
|
|
85
|
+
off = Population.new(X=[{} for _ in range(n_offsprings)])
|
|
86
|
+
|
|
87
|
+
if not parents:
|
|
88
|
+
n_select = math.ceil(n_offsprings / XOVER_N_OFFSPRINGS)
|
|
89
|
+
pop = self.selection(problem, pop, n_select, XOVER_N_PARENTS, random_state=random_state, **kwargs)
|
|
90
|
+
|
|
91
|
+
for clazz, list_of_vars in recomb:
|
|
92
|
+
|
|
93
|
+
crossover = self.crossover[clazz]
|
|
94
|
+
assert crossover.n_parents == XOVER_N_PARENTS and crossover.n_offsprings == XOVER_N_OFFSPRINGS
|
|
95
|
+
|
|
96
|
+
_parents = [
|
|
97
|
+
[Individual(X=np.array([parent.X[var] for var in list_of_vars], dtype="O" if clazz is Choice else None))
|
|
98
|
+
for parent in parents]
|
|
99
|
+
for parents in pop
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
_vars = {e: vars[e] for e in list_of_vars}
|
|
103
|
+
_xl = np.array([vars[e].lb if hasattr(vars[e], "lb") else None for e in list_of_vars])
|
|
104
|
+
_xu = np.array([vars[e].ub if hasattr(vars[e], "ub") else None for e in list_of_vars])
|
|
105
|
+
_problem = Problem(vars=_vars, xl=_xl, xu=_xu)
|
|
106
|
+
|
|
107
|
+
_off = crossover(_problem, _parents, random_state=random_state, **kwargs)
|
|
108
|
+
|
|
109
|
+
mutation = self.mutation[clazz]
|
|
110
|
+
_off = mutation(_problem, _off, random_state=random_state, **kwargs)
|
|
111
|
+
|
|
112
|
+
for k in range(n_offsprings):
|
|
113
|
+
for i, name in enumerate(list_of_vars):
|
|
114
|
+
off[k].X[name] = _off[k].X[i]
|
|
115
|
+
|
|
116
|
+
return off
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class MixedVariableSampling(Sampling):
|
|
120
|
+
|
|
121
|
+
def _do(self, problem, n_samples, random_state=None, **kwargs):
|
|
122
|
+
V = {name: var.sample(n_samples, random_state=random_state) for name, var in problem.vars.items()}
|
|
123
|
+
|
|
124
|
+
X = []
|
|
125
|
+
for k in range(n_samples):
|
|
126
|
+
X.append({name: V[name][k] for name in problem.vars.keys()})
|
|
127
|
+
|
|
128
|
+
return X
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class MixedVariableDuplicateElimination(ElementwiseDuplicateElimination):
|
|
132
|
+
|
|
133
|
+
def is_equal(self, a, b):
|
|
134
|
+
a, b = a.X, b.X
|
|
135
|
+
for k, v in a.items():
|
|
136
|
+
if k not in b or b[k] != v:
|
|
137
|
+
return False
|
|
138
|
+
return True
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def groups_of_vars(vars):
|
|
142
|
+
ret = {}
|
|
143
|
+
for name, var in vars.items():
|
|
144
|
+
if var.__class__ not in ret:
|
|
145
|
+
ret[var.__class__] = []
|
|
146
|
+
|
|
147
|
+
ret[var.__class__].append((name, var))
|
|
148
|
+
|
|
149
|
+
return ret
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class MixedVariableGA(GeneticAlgorithm):
|
|
153
|
+
|
|
154
|
+
def __init__(self,
|
|
155
|
+
pop_size=50,
|
|
156
|
+
n_offsprings=None,
|
|
157
|
+
output=SingleObjectiveOutput(),
|
|
158
|
+
sampling=MixedVariableSampling(),
|
|
159
|
+
mating=MixedVariableMating(eliminate_duplicates=MixedVariableDuplicateElimination()),
|
|
160
|
+
eliminate_duplicates=MixedVariableDuplicateElimination(),
|
|
161
|
+
survival=FitnessSurvival(),
|
|
162
|
+
**kwargs):
|
|
163
|
+
super().__init__(pop_size=pop_size, n_offsprings=n_offsprings, sampling=sampling, mating=mating,
|
|
164
|
+
eliminate_duplicates=eliminate_duplicates, output=output, survival=survival, **kwargs)
|
pymoo/core/mutation.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from copy import deepcopy
|
|
2
|
+
|
|
3
|
+
from pymoo.core.operator import Operator
|
|
4
|
+
from pymoo.core.variable import Real, get
|
|
5
|
+
from pymoo.util import default_random_state
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Mutation(Operator):
|
|
9
|
+
|
|
10
|
+
def __init__(self, prob=1.0, prob_var=None, **kwargs) -> None:
|
|
11
|
+
super().__init__(**kwargs)
|
|
12
|
+
self.prob = Real(prob, bounds=(0.7, 1.0), strict=(0.0, 1.0))
|
|
13
|
+
self.prob_var = Real(prob_var, bounds=(0.0, 0.25), strict=(0.0, 1.0)) if prob_var is not None else None
|
|
14
|
+
|
|
15
|
+
@default_random_state
|
|
16
|
+
def do(self, problem, pop, inplace=True, *args, random_state=None, **kwargs):
|
|
17
|
+
|
|
18
|
+
# if not inplace copy the population first
|
|
19
|
+
if not inplace:
|
|
20
|
+
pop = deepcopy(pop)
|
|
21
|
+
|
|
22
|
+
n_mut = len(pop)
|
|
23
|
+
|
|
24
|
+
# get the variables to be mutated
|
|
25
|
+
X = pop.get("X")
|
|
26
|
+
|
|
27
|
+
# retrieve the mutation variables
|
|
28
|
+
Xp = self._do(problem, X, *args, random_state=random_state, **kwargs)
|
|
29
|
+
|
|
30
|
+
# the likelihood for a mutation on the individuals
|
|
31
|
+
prob = get(self.prob, size=n_mut)
|
|
32
|
+
mut = random_state.random(size=n_mut) <= prob
|
|
33
|
+
|
|
34
|
+
# store the mutated individual back to the population
|
|
35
|
+
pop[mut].set("X", Xp[mut])
|
|
36
|
+
|
|
37
|
+
return pop
|
|
38
|
+
|
|
39
|
+
def _do(self, problem, X, *args, random_state=None, **kwargs):
|
|
40
|
+
return X
|
|
41
|
+
|
|
42
|
+
def get_prob_var(self, problem, **kwargs):
|
|
43
|
+
prob_var = self.prob_var if self.prob_var is not None else min(0.5, 1 / problem.n_var)
|
|
44
|
+
return get(prob_var, **kwargs)
|
pymoo/core/operator.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from pymoo.util import default_random_state
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Operator:
|
|
9
|
+
|
|
10
|
+
def __init__(self,
|
|
11
|
+
name=None,
|
|
12
|
+
vtype=None,
|
|
13
|
+
repair=None) -> None:
|
|
14
|
+
|
|
15
|
+
super().__init__()
|
|
16
|
+
|
|
17
|
+
if name is None:
|
|
18
|
+
name = self.__class__.__name__
|
|
19
|
+
|
|
20
|
+
self.name = name
|
|
21
|
+
self.vtype = vtype
|
|
22
|
+
self.repair = repair
|
|
23
|
+
|
|
24
|
+
@default_random_state
|
|
25
|
+
def do(self, problem, elem, *args, random_state, **kwargs):
|
|
26
|
+
return self._do(problem, elem, *args, random_state=random_state, **kwargs)
|
|
27
|
+
|
|
28
|
+
@abc.abstractmethod
|
|
29
|
+
def _do(self, problem, elem, *args, random_state, **kwargs):
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
def __call__(self, problem, elem, *args, to_numpy=False, **kwargs):
|
|
33
|
+
out = self.do(problem, elem, *args, **kwargs)
|
|
34
|
+
|
|
35
|
+
if self.vtype is not None:
|
|
36
|
+
for ind in out:
|
|
37
|
+
ind.X = ind.X.astype(self.vtype)
|
|
38
|
+
|
|
39
|
+
# allow to have a built-in repair (can be useful to customize standard crossover)
|
|
40
|
+
if self.repair is not None:
|
|
41
|
+
self.repair.do(problem, out)
|
|
42
|
+
|
|
43
|
+
if to_numpy:
|
|
44
|
+
out = np.array([ind.X for ind in out])
|
|
45
|
+
|
|
46
|
+
return out
|
pymoo/core/parameters.py
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
from pymoo.core.variable import Variable
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
5
|
+
# Functions
|
|
6
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
def get_data(obj):
|
|
9
|
+
if not isinstance(obj, dict):
|
|
10
|
+
if hasattr(obj, "__dict__"):
|
|
11
|
+
return obj.__dict__
|
|
12
|
+
else:
|
|
13
|
+
return {}
|
|
14
|
+
else:
|
|
15
|
+
return obj
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_params(obj, flag="default", only_active=True):
|
|
19
|
+
return get_params_bfs(obj, flag, only_active)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_params_bfs(obj, flag, only_active):
|
|
23
|
+
ret = {}
|
|
24
|
+
|
|
25
|
+
q = [(None, obj)]
|
|
26
|
+
|
|
27
|
+
visited = set()
|
|
28
|
+
|
|
29
|
+
while len(q) > 0:
|
|
30
|
+
|
|
31
|
+
prefix, obj = q.pop()
|
|
32
|
+
|
|
33
|
+
if isinstance(obj, Variable):
|
|
34
|
+
|
|
35
|
+
if obj not in visited and obj.flag == flag and (not only_active or obj.active):
|
|
36
|
+
|
|
37
|
+
# find the right spot in the ret dictionary
|
|
38
|
+
e = ret
|
|
39
|
+
|
|
40
|
+
for name in prefix[:-1]:
|
|
41
|
+
if name not in e:
|
|
42
|
+
e[name] = {}
|
|
43
|
+
e = e[name]
|
|
44
|
+
|
|
45
|
+
# set it so the value
|
|
46
|
+
e[prefix[-1]] = obj
|
|
47
|
+
|
|
48
|
+
# add it to have been visited
|
|
49
|
+
visited.add(obj)
|
|
50
|
+
|
|
51
|
+
else:
|
|
52
|
+
data = get_data(obj)
|
|
53
|
+
for key in data:
|
|
54
|
+
new_prefix = [key] if prefix is None else prefix + [key]
|
|
55
|
+
entry = (new_prefix, data[key])
|
|
56
|
+
q.append(entry)
|
|
57
|
+
|
|
58
|
+
return ret
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def get_params_rec(obj, visited, flag, only_active):
|
|
62
|
+
data = get_data(obj)
|
|
63
|
+
|
|
64
|
+
ret = {}
|
|
65
|
+
for k, v in data.items():
|
|
66
|
+
if isinstance(v, Variable):
|
|
67
|
+
|
|
68
|
+
if v not in visited and v.flag == flag and (not only_active or v.active):
|
|
69
|
+
ret[k] = v
|
|
70
|
+
|
|
71
|
+
visited.add(v)
|
|
72
|
+
|
|
73
|
+
else:
|
|
74
|
+
entry = get_params_rec(v, visited, flag, only_active)
|
|
75
|
+
if entry is not None and len(entry) > 0:
|
|
76
|
+
ret[k] = entry
|
|
77
|
+
return ret
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def apply_to_params(obj, func_apply):
|
|
81
|
+
for _, v in flatten_rec(get_params(obj)):
|
|
82
|
+
func_apply(v)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def deactivate_params(obj):
|
|
86
|
+
def func(param):
|
|
87
|
+
param.active = False
|
|
88
|
+
|
|
89
|
+
apply_to_params(obj, func)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def set_params(obj, params, as_value=True):
|
|
93
|
+
data = get_data(obj)
|
|
94
|
+
|
|
95
|
+
for k, v in params.items():
|
|
96
|
+
if isinstance(v, dict):
|
|
97
|
+
set_params(data[k], v)
|
|
98
|
+
else:
|
|
99
|
+
if as_value:
|
|
100
|
+
data[k].set(v)
|
|
101
|
+
else:
|
|
102
|
+
data[k] = v
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def flatten(params):
|
|
106
|
+
return {k: v for k, v in flatten_rec(params)}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def flatten_rec(params, prefix=None):
|
|
110
|
+
if hasattr(params, "items"):
|
|
111
|
+
for k, v in params.items():
|
|
112
|
+
yield from flatten_rec(v, prefix=f"{prefix}.{k}" if prefix is not None else k)
|
|
113
|
+
else:
|
|
114
|
+
yield prefix, params
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def hierarchical(data):
|
|
118
|
+
ret = {}
|
|
119
|
+
|
|
120
|
+
groups = {}
|
|
121
|
+
for k, v in data.items():
|
|
122
|
+
a = k.split(".")
|
|
123
|
+
if len(a) > 1:
|
|
124
|
+
prefix = a[0]
|
|
125
|
+
if prefix not in groups:
|
|
126
|
+
groups[prefix] = {}
|
|
127
|
+
groups[prefix][".".join(a[1:])] = v
|
|
128
|
+
else:
|
|
129
|
+
ret[k] = v
|
|
130
|
+
|
|
131
|
+
for name, group in groups.items():
|
|
132
|
+
ret[name] = hierarchical(group)
|
|
133
|
+
|
|
134
|
+
return ret
|