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.

Files changed (328) hide show
  1. pymoo/__init__.py +3 -0
  2. pymoo/algorithms/__init__.py +0 -0
  3. pymoo/algorithms/base/__init__.py +0 -0
  4. pymoo/algorithms/base/bracket.py +38 -0
  5. pymoo/algorithms/base/genetic.py +109 -0
  6. pymoo/algorithms/base/line.py +62 -0
  7. pymoo/algorithms/base/local.py +39 -0
  8. pymoo/algorithms/base/meta.py +79 -0
  9. pymoo/algorithms/hyperparameters.py +89 -0
  10. pymoo/algorithms/moo/__init__.py +0 -0
  11. pymoo/algorithms/moo/age.py +310 -0
  12. pymoo/algorithms/moo/age2.py +194 -0
  13. pymoo/algorithms/moo/ctaea.py +298 -0
  14. pymoo/algorithms/moo/dnsga2.py +76 -0
  15. pymoo/algorithms/moo/kgb.py +446 -0
  16. pymoo/algorithms/moo/moead.py +183 -0
  17. pymoo/algorithms/moo/nsga2.py +113 -0
  18. pymoo/algorithms/moo/nsga3.py +358 -0
  19. pymoo/algorithms/moo/pinsga2.py +370 -0
  20. pymoo/algorithms/moo/rnsga2.py +188 -0
  21. pymoo/algorithms/moo/rnsga3.py +246 -0
  22. pymoo/algorithms/moo/rvea.py +214 -0
  23. pymoo/algorithms/moo/sms.py +195 -0
  24. pymoo/algorithms/moo/spea2.py +190 -0
  25. pymoo/algorithms/moo/unsga3.py +47 -0
  26. pymoo/algorithms/soo/__init__.py +0 -0
  27. pymoo/algorithms/soo/convex/__init__.py +0 -0
  28. pymoo/algorithms/soo/nonconvex/__init__.py +0 -0
  29. pymoo/algorithms/soo/nonconvex/brkga.py +161 -0
  30. pymoo/algorithms/soo/nonconvex/cmaes.py +554 -0
  31. pymoo/algorithms/soo/nonconvex/de.py +279 -0
  32. pymoo/algorithms/soo/nonconvex/direct.py +149 -0
  33. pymoo/algorithms/soo/nonconvex/es.py +203 -0
  34. pymoo/algorithms/soo/nonconvex/g3pcx.py +94 -0
  35. pymoo/algorithms/soo/nonconvex/ga.py +93 -0
  36. pymoo/algorithms/soo/nonconvex/ga_niching.py +223 -0
  37. pymoo/algorithms/soo/nonconvex/isres.py +74 -0
  38. pymoo/algorithms/soo/nonconvex/nelder.py +251 -0
  39. pymoo/algorithms/soo/nonconvex/optuna.py +80 -0
  40. pymoo/algorithms/soo/nonconvex/pattern.py +183 -0
  41. pymoo/algorithms/soo/nonconvex/pso.py +399 -0
  42. pymoo/algorithms/soo/nonconvex/pso_ep.py +297 -0
  43. pymoo/algorithms/soo/nonconvex/random_search.py +25 -0
  44. pymoo/algorithms/soo/nonconvex/sres.py +56 -0
  45. pymoo/algorithms/soo/univariate/__init__.py +0 -0
  46. pymoo/algorithms/soo/univariate/backtracking.py +59 -0
  47. pymoo/algorithms/soo/univariate/exp.py +46 -0
  48. pymoo/algorithms/soo/univariate/golden.py +65 -0
  49. pymoo/algorithms/soo/univariate/quadr_interp.py +81 -0
  50. pymoo/algorithms/soo/univariate/wolfe.py +163 -0
  51. pymoo/config.py +33 -0
  52. pymoo/constraints/__init__.py +3 -0
  53. pymoo/constraints/adaptive.py +62 -0
  54. pymoo/constraints/as_obj.py +56 -0
  55. pymoo/constraints/as_penalty.py +41 -0
  56. pymoo/constraints/eps.py +26 -0
  57. pymoo/constraints/from_bounds.py +36 -0
  58. pymoo/core/__init__.py +0 -0
  59. pymoo/core/algorithm.py +394 -0
  60. pymoo/core/callback.py +38 -0
  61. pymoo/core/crossover.py +77 -0
  62. pymoo/core/decision_making.py +102 -0
  63. pymoo/core/decomposition.py +76 -0
  64. pymoo/core/duplicate.py +163 -0
  65. pymoo/core/evaluator.py +116 -0
  66. pymoo/core/indicator.py +34 -0
  67. pymoo/core/individual.py +784 -0
  68. pymoo/core/infill.py +64 -0
  69. pymoo/core/initialization.py +42 -0
  70. pymoo/core/mating.py +39 -0
  71. pymoo/core/meta.py +21 -0
  72. pymoo/core/mixed.py +165 -0
  73. pymoo/core/mutation.py +44 -0
  74. pymoo/core/operator.py +40 -0
  75. pymoo/core/parameters.py +134 -0
  76. pymoo/core/plot.py +210 -0
  77. pymoo/core/population.py +180 -0
  78. pymoo/core/problem.py +460 -0
  79. pymoo/core/recorder.py +99 -0
  80. pymoo/core/repair.py +23 -0
  81. pymoo/core/replacement.py +96 -0
  82. pymoo/core/result.py +52 -0
  83. pymoo/core/sampling.py +43 -0
  84. pymoo/core/selection.py +61 -0
  85. pymoo/core/solution.py +10 -0
  86. pymoo/core/survival.py +103 -0
  87. pymoo/core/termination.py +70 -0
  88. pymoo/core/variable.py +399 -0
  89. pymoo/cython/__init__.py +0 -0
  90. pymoo/cython/calc_perpendicular_distance.cpython-310-darwin.so +0 -0
  91. pymoo/cython/calc_perpendicular_distance.pyx +67 -0
  92. pymoo/cython/decomposition.cpython-310-darwin.so +0 -0
  93. pymoo/cython/decomposition.pyx +165 -0
  94. pymoo/cython/hv.cpython-310-darwin.so +0 -0
  95. pymoo/cython/hv.pyx +18 -0
  96. pymoo/cython/info.cpython-310-darwin.so +0 -0
  97. pymoo/cython/info.pyx +5 -0
  98. pymoo/cython/mnn.cpython-310-darwin.so +0 -0
  99. pymoo/cython/mnn.pyx +273 -0
  100. pymoo/cython/non_dominated_sorting.cpython-310-darwin.so +0 -0
  101. pymoo/cython/non_dominated_sorting.pyx +645 -0
  102. pymoo/cython/pruning_cd.cpython-310-darwin.so +0 -0
  103. pymoo/cython/pruning_cd.pyx +197 -0
  104. pymoo/cython/stochastic_ranking.cpython-310-darwin.so +0 -0
  105. pymoo/cython/stochastic_ranking.pyx +49 -0
  106. pymoo/cython/utils.pxd +129 -0
  107. pymoo/cython/vendor/__init__.py +0 -0
  108. pymoo/cython/vendor/hypervolume.cpp +1621 -0
  109. pymoo/cython/vendor/hypervolume.h +63 -0
  110. pymoo/decomposition/__init__.py +0 -0
  111. pymoo/decomposition/aasf.py +24 -0
  112. pymoo/decomposition/asf.py +10 -0
  113. pymoo/decomposition/pbi.py +13 -0
  114. pymoo/decomposition/perp_dist.py +13 -0
  115. pymoo/decomposition/tchebicheff.py +11 -0
  116. pymoo/decomposition/util.py +13 -0
  117. pymoo/decomposition/weighted_sum.py +8 -0
  118. pymoo/docs.py +187 -0
  119. pymoo/experimental/__init__.py +0 -0
  120. pymoo/experimental/algorithms/__init__.py +0 -0
  121. pymoo/experimental/algorithms/gde3.py +57 -0
  122. pymoo/gradient/__init__.py +21 -0
  123. pymoo/gradient/automatic.py +57 -0
  124. pymoo/gradient/grad_autograd.py +105 -0
  125. pymoo/gradient/grad_complex.py +35 -0
  126. pymoo/gradient/grad_jax.py +51 -0
  127. pymoo/gradient/toolbox/__init__.py +6 -0
  128. pymoo/indicators/__init__.py +0 -0
  129. pymoo/indicators/distance_indicator.py +55 -0
  130. pymoo/indicators/gd.py +7 -0
  131. pymoo/indicators/gd_plus.py +7 -0
  132. pymoo/indicators/hv/__init__.py +63 -0
  133. pymoo/indicators/hv/exact.py +71 -0
  134. pymoo/indicators/hv/exact_2d.py +102 -0
  135. pymoo/indicators/hv/monte_carlo.py +74 -0
  136. pymoo/indicators/igd.py +7 -0
  137. pymoo/indicators/igd_plus.py +7 -0
  138. pymoo/indicators/kktpm.py +151 -0
  139. pymoo/indicators/migd.py +55 -0
  140. pymoo/indicators/rmetric.py +203 -0
  141. pymoo/indicators/spacing.py +52 -0
  142. pymoo/mcdm/__init__.py +0 -0
  143. pymoo/mcdm/compromise_programming.py +19 -0
  144. pymoo/mcdm/high_tradeoff.py +40 -0
  145. pymoo/mcdm/pseudo_weights.py +32 -0
  146. pymoo/operators/__init__.py +0 -0
  147. pymoo/operators/control.py +187 -0
  148. pymoo/operators/crossover/__init__.py +0 -0
  149. pymoo/operators/crossover/binx.py +45 -0
  150. pymoo/operators/crossover/dex.py +122 -0
  151. pymoo/operators/crossover/erx.py +162 -0
  152. pymoo/operators/crossover/expx.py +51 -0
  153. pymoo/operators/crossover/hux.py +37 -0
  154. pymoo/operators/crossover/nox.py +13 -0
  155. pymoo/operators/crossover/ox.py +84 -0
  156. pymoo/operators/crossover/pcx.py +82 -0
  157. pymoo/operators/crossover/pntx.py +49 -0
  158. pymoo/operators/crossover/sbx.py +125 -0
  159. pymoo/operators/crossover/spx.py +5 -0
  160. pymoo/operators/crossover/ux.py +20 -0
  161. pymoo/operators/mutation/__init__.py +0 -0
  162. pymoo/operators/mutation/bitflip.py +17 -0
  163. pymoo/operators/mutation/gauss.py +58 -0
  164. pymoo/operators/mutation/inversion.py +42 -0
  165. pymoo/operators/mutation/nom.py +7 -0
  166. pymoo/operators/mutation/pm.py +94 -0
  167. pymoo/operators/mutation/rm.py +23 -0
  168. pymoo/operators/repair/__init__.py +0 -0
  169. pymoo/operators/repair/bounce_back.py +32 -0
  170. pymoo/operators/repair/bounds_repair.py +95 -0
  171. pymoo/operators/repair/inverse_penalty.py +89 -0
  172. pymoo/operators/repair/rounding.py +18 -0
  173. pymoo/operators/repair/to_bound.py +31 -0
  174. pymoo/operators/repair/vtype.py +11 -0
  175. pymoo/operators/sampling/__init__.py +0 -0
  176. pymoo/operators/sampling/lhs.py +73 -0
  177. pymoo/operators/sampling/rnd.py +50 -0
  178. pymoo/operators/selection/__init__.py +0 -0
  179. pymoo/operators/selection/rnd.py +72 -0
  180. pymoo/operators/selection/tournament.py +76 -0
  181. pymoo/operators/survival/__init__.py +0 -0
  182. pymoo/operators/survival/rank_and_crowding/__init__.py +1 -0
  183. pymoo/operators/survival/rank_and_crowding/classes.py +209 -0
  184. pymoo/operators/survival/rank_and_crowding/metrics.py +208 -0
  185. pymoo/optimize.py +72 -0
  186. pymoo/problems/__init__.py +157 -0
  187. pymoo/problems/dyn.py +47 -0
  188. pymoo/problems/dynamic/__init__.py +0 -0
  189. pymoo/problems/dynamic/cec2015.py +108 -0
  190. pymoo/problems/dynamic/df.py +452 -0
  191. pymoo/problems/dynamic/misc.py +167 -0
  192. pymoo/problems/functional.py +48 -0
  193. pymoo/problems/many/__init__.py +5 -0
  194. pymoo/problems/many/cdtlz.py +159 -0
  195. pymoo/problems/many/dcdtlz.py +88 -0
  196. pymoo/problems/many/dtlz.py +264 -0
  197. pymoo/problems/many/wfg.py +550 -0
  198. pymoo/problems/multi/__init__.py +14 -0
  199. pymoo/problems/multi/bnh.py +34 -0
  200. pymoo/problems/multi/carside.py +48 -0
  201. pymoo/problems/multi/clutch.py +104 -0
  202. pymoo/problems/multi/csi.py +55 -0
  203. pymoo/problems/multi/ctp.py +198 -0
  204. pymoo/problems/multi/dascmop.py +213 -0
  205. pymoo/problems/multi/kursawe.py +25 -0
  206. pymoo/problems/multi/modact.py +68 -0
  207. pymoo/problems/multi/mw.py +400 -0
  208. pymoo/problems/multi/omnitest.py +48 -0
  209. pymoo/problems/multi/osy.py +32 -0
  210. pymoo/problems/multi/srn.py +28 -0
  211. pymoo/problems/multi/sympart.py +94 -0
  212. pymoo/problems/multi/tnk.py +24 -0
  213. pymoo/problems/multi/truss2d.py +83 -0
  214. pymoo/problems/multi/welded_beam.py +41 -0
  215. pymoo/problems/multi/wrm.py +36 -0
  216. pymoo/problems/multi/zdt.py +151 -0
  217. pymoo/problems/multi_to_single.py +22 -0
  218. pymoo/problems/single/__init__.py +12 -0
  219. pymoo/problems/single/ackley.py +24 -0
  220. pymoo/problems/single/cantilevered_beam.py +34 -0
  221. pymoo/problems/single/flowshop_scheduling.py +112 -0
  222. pymoo/problems/single/g.py +874 -0
  223. pymoo/problems/single/griewank.py +18 -0
  224. pymoo/problems/single/himmelblau.py +15 -0
  225. pymoo/problems/single/knapsack.py +48 -0
  226. pymoo/problems/single/mopta08.py +26 -0
  227. pymoo/problems/single/multimodal.py +20 -0
  228. pymoo/problems/single/pressure_vessel.py +30 -0
  229. pymoo/problems/single/rastrigin.py +20 -0
  230. pymoo/problems/single/rosenbrock.py +22 -0
  231. pymoo/problems/single/schwefel.py +18 -0
  232. pymoo/problems/single/simple.py +13 -0
  233. pymoo/problems/single/sphere.py +19 -0
  234. pymoo/problems/single/traveling_salesman.py +79 -0
  235. pymoo/problems/single/zakharov.py +19 -0
  236. pymoo/problems/static.py +14 -0
  237. pymoo/problems/util.py +42 -0
  238. pymoo/problems/zero_to_one.py +27 -0
  239. pymoo/termination/__init__.py +23 -0
  240. pymoo/termination/collection.py +12 -0
  241. pymoo/termination/cv.py +48 -0
  242. pymoo/termination/default.py +45 -0
  243. pymoo/termination/delta.py +64 -0
  244. pymoo/termination/fmin.py +16 -0
  245. pymoo/termination/ftol.py +144 -0
  246. pymoo/termination/indicator.py +49 -0
  247. pymoo/termination/max_eval.py +14 -0
  248. pymoo/termination/max_gen.py +15 -0
  249. pymoo/termination/max_time.py +20 -0
  250. pymoo/termination/robust.py +34 -0
  251. pymoo/termination/xtol.py +33 -0
  252. pymoo/util/__init__.py +0 -0
  253. pymoo/util/archive.py +150 -0
  254. pymoo/util/cache.py +29 -0
  255. pymoo/util/clearing.py +82 -0
  256. pymoo/util/display/__init__.py +0 -0
  257. pymoo/util/display/column.py +52 -0
  258. pymoo/util/display/display.py +34 -0
  259. pymoo/util/display/multi.py +96 -0
  260. pymoo/util/display/output.py +53 -0
  261. pymoo/util/display/progress.py +54 -0
  262. pymoo/util/display/single.py +67 -0
  263. pymoo/util/dominator.py +67 -0
  264. pymoo/util/function_loader.py +129 -0
  265. pymoo/util/hv.py +23 -0
  266. pymoo/util/matlab_engine.py +39 -0
  267. pymoo/util/misc.py +460 -0
  268. pymoo/util/mnn.py +70 -0
  269. pymoo/util/nds/__init__.py +0 -0
  270. pymoo/util/nds/dominance_degree_non_dominated_sort.py +159 -0
  271. pymoo/util/nds/efficient_non_dominated_sort.py +152 -0
  272. pymoo/util/nds/fast_non_dominated_sort.py +70 -0
  273. pymoo/util/nds/naive_non_dominated_sort.py +36 -0
  274. pymoo/util/nds/non_dominated_sorting.py +67 -0
  275. pymoo/util/nds/tree_based_non_dominated_sort.py +133 -0
  276. pymoo/util/normalization.py +312 -0
  277. pymoo/util/optimum.py +42 -0
  278. pymoo/util/plotting.py +177 -0
  279. pymoo/util/pruning_cd.py +89 -0
  280. pymoo/util/randomized_argsort.py +60 -0
  281. pymoo/util/ref_dirs/__init__.py +24 -0
  282. pymoo/util/ref_dirs/construction.py +88 -0
  283. pymoo/util/ref_dirs/das_dennis.py +52 -0
  284. pymoo/util/ref_dirs/energy.py +319 -0
  285. pymoo/util/ref_dirs/energy_layer.py +119 -0
  286. pymoo/util/ref_dirs/genetic_algorithm.py +63 -0
  287. pymoo/util/ref_dirs/incremental.py +68 -0
  288. pymoo/util/ref_dirs/misc.py +128 -0
  289. pymoo/util/ref_dirs/optimizer.py +59 -0
  290. pymoo/util/ref_dirs/performance.py +162 -0
  291. pymoo/util/ref_dirs/reduction.py +85 -0
  292. pymoo/util/ref_dirs/sample_and_map.py +24 -0
  293. pymoo/util/reference_direction.py +260 -0
  294. pymoo/util/remote.py +55 -0
  295. pymoo/util/roulette.py +27 -0
  296. pymoo/util/running_metric.py +128 -0
  297. pymoo/util/sliding_window.py +25 -0
  298. pymoo/util/stochastic_ranking.py +32 -0
  299. pymoo/util/value_functions.py +719 -0
  300. pymoo/util/vectors.py +40 -0
  301. pymoo/util/vf_dominator.py +99 -0
  302. pymoo/vendor/__init__.py +0 -0
  303. pymoo/vendor/cec2018.py +398 -0
  304. pymoo/vendor/gta.py +617 -0
  305. pymoo/vendor/hv.py +267 -0
  306. pymoo/vendor/vendor_cmaes.py +412 -0
  307. pymoo/vendor/vendor_coco.py +81 -0
  308. pymoo/vendor/vendor_scipy.py +232 -0
  309. pymoo/version.py +1 -0
  310. pymoo/visualization/__init__.py +8 -0
  311. pymoo/visualization/fitness_landscape.py +127 -0
  312. pymoo/visualization/heatmap.py +123 -0
  313. pymoo/visualization/pcp.py +120 -0
  314. pymoo/visualization/petal.py +91 -0
  315. pymoo/visualization/radar.py +108 -0
  316. pymoo/visualization/radviz.py +68 -0
  317. pymoo/visualization/scatter.py +150 -0
  318. pymoo/visualization/star_coordinate.py +75 -0
  319. pymoo/visualization/util.py +123 -0
  320. pymoo/visualization/video/__init__.py +0 -0
  321. pymoo/visualization/video/callback_video.py +82 -0
  322. pymoo/visualization/video/one_var_one_obj.py +57 -0
  323. pymoo/visualization/video/two_var_one_obj.py +62 -0
  324. pymoo-0.6.1.5.dev0.dist-info/METADATA +187 -0
  325. pymoo-0.6.1.5.dev0.dist-info/RECORD +328 -0
  326. pymoo-0.6.1.5.dev0.dist-info/WHEEL +6 -0
  327. pymoo-0.6.1.5.dev0.dist-info/licenses/LICENSE +191 -0
  328. pymoo-0.6.1.5.dev0.dist-info/top_level.txt +1 -0
