pymoo 0.6.1.5.dev0__cp313-cp313-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.

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-darwin.so +0 -0
  91. pymoo/cython/calc_perpendicular_distance.pyx +67 -0
  92. pymoo/cython/decomposition.cpython-313-darwin.so +0 -0
  93. pymoo/cython/decomposition.pyx +165 -0
  94. pymoo/cython/hv.cpython-313-darwin.so +0 -0
  95. pymoo/cython/hv.pyx +18 -0
  96. pymoo/cython/info.cpython-313-darwin.so +0 -0
  97. pymoo/cython/info.pyx +5 -0
  98. pymoo/cython/mnn.cpython-313-darwin.so +0 -0
  99. pymoo/cython/mnn.pyx +273 -0
  100. pymoo/cython/non_dominated_sorting.cpython-313-darwin.so +0 -0
  101. pymoo/cython/non_dominated_sorting.pyx +645 -0
  102. pymoo/cython/pruning_cd.cpython-313-darwin.so +0 -0
  103. pymoo/cython/pruning_cd.pyx +197 -0
  104. pymoo/cython/stochastic_ranking.cpython-313-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
@@ -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,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,67 @@
1
+ import numpy as np
2
+ import sys
3
+ from pymoo.util.dominator import Dominator
4
+ from pymoo.util.function_loader import load_function
5
+
6
+
7
+ class NonDominatedSorting:
8
+
9
+ def __init__(self, epsilon=None, method="fast_non_dominated_sort") -> None:
10
+ super().__init__()
11
+ self.epsilon = epsilon
12
+ self.method = method
13
+
14
+ def do(self, F, return_rank=False, only_non_dominated_front=False, n_stop_if_ranked=None, **kwargs):
15
+ F = F.astype(float)
16
+
17
+ # if not set just set it to a very large values because the cython algorithms do not take None
18
+ if n_stop_if_ranked is None:
19
+ n_stop_if_ranked = int(1e8)
20
+ func = load_function(self.method)
21
+
22
+ # set the epsilon if it should be set
23
+ if self.epsilon is not None:
24
+ kwargs["epsilon"] = float(self.epsilon)
25
+
26
+ fronts = func(F, **kwargs)
27
+
28
+ # convert to numpy array for each front and filter by n_stop_if_ranked if desired
29
+ _fronts = []
30
+ n_ranked = 0
31
+ for front in fronts:
32
+
33
+ _fronts.append(np.array(front, dtype=int))
34
+
35
+ # increment the n_ranked solution counter
36
+ n_ranked += len(front)
37
+
38
+ # stop if more than this solutions are n_ranked
39
+ if n_ranked >= n_stop_if_ranked:
40
+ break
41
+
42
+ fronts = _fronts
43
+
44
+ if only_non_dominated_front:
45
+ return fronts[0]
46
+
47
+ if return_rank:
48
+ rank = rank_from_fronts(fronts, F.shape[0])
49
+ return fronts, rank
50
+
51
+ return fronts
52
+
53
+
54
+ def rank_from_fronts(fronts, n):
55
+ # create the rank array and set values
56
+ rank = np.full(n, sys.maxsize, dtype=int)
57
+ for i, front in enumerate(fronts):
58
+ rank[front] = i
59
+
60
+ return rank
61
+
62
+
63
+ # Returns all indices of F that are not dominated by the other objective values
64
+ def find_non_dominated(F, _F=None):
65
+ M = Dominator.calc_domination_matrix(F, _F)
66
+ I = np.where(np.all(M >= 0, axis=1))[0]
67
+ 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