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.

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-313-x86_64-linux-gnu.so +0 -0
  91. pymoo/cython/calc_perpendicular_distance.pyx +67 -0
  92. pymoo/cython/decomposition.cpython-313-x86_64-linux-gnu.so +0 -0
  93. pymoo/cython/decomposition.pyx +165 -0
  94. pymoo/cython/hv.cpython-313-x86_64-linux-gnu.so +0 -0
  95. pymoo/cython/hv.pyx +18 -0
  96. pymoo/cython/info.cpython-313-x86_64-linux-gnu.so +0 -0
  97. pymoo/cython/info.pyx +5 -0
  98. pymoo/cython/mnn.cpython-313-x86_64-linux-gnu.so +0 -0
  99. pymoo/cython/mnn.pyx +273 -0
  100. pymoo/cython/non_dominated_sorting.cpython-313-x86_64-linux-gnu.so +0 -0
  101. pymoo/cython/non_dominated_sorting.pyx +645 -0
  102. pymoo/cython/pruning_cd.cpython-313-x86_64-linux-gnu.so +0 -0
  103. pymoo/cython/pruning_cd.pyx +197 -0
  104. pymoo/cython/stochastic_ranking.cpython-313-x86_64-linux-gnu.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
@@ -0,0 +1,203 @@
1
+ import numpy as np
2
+ from scipy.spatial.distance import cdist
3
+
4
+ from pymoo.core.indicator import Indicator
5
+ from pymoo.indicators.hv import Hypervolume
6
+ from pymoo.indicators.igd import IGD
7
+
8
+
9
+ class RMetric(Indicator):
10
+
11
+ def __init__(self, problem, ref_points, w=None, delta=0.2, pf=None):
12
+ """
13
+
14
+ Parameters
15
+ ----------
16
+
17
+ problem : class
18
+ problem instance
19
+
20
+ ref_points : numpy.array
21
+ list of reference points
22
+
23
+ w : numpy.array
24
+ weights for each objective
25
+
26
+ delta : float
27
+ The delta value representing the region of interest
28
+
29
+ """
30
+
31
+ Indicator.__init__(self)
32
+ self.ref_points = ref_points
33
+ self.problem = problem
34
+ w_ = np.ones(self.ref_points.shape[1]) if not w else w
35
+ self.w_points = self.ref_points + 2 * w_
36
+ self.delta = delta
37
+
38
+ self.pf = pf
39
+ self.F = None
40
+ self.others = None
41
+
42
+ def _filter(self):
43
+
44
+ def check_dominance(a, b, n_obj):
45
+ flag1 = False
46
+ flag2 = False
47
+ for i in range(n_obj):
48
+ if a[i] < b[i]:
49
+ flag1 = True
50
+ else:
51
+ if a[i] > b[i]:
52
+ flag2 = True
53
+ if flag1 and not flag2:
54
+ return 1
55
+ elif not flag1 and flag2:
56
+ return -1
57
+ else:
58
+ return 0
59
+
60
+ num_objs = np.size(self.F, axis=1)
61
+ index_array = np.zeros(np.size(self.F, axis=0))
62
+
63
+ # filter out all solutions that are dominated by solutions found by other algorithms
64
+ if self.others is not None:
65
+ for i in range(np.size(self.F, 0)):
66
+ for j in range(np.size(self.others, 0)):
67
+ flag = check_dominance(self.F[i, :], self.others[j, :], num_objs)
68
+ if flag == -1:
69
+ index_array[i] = 1
70
+ break
71
+
72
+ final_index = np.logical_not(index_array)
73
+ filtered_pop = self.F[final_index, :]
74
+
75
+ return filtered_pop
76
+
77
+ def _preprocess(self, data, ref_point, w_point):
78
+
79
+ datasize = np.size(data, 0)
80
+
81
+ # Identify representative point
82
+ ref_matrix = np.tile(ref_point, (datasize, 1))
83
+ w_matrix = np.tile(w_point, (datasize, 1))
84
+ # ratio of distance to the ref point over the distance between the w_point and the ref_point
85
+ diff_matrix = (data - ref_matrix) / (w_matrix - ref_matrix)
86
+ agg_value = np.amax(diff_matrix, axis=1)
87
+ idx = np.argmin(agg_value)
88
+ zp = [data[idx, :]]
89
+
90
+ return zp,
91
+
92
+ def _translate(self, zp, trimmed_data, ref_point, w_point):
93
+ # Solution translation - Matlab reproduction
94
+ # find k
95
+ temp = ((zp[0] - ref_point) / (w_point - ref_point))
96
+ kIdx = np.argmax(temp)
97
+
98
+ # find zl
99
+ temp = (zp[0][kIdx] - ref_point[kIdx]) / (w_point[kIdx] - ref_point[kIdx])
100
+ zl = ref_point + temp * (w_point - ref_point)
101
+
102
+ temp = zl - zp
103
+ shift_direction = np.tile(temp, (trimmed_data.shape[0], 1))
104
+ # new_size = self.curr_pop.shape[0]
105
+ return trimmed_data + shift_direction
106
+
107
+ def _trim(self, pop, centeroid, range=0.2):
108
+ popsize, objDim = pop.shape
109
+ diff_matrix = pop - np.tile(centeroid, (popsize, 1))[0]
110
+ flags = np.sum(abs(diff_matrix) < range / 2, axis=1)
111
+ filtered_matrix = pop[np.where(flags == objDim)]
112
+ return filtered_matrix
113
+
114
+ def _trim_fast(self, pop, centeroid, range=0.2):
115
+ centeroid_matrix = cdist(pop, centeroid, metric='euclidean')
116
+ filtered_matrix = pop[np.where(centeroid_matrix < range / 2), :][0]
117
+ return filtered_matrix
118
+
119
+ def do(self, F, others=None, calc_hv=True):
120
+ """
121
+
122
+ This method calculates the R-IGD and R-HV based off of the values provided.
123
+
124
+
125
+ Parameters
126
+ ----------
127
+
128
+ F : numpy.ndarray
129
+ The objective space values
130
+
131
+ others : numpy.ndarray
132
+ Results from other algorithms which should be used for filtering nds solutions
133
+
134
+ calc_hv : bool
135
+ Whether the hv is calculate - (None if more than 3 dimensions)
136
+
137
+
138
+ Returns
139
+ -------
140
+ rigd : float
141
+ R-IGD
142
+
143
+ rhv : float
144
+ R-HV if calc_hv is true and less or equal to 3 dimensions
145
+
146
+ """
147
+ self.F, self.others = F, others
148
+
149
+ translated = []
150
+ final_PF = []
151
+
152
+ # 1. Prescreen Procedure - NDS Filtering
153
+ pop = self._filter()
154
+
155
+ pf = self.pf
156
+ if pf is None:
157
+ pf = self.problem.pareto_front()
158
+
159
+ if pf is None:
160
+ raise Exception("Please provide the Pareto front to calculate the R-Metric!")
161
+
162
+ labels = np.argmin(cdist(pop, self.ref_points), axis=1)
163
+
164
+ for i in range(len(self.ref_points)):
165
+ cluster = pop[np.where(labels == i)]
166
+ if len(cluster) != 0:
167
+ # 2. Representative Point Identification
168
+ zp = self._preprocess(cluster, self.ref_points[i], w_point=self.w_points[i])[0]
169
+ # 3. Filtering Procedure - Filter points
170
+ trimmed_data = self._trim(cluster, zp, range=self.delta)
171
+ # 4. Solution Translation
172
+ pop_t = self._translate(zp, trimmed_data, self.ref_points[i], w_point=self.w_points[i])
173
+ translated.extend(pop_t)
174
+
175
+ # 5. R-Metric Computation
176
+ target = self._preprocess(data=pf, ref_point=self.ref_points[i], w_point=self.w_points[i])
177
+ PF = self._trim(pf, target)
178
+ final_PF.extend(PF)
179
+
180
+ translated = np.array(translated)
181
+ final_PF = np.array(final_PF)
182
+
183
+ rigd, rhv = None, None
184
+
185
+ if len(translated) > 0:
186
+
187
+ # IGD Computation
188
+ rigd = IGD(final_PF).do(translated)
189
+
190
+ nadir_point = np.amax(self.w_points, axis=0)
191
+ front = translated
192
+ dim = self.ref_points[0].shape[0]
193
+ if calc_hv:
194
+ if dim <= 3:
195
+ try:
196
+ rhv = Hypervolume(ref_point=nadir_point).do(front)
197
+ except:
198
+ pass
199
+
200
+ if calc_hv:
201
+ return rigd, rhv
202
+ else:
203
+ return rigd
@@ -0,0 +1,52 @@
1
+ import numpy as np
2
+ from pymoo.core.indicator import Indicator
3
+ from pymoo.indicators.distance_indicator import at_least_2d_array, derive_ideal_and_nadir_from_pf
4
+ from scipy.spatial.distance import pdist, squareform
5
+
6
+
7
+ class SpacingIndicator(Indicator):
8
+
9
+ def __init__(self,
10
+ pf=None,
11
+ zero_to_one=False,
12
+ ideal=None,
13
+ nadir=None):
14
+ """Spacing indicator
15
+
16
+ The smaller the value this indicator assumes, the most uniform is the distribution of elements on the pareto front.
17
+
18
+ Parameters
19
+ ----------
20
+ pf : 2d array, optional
21
+ Pareto front, by default None
22
+ zero_to_one : bool, optional
23
+ Whether or not the objective values should be normalized in calculations, by default False
24
+ ideal : 1d array, optional
25
+ Ideal point, by default None
26
+ nadir : 1d array, optional
27
+ Nadir point, by default None
28
+ """
29
+
30
+ # the pareto front if necessary to calculate the indicator
31
+ pf = at_least_2d_array(pf, extend_as="row")
32
+ ideal, nadir = derive_ideal_and_nadir_from_pf(pf, ideal=ideal, nadir=nadir)
33
+
34
+ super().__init__(pf=pf,
35
+ zero_to_one=zero_to_one,
36
+ ideal=ideal,
37
+ nadir=nadir)
38
+
39
+ def _do(self, F, *args, **kwargs):
40
+
41
+ # Get F dimensions
42
+ n_points, n_obj = F.shape
43
+
44
+ # knn
45
+ D = squareform(pdist(F, metric="cityblock"))
46
+ d = np.partition(D, 1, axis=1)[:, 1]
47
+ dm = np.mean(d)
48
+
49
+ # Get spacing
50
+ S = np.sqrt(np.sum(np.square(d - dm)) / n_points)
51
+
52
+ return S
pymoo/mcdm/__init__.py ADDED
File without changes
@@ -0,0 +1,19 @@
1
+ from pymoo.core.decision_making import DecisionMaking
2
+ from pymoo.util.normalization import normalize
3
+
4
+
5
+ class CompromiseProgramming(DecisionMaking):
6
+
7
+ def __init__(self, metric="euclidean", **kwargs) -> None:
8
+ super().__init__(**kwargs)
9
+ self.metric = metric
10
+
11
+ def _do(self, F, **kwargs):
12
+
13
+ F, _, ideal_point, nadir_point = normalize(F,
14
+ xl=self.ideal_point,
15
+ xu=self.nadir_point,
16
+ estimate_bounds_if_none=True,
17
+ return_bounds=True)
18
+
19
+ return None
@@ -0,0 +1,40 @@
1
+ import warnings
2
+
3
+ import numpy as np
4
+
5
+ from pymoo.core.decision_making import DecisionMaking, find_outliers_upper_tail, NeighborFinder
6
+
7
+
8
+ class HighTradeoffPoints(DecisionMaking):
9
+
10
+ def __init__(self, epsilon=0.125, **kwargs) -> None:
11
+ super().__init__(**kwargs)
12
+ self.epsilon = epsilon
13
+
14
+ def _do(self, F, **kwargs):
15
+ n, m = F.shape
16
+
17
+ neighbors_finder = NeighborFinder(F, epsilon=0.125, n_min_neigbors="auto", consider_2d=False)
18
+
19
+ mu = np.full(n, - np.inf)
20
+
21
+ # for each solution in the set calculate the least amount of improvement per unit deterioration
22
+ for i in range(n):
23
+
24
+ # for each neighbour in a specific radius of that solution
25
+ neighbors = neighbors_finder.find(i)
26
+
27
+ # calculate the trade-off to all neighbours
28
+ diff = F[neighbors] - F[i]
29
+
30
+ # calculate sacrifice and gain
31
+ sacrifice = np.maximum(0, diff).sum(axis=1)
32
+ gain = np.maximum(0, -diff).sum(axis=1)
33
+
34
+ warnings.filterwarnings('ignore')
35
+ tradeoff = sacrifice / gain
36
+
37
+ # otherwise find the one with the smalled one
38
+ mu[i] = np.nanmin(tradeoff)
39
+
40
+ return find_outliers_upper_tail(mu)
@@ -0,0 +1,32 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.decision_making import DecisionMaking
4
+
5
+
6
+ class PseudoWeights(DecisionMaking):
7
+
8
+ def __init__(self, weights, **kwargs) -> None:
9
+ super().__init__(**kwargs)
10
+ self.weights = weights
11
+
12
+ def _do(self, F, return_pseudo_weights=False, **kwargs):
13
+ ideal, nadir = self.ideal, self.nadir
14
+
15
+ if ideal is None:
16
+ ideal = F.min(axis=0)
17
+ if nadir is None:
18
+ nadir = F.max(axis=0)
19
+
20
+ # normalized distance to the worst solution
21
+ pseudo_weights = ((nadir - F) / (nadir - ideal))
22
+
23
+ # normalize weights to sum up to one
24
+ pseudo_weights = pseudo_weights / np.sum(pseudo_weights, axis=1)[:, None]
25
+
26
+ # search for the closest individual having this pseudo weights
27
+ I = np.argmin(np.sum(np.abs(pseudo_weights - self.weights), axis=1))
28
+
29
+ if return_pseudo_weights:
30
+ return I, pseudo_weights
31
+ else:
32
+ return I
File without changes
@@ -0,0 +1,187 @@
1
+ import math
2
+ from abc import abstractmethod
3
+
4
+ import numpy as np
5
+
6
+ from pymoo.core.duplicate import NoDuplicateElimination
7
+ from pymoo.core.individual import Individual
8
+ from pymoo.core.infill import InfillCriterion
9
+ from pymoo.core.mixed import MixedVariableMating
10
+ from pymoo.core.parameters import get_params, flatten
11
+ from pymoo.core.problem import Problem
12
+ from pymoo.core.variable import Choice, Real, Integer, Binary
13
+ from pymoo.operators.crossover.sbx import SBX
14
+ from pymoo.operators.crossover.ux import UX
15
+ from pymoo.operators.mutation.bitflip import BFM
16
+ from pymoo.operators.mutation.pm import PM
17
+ from pymoo.operators.mutation.rm import ChoiceRandomMutation
18
+ from pymoo.operators.repair.rounding import RoundingRepair
19
+ from pymoo.operators.selection.tournament import TournamentSelection, compare
20
+
21
+
22
+ class ParameterControl:
23
+
24
+ def __init__(self, obj) -> None:
25
+ super().__init__()
26
+
27
+ self.data = None
28
+
29
+ params = flatten({"ParameterControl": get_params(obj)})
30
+ self.params = params
31
+
32
+ # print("PARAMETER CONTROL:", list(self.params))
33
+
34
+ def do(self, N, set_to_params=True):
35
+ vals = self._do(N)
36
+ if set_to_params:
37
+ if vals is not None:
38
+ for k, v in vals.items():
39
+ self.params[k].set(v)
40
+ return vals
41
+
42
+ @abstractmethod
43
+ def _do(self, N):
44
+ pass
45
+
46
+ def tell(self, **kwargs):
47
+ self.data = dict(kwargs)
48
+
49
+ def advance(self, infills=None):
50
+ for k, v in self.params.items():
51
+ assert len(v.get()) == len(
52
+ infills), "Make sure that the infills and parameters asked for have the same size."
53
+ infills.set(k, v.get())
54
+
55
+
56
+ class NoParameterControl(ParameterControl):
57
+
58
+ def __init__(self, _) -> None:
59
+ super().__init__(None)
60
+
61
+ def _do(self, N):
62
+ return {}
63
+
64
+
65
+ class RandomParameterControl(ParameterControl):
66
+
67
+ def _do(self, N):
68
+ return {key: value.sample(N) for key, value in self.params.items()}
69
+
70
+
71
+ class EvolutionaryParameterControl(ParameterControl):
72
+
73
+ def __init__(self, obj) -> None:
74
+ super().__init__(obj)
75
+ self.eps = 0.05
76
+
77
+ def _do(self, N):
78
+ params = self.params
79
+ pop = self.data.get("pop")
80
+
81
+ # make sure that for each parameter a value exists - if not simply set it randomly
82
+ for name, param in params.items():
83
+ is_none = np.where(pop.get(name) == None)[0]
84
+ if len(is_none) > 0:
85
+ pop[is_none].set(name, param.sample(len(is_none)))
86
+
87
+ selection = AgeBasedTournamentSelection()
88
+
89
+ crossover = {
90
+ Binary: UX(),
91
+ Real: SBX(),
92
+ Integer: SBX(vtype=float, repair=RoundingRepair()),
93
+ Choice: UX(),
94
+ }
95
+
96
+ mutation = {
97
+ Binary: BFM(),
98
+ Real: PM(),
99
+ Integer: PM(vtype=float, repair=RoundingRepair()),
100
+ Choice: ChoiceRandomMutation(),
101
+ }
102
+
103
+ mating = MixedVariableMating(
104
+ crossover=crossover,
105
+ mutation=mutation,
106
+ eliminate_duplicates=NoDuplicateElimination()
107
+ )
108
+
109
+ problem = Problem(vars=params)
110
+
111
+ parents = selection(problem, pop, N, n_parents=2)
112
+ parents = [[Individual(X={key: parent.get(key) for key in params}) for parent in mating] for mating in parents]
113
+
114
+ off = mating(problem, parents, N, parents=True)
115
+
116
+ Xp = off.get("X")
117
+ ret = {param: np.array([Xp[i][param] for i in range(len(Xp))]) for param in params}
118
+
119
+ return ret
120
+
121
+
122
+ class AgeBasedTournamentSelection(TournamentSelection):
123
+
124
+ def __init__(self, pressure=2):
125
+ super().__init__(age_binary_tournament, pressure)
126
+
127
+
128
+ def age_binary_tournament(pop, P, **kwargs):
129
+ n_tournaments, n_parents = P.shape
130
+
131
+ if n_parents != 2:
132
+ raise ValueError("Only implemented for binary tournament!")
133
+
134
+ S = np.full(n_tournaments, np.nan)
135
+
136
+ for i in range(n_tournaments):
137
+ a, b = P[i, 0], P[i, 1]
138
+ a_gen, b_gen = pop[a].get("n_gen"), pop[b].get("n_gen")
139
+ S[i] = compare(a, a_gen, b, b_gen, method='larger_is_better', return_random_if_equal=True)
140
+
141
+ return S[:, None].astype(int, copy=False)
142
+
143
+
144
+ class ParameterControlMating(InfillCriterion):
145
+
146
+ def __init__(self,
147
+ selection,
148
+ crossover,
149
+ mutation,
150
+ control=NoParameterControl,
151
+ **kwargs):
152
+ super().__init__(**kwargs)
153
+ self.selection = selection
154
+ self.crossover = crossover
155
+ self.mutation = mutation
156
+ self.control = control(self)
157
+
158
+ def _do(self, problem, pop, n_offsprings, parents=None, **kwargs):
159
+
160
+ # how many parents need to be select for the mating - depending on number of offsprings remaining
161
+ n_matings = math.ceil(n_offsprings / self.crossover.n_offsprings)
162
+
163
+ # do the parameter control for the mating
164
+ control = self.control
165
+ control.tell(pop=pop)
166
+ control.do(n_matings)
167
+
168
+ # if the parents for the mating are not provided directly - usually selection will be used
169
+ if parents is None:
170
+
171
+ # select the parents for the mating - just an index array
172
+ parents = self.selection.do(problem, pop, n_matings, n_parents=self.crossover.n_parents, **kwargs)
173
+
174
+ # do the crossover using the parents index and the population - additional data provided if necessary
175
+ off = self.crossover(problem, parents, **kwargs)
176
+
177
+ # now we have to consider during parameter control that a crossover can produce multiple offsprings
178
+ for name, param in control.params.items():
179
+ param.set(np.repeat(param.get(), self.crossover.n_offsprings))
180
+
181
+ # do the mutation on the offsprings created through crossover
182
+ off = self.mutation(problem, off, **kwargs)
183
+
184
+ # finally attach the parameters back to the offsprings
185
+ control.advance(off)
186
+
187
+ return off
File without changes
@@ -0,0 +1,45 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.crossover import Crossover
4
+ from pymoo.core.variable import Real, get
5
+ from pymoo.util.misc import row_at_least_once_true
6
+
7
+
8
+ def mut_binomial(n, m, prob, at_least_once=True):
9
+ prob = np.ones(n) * prob
10
+ M = np.random.random((n, m)) < prob[:, None]
11
+
12
+ if at_least_once:
13
+ M = row_at_least_once_true(M)
14
+
15
+ return M
16
+
17
+
18
+ class BinomialCrossover(Crossover):
19
+
20
+ def __init__(self, bias=0.5, n_offsprings=2, **kwargs):
21
+ super().__init__(2, n_offsprings, **kwargs)
22
+ self.bias = Real(bias, bounds=(0.1, 0.9), strict=(0.0, 1.0))
23
+
24
+ def _do(self, problem, X, **kwargs):
25
+ _, n_matings, n_var = X.shape
26
+
27
+ bias = get(self.bias, size=n_matings)
28
+ M = mut_binomial(n_matings, n_var, bias, at_least_once=True)
29
+
30
+ if self.n_offsprings == 1:
31
+ Xp = X[0].copy()
32
+ Xp[~M] = X[1][~M]
33
+ Xp = Xp[None, ...]
34
+ elif self.n_offsprings == 2:
35
+ Xp = np.copy(X)
36
+ Xp[0][~M] = X[1][~M]
37
+ Xp[1][~M] = X[0][~M]
38
+ else:
39
+ raise Exception
40
+
41
+ return Xp
42
+
43
+
44
+ class BX(BinomialCrossover):
45
+ pass