pymoo/util/misc.py ADDED
@@ -0,0 +1,460 @@
1
+ from collections import OrderedDict
2
+ from datetime import datetime
3
+ from itertools import combinations
4
+
5
+ import numpy as np
6
+
7
+
8
+ from pymoo.core.population import Population
9
+ from pymoo.core.sampling import Sampling
10
+
11
+
12
+
13
+ def parameter_less(F, CV, fmax=None, inplace=False):
14
+ assert len(F) == len(CV)
15
+
16
+ if not inplace:
17
+ F = np.copy(F)
18
+
19
+ if fmax is None:
20
+ fmax = np.max(F)
21
+
22
+ param_less = fmax + CV
23
+
24
+ infeas = (CV > 0).flatten()
25
+ F[infeas] = param_less[infeas]
26
+
27
+ return F
28
+
29
+
30
+ def swap(M, a, b):
31
+ tmp = M[a]
32
+ M[a] = M[b]
33
+ M[b] = tmp
34
+
35
+
36
+ # repairs a numpy array to be in bounds
37
+ def repair(X, xl, xu):
38
+ larger_than_xu = X[0, :] > xu
39
+ X[0, larger_than_xu] = xu[larger_than_xu]
40
+
41
+ smaller_than_xl = X[0, :] < xl
42
+ X[0, smaller_than_xl] = xl[smaller_than_xl]
43
+
44
+ return X
45
+
46
+
47
+ def unique_rows(a):
48
+ a = np.ascontiguousarray(a)
49
+ unique_a = np.unique(a.view([('', a.dtype)] * a.shape[1]))
50
+ return unique_a.view(a.dtype).reshape((unique_a.shape[0], a.shape[1]))
51
+
52
+
53
+ def parameter_less_constraints(F, CV, F_max=None):
54
+ if F_max is None:
55
+ F_max = np.max(F)
56
+ has_constraint_violation = CV > 0
57
+ F[has_constraint_violation] = CV[has_constraint_violation] + F_max
58
+ return F
59
+
60
+
61
+ def random_permutations(n, l, concat=True):
62
+ P = []
63
+ for i in range(n):
64
+ P.append(np.random.permutation(l))
65
+ if concat:
66
+ P = np.concatenate(P)
67
+ return P
68
+
69
+
70
+ def get_duplicates(M):
71
+ res = []
72
+ I = np.lexsort([M[:, i] for i in reversed(range(0, M.shape[1]))])
73
+ S = M[I, :]
74
+
75
+ i = 0
76
+
77
+ while i < S.shape[0] - 1:
78
+ l = []
79
+ while np.all(S[i, :] == S[i + 1, :]):
80
+ l.append(I[i])
81
+ i += 1
82
+ if len(l) > 0:
83
+ l.append(I[i])
84
+ res.append(l)
85
+ i += 1
86
+
87
+ return res
88
+
89
+
90
+ # -----------------------------------------------
91
+ # Euclidean Distance
92
+ # -----------------------------------------------
93
+
94
+ def func_euclidean_distance(a, b):
95
+ return np.sqrt(((a - b) ** 2).sum(axis=1))
96
+
97
+
98
+ def func_norm_euclidean_distance(xl, xu):
99
+ return lambda a, b: np.sqrt((((a - b) / (xu - xl)) ** 2).sum(axis=1))
100
+
101
+
102
+ def norm_eucl_dist_by_bounds(A, B, xl, xu, **kwargs):
103
+ return vectorized_cdist(A, B, func_dist=func_norm_euclidean_distance(xl, xu), **kwargs)
104
+
105
+
106
+ def norm_eucl_dist(problem, A, B, **kwargs):
107
+ return norm_eucl_dist_by_bounds(A, B, *problem.bounds(), **kwargs)
108
+
109
+
110
+ # -----------------------------------------------
111
+ # Manhatten Distance
112
+ # -----------------------------------------------
113
+
114
+ def func_manhatten_distance(a, b):
115
+ return np.abs(a - b).sum(axis=1)
116
+
117
+
118
+ def func_norm_manhatten_distance(xl, xu):
119
+ return lambda a, b: np.abs((a - b) / (xu - xl)).sum(axis=1)
120
+
121
+
122
+ def norm_manhatten_dist_by_bounds(A, B, xl, xu, **kwargs):
123
+ return vectorized_cdist(A, B, func_dist=func_norm_manhatten_distance(xl, xu), **kwargs)
124
+
125
+
126
+ def norm_manhatten_dist(problem, A, B, **kwargs):
127
+ return norm_manhatten_dist_by_bounds(A, B, *problem.bounds(), **kwargs)
128
+
129
+
130
+ # -----------------------------------------------
131
+ # Tchebychev Distance
132
+ # -----------------------------------------------
133
+
134
+
135
+ def func_tchebychev_distance(a, b):
136
+ return np.abs(a - b).max(axis=1)
137
+
138
+
139
+ def func_norm_tchebychev_distance(xl, xu):
140
+ return lambda a, b: np.abs((a - b) / (xu - xl)).max(axis=1)
141
+
142
+
143
+ def norm_tchebychev_dist_by_bounds(A, B, xl, xu, **kwargs):
144
+ return vectorized_cdist(A, B, func_dist=func_norm_tchebychev_distance(xl, xu), **kwargs)
145
+
146
+
147
+ def norm_tchebychev_dist(problem, A, B, **kwargs):
148
+ return norm_tchebychev_dist_by_bounds(A, B, *problem.bounds(), **kwargs)
149
+
150
+
151
+ # -----------------------------------------------
152
+ # Others
153
+ # -----------------------------------------------
154
+
155
+
156
+ def cdist(A, B, **kwargs):
157
+ from scipy.spatial import distance
158
+ return distance.cdist(A.astype(float), B.astype(float), **kwargs)
159
+
160
+
161
+ def vectorized_cdist(A, B, func_dist=func_euclidean_distance, fill_diag_with_inf=False, **kwargs) -> object:
162
+ assert A.ndim <= 2 and B.ndim <= 2
163
+
164
+ A, only_row = at_least_2d_array(A, extend_as="row", return_if_reshaped=True)
165
+ B, only_column = at_least_2d_array(B, extend_as="row", return_if_reshaped=True)
166
+
167
+ u = np.repeat(A, B.shape[0], axis=0)
168
+ v = np.tile(B, (A.shape[0], 1))
169
+
170
+ D = func_dist(u, v, **kwargs)
171
+ M = np.reshape(D, (A.shape[0], B.shape[0]))
172
+
173
+ if fill_diag_with_inf:
174
+ np.fill_diagonal(M, np.inf)
175
+
176
+ if only_row and only_column:
177
+ M = M[0, 0]
178
+ elif only_row:
179
+ M = M[0]
180
+ elif only_column:
181
+ M = M[:, [0]]
182
+
183
+ return M
184
+
185
+
186
+ def covert_to_type(problem, X):
187
+ if problem.vtype == float:
188
+ return X.astype(np.double)
189
+ elif problem.vtype == int:
190
+ return np.round(X).astype(int)
191
+ elif problem.vtype == bool:
192
+ return X < (problem.xu - problem.xl) / 2
193
+
194
+
195
+ def find_duplicates(X, epsilon=1e-16):
196
+ # calculate the distance matrix from each point to another
197
+ D = cdist(X, X)
198
+
199
+ # set the diagonal to infinity
200
+ D[np.triu_indices(len(X))] = np.inf
201
+
202
+ # set as duplicate if a point is really close to this one
203
+ is_duplicate = np.any(D <= epsilon, axis=1)
204
+
205
+ return is_duplicate
206
+
207
+
208
+ def at_least_2d(*args, **kwargs):
209
+ ret = tuple([at_least_2d_array(arg, **kwargs) for arg in args])
210
+ if len(ret) == 1:
211
+ ret = ret[0]
212
+ return ret
213
+
214
+
215
+ def at_least_2d_array(x, extend_as="row", return_if_reshaped=False):
216
+ if x is None:
217
+ return x
218
+ elif not isinstance(x, np.ndarray):
219
+ x = np.array([x])
220
+
221
+ has_been_reshaped = False
222
+
223
+ if x.ndim == 1:
224
+ if extend_as.startswith("r"):
225
+ x = x[None, :]
226
+ elif extend_as.startswith("c"):
227
+ x = x[:, None]
228
+ else:
229
+ raise Exception("The option `extend_as` should be either `row` or `column`.")
230
+
231
+ has_been_reshaped = True
232
+
233
+ if return_if_reshaped:
234
+ return x, has_been_reshaped
235
+ else:
236
+ return x
237
+
238
+
239
+ def to_1d_array_if_possible(x):
240
+ if not isinstance(x, np.ndarray):
241
+ x = np.array([x])
242
+
243
+ if x.ndim == 2:
244
+ if x.shape[0] == 1 or x.shape[1] == 1:
245
+ x = x.flatten()
246
+
247
+ return x
248
+
249
+
250
+ def stack(*args, flatten=True):
251
+ if not flatten:
252
+ ps = np.concatenate([e[None, ...] for e in args])
253
+ else:
254
+ ps = np.row_stack(args)
255
+ return ps
256
+
257
+
258
+ def all_except(x, *args):
259
+ if len(args) == 0:
260
+ return x
261
+ else:
262
+ H = set(args) if len(args) > 5 else args
263
+ I = [k for k in range(len(x)) if k not in H]
264
+ return x[I]
265
+
266
+
267
+ def all_combinations(A, B):
268
+ u = np.repeat(A, B.shape[0], axis=0)
269
+ v = np.tile(B, A.shape[0])
270
+ return np.column_stack([u, v])
271
+
272
+
273
+ def pop_from_sampling(problem, sampling, n_initial_samples, pop=None):
274
+ # the population type can be different - (different type of individuals)
275
+ if pop is None:
276
+ pop = Population()
277
+
278
+ # provide a whole population object - (individuals might be already evaluated)
279
+ if isinstance(sampling, Population):
280
+ pop = sampling
281
+
282
+ else:
283
+ # if just an X array create a pop
284
+ if isinstance(sampling, np.ndarray):
285
+ pop = pop.new("X", sampling)
286
+
287
+ elif isinstance(sampling, Sampling):
288
+ # use the sampling
289
+ pop = sampling.do(problem, n_initial_samples, pop=pop)
290
+
291
+ else:
292
+ return None
293
+
294
+ return pop
295
+
296
+
297
+ def evaluate_if_not_done_yet(evaluator, problem, pop, algorithm=None):
298
+ I = np.where(pop.get("F") == None)[0]
299
+ if len(I) > 0:
300
+ pop[I] = evaluator.process(problem, pop[I], algorithm=algorithm)
301
+
302
+
303
+ def set_if_none(kwargs, str, val):
304
+ if str not in kwargs:
305
+ kwargs[str] = val
306
+
307
+
308
+ def set_if_none_from_tuples(kwargs, *args):
309
+ for key, val in args:
310
+ if key not in kwargs:
311
+ kwargs[key] = val
312
+
313
+
314
+ def calc_perpendicular_distance(N, ref_dirs):
315
+ u = np.tile(ref_dirs, (len(N), 1))
316
+ v = np.repeat(N, len(ref_dirs), axis=0)
317
+
318
+ norm_u = np.linalg.norm(u, axis=1)
319
+
320
+ scalar_proj = np.sum(v * u, axis=1) / norm_u
321
+ proj = scalar_proj[:, None] * u / norm_u[:, None]
322
+ val = np.linalg.norm(proj - v, axis=1)
323
+ matrix = np.reshape(val, (len(N), len(ref_dirs)))
324
+
325
+ return matrix
326
+
327
+
328
+ def distance_of_closest_points_to_others(X):
329
+ D = vectorized_cdist(X, X)
330
+ np.fill_diagonal(D, np.inf)
331
+ return D.argmin(axis=1), D.min(axis=1)
332
+
333
+
334
+ def time_to_int(t):
335
+ vals = [int(e) for e in t.split(":")][::-1]
336
+ s = vals[0]
337
+ if len(vals) > 1:
338
+ s += 60 * vals[1]
339
+ if len(vals) > 2:
340
+ s += 3600 * vals[2]
341
+ return s
342
+
343
+
344
+ def powerset(iterable):
345
+ for n in range(len(iterable) + 1):
346
+ yield from combinations(iterable, n)
347
+
348
+
349
+ def intersect(a, b):
350
+ H = set()
351
+ for entry in b:
352
+ H.add(entry)
353
+
354
+ ret = []
355
+ for entry in a:
356
+ if entry in H:
357
+ ret.append(entry)
358
+
359
+ return ret
360
+
361
+
362
+ def has_feasible(pop):
363
+ return np.any(pop.get("FEAS"))
364
+
365
+
366
+ def to_numpy(a):
367
+ return np.array(a)
368
+
369
+
370
+ def termination_from_tuple(termination):
371
+ from pymoo.core.termination import Termination
372
+
373
+ # get the termination if provided as a tuple - create an object
374
+ if termination is not None and not isinstance(termination, Termination):
375
+ from pymoo.termination import get_termination
376
+ if isinstance(termination, str):
377
+ termination = get_termination(termination)
378
+ else:
379
+ termination = get_termination(*termination)
380
+
381
+ return termination
382
+
383
+
384
+ def unique_and_all_indices(arr):
385
+ sort_indexes = np.argsort(arr)
386
+ arr = np.asarray(arr)[sort_indexes]
387
+ vals, first_indexes, inverse, counts = np.unique(arr,
388
+ return_index=True, return_inverse=True, return_counts=True)
389
+ indexes = np.split(sort_indexes, first_indexes[1:])
390
+ for x in indexes:
391
+ x.sort()
392
+ return vals, indexes
393
+
394
+
395
+ def from_dict(D, *keys):
396
+ return [D.get(k) for k in keys]
397
+
398
+
399
+ def list_of_dicts_unique(l, k):
400
+ return list(OrderedDict([(e[k], None) for e in l]).keys())
401
+
402
+
403
+ def list_of_dicts_filter(l, *pairs):
404
+ return [e for e in l if all(e[k] == v for (k, v) in pairs)]
405
+
406
+
407
+ def logical_op(func, a, b, *args):
408
+ ret = func(a, b)
409
+ for c in args:
410
+ ret = func(ret, c)
411
+ return ret
412
+
413
+
414
+ def replace_nan_by(x, val, inplace=False):
415
+ is_nan = np.isnan(x)
416
+ if np.sum(is_nan) > 0:
417
+ if not inplace:
418
+ x = x.copy()
419
+ x[is_nan] = val
420
+ return x
421
+
422
+
423
+ def set_defaults(kwargs, defaults, overwrite=False, func_get=lambda x: x):
424
+ for k, v in defaults.items():
425
+ if overwrite or k not in kwargs:
426
+ kwargs[k] = func_get(v)
427
+
428
+
429
+ def filter_params(params, prefix, delete_prefix=True):
430
+ ret = {}
431
+ for k, v in params.items():
432
+ if k.startswith(prefix):
433
+ if delete_prefix:
434
+ k = k[len(prefix):]
435
+ ret[k] = v
436
+ return ret
437
+
438
+
439
+ def where_is_what(x):
440
+ H = {}
441
+ for k, e in enumerate(x):
442
+ if e not in H:
443
+ H[e] = []
444
+ H[e].append(k)
445
+ return H
446
+
447
+
448
+ def crossover_mask(X, M):
449
+ # convert input to output by flatting along the first axis
450
+ _X = np.copy(X)
451
+ _X[0][M] = X[1][M]
452
+ _X[1][M] = X[0][M]
453
+ return _X
454
+
455
+
456
+ def row_at_least_once_true(M):
457
+ _, d = M.shape
458
+ for k in np.where(~np.any(M, axis=1))[0]:
459
+ M[k, np.random.randint(d)] = True
460
+ return M
pymoo/util/mnn.py ADDED
@@ -0,0 +1,70 @@
1
+ import numpy as np
2
+ from scipy.spatial.distance import pdist, squareform
3
+
4
+ def calc_mnn(X, n_remove=0):
5
+ return calc_mnn_base(X, n_remove=n_remove, twonn=False)
6
+
7
+ def calc_2nn(X, n_remove=0):
8
+ return calc_mnn_base(X, n_remove=n_remove, twonn=True)
9
+
10
+ def calc_mnn_base(X, n_remove=0, twonn=False):
11
+
12
+ N = X.shape[0]
13
+ M = X.shape[1]
14
+
15
+ if N <= M:
16
+ return np.full(N, np.inf)
17
+
18
+ if n_remove <= (N - M):
19
+ if n_remove < 0:
20
+ n_remove = 0
21
+ else:
22
+ pass
23
+ else:
24
+ n_remove = N - M
25
+
26
+ if twonn:
27
+ M = 2
28
+
29
+ extremes_min = np.argmin(X, axis=0)
30
+ extremes_max = np.argmax(X, axis=0)
31
+
32
+ min_vals = np.min(X, axis=0)
33
+ max_vals = np.max(X, axis=0)
34
+
35
+ extremes = np.concatenate((extremes_min, extremes_max))
36
+
37
+ X = (X - min_vals) / (max_vals - min_vals)
38
+
39
+ H = np.arange(N)
40
+
41
+ D = squareform(pdist(X, metric="sqeuclidean"))
42
+ Dnn = np.partition(D, range(1, M+1), axis=1)[:, 1:M+1]
43
+ d = np.prod(Dnn, axis=1)
44
+ d[extremes] = np.inf
45
+
46
+ n_removed = 0
47
+
48
+ #While n_remove not acheived
49
+ while n_removed < (n_remove - 1):
50
+
51
+ #Obtain element to drop
52
+ _d = d[H]
53
+ _k = np.argmin(_d)
54
+ k = H[_k]
55
+ H = H[H != k]
56
+
57
+ #Update index
58
+ n_removed = n_removed + 1
59
+ if n_removed == n_remove:
60
+ break
61
+
62
+ else:
63
+
64
+ D[:, k] = np.inf
65
+ Dnn[H] = np.partition(D[H], range(1, M+1), axis=1)[:, 1:M+1]
66
+ d[H] = np.prod(Dnn[H], axis=1)
67
+ d[extremes] = np.inf
68
+
69
+ return d
70
+
File without changes
@@ -0,0 +1,159 @@
1
+ """Module which implements Dominance Degree Approaches for Non-dominated Sorting.
2
+
3
+ For the original work see:
4
+ DDA-NS https://ieeexplore.ieee.org/document/7469397
5
+ DDA-ENS https://ieeexplore.ieee.org/document/9282978
6
+
7
+ Adapted from https://github.com/rsenwar/Non-Dominated-Sorting-Algorithms/tree/master
8
+ """
9
+
10
+
11
+ from typing import Literal, List
12
+ import numpy as np
13
+
14
+
15
+ def construct_comp_matrix(vec: np.ndarray, sorted_idx: np.ndarray) -> np.ndarray:
16
+ """
17
+ const_comp_mat construct the comparison matrix from a row-vector vec.
18
+
19
+ Parameters
20
+ ----------
21
+ vec : np.ndarray
22
+ The vector of scores for the population on a single objective
23
+ sorted_idx : np.ndarray
24
+ The indices which would sort `vec`
25
+
26
+ Returns
27
+ -------
28
+ np.ndarray
29
+ The comparison matrix indicating whether each member in the population dominates the other member for the
30
+ objective in `vec`
31
+ """
32
+ n = vec.shape[0]
33
+ c = np.zeros(shape=(n, n), dtype=np.int32)
34
+
35
+ # the elements of the b(0)-th row in C are all set to 1
36
+ c[sorted_idx[0], :] = 1
37
+
38
+ for i in range(1, n):
39
+ if vec[sorted_idx[i]] == vec[sorted_idx[i - 1]]:
40
+ # the rows in C corresponding to the same elements in w are identical
41
+ c[sorted_idx[i]] = c[sorted_idx[i - 1]]
42
+ else:
43
+ c[sorted_idx[i], sorted_idx[i:]] = 1
44
+
45
+ return c
46
+
47
+
48
+ def construct_domination_matrix(f_scores: np.ndarray, **kwargs) -> np.ndarray:
49
+ """
50
+ construct_domination_matrix calculates the dominance degree matrix for a set of vectors.
51
+
52
+ The dominance degree indicate the degree of dominance of a solution, which is the number of
53
+ objectives for which it is the dominating solution.
54
+
55
+ Parameters
56
+ ----------
57
+ f_scores : np.ndarray
58
+ an N x M matrix of N (population size) objective function values for M objectives
59
+ """
60
+ d = np.zeros((f_scores.shape[0], f_scores.shape[0]), dtype=np.int32)
61
+ b = np.apply_over_axes(np.argsort, f_scores, axes=0)
62
+ for vec, srt in zip(f_scores.T, b.T):
63
+ d += construct_comp_matrix(vec, srt)
64
+ d = np.where(
65
+ np.logical_and(d == f_scores.shape[-1], d.T == f_scores.shape[-1]), 0, d
66
+ )
67
+ return d
68
+
69
+
70
+ def dda_ns(f_scores: np.ndarray, **kwargs) -> List[List[int]]:
71
+ """
72
+ dda_ns runs the DDA-NS algorithm.
73
+
74
+ Parameters
75
+ ----------
76
+ f_scores : np.ndarray
77
+ an N x M matrix of N (population size) objective function values for M objectives
78
+
79
+ Returns
80
+ -------
81
+ List[List[int]]
82
+ A list of members of each Pareto front. The index in the outer most list corresponds to the level in the Pareto front
83
+ while the value in the inner-most list is the id of the member of the population belonging to that front.
84
+ """
85
+ d_mx = construct_domination_matrix(f_scores)
86
+ max_d = np.empty((f_scores.shape[0],), dtype=np.int32)
87
+
88
+ fronts = []
89
+ count = 0
90
+ while count < f_scores.shape[0]:
91
+ # Max(D) is the row vector containing the maximum elements from each column of D
92
+ np.max(d_mx, out=max_d, axis=0)
93
+ front = [i for i, m_d in enumerate(max_d) if 0 <= m_d < f_scores.shape[-1]]
94
+ count += len(front)
95
+ d_mx[front] = -1
96
+ d_mx[:, front] = -1
97
+ fronts.append(front)
98
+
99
+ return fronts
100
+
101
+
102
+ def dda_ens(f_scores: np.ndarray, **kwargs) -> List[List[int]]:
103
+ """
104
+ dda_ens runs the DDA-ENS (efficient DDA) algorithm
105
+
106
+ Parameters
107
+ ----------
108
+ f_scores : np.ndarray
109
+ The N x M matrix of N (population size) objective function values for M objectives
110
+
111
+ Returns
112
+ -------
113
+ List[List[int]]
114
+ an N x M matrix of N (population size) objective function values for M objectives
115
+ """
116
+ d_mx = construct_domination_matrix(f_scores)
117
+
118
+ fronts: List[List[int]] = []
119
+ for s in np.lexsort(f_scores.T):
120
+ isinserted = False
121
+ for fk in fronts:
122
+ if not (d_mx[fk, s] == f_scores.shape[1]).any():
123
+ fk.append(s)
124
+ isinserted = True
125
+ break
126
+ if not isinserted:
127
+ fronts.append([s])
128
+ return fronts
129
+
130
+
131
+ def dominance_degree_non_dominated_sort(
132
+ f_scores: np.ndarray, strategy: Literal["efficient", "fast"] = "efficient"
133
+ ) -> List[List[int]]:
134
+ """
135
+ dominance_degree_non_dominated_sort performs the non-dominating sort with the specified algorithm
136
+
137
+ Parameters
138
+ ----------
139
+ f_scores : np.ndarray
140
+ The N x M matrix of N (population size) objective function values for M objectives
141
+ strategy : Literal["efficient", "fast"], optional
142
+ The dominance degree algorithm to use, by default "efficient"
143
+
144
+ Returns
145
+ -------
146
+ List[List[int]]
147
+ A list of members of each Pareto front. The index in the outer most list corresponds to the level in the Pareto front
148
+ while the value in the inner-most list is the id of the member of the population belonging to that front.
149
+
150
+ Raises
151
+ ------
152
+ ValueError
153
+ If an invalid strategy is specified
154
+ """
155
+ if strategy == "efficient":
156
+ return dda_ens(f_scores)
157
+ if strategy == "fast":
158
+ return dda_ns(f_scores)
159
+ raise ValueError("Invalid search strategy")