pymoo 0.6.1.6__cp312-cp312-macosx_10_13_universal2.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.
Files changed (337) 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 +110 -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 +91 -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/cmopso.py +239 -0
  14. pymoo/algorithms/moo/ctaea.py +305 -0
  15. pymoo/algorithms/moo/dnsga2.py +80 -0
  16. pymoo/algorithms/moo/kgb.py +450 -0
  17. pymoo/algorithms/moo/moead.py +183 -0
  18. pymoo/algorithms/moo/mopso_cd.py +309 -0
  19. pymoo/algorithms/moo/nsga2.py +113 -0
  20. pymoo/algorithms/moo/nsga3.py +361 -0
  21. pymoo/algorithms/moo/pinsga2.py +370 -0
  22. pymoo/algorithms/moo/rnsga2.py +188 -0
  23. pymoo/algorithms/moo/rnsga3.py +246 -0
  24. pymoo/algorithms/moo/rvea.py +214 -0
  25. pymoo/algorithms/moo/sms.py +196 -0
  26. pymoo/algorithms/moo/spea2.py +191 -0
  27. pymoo/algorithms/moo/unsga3.py +49 -0
  28. pymoo/algorithms/soo/__init__.py +0 -0
  29. pymoo/algorithms/soo/convex/__init__.py +0 -0
  30. pymoo/algorithms/soo/nonconvex/__init__.py +0 -0
  31. pymoo/algorithms/soo/nonconvex/brkga.py +162 -0
  32. pymoo/algorithms/soo/nonconvex/cmaes.py +556 -0
  33. pymoo/algorithms/soo/nonconvex/de.py +283 -0
  34. pymoo/algorithms/soo/nonconvex/direct.py +148 -0
  35. pymoo/algorithms/soo/nonconvex/es.py +213 -0
  36. pymoo/algorithms/soo/nonconvex/g3pcx.py +94 -0
  37. pymoo/algorithms/soo/nonconvex/ga.py +95 -0
  38. pymoo/algorithms/soo/nonconvex/ga_niching.py +223 -0
  39. pymoo/algorithms/soo/nonconvex/isres.py +74 -0
  40. pymoo/algorithms/soo/nonconvex/nelder.py +251 -0
  41. pymoo/algorithms/soo/nonconvex/nrbo.py +191 -0
  42. pymoo/algorithms/soo/nonconvex/optuna.py +80 -0
  43. pymoo/algorithms/soo/nonconvex/pattern.py +185 -0
  44. pymoo/algorithms/soo/nonconvex/pso.py +337 -0
  45. pymoo/algorithms/soo/nonconvex/pso_ep.py +307 -0
  46. pymoo/algorithms/soo/nonconvex/random_search.py +25 -0
  47. pymoo/algorithms/soo/nonconvex/sres.py +56 -0
  48. pymoo/algorithms/soo/univariate/__init__.py +0 -0
  49. pymoo/algorithms/soo/univariate/exp.py +46 -0
  50. pymoo/algorithms/soo/univariate/golden.py +65 -0
  51. pymoo/algorithms/soo/univariate/quadr_interp.py +81 -0
  52. pymoo/algorithms/soo/univariate/wolfe.py +163 -0
  53. pymoo/config.py +33 -0
  54. pymoo/constraints/__init__.py +3 -0
  55. pymoo/constraints/adaptive.py +66 -0
  56. pymoo/constraints/as_obj.py +56 -0
  57. pymoo/constraints/as_penalty.py +41 -0
  58. pymoo/constraints/eps.py +34 -0
  59. pymoo/constraints/from_bounds.py +36 -0
  60. pymoo/core/__init__.py +0 -0
  61. pymoo/core/algorithm.py +408 -0
  62. pymoo/core/callback.py +38 -0
  63. pymoo/core/crossover.py +79 -0
  64. pymoo/core/decision_making.py +102 -0
  65. pymoo/core/decomposition.py +76 -0
  66. pymoo/core/duplicate.py +163 -0
  67. pymoo/core/evaluator.py +116 -0
  68. pymoo/core/indicator.py +34 -0
  69. pymoo/core/individual.py +784 -0
  70. pymoo/core/infill.py +65 -0
  71. pymoo/core/initialization.py +44 -0
  72. pymoo/core/mating.py +39 -0
  73. pymoo/core/meta.py +21 -0
  74. pymoo/core/mixed.py +164 -0
  75. pymoo/core/mutation.py +44 -0
  76. pymoo/core/operator.py +46 -0
  77. pymoo/core/parameters.py +134 -0
  78. pymoo/core/plot.py +208 -0
  79. pymoo/core/population.py +180 -0
  80. pymoo/core/problem.py +373 -0
  81. pymoo/core/recorder.py +99 -0
  82. pymoo/core/repair.py +23 -0
  83. pymoo/core/replacement.py +96 -0
  84. pymoo/core/result.py +52 -0
  85. pymoo/core/sampling.py +45 -0
  86. pymoo/core/selection.py +61 -0
  87. pymoo/core/solution.py +10 -0
  88. pymoo/core/survival.py +107 -0
  89. pymoo/core/termination.py +70 -0
  90. pymoo/core/variable.py +415 -0
  91. pymoo/decomposition/__init__.py +0 -0
  92. pymoo/decomposition/aasf.py +24 -0
  93. pymoo/decomposition/asf.py +10 -0
  94. pymoo/decomposition/pbi.py +13 -0
  95. pymoo/decomposition/perp_dist.py +13 -0
  96. pymoo/decomposition/tchebicheff.py +11 -0
  97. pymoo/decomposition/util.py +13 -0
  98. pymoo/decomposition/weighted_sum.py +8 -0
  99. pymoo/docs.py +187 -0
  100. pymoo/experimental/__init__.py +0 -0
  101. pymoo/experimental/algorithms/__init__.py +0 -0
  102. pymoo/experimental/algorithms/gde3.py +57 -0
  103. pymoo/functions/__init__.py +135 -0
  104. pymoo/functions/compiled/__init__.py +0 -0
  105. pymoo/functions/compiled/calc_perpendicular_distance.cpp +27464 -0
  106. pymoo/functions/compiled/calc_perpendicular_distance.cpython-312-darwin.so +0 -0
  107. pymoo/functions/compiled/decomposition.cpp +28853 -0
  108. pymoo/functions/compiled/decomposition.cpython-312-darwin.so +0 -0
  109. pymoo/functions/compiled/info.cpp +7058 -0
  110. pymoo/functions/compiled/info.cpython-312-darwin.so +0 -0
  111. pymoo/functions/compiled/mnn.cpp +30095 -0
  112. pymoo/functions/compiled/mnn.cpython-312-darwin.so +0 -0
  113. pymoo/functions/compiled/non_dominated_sorting.cpp +35692 -0
  114. pymoo/functions/compiled/non_dominated_sorting.cpython-312-darwin.so +0 -0
  115. pymoo/functions/compiled/pruning_cd.cpp +29248 -0
  116. pymoo/functions/compiled/pruning_cd.cpython-312-darwin.so +0 -0
  117. pymoo/functions/compiled/stochastic_ranking.cpp +28042 -0
  118. pymoo/functions/compiled/stochastic_ranking.cpython-312-darwin.so +0 -0
  119. pymoo/functions/standard/__init__.py +1 -0
  120. pymoo/functions/standard/calc_perpendicular_distance.py +20 -0
  121. pymoo/functions/standard/decomposition.py +18 -0
  122. pymoo/functions/standard/hv.py +5 -0
  123. pymoo/functions/standard/mnn.py +78 -0
  124. pymoo/functions/standard/non_dominated_sorting.py +474 -0
  125. pymoo/functions/standard/pruning_cd.py +93 -0
  126. pymoo/functions/standard/stochastic_ranking.py +42 -0
  127. pymoo/gradient/__init__.py +24 -0
  128. pymoo/gradient/automatic.py +85 -0
  129. pymoo/gradient/grad_autograd.py +105 -0
  130. pymoo/gradient/grad_complex.py +35 -0
  131. pymoo/gradient/grad_jax.py +51 -0
  132. pymoo/gradient/numpy.py +22 -0
  133. pymoo/gradient/toolbox/__init__.py +19 -0
  134. pymoo/indicators/__init__.py +0 -0
  135. pymoo/indicators/distance_indicator.py +55 -0
  136. pymoo/indicators/gd.py +7 -0
  137. pymoo/indicators/gd_plus.py +7 -0
  138. pymoo/indicators/hv/__init__.py +59 -0
  139. pymoo/indicators/hv/approximate.py +105 -0
  140. pymoo/indicators/hv/exact.py +68 -0
  141. pymoo/indicators/hv/exact_2d.py +102 -0
  142. pymoo/indicators/igd.py +7 -0
  143. pymoo/indicators/igd_plus.py +7 -0
  144. pymoo/indicators/kktpm.py +151 -0
  145. pymoo/indicators/migd.py +55 -0
  146. pymoo/indicators/rmetric.py +203 -0
  147. pymoo/indicators/spacing.py +52 -0
  148. pymoo/mcdm/__init__.py +0 -0
  149. pymoo/mcdm/compromise_programming.py +19 -0
  150. pymoo/mcdm/high_tradeoff.py +40 -0
  151. pymoo/mcdm/pseudo_weights.py +32 -0
  152. pymoo/operators/__init__.py +0 -0
  153. pymoo/operators/control.py +190 -0
  154. pymoo/operators/crossover/__init__.py +0 -0
  155. pymoo/operators/crossover/binx.py +47 -0
  156. pymoo/operators/crossover/dex.py +125 -0
  157. pymoo/operators/crossover/erx.py +164 -0
  158. pymoo/operators/crossover/expx.py +53 -0
  159. pymoo/operators/crossover/hux.py +37 -0
  160. pymoo/operators/crossover/nox.py +25 -0
  161. pymoo/operators/crossover/ox.py +88 -0
  162. pymoo/operators/crossover/pcx.py +84 -0
  163. pymoo/operators/crossover/pntx.py +49 -0
  164. pymoo/operators/crossover/sbx.py +137 -0
  165. pymoo/operators/crossover/spx.py +5 -0
  166. pymoo/operators/crossover/ux.py +20 -0
  167. pymoo/operators/mutation/__init__.py +0 -0
  168. pymoo/operators/mutation/bitflip.py +17 -0
  169. pymoo/operators/mutation/gauss.py +60 -0
  170. pymoo/operators/mutation/inversion.py +42 -0
  171. pymoo/operators/mutation/nom.py +7 -0
  172. pymoo/operators/mutation/pm.py +96 -0
  173. pymoo/operators/mutation/rm.py +23 -0
  174. pymoo/operators/repair/__init__.py +0 -0
  175. pymoo/operators/repair/bounce_back.py +32 -0
  176. pymoo/operators/repair/bounds_repair.py +97 -0
  177. pymoo/operators/repair/inverse_penalty.py +91 -0
  178. pymoo/operators/repair/rounding.py +18 -0
  179. pymoo/operators/repair/to_bound.py +31 -0
  180. pymoo/operators/repair/vtype.py +11 -0
  181. pymoo/operators/sampling/__init__.py +0 -0
  182. pymoo/operators/sampling/lhs.py +76 -0
  183. pymoo/operators/sampling/rnd.py +52 -0
  184. pymoo/operators/selection/__init__.py +0 -0
  185. pymoo/operators/selection/rnd.py +75 -0
  186. pymoo/operators/selection/tournament.py +78 -0
  187. pymoo/operators/survival/__init__.py +0 -0
  188. pymoo/operators/survival/rank_and_crowding/__init__.py +1 -0
  189. pymoo/operators/survival/rank_and_crowding/classes.py +212 -0
  190. pymoo/operators/survival/rank_and_crowding/metrics.py +208 -0
  191. pymoo/optimize.py +72 -0
  192. pymoo/parallelization/__init__.py +15 -0
  193. pymoo/parallelization/dask.py +25 -0
  194. pymoo/parallelization/joblib.py +28 -0
  195. pymoo/parallelization/ray.py +31 -0
  196. pymoo/parallelization/starmap.py +24 -0
  197. pymoo/problems/__init__.py +157 -0
  198. pymoo/problems/dyn.py +47 -0
  199. pymoo/problems/dynamic/__init__.py +0 -0
  200. pymoo/problems/dynamic/cec2015.py +108 -0
  201. pymoo/problems/dynamic/df.py +451 -0
  202. pymoo/problems/dynamic/misc.py +167 -0
  203. pymoo/problems/functional.py +48 -0
  204. pymoo/problems/many/__init__.py +5 -0
  205. pymoo/problems/many/cdtlz.py +159 -0
  206. pymoo/problems/many/dcdtlz.py +88 -0
  207. pymoo/problems/many/dtlz.py +264 -0
  208. pymoo/problems/many/wfg.py +553 -0
  209. pymoo/problems/multi/__init__.py +14 -0
  210. pymoo/problems/multi/bnh.py +34 -0
  211. pymoo/problems/multi/carside.py +48 -0
  212. pymoo/problems/multi/clutch.py +104 -0
  213. pymoo/problems/multi/csi.py +55 -0
  214. pymoo/problems/multi/ctp.py +198 -0
  215. pymoo/problems/multi/dascmop.py +213 -0
  216. pymoo/problems/multi/kursawe.py +25 -0
  217. pymoo/problems/multi/modact.py +68 -0
  218. pymoo/problems/multi/mw.py +400 -0
  219. pymoo/problems/multi/omnitest.py +48 -0
  220. pymoo/problems/multi/osy.py +32 -0
  221. pymoo/problems/multi/srn.py +28 -0
  222. pymoo/problems/multi/sympart.py +94 -0
  223. pymoo/problems/multi/tnk.py +24 -0
  224. pymoo/problems/multi/truss2d.py +83 -0
  225. pymoo/problems/multi/welded_beam.py +41 -0
  226. pymoo/problems/multi/wrm.py +36 -0
  227. pymoo/problems/multi/zdt.py +151 -0
  228. pymoo/problems/multi_to_single.py +22 -0
  229. pymoo/problems/single/__init__.py +12 -0
  230. pymoo/problems/single/ackley.py +24 -0
  231. pymoo/problems/single/cantilevered_beam.py +34 -0
  232. pymoo/problems/single/flowshop_scheduling.py +113 -0
  233. pymoo/problems/single/g.py +874 -0
  234. pymoo/problems/single/griewank.py +18 -0
  235. pymoo/problems/single/himmelblau.py +15 -0
  236. pymoo/problems/single/knapsack.py +49 -0
  237. pymoo/problems/single/mopta08.py +26 -0
  238. pymoo/problems/single/multimodal.py +20 -0
  239. pymoo/problems/single/pressure_vessel.py +30 -0
  240. pymoo/problems/single/rastrigin.py +20 -0
  241. pymoo/problems/single/rosenbrock.py +22 -0
  242. pymoo/problems/single/schwefel.py +18 -0
  243. pymoo/problems/single/simple.py +13 -0
  244. pymoo/problems/single/sphere.py +19 -0
  245. pymoo/problems/single/traveling_salesman.py +79 -0
  246. pymoo/problems/single/zakharov.py +19 -0
  247. pymoo/problems/static.py +14 -0
  248. pymoo/problems/util.py +42 -0
  249. pymoo/problems/zero_to_one.py +27 -0
  250. pymoo/termination/__init__.py +23 -0
  251. pymoo/termination/collection.py +12 -0
  252. pymoo/termination/cv.py +48 -0
  253. pymoo/termination/default.py +45 -0
  254. pymoo/termination/delta.py +64 -0
  255. pymoo/termination/fmin.py +16 -0
  256. pymoo/termination/ftol.py +144 -0
  257. pymoo/termination/indicator.py +49 -0
  258. pymoo/termination/max_eval.py +14 -0
  259. pymoo/termination/max_gen.py +15 -0
  260. pymoo/termination/max_time.py +20 -0
  261. pymoo/termination/robust.py +34 -0
  262. pymoo/termination/xtol.py +33 -0
  263. pymoo/util/__init__.py +33 -0
  264. pymoo/util/archive.py +152 -0
  265. pymoo/util/cache.py +29 -0
  266. pymoo/util/clearing.py +82 -0
  267. pymoo/util/display/__init__.py +0 -0
  268. pymoo/util/display/column.py +52 -0
  269. pymoo/util/display/display.py +34 -0
  270. pymoo/util/display/multi.py +100 -0
  271. pymoo/util/display/output.py +53 -0
  272. pymoo/util/display/progress.py +54 -0
  273. pymoo/util/display/single.py +67 -0
  274. pymoo/util/dominator.py +67 -0
  275. pymoo/util/hv.py +21 -0
  276. pymoo/util/matlab_engine.py +39 -0
  277. pymoo/util/misc.py +447 -0
  278. pymoo/util/nds/__init__.py +0 -0
  279. pymoo/util/nds/dominance_degree_non_dominated_sort.py +159 -0
  280. pymoo/util/nds/efficient_non_dominated_sort.py +152 -0
  281. pymoo/util/nds/fast_non_dominated_sort.py +70 -0
  282. pymoo/util/nds/find_non_dominated.py +54 -0
  283. pymoo/util/nds/naive_non_dominated_sort.py +36 -0
  284. pymoo/util/nds/non_dominated_sorting.py +94 -0
  285. pymoo/util/nds/tree_based_non_dominated_sort.py +133 -0
  286. pymoo/util/normalization.py +312 -0
  287. pymoo/util/optimum.py +42 -0
  288. pymoo/util/randomized_argsort.py +63 -0
  289. pymoo/util/ref_dirs/__init__.py +24 -0
  290. pymoo/util/ref_dirs/construction.py +89 -0
  291. pymoo/util/ref_dirs/das_dennis.py +52 -0
  292. pymoo/util/ref_dirs/energy.py +317 -0
  293. pymoo/util/ref_dirs/energy_layer.py +119 -0
  294. pymoo/util/ref_dirs/genetic_algorithm.py +64 -0
  295. pymoo/util/ref_dirs/incremental.py +69 -0
  296. pymoo/util/ref_dirs/misc.py +128 -0
  297. pymoo/util/ref_dirs/optimizer.py +59 -0
  298. pymoo/util/ref_dirs/performance.py +162 -0
  299. pymoo/util/ref_dirs/reduction.py +85 -0
  300. pymoo/util/ref_dirs/sample_and_map.py +24 -0
  301. pymoo/util/reference_direction.py +258 -0
  302. pymoo/util/remote.py +55 -0
  303. pymoo/util/roulette.py +29 -0
  304. pymoo/util/running_metric.py +128 -0
  305. pymoo/util/sliding_window.py +25 -0
  306. pymoo/util/value_functions.py +720 -0
  307. pymoo/util/vectors.py +40 -0
  308. pymoo/util/vf_dominator.py +102 -0
  309. pymoo/vendor/__init__.py +0 -0
  310. pymoo/vendor/cec2018.py +398 -0
  311. pymoo/vendor/gta.py +617 -0
  312. pymoo/vendor/vendor_cmaes.py +421 -0
  313. pymoo/vendor/vendor_coco.py +81 -0
  314. pymoo/vendor/vendor_scipy.py +232 -0
  315. pymoo/version.py +1 -0
  316. pymoo/visualization/__init__.py +21 -0
  317. pymoo/visualization/app/__init__.py +0 -0
  318. pymoo/visualization/app/pso.py +61 -0
  319. pymoo/visualization/fitness_landscape.py +128 -0
  320. pymoo/visualization/heatmap.py +123 -0
  321. pymoo/visualization/matplotlib.py +61 -0
  322. pymoo/visualization/pcp.py +121 -0
  323. pymoo/visualization/petal.py +91 -0
  324. pymoo/visualization/radar.py +108 -0
  325. pymoo/visualization/radviz.py +68 -0
  326. pymoo/visualization/scatter.py +150 -0
  327. pymoo/visualization/star_coordinate.py +75 -0
  328. pymoo/visualization/util.py +296 -0
  329. pymoo/visualization/video/__init__.py +0 -0
  330. pymoo/visualization/video/callback_video.py +82 -0
  331. pymoo/visualization/video/one_var_one_obj.py +57 -0
  332. pymoo/visualization/video/two_var_one_obj.py +62 -0
  333. pymoo-0.6.1.6.dist-info/METADATA +209 -0
  334. pymoo-0.6.1.6.dist-info/RECORD +337 -0
  335. pymoo-0.6.1.6.dist-info/WHEEL +6 -0
  336. pymoo-0.6.1.6.dist-info/licenses/LICENSE +191 -0
  337. pymoo-0.6.1.6.dist-info/top_level.txt +1 -0
