pymoo 0.6.1.5.dev0__cp310-cp310-macosx_11_0_arm64.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-310-darwin.so +0 -0
- pymoo/cython/calc_perpendicular_distance.pyx +67 -0
- pymoo/cython/decomposition.cpython-310-darwin.so +0 -0
- pymoo/cython/decomposition.pyx +165 -0
- pymoo/cython/hv.cpython-310-darwin.so +0 -0
- pymoo/cython/hv.pyx +18 -0
- pymoo/cython/info.cpython-310-darwin.so +0 -0
- pymoo/cython/info.pyx +5 -0
- pymoo/cython/mnn.cpython-310-darwin.so +0 -0
- pymoo/cython/mnn.pyx +273 -0
- pymoo/cython/non_dominated_sorting.cpython-310-darwin.so +0 -0
- pymoo/cython/non_dominated_sorting.pyx +645 -0
- pymoo/cython/pruning_cd.cpython-310-darwin.so +0 -0
- pymoo/cython/pruning_cd.pyx +197 -0
- pymoo/cython/stochastic_ranking.cpython-310-darwin.so +0 -0
- pymoo/cython/stochastic_ranking.pyx +49 -0
- pymoo/cython/utils.pxd +129 -0
- pymoo/cython/vendor/__init__.py +0 -0
- pymoo/cython/vendor/hypervolume.cpp +1621 -0
- pymoo/cython/vendor/hypervolume.h +63 -0
- pymoo/decomposition/__init__.py +0 -0
- pymoo/decomposition/aasf.py +24 -0
- pymoo/decomposition/asf.py +10 -0
- pymoo/decomposition/pbi.py +13 -0
- pymoo/decomposition/perp_dist.py +13 -0
- pymoo/decomposition/tchebicheff.py +11 -0
- pymoo/decomposition/util.py +13 -0
- pymoo/decomposition/weighted_sum.py +8 -0
- pymoo/docs.py +187 -0
- pymoo/experimental/__init__.py +0 -0
- pymoo/experimental/algorithms/__init__.py +0 -0
- pymoo/experimental/algorithms/gde3.py +57 -0
- pymoo/gradient/__init__.py +21 -0
- pymoo/gradient/automatic.py +57 -0
- pymoo/gradient/grad_autograd.py +105 -0
- pymoo/gradient/grad_complex.py +35 -0
- pymoo/gradient/grad_jax.py +51 -0
- pymoo/gradient/toolbox/__init__.py +6 -0
- pymoo/indicators/__init__.py +0 -0
- pymoo/indicators/distance_indicator.py +55 -0
- pymoo/indicators/gd.py +7 -0
- pymoo/indicators/gd_plus.py +7 -0
- pymoo/indicators/hv/__init__.py +63 -0
- pymoo/indicators/hv/exact.py +71 -0
- pymoo/indicators/hv/exact_2d.py +102 -0
- pymoo/indicators/hv/monte_carlo.py +74 -0
- pymoo/indicators/igd.py +7 -0
- pymoo/indicators/igd_plus.py +7 -0
- pymoo/indicators/kktpm.py +151 -0
- pymoo/indicators/migd.py +55 -0
- pymoo/indicators/rmetric.py +203 -0
- pymoo/indicators/spacing.py +52 -0
- pymoo/mcdm/__init__.py +0 -0
- pymoo/mcdm/compromise_programming.py +19 -0
- pymoo/mcdm/high_tradeoff.py +40 -0
- pymoo/mcdm/pseudo_weights.py +32 -0
- pymoo/operators/__init__.py +0 -0
- pymoo/operators/control.py +187 -0
- pymoo/operators/crossover/__init__.py +0 -0
- pymoo/operators/crossover/binx.py +45 -0
- pymoo/operators/crossover/dex.py +122 -0
- pymoo/operators/crossover/erx.py +162 -0
- pymoo/operators/crossover/expx.py +51 -0
- pymoo/operators/crossover/hux.py +37 -0
- pymoo/operators/crossover/nox.py +13 -0
- pymoo/operators/crossover/ox.py +84 -0
- pymoo/operators/crossover/pcx.py +82 -0
- pymoo/operators/crossover/pntx.py +49 -0
- pymoo/operators/crossover/sbx.py +125 -0
- pymoo/operators/crossover/spx.py +5 -0
- pymoo/operators/crossover/ux.py +20 -0
- pymoo/operators/mutation/__init__.py +0 -0
- pymoo/operators/mutation/bitflip.py +17 -0
- pymoo/operators/mutation/gauss.py +58 -0
- pymoo/operators/mutation/inversion.py +42 -0
- pymoo/operators/mutation/nom.py +7 -0
- pymoo/operators/mutation/pm.py +94 -0
- pymoo/operators/mutation/rm.py +23 -0
- pymoo/operators/repair/__init__.py +0 -0
- pymoo/operators/repair/bounce_back.py +32 -0
- pymoo/operators/repair/bounds_repair.py +95 -0
- pymoo/operators/repair/inverse_penalty.py +89 -0
- pymoo/operators/repair/rounding.py +18 -0
- pymoo/operators/repair/to_bound.py +31 -0
- pymoo/operators/repair/vtype.py +11 -0
- pymoo/operators/sampling/__init__.py +0 -0
- pymoo/operators/sampling/lhs.py +73 -0
- pymoo/operators/sampling/rnd.py +50 -0
- pymoo/operators/selection/__init__.py +0 -0
- pymoo/operators/selection/rnd.py +72 -0
- pymoo/operators/selection/tournament.py +76 -0
- pymoo/operators/survival/__init__.py +0 -0
- pymoo/operators/survival/rank_and_crowding/__init__.py +1 -0
- pymoo/operators/survival/rank_and_crowding/classes.py +209 -0
- pymoo/operators/survival/rank_and_crowding/metrics.py +208 -0
- pymoo/optimize.py +72 -0
- pymoo/problems/__init__.py +157 -0
- pymoo/problems/dyn.py +47 -0
- pymoo/problems/dynamic/__init__.py +0 -0
- pymoo/problems/dynamic/cec2015.py +108 -0
- pymoo/problems/dynamic/df.py +452 -0
- pymoo/problems/dynamic/misc.py +167 -0
- pymoo/problems/functional.py +48 -0
- pymoo/problems/many/__init__.py +5 -0
- pymoo/problems/many/cdtlz.py +159 -0
- pymoo/problems/many/dcdtlz.py +88 -0
- pymoo/problems/many/dtlz.py +264 -0
- pymoo/problems/many/wfg.py +550 -0
- pymoo/problems/multi/__init__.py +14 -0
- pymoo/problems/multi/bnh.py +34 -0
- pymoo/problems/multi/carside.py +48 -0
- pymoo/problems/multi/clutch.py +104 -0
- pymoo/problems/multi/csi.py +55 -0
- pymoo/problems/multi/ctp.py +198 -0
- pymoo/problems/multi/dascmop.py +213 -0
- pymoo/problems/multi/kursawe.py +25 -0
- pymoo/problems/multi/modact.py +68 -0
- pymoo/problems/multi/mw.py +400 -0
- pymoo/problems/multi/omnitest.py +48 -0
- pymoo/problems/multi/osy.py +32 -0
- pymoo/problems/multi/srn.py +28 -0
- pymoo/problems/multi/sympart.py +94 -0
- pymoo/problems/multi/tnk.py +24 -0
- pymoo/problems/multi/truss2d.py +83 -0
- pymoo/problems/multi/welded_beam.py +41 -0
- pymoo/problems/multi/wrm.py +36 -0
- pymoo/problems/multi/zdt.py +151 -0
- pymoo/problems/multi_to_single.py +22 -0
- pymoo/problems/single/__init__.py +12 -0
- pymoo/problems/single/ackley.py +24 -0
- pymoo/problems/single/cantilevered_beam.py +34 -0
- pymoo/problems/single/flowshop_scheduling.py +112 -0
- pymoo/problems/single/g.py +874 -0
- pymoo/problems/single/griewank.py +18 -0
- pymoo/problems/single/himmelblau.py +15 -0
- pymoo/problems/single/knapsack.py +48 -0
- pymoo/problems/single/mopta08.py +26 -0
- pymoo/problems/single/multimodal.py +20 -0
- pymoo/problems/single/pressure_vessel.py +30 -0
- pymoo/problems/single/rastrigin.py +20 -0
- pymoo/problems/single/rosenbrock.py +22 -0
- pymoo/problems/single/schwefel.py +18 -0
- pymoo/problems/single/simple.py +13 -0
- pymoo/problems/single/sphere.py +19 -0
- pymoo/problems/single/traveling_salesman.py +79 -0
- pymoo/problems/single/zakharov.py +19 -0
- pymoo/problems/static.py +14 -0
- pymoo/problems/util.py +42 -0
- pymoo/problems/zero_to_one.py +27 -0
- pymoo/termination/__init__.py +23 -0
- pymoo/termination/collection.py +12 -0
- pymoo/termination/cv.py +48 -0
- pymoo/termination/default.py +45 -0
- pymoo/termination/delta.py +64 -0
- pymoo/termination/fmin.py +16 -0
- pymoo/termination/ftol.py +144 -0
- pymoo/termination/indicator.py +49 -0
- pymoo/termination/max_eval.py +14 -0
- pymoo/termination/max_gen.py +15 -0
- pymoo/termination/max_time.py +20 -0
- pymoo/termination/robust.py +34 -0
- pymoo/termination/xtol.py +33 -0
- pymoo/util/__init__.py +0 -0
- pymoo/util/archive.py +150 -0
- pymoo/util/cache.py +29 -0
- pymoo/util/clearing.py +82 -0
- pymoo/util/display/__init__.py +0 -0
- pymoo/util/display/column.py +52 -0
- pymoo/util/display/display.py +34 -0
- pymoo/util/display/multi.py +96 -0
- pymoo/util/display/output.py +53 -0
- pymoo/util/display/progress.py +54 -0
- pymoo/util/display/single.py +67 -0
- pymoo/util/dominator.py +67 -0
- pymoo/util/function_loader.py +129 -0
- pymoo/util/hv.py +23 -0
- pymoo/util/matlab_engine.py +39 -0
- pymoo/util/misc.py +460 -0
- pymoo/util/mnn.py +70 -0
- pymoo/util/nds/__init__.py +0 -0
- pymoo/util/nds/dominance_degree_non_dominated_sort.py +159 -0
- pymoo/util/nds/efficient_non_dominated_sort.py +152 -0
- pymoo/util/nds/fast_non_dominated_sort.py +70 -0
- pymoo/util/nds/naive_non_dominated_sort.py +36 -0
- pymoo/util/nds/non_dominated_sorting.py +67 -0
- pymoo/util/nds/tree_based_non_dominated_sort.py +133 -0
- pymoo/util/normalization.py +312 -0
- pymoo/util/optimum.py +42 -0
- pymoo/util/plotting.py +177 -0
- pymoo/util/pruning_cd.py +89 -0
- pymoo/util/randomized_argsort.py +60 -0
- pymoo/util/ref_dirs/__init__.py +24 -0
- pymoo/util/ref_dirs/construction.py +88 -0
- pymoo/util/ref_dirs/das_dennis.py +52 -0
- pymoo/util/ref_dirs/energy.py +319 -0
- pymoo/util/ref_dirs/energy_layer.py +119 -0
- pymoo/util/ref_dirs/genetic_algorithm.py +63 -0
- pymoo/util/ref_dirs/incremental.py +68 -0
- pymoo/util/ref_dirs/misc.py +128 -0
- pymoo/util/ref_dirs/optimizer.py +59 -0
- pymoo/util/ref_dirs/performance.py +162 -0
- pymoo/util/ref_dirs/reduction.py +85 -0
- pymoo/util/ref_dirs/sample_and_map.py +24 -0
- pymoo/util/reference_direction.py +260 -0
- pymoo/util/remote.py +55 -0
- pymoo/util/roulette.py +27 -0
- pymoo/util/running_metric.py +128 -0
- pymoo/util/sliding_window.py +25 -0
- pymoo/util/stochastic_ranking.py +32 -0
- pymoo/util/value_functions.py +719 -0
- pymoo/util/vectors.py +40 -0
- pymoo/util/vf_dominator.py +99 -0
- pymoo/vendor/__init__.py +0 -0
- pymoo/vendor/cec2018.py +398 -0
- pymoo/vendor/gta.py +617 -0
- pymoo/vendor/hv.py +267 -0
- pymoo/vendor/vendor_cmaes.py +412 -0
- pymoo/vendor/vendor_coco.py +81 -0
- pymoo/vendor/vendor_scipy.py +232 -0
- pymoo/version.py +1 -0
- pymoo/visualization/__init__.py +8 -0
- pymoo/visualization/fitness_landscape.py +127 -0
- pymoo/visualization/heatmap.py +123 -0
- pymoo/visualization/pcp.py +120 -0
- pymoo/visualization/petal.py +91 -0
- pymoo/visualization/radar.py +108 -0
- pymoo/visualization/radviz.py +68 -0
- pymoo/visualization/scatter.py +150 -0
- pymoo/visualization/star_coordinate.py +75 -0
- pymoo/visualization/util.py +123 -0
- pymoo/visualization/video/__init__.py +0 -0
- pymoo/visualization/video/callback_video.py +82 -0
- pymoo/visualization/video/one_var_one_obj.py +57 -0
- pymoo/visualization/video/two_var_one_obj.py +62 -0
- pymoo-0.6.1.5.dev0.dist-info/METADATA +187 -0
- pymoo-0.6.1.5.dev0.dist-info/RECORD +328 -0
- pymoo-0.6.1.5.dev0.dist-info/WHEEL +6 -0
- pymoo-0.6.1.5.dev0.dist-info/licenses/LICENSE +191 -0
- pymoo-0.6.1.5.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from scipy import special
|
|
5
|
+
|
|
6
|
+
from pymoo.util.misc import find_duplicates, cdist
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# =========================================================================================================
|
|
10
|
+
# Model
|
|
11
|
+
# =========================================================================================================
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def default_ref_dirs(m):
|
|
15
|
+
if m == 1:
|
|
16
|
+
return np.array([[1.0]])
|
|
17
|
+
elif m == 2:
|
|
18
|
+
return UniformReferenceDirectionFactory(m, n_partitions=99).do()
|
|
19
|
+
elif m == 3:
|
|
20
|
+
return UniformReferenceDirectionFactory(m, n_partitions=12).do()
|
|
21
|
+
else:
|
|
22
|
+
raise Exception("No default reference directions for more than 3 objectives. Please provide them directly:"
|
|
23
|
+
"https://pymoo.org/misc/reference_directions.html")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ReferenceDirectionFactory:
|
|
27
|
+
|
|
28
|
+
def __init__(self, n_dim, scaling=None, lexsort=True, verbose=False, seed=None, **kwargs) -> None:
|
|
29
|
+
super().__init__()
|
|
30
|
+
self.n_dim = n_dim
|
|
31
|
+
self.scaling = scaling
|
|
32
|
+
self.lexsort = lexsort
|
|
33
|
+
self.verbose = verbose
|
|
34
|
+
self.seed = seed
|
|
35
|
+
|
|
36
|
+
def __call__(self):
|
|
37
|
+
return self.do()
|
|
38
|
+
|
|
39
|
+
def do(self):
|
|
40
|
+
|
|
41
|
+
# set the random seed if it is provided
|
|
42
|
+
if self.seed is not None:
|
|
43
|
+
np.random.seed(self.seed)
|
|
44
|
+
|
|
45
|
+
if self.n_dim == 1:
|
|
46
|
+
return np.array([[1.0]])
|
|
47
|
+
else:
|
|
48
|
+
|
|
49
|
+
val = self._do()
|
|
50
|
+
if isinstance(val, tuple):
|
|
51
|
+
ref_dirs, other = val[0], val[1:]
|
|
52
|
+
else:
|
|
53
|
+
ref_dirs = val
|
|
54
|
+
|
|
55
|
+
if self.scaling is not None:
|
|
56
|
+
ref_dirs = scale_reference_directions(ref_dirs, self.scaling)
|
|
57
|
+
|
|
58
|
+
# do ref_dirs is desired
|
|
59
|
+
if self.lexsort:
|
|
60
|
+
I = np.lexsort([ref_dirs[:, j] for j in range(ref_dirs.shape[1])][::-1])
|
|
61
|
+
ref_dirs = ref_dirs[I]
|
|
62
|
+
|
|
63
|
+
return ref_dirs
|
|
64
|
+
|
|
65
|
+
def _do(self):
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# =========================================================================================================
|
|
70
|
+
# Das Dennis Reference Directions (Uniform)
|
|
71
|
+
# =========================================================================================================
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_number_of_uniform_points(n_partitions, n_dim):
|
|
75
|
+
"""
|
|
76
|
+
Returns the number of uniform points that can be created uniformly.
|
|
77
|
+
"""
|
|
78
|
+
return int(special.binom(n_dim + n_partitions - 1, n_partitions))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def get_partition_closest_to_points(n_points, n_dim):
|
|
82
|
+
"""
|
|
83
|
+
Returns the corresponding partition number which create the desired number of points
|
|
84
|
+
or less!
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
if n_dim == 1:
|
|
88
|
+
return 0
|
|
89
|
+
|
|
90
|
+
n_partitions = 1
|
|
91
|
+
_n_points = get_number_of_uniform_points(n_partitions, n_dim)
|
|
92
|
+
while _n_points <= n_points:
|
|
93
|
+
n_partitions += 1
|
|
94
|
+
_n_points = get_number_of_uniform_points(n_partitions, n_dim)
|
|
95
|
+
return n_partitions - 1
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def das_dennis(n_partitions, n_dim):
|
|
99
|
+
if n_partitions == 0:
|
|
100
|
+
return np.full((1, n_dim), 1 / n_dim)
|
|
101
|
+
else:
|
|
102
|
+
ref_dirs = []
|
|
103
|
+
ref_dir = np.full(n_dim, np.nan)
|
|
104
|
+
das_dennis_recursion(ref_dirs, ref_dir, n_partitions, n_partitions, 0)
|
|
105
|
+
return np.concatenate(ref_dirs, axis=0)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def das_dennis_recursion(ref_dirs, ref_dir, n_partitions, beta, depth):
|
|
109
|
+
if depth == len(ref_dir) - 1:
|
|
110
|
+
ref_dir[depth] = beta / (1.0 * n_partitions)
|
|
111
|
+
ref_dirs.append(ref_dir[None, :])
|
|
112
|
+
else:
|
|
113
|
+
for i in range(beta + 1):
|
|
114
|
+
ref_dir[depth] = 1.0 * i / (1.0 * n_partitions)
|
|
115
|
+
das_dennis_recursion(ref_dirs, np.copy(ref_dir), n_partitions, beta - i, depth + 1)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class UniformReferenceDirectionFactory(ReferenceDirectionFactory):
|
|
119
|
+
|
|
120
|
+
def __init__(self, n_dim, scaling=None, n_points=None, n_partitions=None, **kwargs) -> None:
|
|
121
|
+
super().__init__(n_dim, scaling=scaling, **kwargs)
|
|
122
|
+
|
|
123
|
+
if n_points is not None:
|
|
124
|
+
n_partitions = get_partition_closest_to_points(n_points, n_dim)
|
|
125
|
+
results_in = get_number_of_uniform_points(n_partitions, n_dim)
|
|
126
|
+
|
|
127
|
+
# the number of points are not matching to any partition number
|
|
128
|
+
if results_in != n_points:
|
|
129
|
+
results_in_next = get_number_of_uniform_points(n_partitions + 1, n_dim)
|
|
130
|
+
raise Exception("The number of points (n_points = %s) can not be created uniformly.\n"
|
|
131
|
+
"Either choose n_points = %s (n_partitions = %s) or "
|
|
132
|
+
"n_points = %s (n_partitions = %s)." %
|
|
133
|
+
(n_points, results_in, n_partitions, results_in_next, n_partitions + 1))
|
|
134
|
+
|
|
135
|
+
self.n_partitions = n_partitions
|
|
136
|
+
|
|
137
|
+
elif n_partitions is not None:
|
|
138
|
+
self.n_partitions = n_partitions
|
|
139
|
+
|
|
140
|
+
else:
|
|
141
|
+
raise Exception("Either provide number of partitions or number of points.")
|
|
142
|
+
|
|
143
|
+
def _do(self):
|
|
144
|
+
return das_dennis(self.n_partitions, self.n_dim)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
# =========================================================================================================
|
|
148
|
+
# Multi Layer
|
|
149
|
+
# =========================================================================================================
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class MultiLayerReferenceDirectionFactory:
|
|
153
|
+
|
|
154
|
+
def __init__(self, *args) -> None:
|
|
155
|
+
self.layers = []
|
|
156
|
+
self.layers.extend(args)
|
|
157
|
+
|
|
158
|
+
def __call__(self):
|
|
159
|
+
return self.do()
|
|
160
|
+
|
|
161
|
+
def add_layer(self, *args):
|
|
162
|
+
self.layers.extend(args)
|
|
163
|
+
|
|
164
|
+
def do(self):
|
|
165
|
+
ref_dirs = []
|
|
166
|
+
for factory in self.layers:
|
|
167
|
+
ref_dirs.append(factory)
|
|
168
|
+
ref_dirs = np.concatenate(ref_dirs, axis=0)
|
|
169
|
+
is_duplicate = find_duplicates(ref_dirs)
|
|
170
|
+
return ref_dirs[np.logical_not(is_duplicate)]
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
# =========================================================================================================
|
|
174
|
+
# Util
|
|
175
|
+
# =========================================================================================================
|
|
176
|
+
|
|
177
|
+
def get_rng(seed=None):
|
|
178
|
+
if seed is None or type(seed) == int:
|
|
179
|
+
rng = np.random.default_rng(seed)
|
|
180
|
+
return rng
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def sample_on_unit_simplex(n_points, n_dim, unit_simplex_mapping="kraemer", seed=None):
|
|
184
|
+
if unit_simplex_mapping == "sum":
|
|
185
|
+
rnd = map_onto_unit_simplex(get_rng(seed).random((n_points, n_dim)), "sum")
|
|
186
|
+
|
|
187
|
+
elif unit_simplex_mapping == "kraemer":
|
|
188
|
+
rnd = map_onto_unit_simplex(get_rng(seed).random((n_points, n_dim)), "kraemer")
|
|
189
|
+
|
|
190
|
+
elif unit_simplex_mapping == "das-dennis":
|
|
191
|
+
n_partitions = get_partition_closest_to_points(n_points, n_dim)
|
|
192
|
+
rnd = UniformReferenceDirectionFactory(n_dim, n_partitions=n_partitions).do()
|
|
193
|
+
|
|
194
|
+
else:
|
|
195
|
+
raise Exception("Please define a valid sampling on unit simplex strategy!")
|
|
196
|
+
|
|
197
|
+
return rnd
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def map_onto_unit_simplex(rnd, method):
|
|
201
|
+
n_points, n_dim = rnd.shape
|
|
202
|
+
|
|
203
|
+
if method == "sum":
|
|
204
|
+
ret = rnd / rnd.sum(axis=1)[:, None]
|
|
205
|
+
|
|
206
|
+
elif method == "kraemer":
|
|
207
|
+
M = sys.maxsize
|
|
208
|
+
|
|
209
|
+
rnd *= M
|
|
210
|
+
rnd = rnd[:, :n_dim - 1]
|
|
211
|
+
rnd = np.column_stack([np.zeros(n_points), rnd, np.full(n_points, M)])
|
|
212
|
+
|
|
213
|
+
rnd = np.sort(rnd, axis=1)
|
|
214
|
+
|
|
215
|
+
ret = np.full((n_points, n_dim), np.nan)
|
|
216
|
+
for i in range(1, n_dim + 1):
|
|
217
|
+
ret[:, i - 1] = rnd[:, i] - rnd[:, i - 1]
|
|
218
|
+
ret /= M
|
|
219
|
+
|
|
220
|
+
else:
|
|
221
|
+
raise Exception("Invalid unit simplex mapping!")
|
|
222
|
+
|
|
223
|
+
return ret
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def scale_reference_directions(ref_dirs, scaling):
|
|
227
|
+
return ref_dirs * scaling + ((1 - scaling) / ref_dirs.shape[1])
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def select_points_with_maximum_distance(X, n_select, selected=[]):
|
|
231
|
+
n_points, n_dim = X.shape
|
|
232
|
+
|
|
233
|
+
# calculate the distance matrix
|
|
234
|
+
D = cdist(X, X)
|
|
235
|
+
|
|
236
|
+
# if no selection provided pick randomly in the beginning
|
|
237
|
+
if len(selected) == 0:
|
|
238
|
+
selected = [np.random.randint(len(X))]
|
|
239
|
+
|
|
240
|
+
# create variables to store what selected and what not
|
|
241
|
+
not_selected = [i for i in range(n_points) if i not in selected]
|
|
242
|
+
|
|
243
|
+
# remove unnecessary points
|
|
244
|
+
dist_to_closest_selected = D[:, selected].min(axis=1)
|
|
245
|
+
|
|
246
|
+
# now select the points until sufficient ones are found
|
|
247
|
+
while len(selected) < n_select:
|
|
248
|
+
# find point that has the maximum distance to all others
|
|
249
|
+
index_in_not_selected = dist_to_closest_selected[not_selected].argmax()
|
|
250
|
+
I = not_selected[index_in_not_selected]
|
|
251
|
+
|
|
252
|
+
# add the closest distance to selected point
|
|
253
|
+
is_closer = D[I] < dist_to_closest_selected
|
|
254
|
+
dist_to_closest_selected[is_closer] = D[I][is_closer]
|
|
255
|
+
|
|
256
|
+
# add it to the selected and remove from not selected
|
|
257
|
+
selected.append(I)
|
|
258
|
+
not_selected = np.delete(not_selected, index_in_not_selected)
|
|
259
|
+
|
|
260
|
+
return selected
|
pymoo/util/remote.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import urllib.request
|
|
4
|
+
from os.path import join, dirname, abspath
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from pymoo.config import Config
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Remote:
|
|
12
|
+
# -------------------------------------------------
|
|
13
|
+
# Singleton Pattern
|
|
14
|
+
# -------------------------------------------------
|
|
15
|
+
__instance = None
|
|
16
|
+
|
|
17
|
+
@staticmethod
|
|
18
|
+
def get_instance():
|
|
19
|
+
if Remote.__instance is None:
|
|
20
|
+
server = Config.data()
|
|
21
|
+
folder = join(dirname(dirname(abspath(__file__))), 'data')
|
|
22
|
+
Remote.__instance = Remote(server, folder)
|
|
23
|
+
return Remote.__instance
|
|
24
|
+
|
|
25
|
+
# -------------------------------------------------
|
|
26
|
+
|
|
27
|
+
def __init__(self, server, folder=None) -> None:
|
|
28
|
+
super().__init__()
|
|
29
|
+
self.server = server
|
|
30
|
+
self.folder = folder
|
|
31
|
+
|
|
32
|
+
def load(self, *args, to="numpy"):
|
|
33
|
+
|
|
34
|
+
# the local file we can try loading
|
|
35
|
+
f = join(str(self.folder), *args)
|
|
36
|
+
|
|
37
|
+
# check if that path already exists
|
|
38
|
+
if not os.path.exists(f):
|
|
39
|
+
|
|
40
|
+
# if not make sure to create it that the file can be written
|
|
41
|
+
folder = dirname(f)
|
|
42
|
+
if not os.path.exists(folder):
|
|
43
|
+
os.makedirs(folder)
|
|
44
|
+
|
|
45
|
+
# create the url to load it from and download the file remotely
|
|
46
|
+
url = self.server + "/".join(args)
|
|
47
|
+
urllib.request.urlretrieve(url, f)
|
|
48
|
+
|
|
49
|
+
if to == "numpy":
|
|
50
|
+
return np.loadtxt(f)
|
|
51
|
+
elif to == "json":
|
|
52
|
+
with open(f) as file:
|
|
53
|
+
return json.load(file)
|
|
54
|
+
|
|
55
|
+
return f
|
pymoo/util/roulette.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class RouletteWheelSelection:
|
|
5
|
+
|
|
6
|
+
def __init__(self, val, larger_is_better=True):
|
|
7
|
+
super().__init__()
|
|
8
|
+
if not larger_is_better:
|
|
9
|
+
val = val.max() - val
|
|
10
|
+
_sum = val.sum()
|
|
11
|
+
self.cumulative = np.array([val[:k].sum() / _sum for k in range(1, len(val))])
|
|
12
|
+
|
|
13
|
+
def next(self, n=None):
|
|
14
|
+
if n is None:
|
|
15
|
+
X = np.random.random((1, 1))
|
|
16
|
+
else:
|
|
17
|
+
X = np.random.random((n, 1))
|
|
18
|
+
if n > 1:
|
|
19
|
+
X.repeat(n - 1, axis=1)
|
|
20
|
+
|
|
21
|
+
M = self.cumulative[None, :].repeat(len(X), axis=0)
|
|
22
|
+
B = X >= M
|
|
23
|
+
ret = B.sum(axis=1)
|
|
24
|
+
|
|
25
|
+
if n is None:
|
|
26
|
+
return ret[0]
|
|
27
|
+
return ret
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import matplotlib.pyplot as plt
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from pymoo.core.callback import Callback
|
|
5
|
+
from pymoo.indicators.hv import Hypervolume
|
|
6
|
+
from pymoo.indicators.igd import IGD
|
|
7
|
+
from pymoo.termination.ftol import calc_delta_norm
|
|
8
|
+
from pymoo.util.normalization import normalize
|
|
9
|
+
from pymoo.util.sliding_window import SlidingWindow
|
|
10
|
+
from pymoo.visualization.video.callback_video import AnimationCallback
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class RunningMetric(Callback):
|
|
14
|
+
|
|
15
|
+
def __init__(self,
|
|
16
|
+
period=None,
|
|
17
|
+
indicator="igd") -> None:
|
|
18
|
+
|
|
19
|
+
super().__init__()
|
|
20
|
+
self.indicator = indicator
|
|
21
|
+
|
|
22
|
+
self.delta_ideal = None
|
|
23
|
+
self.delta_nadir = None
|
|
24
|
+
self.delta_f = None
|
|
25
|
+
|
|
26
|
+
self.history = SlidingWindow(period)
|
|
27
|
+
|
|
28
|
+
def update(self, algorithm):
|
|
29
|
+
history = self.history
|
|
30
|
+
|
|
31
|
+
F = algorithm.opt.get("F")
|
|
32
|
+
c_F, c_ideal, c_nadir = F, F.min(axis=0), F.max(axis=0)
|
|
33
|
+
|
|
34
|
+
# find the normalization constant to divide by
|
|
35
|
+
norm = c_nadir - c_ideal
|
|
36
|
+
|
|
37
|
+
# make sure all dimensions in ideal are strictly lower than in nadir
|
|
38
|
+
c_nadir[c_ideal == c_nadir] += 1e-16
|
|
39
|
+
norm[c_ideal == c_nadir] = 1.0
|
|
40
|
+
|
|
41
|
+
# append the current optimum to the history
|
|
42
|
+
history.append(dict(F=F, ideal=c_ideal, nadir=c_nadir))
|
|
43
|
+
|
|
44
|
+
# normalize the current objective space values (use the utopian if equal)
|
|
45
|
+
c_N = normalize(c_F, c_ideal, c_nadir)
|
|
46
|
+
|
|
47
|
+
# normalize all previous generations with respect to current ideal and nadir
|
|
48
|
+
N = [normalize(e["F"], c_ideal, c_nadir) for e in history]
|
|
49
|
+
|
|
50
|
+
# calculate the delta difference for each previous ideal and nadir point to current
|
|
51
|
+
delta_ideal = [calc_delta_norm(history[k]["ideal"], history[k - 1]["ideal"], norm) for k in
|
|
52
|
+
range(1, len(history))] + [0.0]
|
|
53
|
+
delta_nadir = [calc_delta_norm(history[k]["nadir"], history[k - 1]["nadir"], norm) for k in
|
|
54
|
+
range(1, len(history))] + [0.0]
|
|
55
|
+
|
|
56
|
+
# now calculate the indicator from each previous one to the current
|
|
57
|
+
if self.indicator == "igd":
|
|
58
|
+
delta_f = [IGD(c_N).do(N[k]) for k in range(len(N))]
|
|
59
|
+
elif self.indicator == "hv":
|
|
60
|
+
hv = Hypervolume(ref_point=np.ones(c_F.shape[1]))
|
|
61
|
+
delta_f = [hv.do(N[k]) for k in range(len(N))]
|
|
62
|
+
else:
|
|
63
|
+
raise Exception("Unknown indicator.")
|
|
64
|
+
|
|
65
|
+
self.delta_ideal, self.delta_nadir, self.delta_f = delta_ideal, delta_nadir, delta_f
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class RunningMetricAnimation(AnimationCallback):
|
|
69
|
+
|
|
70
|
+
def __init__(self,
|
|
71
|
+
delta_gen,
|
|
72
|
+
n_plots=4,
|
|
73
|
+
key_press=True,
|
|
74
|
+
**kwargs) -> None:
|
|
75
|
+
|
|
76
|
+
super().__init__(**kwargs)
|
|
77
|
+
self.running = RunningMetric()
|
|
78
|
+
self.delta_gen = delta_gen
|
|
79
|
+
self.key_press = key_press
|
|
80
|
+
self.data = SlidingWindow(n_plots)
|
|
81
|
+
|
|
82
|
+
def draw(self, data, ax):
|
|
83
|
+
|
|
84
|
+
for tau, x, f, v in data[:-1]:
|
|
85
|
+
ax.plot(x, f, label="t=%s" % tau, alpha=0.6, linewidth=3)
|
|
86
|
+
|
|
87
|
+
tau, x, f, v = data[-1]
|
|
88
|
+
ax.plot(x, f, label="t=%s (*)" % tau, alpha=0.9, linewidth=3)
|
|
89
|
+
|
|
90
|
+
for k in range(len(v)):
|
|
91
|
+
if v[k]:
|
|
92
|
+
ax.plot([k + 1, k + 1], [0, f[k]], color="black", linewidth=0.5, alpha=0.5)
|
|
93
|
+
ax.plot([k + 1], [f[k]], "o", color="black", alpha=0.5, markersize=2)
|
|
94
|
+
|
|
95
|
+
ax.set_yscale("symlog")
|
|
96
|
+
ax.legend()
|
|
97
|
+
|
|
98
|
+
ax.set_xlabel("Generation")
|
|
99
|
+
ax.set_ylabel("$\Delta \, f$", rotation=0)
|
|
100
|
+
|
|
101
|
+
def do(self, _, algorithm, force_plot=False, **kwargs):
|
|
102
|
+
running = self.running
|
|
103
|
+
|
|
104
|
+
# update the running metric to have the most recent information
|
|
105
|
+
running.update(algorithm)
|
|
106
|
+
|
|
107
|
+
tau = algorithm.n_gen
|
|
108
|
+
|
|
109
|
+
if (tau > 0 and tau % self.delta_gen == 0) or force_plot:
|
|
110
|
+
|
|
111
|
+
f = running.delta_f
|
|
112
|
+
x = np.arange(len(f)) + 1
|
|
113
|
+
v = [max(ideal, nadir) > 0.005 for ideal, nadir in zip(running.delta_ideal, running.delta_nadir)]
|
|
114
|
+
self.data.append((tau, x, f, v))
|
|
115
|
+
|
|
116
|
+
fig, ax = plt.subplots()
|
|
117
|
+
self.draw(self.data, ax)
|
|
118
|
+
|
|
119
|
+
if self.key_press:
|
|
120
|
+
def press(event):
|
|
121
|
+
if event.key == 'q':
|
|
122
|
+
algorithm.termination.force_termination = True
|
|
123
|
+
|
|
124
|
+
fig.canvas.mpl_connect('key_press_event', press)
|
|
125
|
+
|
|
126
|
+
plt.draw()
|
|
127
|
+
plt.waitforbuttonpress()
|
|
128
|
+
plt.close('all')
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SlidingWindow(list):
|
|
5
|
+
|
|
6
|
+
def __init__(self, size=None) -> None:
|
|
7
|
+
super().__init__()
|
|
8
|
+
self.size = size
|
|
9
|
+
|
|
10
|
+
def append(self, entry):
|
|
11
|
+
super().append(entry)
|
|
12
|
+
|
|
13
|
+
if self.size is not None:
|
|
14
|
+
while len(self) > self.size:
|
|
15
|
+
self.pop(0)
|
|
16
|
+
|
|
17
|
+
def is_full(self):
|
|
18
|
+
return self.size == len(self)
|
|
19
|
+
|
|
20
|
+
def to_numpy(self):
|
|
21
|
+
return np.array(self)
|
|
22
|
+
|
|
23
|
+
def clear(self):
|
|
24
|
+
while len(self) > 0:
|
|
25
|
+
self.pop()
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from pymoo.util.misc import swap
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def stochastic_ranking(f, phi, pr, I=None):
|
|
7
|
+
_lambda = len(f)
|
|
8
|
+
|
|
9
|
+
if I is None:
|
|
10
|
+
I = np.arange(_lambda)
|
|
11
|
+
|
|
12
|
+
for i in range(_lambda):
|
|
13
|
+
|
|
14
|
+
at_least_one_swap = False
|
|
15
|
+
|
|
16
|
+
for j in range(_lambda - 1):
|
|
17
|
+
|
|
18
|
+
u = np.random.random()
|
|
19
|
+
|
|
20
|
+
if u < pr or (phi[I[j]] == 0 and phi[I[j + 1]] == 0):
|
|
21
|
+
if f[I[j]] > f[I[j + 1]]:
|
|
22
|
+
swap(I, j, j + 1)
|
|
23
|
+
at_least_one_swap = True
|
|
24
|
+
else:
|
|
25
|
+
if phi[I[j]] > phi[I[j + 1]]:
|
|
26
|
+
swap(I, j, j + 1)
|
|
27
|
+
at_least_one_swap = True
|
|
28
|
+
|
|
29
|
+
if not at_least_one_swap:
|
|
30
|
+
break
|
|
31
|
+
|
|
32
|
+
return I
|