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,102 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from scipy.spatial.ckdtree import cKDTree
|
|
3
|
+
|
|
4
|
+
from pymoo.core.indicator import Indicator
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DecisionMaking(Indicator):
|
|
8
|
+
|
|
9
|
+
def __init__(self, **kwargs) -> None:
|
|
10
|
+
super().__init__(**kwargs)
|
|
11
|
+
self.default_if_empty = None
|
|
12
|
+
|
|
13
|
+
def _do(self, F, *args, **kwargs):
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class NeighborFinder:
|
|
18
|
+
|
|
19
|
+
def __init__(self, N,
|
|
20
|
+
epsilon=0.125,
|
|
21
|
+
n_neighbors=None,
|
|
22
|
+
n_min_neigbors=None,
|
|
23
|
+
consider_2d=True):
|
|
24
|
+
|
|
25
|
+
super().__init__()
|
|
26
|
+
self.N = N
|
|
27
|
+
self.consider_2d = consider_2d
|
|
28
|
+
|
|
29
|
+
_, n_dim = N.shape
|
|
30
|
+
|
|
31
|
+
# at least find min(dimensionality times two neighbors, number PO solutions - 1) - if enabled
|
|
32
|
+
if n_min_neigbors == "auto":
|
|
33
|
+
self.n_min_neigbors = min(2 * n_dim, _ - 1)
|
|
34
|
+
|
|
35
|
+
# disable the minimum neighbor variable
|
|
36
|
+
else:
|
|
37
|
+
self.n_min_neigbors = np.inf
|
|
38
|
+
|
|
39
|
+
# either choose epsilon
|
|
40
|
+
self.epsilon = epsilon
|
|
41
|
+
|
|
42
|
+
# if none choose the number of neighbors
|
|
43
|
+
self.n_neighbors = n_neighbors
|
|
44
|
+
|
|
45
|
+
if self.N.shape[1] == 1:
|
|
46
|
+
raise Exception("At least 2 objectives must be provided.")
|
|
47
|
+
|
|
48
|
+
elif self.consider_2d and self.N.shape[1] == 2:
|
|
49
|
+
self.min, self.max = N.min(), N.max()
|
|
50
|
+
self.rank = np.argsort(N[:, 0])
|
|
51
|
+
self.pos_in_rank = np.argsort(self.rank)
|
|
52
|
+
|
|
53
|
+
else:
|
|
54
|
+
self.tree = cKDTree(N)
|
|
55
|
+
|
|
56
|
+
def find(self, i):
|
|
57
|
+
|
|
58
|
+
if self.consider_2d and self.N.shape[1] == 2:
|
|
59
|
+
neighbours = []
|
|
60
|
+
|
|
61
|
+
pos = self.pos_in_rank[i]
|
|
62
|
+
if pos > 0:
|
|
63
|
+
neighbours.append(self.rank[pos - 1])
|
|
64
|
+
if pos < len(self.N) - 1:
|
|
65
|
+
neighbours.append(self.rank[pos + 1])
|
|
66
|
+
|
|
67
|
+
else:
|
|
68
|
+
|
|
69
|
+
# for each neighbour in a specific radius of that solution
|
|
70
|
+
if self.epsilon is not None:
|
|
71
|
+
neighbours = self.tree.query_ball_point([self.N[i]], self.epsilon).tolist()[0]
|
|
72
|
+
elif self.n_neighbors is not None:
|
|
73
|
+
neighbours = self.tree.query([self.N[i]], k=self.n_neighbors + 1)[1].tolist()[0]
|
|
74
|
+
else:
|
|
75
|
+
raise Exception("Either define epsilon or number of neighbors.")
|
|
76
|
+
|
|
77
|
+
# in case n_min_neigbors is enabled
|
|
78
|
+
if len(neighbours) < self.n_min_neigbors:
|
|
79
|
+
neighbours = self.tree.query([self.N[i]], k=self.n_min_neigbors + 1)[1].tolist()[0]
|
|
80
|
+
|
|
81
|
+
return neighbours
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def find_outliers_upper_tail(mu):
|
|
85
|
+
|
|
86
|
+
# remove values that are nan
|
|
87
|
+
I = np.where(np.logical_and(np.logical_not(np.isnan(mu)), np.logical_not(np.isinf(mu))))[0]
|
|
88
|
+
mu = mu[I]
|
|
89
|
+
|
|
90
|
+
# calculate mean and sigma
|
|
91
|
+
mean, sigma = mu.mean(), mu.std()
|
|
92
|
+
|
|
93
|
+
# calculate the deviation in terms of sigma
|
|
94
|
+
deviation = (mu - mean) / sigma
|
|
95
|
+
|
|
96
|
+
# 2 * sigma is considered as an outlier
|
|
97
|
+
S = I[np.where(deviation >= 2)[0]]
|
|
98
|
+
|
|
99
|
+
if len(S) == 0 and deviation.max() > 1:
|
|
100
|
+
S = I[[np.argmax(mu)]]
|
|
101
|
+
|
|
102
|
+
return S if len(S) > 0 else None
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.util.misc import at_least_2d_array, to_1d_array_if_possible
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Decomposition:
|
|
7
|
+
|
|
8
|
+
def __init__(self, eps=0.0, _type="auto", **kwargs) -> None:
|
|
9
|
+
super().__init__()
|
|
10
|
+
self.eps = eps
|
|
11
|
+
self._type = _type
|
|
12
|
+
self.ideal_point, self.utopian_point, self.nadir_point = None, None, None
|
|
13
|
+
|
|
14
|
+
def __call__(self, *args, **kwargs):
|
|
15
|
+
return self.do(*args, **kwargs)
|
|
16
|
+
|
|
17
|
+
def do(self,
|
|
18
|
+
F,
|
|
19
|
+
weights,
|
|
20
|
+
_type="auto",
|
|
21
|
+
ideal_point=None,
|
|
22
|
+
utopian_point=None,
|
|
23
|
+
nadir_point=None,
|
|
24
|
+
**kwargs):
|
|
25
|
+
|
|
26
|
+
_F, _weights = to_1d_array_if_possible(F), to_1d_array_if_possible(weights)
|
|
27
|
+
|
|
28
|
+
if _type == "auto":
|
|
29
|
+
if _F.ndim == 1 and _weights.ndim > 1:
|
|
30
|
+
_type = "one_to_many"
|
|
31
|
+
elif _F.ndim > 1 and _weights.ndim == 1:
|
|
32
|
+
_type = "many_to_one"
|
|
33
|
+
elif _F.ndim == 2 and _weights.ndim == 2 and _F.shape[0] == _weights.shape[0]:
|
|
34
|
+
_type = "one_to_one"
|
|
35
|
+
else:
|
|
36
|
+
_type = "many_to_many"
|
|
37
|
+
|
|
38
|
+
# make both at least 2d arrays
|
|
39
|
+
F, weights = at_least_2d_array(F), at_least_2d_array(weights)
|
|
40
|
+
|
|
41
|
+
# get the number of points and weights
|
|
42
|
+
n_points, n_weights = F.shape[0], weights.shape[0]
|
|
43
|
+
|
|
44
|
+
self.ideal_point = ideal_point
|
|
45
|
+
if self.ideal_point is None:
|
|
46
|
+
self.ideal_point = np.zeros(F.shape[1])
|
|
47
|
+
|
|
48
|
+
self.utopian_point = utopian_point
|
|
49
|
+
if self.utopian_point is None:
|
|
50
|
+
self.utopian_point = self.ideal_point - self.eps
|
|
51
|
+
|
|
52
|
+
# set the nadir point by default to value or default
|
|
53
|
+
self.nadir_point = nadir_point
|
|
54
|
+
if self.nadir_point is None:
|
|
55
|
+
self.nadir_point = self.utopian_point + np.ones(F.shape[1])
|
|
56
|
+
|
|
57
|
+
if _type == "one_to_one":
|
|
58
|
+
D = self._do(F, weights=weights, **kwargs).flatten()
|
|
59
|
+
|
|
60
|
+
elif _type == "one_to_many":
|
|
61
|
+
F = np.repeat(F, n_weights, axis=0)
|
|
62
|
+
D = self._do(F, weights=weights, **kwargs).flatten()
|
|
63
|
+
|
|
64
|
+
elif _type == "many_to_one":
|
|
65
|
+
weights = np.repeat(weights, n_points, axis=0)
|
|
66
|
+
D = self._do(F, weights=weights, **kwargs).flatten()
|
|
67
|
+
|
|
68
|
+
elif _type == "many_to_many":
|
|
69
|
+
F = np.repeat(F, n_weights, axis=0)
|
|
70
|
+
weights = np.tile(weights, (n_points, 1))
|
|
71
|
+
D = self._do(F, weights=weights, **kwargs).reshape(n_points, n_weights)
|
|
72
|
+
|
|
73
|
+
else:
|
|
74
|
+
raise Exception("Unknown type for decomposition: %s" % _type)
|
|
75
|
+
|
|
76
|
+
return D
|
pymoo/core/duplicate.py
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.util.misc import cdist
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def default_attr(pop):
|
|
7
|
+
return pop.get("X")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DuplicateElimination:
|
|
11
|
+
|
|
12
|
+
def __init__(self, func=None) -> None:
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.func = func
|
|
15
|
+
|
|
16
|
+
if self.func is None:
|
|
17
|
+
self.func = default_attr
|
|
18
|
+
|
|
19
|
+
def do(self, pop, *args, return_indices=False, to_itself=True):
|
|
20
|
+
original = pop
|
|
21
|
+
|
|
22
|
+
if len(pop) == 0:
|
|
23
|
+
return (pop, [], []) if return_indices else pop
|
|
24
|
+
|
|
25
|
+
if to_itself:
|
|
26
|
+
pop = pop[~self._do(pop, None, np.full(len(pop), False))]
|
|
27
|
+
|
|
28
|
+
for arg in args:
|
|
29
|
+
if len(arg) > 0:
|
|
30
|
+
|
|
31
|
+
if len(pop) == 0:
|
|
32
|
+
break
|
|
33
|
+
elif len(arg) == 0:
|
|
34
|
+
continue
|
|
35
|
+
else:
|
|
36
|
+
pop = pop[~self._do(pop, arg, np.full(len(pop), False))]
|
|
37
|
+
|
|
38
|
+
if return_indices:
|
|
39
|
+
no_duplicate, is_duplicate = [], []
|
|
40
|
+
H = set(pop)
|
|
41
|
+
|
|
42
|
+
for i, ind in enumerate(original):
|
|
43
|
+
if ind in H:
|
|
44
|
+
no_duplicate.append(i)
|
|
45
|
+
else:
|
|
46
|
+
is_duplicate.append(i)
|
|
47
|
+
|
|
48
|
+
return pop, no_duplicate, is_duplicate
|
|
49
|
+
else:
|
|
50
|
+
return pop
|
|
51
|
+
|
|
52
|
+
def _do(self, pop, other, is_duplicate):
|
|
53
|
+
return is_duplicate
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class DefaultDuplicateElimination(DuplicateElimination):
|
|
57
|
+
|
|
58
|
+
def __init__(self, epsilon=1e-16, **kwargs) -> None:
|
|
59
|
+
super().__init__(**kwargs)
|
|
60
|
+
self.epsilon = epsilon
|
|
61
|
+
|
|
62
|
+
def calc_dist(self, pop, other=None):
|
|
63
|
+
X = self.func(pop)
|
|
64
|
+
|
|
65
|
+
if other is None:
|
|
66
|
+
D = cdist(X, X)
|
|
67
|
+
D[np.triu_indices(len(X))] = np.inf
|
|
68
|
+
else:
|
|
69
|
+
_X = self.func(other)
|
|
70
|
+
D = cdist(X, _X)
|
|
71
|
+
|
|
72
|
+
return D
|
|
73
|
+
|
|
74
|
+
def _do(self, pop, other, is_duplicate):
|
|
75
|
+
D = self.calc_dist(pop, other)
|
|
76
|
+
D[np.isnan(D)] = np.inf
|
|
77
|
+
|
|
78
|
+
is_duplicate[np.any(D <= self.epsilon, axis=1)] = True
|
|
79
|
+
return is_duplicate
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def to_float(val):
|
|
83
|
+
if isinstance(val, bool) or isinstance(val, np.bool_):
|
|
84
|
+
return 0.0 if val else 1.0
|
|
85
|
+
else:
|
|
86
|
+
return val
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class ElementwiseDuplicateElimination(DefaultDuplicateElimination):
|
|
90
|
+
|
|
91
|
+
def __init__(self, cmp_func=None, **kwargs) -> None:
|
|
92
|
+
super().__init__(**kwargs)
|
|
93
|
+
|
|
94
|
+
if cmp_func is None:
|
|
95
|
+
cmp_func = self.is_equal
|
|
96
|
+
|
|
97
|
+
self.cmp_func = cmp_func
|
|
98
|
+
|
|
99
|
+
def is_equal(self, a, b):
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
def _do(self, pop, other, is_duplicate):
|
|
103
|
+
|
|
104
|
+
if other is None:
|
|
105
|
+
for i in range(len(pop)):
|
|
106
|
+
for j in range(i + 1, len(pop)):
|
|
107
|
+
val = to_float(self.cmp_func(pop[i], pop[j]))
|
|
108
|
+
if val < self.epsilon:
|
|
109
|
+
is_duplicate[i] = True
|
|
110
|
+
break
|
|
111
|
+
else:
|
|
112
|
+
for i in range(len(pop)):
|
|
113
|
+
for j in range(len(other)):
|
|
114
|
+
val = to_float(self.cmp_func(pop[i], other[j]))
|
|
115
|
+
if val < self.epsilon:
|
|
116
|
+
is_duplicate[i] = True
|
|
117
|
+
break
|
|
118
|
+
|
|
119
|
+
return is_duplicate
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def to_hash(x):
|
|
123
|
+
try:
|
|
124
|
+
h = hash(x)
|
|
125
|
+
except:
|
|
126
|
+
try:
|
|
127
|
+
h = hash(str(x))
|
|
128
|
+
except:
|
|
129
|
+
raise Exception("Hash could not be calculated. Please use another duplicate elimination.")
|
|
130
|
+
|
|
131
|
+
return h
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class HashDuplicateElimination(DuplicateElimination):
|
|
135
|
+
|
|
136
|
+
def __init__(self, func=to_hash) -> None:
|
|
137
|
+
super().__init__()
|
|
138
|
+
self.func = func
|
|
139
|
+
|
|
140
|
+
def _do(self, pop, other, is_duplicate):
|
|
141
|
+
H = set()
|
|
142
|
+
|
|
143
|
+
if other is not None:
|
|
144
|
+
for o in other:
|
|
145
|
+
val = self.func(o)
|
|
146
|
+
H.add(self.func(val))
|
|
147
|
+
|
|
148
|
+
for i, ind in enumerate(pop):
|
|
149
|
+
val = self.func(ind)
|
|
150
|
+
h = self.func(val)
|
|
151
|
+
|
|
152
|
+
if h in H:
|
|
153
|
+
is_duplicate[i] = True
|
|
154
|
+
else:
|
|
155
|
+
H.add(h)
|
|
156
|
+
|
|
157
|
+
return is_duplicate
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class NoDuplicateElimination(DuplicateElimination):
|
|
161
|
+
|
|
162
|
+
def do(self, pop, *args, **kwargs):
|
|
163
|
+
return pop
|
pymoo/core/evaluator.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.individual import Individual
|
|
4
|
+
from pymoo.core.population import Population
|
|
5
|
+
from pymoo.core.problem import Problem
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Evaluator:
|
|
9
|
+
|
|
10
|
+
def __init__(self,
|
|
11
|
+
skip_already_evaluated: bool = True,
|
|
12
|
+
evaluate_values_of: list = ["F", "G", "H"],
|
|
13
|
+
callback=None):
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
The evaluator has the purpose to glue the problem with the population/individual objects.
|
|
17
|
+
Additionally, it serves as a bookkeeper to store determine the number of function evaluations of runs, time,
|
|
18
|
+
and others.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
skip_already_evaluated : bool
|
|
24
|
+
If individual that are already evaluated shall be skipped.
|
|
25
|
+
|
|
26
|
+
evaluate_values_of : list
|
|
27
|
+
The type of values to be asked the problem to evaluated. By default all objective, ieq. and eq. constraints.
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
self.evaluate_values_of = evaluate_values_of
|
|
32
|
+
self.skip_already_evaluated = skip_already_evaluated
|
|
33
|
+
self.callback = callback
|
|
34
|
+
|
|
35
|
+
# current number of function evaluations - initialized to zero
|
|
36
|
+
self.n_eval = 0
|
|
37
|
+
|
|
38
|
+
def eval(self,
|
|
39
|
+
problem: Problem,
|
|
40
|
+
pop: Population,
|
|
41
|
+
skip_already_evaluated: bool = None,
|
|
42
|
+
evaluate_values_of: list = None,
|
|
43
|
+
count_evals: bool = True,
|
|
44
|
+
**kwargs):
|
|
45
|
+
|
|
46
|
+
# load the default settings from the evaluator object if not already provided
|
|
47
|
+
evaluate_values_of = self.evaluate_values_of if evaluate_values_of is None else evaluate_values_of
|
|
48
|
+
skip_already_evaluated = self.skip_already_evaluated if skip_already_evaluated is None else skip_already_evaluated
|
|
49
|
+
|
|
50
|
+
# check the type of the input
|
|
51
|
+
is_individual = isinstance(pop, Individual)
|
|
52
|
+
|
|
53
|
+
# make sure the object is a population
|
|
54
|
+
if is_individual:
|
|
55
|
+
pop = Population().create(pop)
|
|
56
|
+
|
|
57
|
+
# filter the index to have individual where not all attributes have been evaluated
|
|
58
|
+
if skip_already_evaluated:
|
|
59
|
+
I = [i for i, ind in enumerate(pop) if not all([e in ind.evaluated for e in evaluate_values_of])]
|
|
60
|
+
|
|
61
|
+
# if skipping is deactivated simply make the index being all individuals
|
|
62
|
+
else:
|
|
63
|
+
I = np.arange(len(pop))
|
|
64
|
+
|
|
65
|
+
# evaluate the solutions (if there are any)
|
|
66
|
+
if len(I) > 0:
|
|
67
|
+
|
|
68
|
+
# do the actual evaluation - call the sub-function to set the corresponding values to the population
|
|
69
|
+
self._eval(problem, pop[I], evaluate_values_of, **kwargs)
|
|
70
|
+
|
|
71
|
+
# update the function evaluation counter
|
|
72
|
+
if count_evals:
|
|
73
|
+
self.n_eval += len(I)
|
|
74
|
+
|
|
75
|
+
# allow to have a callback registered
|
|
76
|
+
if self.callback:
|
|
77
|
+
self.callback(pop)
|
|
78
|
+
|
|
79
|
+
if is_individual:
|
|
80
|
+
return pop[0]
|
|
81
|
+
else:
|
|
82
|
+
return pop
|
|
83
|
+
|
|
84
|
+
def _eval(self, problem, pop, evaluate_values_of, **kwargs):
|
|
85
|
+
|
|
86
|
+
# get the design space value from the individuals
|
|
87
|
+
X = pop.get("X")
|
|
88
|
+
|
|
89
|
+
# call the problem to evaluate the solutions
|
|
90
|
+
out = problem.evaluate(X, return_values_of=evaluate_values_of, return_as_dictionary=True, **kwargs)
|
|
91
|
+
|
|
92
|
+
# for each of the attributes set it to the problem
|
|
93
|
+
for key, val in out.items():
|
|
94
|
+
if val is not None:
|
|
95
|
+
pop.set(key, val)
|
|
96
|
+
|
|
97
|
+
# finally set all the attributes to be evaluated for all individuals
|
|
98
|
+
pop.apply(lambda ind: ind.evaluated.update(out.keys()))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class VoidEvaluator(Evaluator):
|
|
102
|
+
|
|
103
|
+
def __init__(self, value=np.inf, **kwargs):
|
|
104
|
+
super().__init__(**kwargs)
|
|
105
|
+
self.value = value
|
|
106
|
+
|
|
107
|
+
def eval(self, problem, pop, **kwargs):
|
|
108
|
+
val = self.value
|
|
109
|
+
if val is not None:
|
|
110
|
+
for individual in pop:
|
|
111
|
+
if len(individual.evaluated) == 0:
|
|
112
|
+
individual.F = np.full(problem.n_obj, val)
|
|
113
|
+
individual.G = np.full(problem.n_ieq_constr, val) if problem.n_ieq_constr > 0 else None
|
|
114
|
+
individual.H = np.full(problem.n_eq_constr, val) if problem.n_eq_constr else None
|
|
115
|
+
individual.CV = [-np.inf]
|
|
116
|
+
individual.feas = [False]
|
pymoo/core/indicator.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
|
|
3
|
+
from pymoo.util.normalization import PreNormalization
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Indicator(PreNormalization):
|
|
7
|
+
|
|
8
|
+
def __init__(self, **kwargs):
|
|
9
|
+
super().__init__(**kwargs)
|
|
10
|
+
|
|
11
|
+
# what should an indicator return if no solutions are provided is defined here
|
|
12
|
+
self.default_if_empty = 0.0
|
|
13
|
+
|
|
14
|
+
def __call__(self, F, *args, **kwargs):
|
|
15
|
+
return self.do(F, *args, **kwargs)
|
|
16
|
+
|
|
17
|
+
def do(self, F, *args, **kwargs):
|
|
18
|
+
|
|
19
|
+
# if it is a 1d array
|
|
20
|
+
if F.ndim == 1:
|
|
21
|
+
F = F[None, :]
|
|
22
|
+
|
|
23
|
+
# if no points have been provided just return the default
|
|
24
|
+
if len(F) == 0:
|
|
25
|
+
return self.default_if_empty
|
|
26
|
+
|
|
27
|
+
# do the normalization - will only be done if zero_to_one is enabled
|
|
28
|
+
F = self.normalization.forward(F)
|
|
29
|
+
|
|
30
|
+
return self._do(F, *args, **kwargs)
|
|
31
|
+
|
|
32
|
+
@abc.abstractmethod
|
|
33
|
+
def _do(self, F, *args, **kwargs):
|
|
34
|
+
return
|