@@ -0,0 +1,152 @@
1
+ from math import floor
2
+
3
+ import numpy as np
4
+
5
+ from pymoo.util.dominator import Dominator
6
+
7
+
8
+ def efficient_non_dominated_sort(F, strategy="sequential"):
9
+ """
10
+ Efficient Non-dominated Sorting (ENS)
11
+
12
+ Parameters
13
+ ----------
14
+ F: numpy.ndarray
15
+ objective values for each individual.
16
+ strategy: str
17
+ search strategy, can be "sequential" or "binary".
18
+
19
+ Returns
20
+ -------
21
+ fronts: list
22
+ Indices of the individuals in each front.
23
+
24
+ References
25
+ ----------
26
+ X. Zhang, Y. Tian, R. Cheng, and Y. Jin,
27
+ An efficient approach to nondominated sorting for evolutionary multiobjective optimization,
28
+ IEEE Transactions on Evolutionary Computation, 2015, 19(2): 201-213.
29
+ """
30
+
31
+ assert (strategy in ["sequential", 'binary']), "Invalid search strategy"
32
+
33
+ # the shape of the input
34
+ N, M = F.shape
35
+
36
+ # do a lexicographic ordering
37
+ I = np.lexsort(F.T[::-1])
38
+ F = F[I]
39
+
40
+ # front ranks for each individual
41
+ fronts = []
42
+
43
+ for i in range(N):
44
+
45
+ if strategy == 'sequential':
46
+ k = sequential_search(F, i, fronts)
47
+ else:
48
+ k = binary_search(F, i, fronts)
49
+
50
+ # create empty fronts if necessary
51
+ if k >= len(fronts):
52
+ fronts.append([])
53
+
54
+ # append the current individual to a front
55
+ fronts[k].append(i)
56
+
57
+ # now map the fronts back to the originally sorting
58
+ ret = []
59
+ for front in fronts:
60
+ ret.append(I[front])
61
+
62
+ return ret
63
+
64
+
65
+ def sequential_search(F, i, fronts) -> int:
66
+ """
67
+ Find the front rank for the i-th individual through sequential search.
68
+
69
+ Parameters
70
+ ----------
71
+ F: np.ndarray
72
+ the objective values
73
+ i: int
74
+ the index of the individual
75
+ fronts: list
76
+ individuals in each front
77
+ """
78
+
79
+ num_found_fronts = len(fronts)
80
+ k = 0 # the front now checked
81
+ current = F[i]
82
+ while True:
83
+ if num_found_fronts == 0:
84
+ return 0
85
+ # solutions in the k-th front, examine in reverse order
86
+ fk_indices = fronts[k]
87
+ solutions = F[fk_indices[::-1]]
88
+ non_dominated = True
89
+ for f in solutions:
90
+ relation = Dominator.get_relation(current, f)
91
+ if relation == -1:
92
+ non_dominated = False
93
+ break
94
+ if non_dominated:
95
+ return k
96
+ else:
97
+ k += 1
98
+ if k >= num_found_fronts:
99
+ # move the individual to a new front
100
+ return num_found_fronts
101
+
102
+
103
+ def binary_search(F, i, fronts):
104
+ """
105
+ Find the front rank for the i-th individual through binary search.
106
+
107
+ Parameters
108
+ ----------
109
+ F: np.ndarray
110
+ the objective values
111
+ i: int
112
+ the index of the individual
113
+ fronts: list
114
+ individuals in each front
115
+ """
116
+
117
+ num_found_fronts = len(fronts)
118
+ if num_found_fronts == 0:
119
+ return 0
120
+
121
+ k_min = 0 # the lower bound for checking
122
+ k_max = num_found_fronts # the upper bound for checking
123
+ k = floor((k_max + k_min) / 2 + 0.5) # the front now checked
124
+ current = F[i]
125
+ while True:
126
+
127
+ # solutions in the k-th front, examine in reverse order
128
+ fk_indices = fronts[k - 1]
129
+ solutions = F[fk_indices[::-1]]
130
+ non_dominated = True
131
+
132
+ for f in solutions:
133
+ relation = Dominator.get_relation(current, f)
134
+ if relation == -1:
135
+ non_dominated = False
136
+ break
137
+
138
+ # binary search
139
+ if non_dominated:
140
+ if k == k_min + 1:
141
+ return k - 1
142
+ else:
143
+ k_max = k
144
+ k = floor((k_max + k_min) / 2 + 0.5)
145
+ else:
146
+ k_min = k
147
+ if k_max == k_min + 1 and k_max < num_found_fronts:
148
+ return k_max - 1
149
+ elif k_min == num_found_fronts:
150
+ return num_found_fronts
151
+ else:
152
+ k = floor((k_max + k_min) / 2 + 0.5)
@@ -0,0 +1,70 @@
1
+ import numpy as np
2
+
3
+ from pymoo.util.dominator import Dominator
4
+
5
+
6
+ def fast_non_dominated_sort(F, dominator=Dominator(), **kwargs):
7
+ if "dominator" in kwargs:
8
+ M = Dominator.calc_domination_matrix(F)
9
+ else:
10
+ M = dominator.calc_domination_matrix(F)
11
+
12
+ # calculate the dominance matrix
13
+ n = M.shape[0]
14
+
15
+ fronts = []
16
+
17
+ if n == 0:
18
+ return fronts
19
+
20
+ # final rank that will be returned
21
+ n_ranked = 0
22
+ ranked = np.zeros(n, dtype=int)
23
+
24
+ # for each individual a list of all individuals that are dominated by this one
25
+ is_dominating = [[] for _ in range(n)]
26
+
27
+ # storage for the number of solutions dominated this one
28
+ n_dominated = np.zeros(n)
29
+
30
+ current_front = []
31
+
32
+ for i in range(n):
33
+
34
+ for j in range(i + 1, n):
35
+ rel = M[i, j]
36
+ if rel == 1:
37
+ is_dominating[i].append(j)
38
+ n_dominated[j] += 1
39
+ elif rel == -1:
40
+ is_dominating[j].append(i)
41
+ n_dominated[i] += 1
42
+
43
+ if n_dominated[i] == 0:
44
+ current_front.append(i)
45
+ ranked[i] = 1.0
46
+ n_ranked += 1
47
+
48
+ # append the first front to the current front
49
+ fronts.append(current_front)
50
+
51
+ # while not all solutions are assigned to a pareto front
52
+ while n_ranked < n:
53
+
54
+ next_front = []
55
+
56
+ # for each individual in the current front
57
+ for i in current_front:
58
+
59
+ # all solutions that are dominated by this individuals
60
+ for j in is_dominating[i]:
61
+ n_dominated[j] -= 1
62
+ if n_dominated[j] == 0:
63
+ next_front.append(j)
64
+ ranked[j] = 1.0
65
+ n_ranked += 1
66
+
67
+ fronts.append(next_front)
68
+ current_front = next_front
69
+
70
+ return fronts
@@ -0,0 +1,54 @@
1
+ import numpy as np
2
+
3
+
4
+ def find_non_dominated(F, epsilon=0.0):
5
+ """
6
+ Simple and efficient implementation to find only non-dominated points.
7
+ Uses straightforward O(n²) algorithm with early termination.
8
+
9
+ Parameters
10
+ ----------
11
+ F : np.ndarray
12
+ Objective values matrix of shape (n_points, n_objectives)
13
+ epsilon : float, optional
14
+ Epsilon value for dominance comparison (default: 0.0)
15
+
16
+ Returns
17
+ -------
18
+ np.ndarray
19
+ Array of indices of non-dominated points
20
+ """
21
+ n_points = F.shape[0]
22
+ non_dominated_indices = []
23
+
24
+ if n_points == 0:
25
+ return np.array([], dtype=int)
26
+
27
+ # Check each point to see if it's non-dominated
28
+ for i in range(n_points):
29
+ is_dominated = False
30
+
31
+ # Check if point i is dominated by any other point j
32
+ for j in range(n_points):
33
+ if i != j:
34
+ # Check if j dominates i
35
+ dominates = True
36
+ at_least_one_better = False
37
+
38
+ for k in range(F.shape[1]): # for each objective
39
+ if F[j, k] + epsilon < F[i, k]: # j is better than i in objective k
40
+ at_least_one_better = True
41
+ elif F[j, k] > F[i, k] + epsilon: # j is worse than i in objective k
42
+ dominates = False
43
+ break # Early termination in objective loop
44
+
45
+ # j dominates i if j is at least as good in all objectives and better in at least one
46
+ if dominates and at_least_one_better:
47
+ is_dominated = True
48
+ break # Early termination - no need to check other points
49
+
50
+ # If point i is not dominated by any other point, it's non-dominated
51
+ if not is_dominated:
52
+ non_dominated_indices.append(i)
53
+
54
+ return np.array(non_dominated_indices, dtype=int)
@@ -0,0 +1,36 @@
1
+ from pymoo.util.dominator import Dominator
2
+
3
+
4
+ def naive_non_dominated_sort(F, **kwargs):
5
+ M = Dominator.calc_domination_matrix(F)
6
+
7
+ fronts = []
8
+ remaining = set(range(M.shape[0]))
9
+
10
+ while len(remaining) > 0:
11
+
12
+ front = []
13
+
14
+ for i in remaining:
15
+
16
+ is_dominated = False
17
+ dominating = set()
18
+
19
+ for j in front:
20
+ rel = M[i, j]
21
+ if rel == 1:
22
+ dominating.add(j)
23
+ elif rel == -1:
24
+ is_dominated = True
25
+ break
26
+
27
+ if is_dominated:
28
+ continue
29
+ else:
30
+ front = [x for x in front if x not in dominating]
31
+ front.append(i)
32
+
33
+ [remaining.remove(e) for e in front]
34
+ fronts.append(front)
35
+
36
+ return fronts
@@ -0,0 +1,94 @@
1
+ import sys
2
+
3
+ import numpy as np
4
+
5
+ from pymoo.functions import load_function
6
+ from pymoo.util.dominator import Dominator
7
+
8
+
9
+ class NonDominatedSorting:
10
+
11
+ def __init__(self, epsilon=None, method="fast_non_dominated_sort", dominator=None) -> None:
12
+ super().__init__()
13
+ self.epsilon = epsilon
14
+ self.method = method
15
+ self.dominator = dominator
16
+
17
+ def do(self, F, return_rank=False, only_non_dominated_front=False, n_stop_if_ranked=None, n_fronts=None, **kwargs):
18
+ F = F.astype(float)
19
+
20
+ # if not set just set it to a very large values because the cython algorithms do not take None
21
+ if n_stop_if_ranked is None:
22
+ n_stop_if_ranked = int(1e8)
23
+
24
+ # if only_non_dominated_front is True, we only need 1 front
25
+ if only_non_dominated_front:
26
+ n_fronts = 1
27
+ elif n_fronts is None:
28
+ n_fronts = int(1e8)
29
+
30
+ # if a custom dominator is provided, use the custom dominator and run fast_non_dominated_sort
31
+ if self.dominator is not None:
32
+ # Use the custom dominator directly
33
+ from pymoo.util.nds.fast_non_dominated_sort import fast_non_dominated_sort
34
+ fronts = fast_non_dominated_sort(F, dominator=self.dominator, **kwargs)
35
+ else:
36
+ # Use the standard function loader approach
37
+ func = load_function(self.method)
38
+
39
+ # set the epsilon if it should be set
40
+ if self.epsilon is not None:
41
+ kwargs["epsilon"] = float(self.epsilon)
42
+
43
+ # add n_fronts parameter if the method supports it
44
+ if self.method == "fast_non_dominated_sort":
45
+ kwargs["n_fronts"] = n_fronts
46
+ kwargs["n_stop_if_ranked"] = n_stop_if_ranked
47
+
48
+ fronts = func(F, **kwargs)
49
+
50
+ # convert to numpy array for each front and filter by n_stop_if_ranked
51
+ _fronts = []
52
+ n_ranked = 0
53
+ for front in fronts:
54
+
55
+ _fronts.append(np.array(front, dtype=int))
56
+
57
+ # increment the n_ranked solution counter
58
+ n_ranked += len(front)
59
+
60
+ # stop if more solutions than n_ranked are ranked
61
+ if n_ranked >= n_stop_if_ranked:
62
+ break
63
+
64
+ fronts = _fronts
65
+
66
+ if only_non_dominated_front:
67
+ return fronts[0]
68
+
69
+ if return_rank:
70
+ rank = rank_from_fronts(fronts, F.shape[0])
71
+ return fronts, rank
72
+
73
+ return fronts
74
+
75
+
76
+ def rank_from_fronts(fronts, n):
77
+ # create the rank array and set values
78
+ rank = np.full(n, sys.maxsize, dtype=int)
79
+ for i, front in enumerate(fronts):
80
+ rank[front] = i
81
+
82
+ return rank
83
+
84
+
85
+ # Returns all indices of F that are not dominated by the other objective values
86
+ def find_non_dominated(F, _F=None, func=load_function("find_non_dominated")):
87
+ if _F is None:
88
+ indices = func(F.astype(float))
89
+ return np.array(indices, dtype=int)
90
+ else:
91
+ # Fallback to the matrix-based approach when _F is provided
92
+ M = Dominator.calc_domination_matrix(F, _F)
93
+ I = np.where(np.all(M >= 0, axis=1))[0]
94
+ return I
@@ -0,0 +1,133 @@
1
+ import weakref
2
+
3
+ import numpy as np
4
+
5
+
6
+
7
+ class Tree:
8
+ '''
9
+ Implementation of Nary-tree.
10
+ The source code is modified based on https://github.com/lianemeth/forest/blob/master/forest/NaryTree.py
11
+
12
+ Parameters
13
+ ----------
14
+ key: object
15
+ key of the node
16
+ num_branch: int
17
+ how many branches in each node
18
+ children: Iterable[Tree]
19
+ reference of the children
20
+ parent: Tree
21
+ reference of the parent node
22
+ Returns
23
+ -------
24
+ an N-ary tree.
25
+ '''
26
+
27
+ def __init__(self, key, num_branch, children=None, parent=None):
28
+ self.key = key
29
+ self.children = children or [None for _ in range(num_branch)]
30
+
31
+ self._parent = weakref.ref(parent) if parent else None
32
+
33
+ @property
34
+ def parent(self):
35
+ if self._parent:
36
+ return self._parent()
37
+
38
+ def __getstate__(self):
39
+ self._parent = None
40
+
41
+ def __setstate__(self, state):
42
+ self.__dict__ = state
43
+ for child in self.children:
44
+ child._parent = weakref.ref(self)
45
+
46
+ def traversal(self, visit=None, *args, **kwargs):
47
+ if visit is not None:
48
+ visit(self, *args, **kwargs)
49
+ l = [self]
50
+ for child in self.children:
51
+ if child is not None:
52
+ l += child.traversal(visit, *args, **kwargs)
53
+ return l
54
+
55
+
56
+ def tree_based_non_dominated_sort(F):
57
+ """
58
+ Tree-based efficient non-dominated sorting (T-ENS).
59
+ This algorithm is very efficient in many-objective optimization problems (MaOPs).
60
+ Parameters
61
+ ----------
62
+ F: np.array
63
+ objective values for each individual.
64
+ Returns
65
+ -------
66
+ indices of the individuals in each front.
67
+ References
68
+ ----------
69
+ X. Zhang, Y. Tian, R. Cheng, and Y. Jin,
70
+ A decision variable clustering based evolutionary algorithm for large-scale many-objective optimization,
71
+ IEEE Transactions on Evolutionary Computation, 2018, 22(1): 97-112.
72
+ """
73
+
74
+ N, M = F.shape
75
+ # sort the rows in F
76
+ indices = np.lexsort(F.T[::-1])
77
+ F = F[indices]
78
+
79
+ obj_seq = np.argsort(F[:, :0:-1], axis=1) + 1
80
+
81
+ k = 0
82
+
83
+ forest = []
84
+
85
+ left = np.full(N, True)
86
+ while np.any(left):
87
+ forest.append(None)
88
+ for p, flag in enumerate(left):
89
+ if flag:
90
+ update_tree(F, p, forest, k, left, obj_seq)
91
+ k += 1
92
+
93
+ # convert forest to fronts
94
+ fronts = [[] for _ in range(k)]
95
+ for k, tree in enumerate(forest):
96
+ fronts[k].extend([indices[node.key] for node in tree.traversal()])
97
+ return fronts
98
+
99
+
100
+ def update_tree(F, p, forest, k, left, obj_seq):
101
+ _, M = F.shape
102
+ if forest[k] is None:
103
+ forest[k] = Tree(key=p, num_branch=M - 1)
104
+ left[p] = False
105
+ elif check_tree(F, p, forest[k], obj_seq, True):
106
+ left[p] = False
107
+
108
+
109
+ def check_tree(F, p, tree, obj_seq, add_pos):
110
+ if tree is None:
111
+ return True
112
+
113
+ N, M = F.shape
114
+
115
+ # find the minimal index m satisfying that p[obj_seq[tree.root][m]] < tree.root[obj_seq[tree.root][m]]
116
+ m = 0
117
+ while m < M - 1 and F[p, obj_seq[tree.key, m]] >= F[tree.key, obj_seq[tree.key, m]]:
118
+ m += 1
119
+
120
+ # if m not found
121
+ if m == M - 1:
122
+ # p is dominated by the solution at the root
123
+ return False
124
+ else:
125
+ for i in range(m + 1):
126
+ # p is dominated by a solution in the branch of the tree
127
+ if not check_tree(F, p, tree.children[i], obj_seq, i == m and add_pos):
128
+ return False
129
+
130
+ if tree.children[m] is None and add_pos:
131
+ # add p to the branch of the tree
132
+ tree.children[m] = Tree(key=p, num_branch=M - 1)
133
+ return True