pymoo 0.6.1.5.dev0__cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pymoo might be problematic. Click here for more details.
- pymoo/__init__.py +3 -0
- pymoo/algorithms/__init__.py +0 -0
- pymoo/algorithms/base/__init__.py +0 -0
- pymoo/algorithms/base/bracket.py +38 -0
- pymoo/algorithms/base/genetic.py +109 -0
- pymoo/algorithms/base/line.py +62 -0
- pymoo/algorithms/base/local.py +39 -0
- pymoo/algorithms/base/meta.py +79 -0
- pymoo/algorithms/hyperparameters.py +89 -0
- pymoo/algorithms/moo/__init__.py +0 -0
- pymoo/algorithms/moo/age.py +310 -0
- pymoo/algorithms/moo/age2.py +194 -0
- pymoo/algorithms/moo/ctaea.py +298 -0
- pymoo/algorithms/moo/dnsga2.py +76 -0
- pymoo/algorithms/moo/kgb.py +446 -0
- pymoo/algorithms/moo/moead.py +183 -0
- pymoo/algorithms/moo/nsga2.py +113 -0
- pymoo/algorithms/moo/nsga3.py +358 -0
- pymoo/algorithms/moo/pinsga2.py +370 -0
- pymoo/algorithms/moo/rnsga2.py +188 -0
- pymoo/algorithms/moo/rnsga3.py +246 -0
- pymoo/algorithms/moo/rvea.py +214 -0
- pymoo/algorithms/moo/sms.py +195 -0
- pymoo/algorithms/moo/spea2.py +190 -0
- pymoo/algorithms/moo/unsga3.py +47 -0
- pymoo/algorithms/soo/__init__.py +0 -0
- pymoo/algorithms/soo/convex/__init__.py +0 -0
- pymoo/algorithms/soo/nonconvex/__init__.py +0 -0
- pymoo/algorithms/soo/nonconvex/brkga.py +161 -0
- pymoo/algorithms/soo/nonconvex/cmaes.py +554 -0
- pymoo/algorithms/soo/nonconvex/de.py +279 -0
- pymoo/algorithms/soo/nonconvex/direct.py +149 -0
- pymoo/algorithms/soo/nonconvex/es.py +203 -0
- pymoo/algorithms/soo/nonconvex/g3pcx.py +94 -0
- pymoo/algorithms/soo/nonconvex/ga.py +93 -0
- pymoo/algorithms/soo/nonconvex/ga_niching.py +223 -0
- pymoo/algorithms/soo/nonconvex/isres.py +74 -0
- pymoo/algorithms/soo/nonconvex/nelder.py +251 -0
- pymoo/algorithms/soo/nonconvex/optuna.py +80 -0
- pymoo/algorithms/soo/nonconvex/pattern.py +183 -0
- pymoo/algorithms/soo/nonconvex/pso.py +399 -0
- pymoo/algorithms/soo/nonconvex/pso_ep.py +297 -0
- pymoo/algorithms/soo/nonconvex/random_search.py +25 -0
- pymoo/algorithms/soo/nonconvex/sres.py +56 -0
- pymoo/algorithms/soo/univariate/__init__.py +0 -0
- pymoo/algorithms/soo/univariate/backtracking.py +59 -0
- pymoo/algorithms/soo/univariate/exp.py +46 -0
- pymoo/algorithms/soo/univariate/golden.py +65 -0
- pymoo/algorithms/soo/univariate/quadr_interp.py +81 -0
- pymoo/algorithms/soo/univariate/wolfe.py +163 -0
- pymoo/config.py +33 -0
- pymoo/constraints/__init__.py +3 -0
- pymoo/constraints/adaptive.py +62 -0
- pymoo/constraints/as_obj.py +56 -0
- pymoo/constraints/as_penalty.py +41 -0
- pymoo/constraints/eps.py +26 -0
- pymoo/constraints/from_bounds.py +36 -0
- pymoo/core/__init__.py +0 -0
- pymoo/core/algorithm.py +394 -0
- pymoo/core/callback.py +38 -0
- pymoo/core/crossover.py +77 -0
- pymoo/core/decision_making.py +102 -0
- pymoo/core/decomposition.py +76 -0
- pymoo/core/duplicate.py +163 -0
- pymoo/core/evaluator.py +116 -0
- pymoo/core/indicator.py +34 -0
- pymoo/core/individual.py +784 -0
- pymoo/core/infill.py +64 -0
- pymoo/core/initialization.py +42 -0
- pymoo/core/mating.py +39 -0
- pymoo/core/meta.py +21 -0
- pymoo/core/mixed.py +165 -0
- pymoo/core/mutation.py +44 -0
- pymoo/core/operator.py +40 -0
- pymoo/core/parameters.py +134 -0
- pymoo/core/plot.py +210 -0
- pymoo/core/population.py +180 -0
- pymoo/core/problem.py +460 -0
- pymoo/core/recorder.py +99 -0
- pymoo/core/repair.py +23 -0
- pymoo/core/replacement.py +96 -0
- pymoo/core/result.py +52 -0
- pymoo/core/sampling.py +43 -0
- pymoo/core/selection.py +61 -0
- pymoo/core/solution.py +10 -0
- pymoo/core/survival.py +103 -0
- pymoo/core/termination.py +70 -0
- pymoo/core/variable.py +399 -0
- pymoo/cython/__init__.py +0 -0
- pymoo/cython/calc_perpendicular_distance.cpython-313-x86_64-linux-gnu.so +0 -0
- pymoo/cython/calc_perpendicular_distance.pyx +67 -0
- pymoo/cython/decomposition.cpython-313-x86_64-linux-gnu.so +0 -0
- pymoo/cython/decomposition.pyx +165 -0
- pymoo/cython/hv.cpython-313-x86_64-linux-gnu.so +0 -0
- pymoo/cython/hv.pyx +18 -0
- pymoo/cython/info.cpython-313-x86_64-linux-gnu.so +0 -0
- pymoo/cython/info.pyx +5 -0
- pymoo/cython/mnn.cpython-313-x86_64-linux-gnu.so +0 -0
- pymoo/cython/mnn.pyx +273 -0
- pymoo/cython/non_dominated_sorting.cpython-313-x86_64-linux-gnu.so +0 -0
- pymoo/cython/non_dominated_sorting.pyx +645 -0
- pymoo/cython/pruning_cd.cpython-313-x86_64-linux-gnu.so +0 -0
- pymoo/cython/pruning_cd.pyx +197 -0
- pymoo/cython/stochastic_ranking.cpython-313-x86_64-linux-gnu.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,68 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.util.reference_direction import ReferenceDirectionFactory
|
|
4
|
+
|
|
5
|
+
def check_n_points(n_points, n_dim):
|
|
6
|
+
"""
|
|
7
|
+
Returns n_partitions or a numeric value associated with the exception message.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
if n_dim == 1:
|
|
11
|
+
return [0]
|
|
12
|
+
|
|
13
|
+
I = n_dim * np.eye(n_dim)
|
|
14
|
+
W = np.zeros((1, n_dim))
|
|
15
|
+
edgeW = W
|
|
16
|
+
i = 0
|
|
17
|
+
|
|
18
|
+
while len(W) < n_points:
|
|
19
|
+
edgeW = np.tile(edgeW, (n_dim, 1)) + np.repeat(I, edgeW.shape[0], axis=0)
|
|
20
|
+
edgeW = np.unique(edgeW, axis=0)
|
|
21
|
+
edgeW = edgeW [np.any(edgeW == 0, axis=1)]
|
|
22
|
+
W = np.vstack((W + 1, edgeW))
|
|
23
|
+
i += 1
|
|
24
|
+
|
|
25
|
+
if len(W) == n_points:
|
|
26
|
+
return [i]
|
|
27
|
+
|
|
28
|
+
return [len(W) - len(edgeW), i - 1, len(W), i]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def incremental_lattice(n_partitions, n_dim):
|
|
32
|
+
I = n_dim * np.eye(n_dim)
|
|
33
|
+
W = np.zeros((1, n_dim))
|
|
34
|
+
edgeW = W
|
|
35
|
+
|
|
36
|
+
for _ in range(n_partitions):
|
|
37
|
+
edgeW = np.tile(edgeW, (n_dim, 1)) + np.repeat(I, edgeW.shape[0], axis=0)
|
|
38
|
+
edgeW = np.unique(edgeW, axis=0)
|
|
39
|
+
edgeW = edgeW [np.any(edgeW == 0, axis=1)]
|
|
40
|
+
W = np.vstack((W + 1, edgeW))
|
|
41
|
+
|
|
42
|
+
return W / (n_dim * n_partitions)
|
|
43
|
+
|
|
44
|
+
class IncrementalReferenceDirectionFactory(ReferenceDirectionFactory):
|
|
45
|
+
|
|
46
|
+
def __init__(self, n_dim, scaling=None, n_points=None, n_partitions=None, **kwargs) -> None:
|
|
47
|
+
super().__init__(n_dim, scaling=scaling, **kwargs)
|
|
48
|
+
|
|
49
|
+
if n_points is not None:
|
|
50
|
+
results = check_n_points(n_points, n_dim)
|
|
51
|
+
|
|
52
|
+
# the number of points are not matching to any partition number
|
|
53
|
+
if len(results) > 1:
|
|
54
|
+
raise Exception("The number of points (n_points = %s) can not be created uniformly.\n"
|
|
55
|
+
"Either choose n_points = %s (n_partitions = %s) or "
|
|
56
|
+
"n_points = %s (n_partitions = %s)." %
|
|
57
|
+
(n_points, results[0], results[1], results[2], results[3]))
|
|
58
|
+
|
|
59
|
+
self.n_partitions = results[0]
|
|
60
|
+
|
|
61
|
+
elif n_partitions is not None:
|
|
62
|
+
self.n_partitions = n_partitions
|
|
63
|
+
|
|
64
|
+
else:
|
|
65
|
+
raise Exception("Either provide number of partitions or number of points.")
|
|
66
|
+
|
|
67
|
+
def _do(self):
|
|
68
|
+
return incremental_lattice(self.n_partitions, self.n_dim)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def project_onto(y, p, n):
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
Project a point onto a plane.
|
|
8
|
+
|
|
9
|
+
Parameters
|
|
10
|
+
----------
|
|
11
|
+
y : The point that should be project
|
|
12
|
+
p : A point which lies on the plane
|
|
13
|
+
n : The normal vector of the plane
|
|
14
|
+
|
|
15
|
+
Returns
|
|
16
|
+
-------
|
|
17
|
+
|
|
18
|
+
proj_y : The projection onto the plane
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
is_1d = False
|
|
23
|
+
if len(y.shape) == 1:
|
|
24
|
+
is_1d = True
|
|
25
|
+
y = np.atleast_2d(y)
|
|
26
|
+
|
|
27
|
+
# make sure the plane vector is normalized
|
|
28
|
+
n = n / np.linalg.norm(n)
|
|
29
|
+
|
|
30
|
+
proj_y = y - n[None, :] * ((y - p) @ n)[:, None]
|
|
31
|
+
|
|
32
|
+
if is_1d:
|
|
33
|
+
proj_y = proj_y[0]
|
|
34
|
+
|
|
35
|
+
return proj_y
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def project_onto_sum_equals_one_plane(y):
|
|
39
|
+
n_dim = y.shape[-1]
|
|
40
|
+
return project_onto(y, np.eye(n_dim)[0], np.ones(n_dim))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def project_onto_sum_equals_zero_plane(y):
|
|
44
|
+
n_dim = y.shape[-1]
|
|
45
|
+
return project_onto(y, np.zeros(n_dim), np.ones(n_dim))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def project_onto_unit_simplex(X):
|
|
49
|
+
n_points, n_dim = X.shape
|
|
50
|
+
|
|
51
|
+
# a boolean mask of violating values - less than 0
|
|
52
|
+
I = X < 0
|
|
53
|
+
|
|
54
|
+
# get all the points which are out of bounds and need to be fixed
|
|
55
|
+
out_of_unit_simplex = np.where(I.sum(axis=1) > 0)[0]
|
|
56
|
+
|
|
57
|
+
# now check for each point if it is still in bound
|
|
58
|
+
for j in out_of_unit_simplex:
|
|
59
|
+
|
|
60
|
+
# indices where the last point was already out of bounds
|
|
61
|
+
subspace = np.logical_not(I[j])
|
|
62
|
+
|
|
63
|
+
# project the bounds back onto the simplex in the subspace
|
|
64
|
+
proj = np.zeros(n_dim)
|
|
65
|
+
proj[subspace] = project_onto_sum_equals_one_plane(X[j][subspace])
|
|
66
|
+
|
|
67
|
+
# set the result to the corresponding value
|
|
68
|
+
X[j] = proj
|
|
69
|
+
|
|
70
|
+
test1 = matrix_project_onto_sum_equals_one_plane(X[j][subspace])
|
|
71
|
+
test2 = project_onto_sum_equals_one_plane(X[j][subspace])
|
|
72
|
+
|
|
73
|
+
if not np.allclose(test1, test2):
|
|
74
|
+
print("test")
|
|
75
|
+
|
|
76
|
+
if np.any(X[j] < 0):
|
|
77
|
+
print("test")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def project_onto_unit_simplex_recursive(X):
|
|
81
|
+
# get all the points which are out of bounds and need to be fixed
|
|
82
|
+
out_of_unit_simplex = np.where(np.any(X < 0, axis=1))[0]
|
|
83
|
+
|
|
84
|
+
# now check for each point if it is still in bound
|
|
85
|
+
for j in out_of_unit_simplex:
|
|
86
|
+
|
|
87
|
+
while True:
|
|
88
|
+
X[j, X[j] < 0] = 0
|
|
89
|
+
|
|
90
|
+
# indices where the last point was already out of bounds
|
|
91
|
+
subspace = X[j] > 0
|
|
92
|
+
|
|
93
|
+
# project the bounds back onto the simplex in the subspace
|
|
94
|
+
X[j, subspace] = project_onto_sum_equals_one_plane(X[j][subspace])
|
|
95
|
+
|
|
96
|
+
if np.all(X[j] >= 0):
|
|
97
|
+
break
|
|
98
|
+
|
|
99
|
+
return X
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def matrix_project_onto_sum_equals_one_plane(next):
|
|
103
|
+
n_dim = len(next)
|
|
104
|
+
P, S = np.eye(n_dim)[0], next
|
|
105
|
+
|
|
106
|
+
# create for each subspace dimension a point on the hyperplane
|
|
107
|
+
points = P + np.eye(n_dim)[1:]
|
|
108
|
+
points /= points.sum(axis=1)[:, None]
|
|
109
|
+
|
|
110
|
+
v = points - P
|
|
111
|
+
s = S - P
|
|
112
|
+
|
|
113
|
+
# solve a system of linear equations to project the point
|
|
114
|
+
A = np.zeros((n_dim - 1, n_dim - 1))
|
|
115
|
+
for i in range(n_dim - 1):
|
|
116
|
+
for j in range(n_dim - 1):
|
|
117
|
+
A[i, j] = np.dot(v[i], v[j])
|
|
118
|
+
|
|
119
|
+
b = np.zeros(n_dim - 1)
|
|
120
|
+
for i in range(n_dim - 1):
|
|
121
|
+
b[i] = np.dot(s, v[i])
|
|
122
|
+
|
|
123
|
+
x = np.linalg.solve(A, b)
|
|
124
|
+
|
|
125
|
+
# finally calculate the projection onto the plane
|
|
126
|
+
proj = (P + x @ v)
|
|
127
|
+
|
|
128
|
+
return proj
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Optimizer:
|
|
5
|
+
|
|
6
|
+
def __init__(self, precision=1e-6) -> None:
|
|
7
|
+
super().__init__()
|
|
8
|
+
self.has_converged = False
|
|
9
|
+
self.precision = precision
|
|
10
|
+
|
|
11
|
+
def next(self, X, dX):
|
|
12
|
+
_X = self._next(X, dX)
|
|
13
|
+
|
|
14
|
+
if np.abs(_X - X).mean() < self.precision:
|
|
15
|
+
self.has_converged = True
|
|
16
|
+
|
|
17
|
+
return _X
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class GradientDescent(Optimizer):
|
|
21
|
+
|
|
22
|
+
def __init__(self, learning_rate=0.01, **kwargs) -> None:
|
|
23
|
+
super().__init__(**kwargs)
|
|
24
|
+
self.learning_rate = learning_rate
|
|
25
|
+
|
|
26
|
+
def _next(self, X, dX):
|
|
27
|
+
return X - self.learning_rate * dX
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Adam(Optimizer):
|
|
31
|
+
|
|
32
|
+
def __init__(self, alpha=0.01, beta_1=0.9, beta_2=0.999, epsilon=1e-8, **kwargs) -> None:
|
|
33
|
+
super().__init__(**kwargs)
|
|
34
|
+
|
|
35
|
+
self.alpha = alpha
|
|
36
|
+
self.beta_1 = beta_1
|
|
37
|
+
self.beta_2 = beta_2
|
|
38
|
+
self.epsilon = epsilon
|
|
39
|
+
|
|
40
|
+
self.m_t = 0
|
|
41
|
+
self.v_t = 0
|
|
42
|
+
self.t = 0
|
|
43
|
+
|
|
44
|
+
def _next(self, X, dX):
|
|
45
|
+
self.t += 1
|
|
46
|
+
beta_1, beta_2 = self.beta_1, self.beta_2
|
|
47
|
+
|
|
48
|
+
# update moving average of gradient and squared gradient
|
|
49
|
+
self.m_t = beta_1 * self.m_t + (1 - beta_1) * dX
|
|
50
|
+
self.v_t = beta_2 * self.v_t + (1 - beta_2) * (dX * dX)
|
|
51
|
+
|
|
52
|
+
# calculates the bias-corrected estimates
|
|
53
|
+
m_cap = self.m_t / (1 - (beta_1 ** self.t))
|
|
54
|
+
v_cap = self.v_t / (1 - (beta_2 ** self.t))
|
|
55
|
+
|
|
56
|
+
# do the gradient update
|
|
57
|
+
_X = X - (self.alpha * m_cap) / (np.sqrt(v_cap) + self.epsilon)
|
|
58
|
+
|
|
59
|
+
return _X
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import numpy as np
|
|
3
|
+
from scipy.spatial.qhull import Delaunay
|
|
4
|
+
from scipy.stats import gmean
|
|
5
|
+
|
|
6
|
+
from pymoo.util.misc import distance_of_closest_points_to_others, vectorized_cdist, cdist
|
|
7
|
+
from pymoo.util.ref_dirs.das_dennis import DasDennis
|
|
8
|
+
from pymoo.util.reference_direction import get_partition_closest_to_points
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def distance_of_closest_point(ref_dirs):
|
|
12
|
+
_, dist = distance_of_closest_points_to_others(ref_dirs)
|
|
13
|
+
return dist.min()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def average_distance_to_other_points(ref_dirs):
|
|
17
|
+
D = vectorized_cdist(ref_dirs, ref_dirs)
|
|
18
|
+
D = D[np.triu_indices(len(ref_dirs), 1)]
|
|
19
|
+
return D.mean()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def closest_point_variance(z):
|
|
23
|
+
for row in np.eye(z.shape[1]):
|
|
24
|
+
if not np.any(np.all(row == z, axis=1)):
|
|
25
|
+
z = np.row_stack([z, row])
|
|
26
|
+
|
|
27
|
+
D = vectorized_cdist(z, z)
|
|
28
|
+
np.fill_diagonal(D, 1)
|
|
29
|
+
|
|
30
|
+
return D.min(axis=1).var()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def closest_point_variance_mod(z):
|
|
34
|
+
n_points, n_dim = z.shape
|
|
35
|
+
|
|
36
|
+
for row in np.eye(z.shape[1]):
|
|
37
|
+
if not np.any(np.all(row == z, axis=1)):
|
|
38
|
+
z = np.row_stack([z, row])
|
|
39
|
+
|
|
40
|
+
D = vectorized_cdist(z, z)
|
|
41
|
+
np.fill_diagonal(D, np.inf)
|
|
42
|
+
|
|
43
|
+
k = int(np.ceil(np.sqrt(n_dim)))
|
|
44
|
+
I = D.argsort(axis=1)[:, k - 1]
|
|
45
|
+
|
|
46
|
+
return D[np.arange(n_points), I].var()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def geometric_mean_var(z):
|
|
50
|
+
for row in np.eye(z.shape[1]):
|
|
51
|
+
if not np.any(np.all(row == z, axis=1)):
|
|
52
|
+
z = np.row_stack([z, row])
|
|
53
|
+
n_points, n_dim = z.shape
|
|
54
|
+
|
|
55
|
+
D = vectorized_cdist(z, z)
|
|
56
|
+
np.fill_diagonal(D, np.inf)
|
|
57
|
+
|
|
58
|
+
k = n_dim - 1
|
|
59
|
+
I = D.argsort(axis=1)[:, :k]
|
|
60
|
+
|
|
61
|
+
first = np.column_stack([np.arange(n_points) for _ in range(k)])
|
|
62
|
+
|
|
63
|
+
val = gmean(D[first, I], axis=1)
|
|
64
|
+
|
|
65
|
+
return val.var()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def mean_mean(z):
|
|
69
|
+
for row in np.eye(z.shape[1]):
|
|
70
|
+
if not np.any(np.all(row == z, axis=1)):
|
|
71
|
+
z = np.row_stack([z, row])
|
|
72
|
+
n_points, n_dim = z.shape
|
|
73
|
+
|
|
74
|
+
D = vectorized_cdist(z, z)
|
|
75
|
+
np.fill_diagonal(D, np.inf)
|
|
76
|
+
|
|
77
|
+
k = n_dim - 1
|
|
78
|
+
I = D.argsort(axis=1)[:, :k]
|
|
79
|
+
|
|
80
|
+
first = np.column_stack([np.arange(n_points) for _ in range(k)])
|
|
81
|
+
|
|
82
|
+
val = np.mean(D[first, I], axis=1)
|
|
83
|
+
|
|
84
|
+
return val.mean()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def potential_energy(x):
|
|
88
|
+
_x = x / x.sum(axis=1)[:, None]
|
|
89
|
+
D = ((_x[:, None] - _x[None, :]) ** 2).sum(axis=2)
|
|
90
|
+
D = D[np.triu_indices(len(_x), 1)]
|
|
91
|
+
return (1 / D).mean()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def iterative_igd(X, n_partitions=None, batch_size=100):
|
|
95
|
+
n_points, n_dim = X.shape
|
|
96
|
+
|
|
97
|
+
if n_partitions is None:
|
|
98
|
+
n_partitions = get_partition_closest_to_points(n_points * n_dim * 10, n_dim) + 1
|
|
99
|
+
|
|
100
|
+
scaling = 1 + 1 / 2
|
|
101
|
+
|
|
102
|
+
dd = DasDennis(n_partitions, n_dim, scaling=scaling)
|
|
103
|
+
val = 0
|
|
104
|
+
|
|
105
|
+
while dd.has_next():
|
|
106
|
+
points = dd.next(n_points=batch_size)
|
|
107
|
+
val += cdist(points, X).min(axis=1).sum()
|
|
108
|
+
|
|
109
|
+
val /= dd.number_of_points()
|
|
110
|
+
return val
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def gram_schmidt(X, row_vecs=True, norm=True):
|
|
114
|
+
if not row_vecs:
|
|
115
|
+
X = X.T
|
|
116
|
+
Y = X[0:1, :].copy()
|
|
117
|
+
for i in range(1, X.shape[0]):
|
|
118
|
+
proj = np.diag((X[i, :].dot(Y.T) / np.linalg.norm(Y, axis=1) ** 2).flat).dot(Y)
|
|
119
|
+
Y = np.vstack((Y, X[i, :] - proj.sum(0)))
|
|
120
|
+
if norm:
|
|
121
|
+
Y = np.diag(1 / np.linalg.norm(Y, axis=1)).dot(Y)
|
|
122
|
+
if row_vecs:
|
|
123
|
+
return Y
|
|
124
|
+
else:
|
|
125
|
+
return Y.T
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def triangulation(X):
|
|
129
|
+
return simplex_edge_difference(project_onto_one_dim_less(X))
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def project_onto_one_dim_less(X):
|
|
133
|
+
E = np.eye(X.shape[1])
|
|
134
|
+
P = E[0]
|
|
135
|
+
D = E[1:] - P
|
|
136
|
+
O = gram_schmidt(D)
|
|
137
|
+
return (X - P) @ O.T
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def simplex_edge_difference(X):
|
|
141
|
+
tri = Delaunay(X, qhull_options="QJ")
|
|
142
|
+
|
|
143
|
+
simplices = []
|
|
144
|
+
for e in tri.simplices:
|
|
145
|
+
diff = X[e[1:]] - X[e[0]]
|
|
146
|
+
det = np.linalg.det(diff)
|
|
147
|
+
if det > 1e-6:
|
|
148
|
+
simplices.append(e)
|
|
149
|
+
|
|
150
|
+
val = []
|
|
151
|
+
for triangle in simplices:
|
|
152
|
+
dists = np.zeros(len(triangle))
|
|
153
|
+
|
|
154
|
+
for i in range(len(triangle)):
|
|
155
|
+
a, b = triangle[i], triangle[(i + 1) % len(triangle)]
|
|
156
|
+
dists[i] = np.linalg.norm(X[a] - X[b])
|
|
157
|
+
|
|
158
|
+
val.append(dists.max() - dists.min())
|
|
159
|
+
|
|
160
|
+
val = np.array(val)
|
|
161
|
+
|
|
162
|
+
return val.mean()
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from pymoo.util.misc import cdist
|
|
5
|
+
|
|
6
|
+
from pymoo.util.ref_dirs.misc import project_onto_unit_simplex_recursive
|
|
7
|
+
from pymoo.util.reference_direction import ReferenceDirectionFactory, sample_on_unit_simplex, \
|
|
8
|
+
select_points_with_maximum_distance, get_partition_closest_to_points, UniformReferenceDirectionFactory
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def kmeans(X, centroids, n_max_iter, a_tol, n_ignore):
|
|
12
|
+
|
|
13
|
+
for i in range(n_max_iter):
|
|
14
|
+
|
|
15
|
+
# copy the old centroids
|
|
16
|
+
last_centroids = np.copy(centroids)
|
|
17
|
+
|
|
18
|
+
# assign all points to one of the centroids
|
|
19
|
+
points_to_centroid = cdist(X, centroids).argmin(axis=1)
|
|
20
|
+
|
|
21
|
+
centroids_to_points = [[] for _ in range(len(centroids))]
|
|
22
|
+
for j, k in enumerate(points_to_centroid):
|
|
23
|
+
centroids_to_points[k].append(j)
|
|
24
|
+
|
|
25
|
+
for j in range(n_ignore, len(centroids_to_points)):
|
|
26
|
+
centroids[j] = np.mean(X[centroids_to_points[j]], axis=0)
|
|
27
|
+
|
|
28
|
+
project_onto_unit_simplex_recursive(centroids)
|
|
29
|
+
centroids /= centroids.sum(axis=1)[:, None]
|
|
30
|
+
|
|
31
|
+
delta = np.abs(centroids - last_centroids).sum(axis=1).mean()
|
|
32
|
+
|
|
33
|
+
if delta < a_tol:
|
|
34
|
+
break
|
|
35
|
+
|
|
36
|
+
return centroids
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ReductionBasedReferenceDirectionFactory(ReferenceDirectionFactory):
|
|
40
|
+
|
|
41
|
+
def __init__(self,
|
|
42
|
+
n_dim,
|
|
43
|
+
n_points,
|
|
44
|
+
scaling=None,
|
|
45
|
+
n_sample_points=10000,
|
|
46
|
+
sampling="kraemer",
|
|
47
|
+
kmeans=True,
|
|
48
|
+
kmeans_max_iter=1000,
|
|
49
|
+
kmeans_a_tol=0.0001,
|
|
50
|
+
**kwargs):
|
|
51
|
+
|
|
52
|
+
super().__init__(n_dim, scaling, **kwargs)
|
|
53
|
+
self.n_sample_points = n_sample_points
|
|
54
|
+
self.sampling = sampling
|
|
55
|
+
self.kmeans = kmeans
|
|
56
|
+
self.kmeans_max_iter = kmeans_max_iter
|
|
57
|
+
self.kmeans_a_tol = kmeans_a_tol
|
|
58
|
+
|
|
59
|
+
if n_points is None:
|
|
60
|
+
raise Exception("Please provide the number of points to be factored!")
|
|
61
|
+
|
|
62
|
+
self.n_points = n_points
|
|
63
|
+
|
|
64
|
+
def _do(self):
|
|
65
|
+
rnd = sample_on_unit_simplex(self.n_sample_points, self.n_dim, seed=self.seed, unit_simplex_mapping=self.sampling)
|
|
66
|
+
|
|
67
|
+
def h(n):
|
|
68
|
+
return get_partition_closest_to_points(n, self.n_dim)
|
|
69
|
+
|
|
70
|
+
H = h(self.n_points)
|
|
71
|
+
|
|
72
|
+
E = UniformReferenceDirectionFactory(self.n_dim, n_partitions=H).do()
|
|
73
|
+
E = E[np.any(E == 0, axis=1)]
|
|
74
|
+
|
|
75
|
+
# add the edge coordinates
|
|
76
|
+
X = np.row_stack([E, rnd])
|
|
77
|
+
|
|
78
|
+
I = select_points_with_maximum_distance(X, self.n_points, selected=list(range((len(E)))))
|
|
79
|
+
centroids = X[I].copy()
|
|
80
|
+
|
|
81
|
+
if self.kmeans:
|
|
82
|
+
#centroids = kmeans(X, centroids, self.kmeans_max_iter, self.kmeans_a_tol, 0)
|
|
83
|
+
centroids = kmeans(X, centroids, self.kmeans_max_iter, self.kmeans_a_tol, len(E))
|
|
84
|
+
|
|
85
|
+
return centroids
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.problem import Problem
|
|
4
|
+
from pymoo.operators.sampling.lhs import LatinHypercubeSampling
|
|
5
|
+
from pymoo.util.reference_direction import ReferenceDirectionFactory, map_onto_unit_simplex
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class RandomSamplingAndMap(ReferenceDirectionFactory):
|
|
9
|
+
|
|
10
|
+
def __init__(self,
|
|
11
|
+
n_dim,
|
|
12
|
+
n_points,
|
|
13
|
+
**kwargs):
|
|
14
|
+
super().__init__(n_dim, **kwargs)
|
|
15
|
+
self.n_points = n_points
|
|
16
|
+
|
|
17
|
+
def _do(self):
|
|
18
|
+
problem = Problem(n_var=self.n_dim, xl=0.0, xu=1.0)
|
|
19
|
+
sampling = LatinHypercubeSampling()
|
|
20
|
+
|
|
21
|
+
x = sampling(problem, self.n_points - self.n_dim, to_numpy=True)
|
|
22
|
+
x = map_onto_unit_simplex(x, "kraemer")
|
|
23
|
+
x = np.row_stack([x, np.eye(self.n_dim)])
|
|
24
|
+
return x
|