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,212 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.population import Population
4
+ from pymoo.core.survival import Survival, split_by_feasibility
5
+ from pymoo.operators.survival.rank_and_crowding.metrics import get_crowding_function
6
+ from pymoo.util.nds.non_dominated_sorting import NonDominatedSorting
7
+ from pymoo.util.randomized_argsort import randomized_argsort
8
+
9
+
10
+ class RankAndCrowding(Survival):
11
+
12
+ def __init__(self, nds=None, crowding_func="cd"):
13
+ """
14
+ A generalization of the NSGA-II survival operator that ranks individuals by dominance criteria
15
+ and sorts the last front by some user-specified crowding metric. The default is NSGA-II's crowding distances
16
+ although others might be more effective.
17
+
18
+ For many-objective problems, try using 'mnn' or '2nn'.
19
+
20
+ For Bi-objective problems, 'pcd' is very effective.
21
+
22
+ Parameters
23
+ ----------
24
+ nds : str or None, optional
25
+ Pymoo type of non-dominated sorting. Defaults to None.
26
+
27
+ crowding_func : str or callable, optional
28
+ Crowding metric. Options are:
29
+
30
+ - 'cd': crowding distances
31
+ - 'pcd' or 'pruning-cd': improved pruning based on crowding distances
32
+ - 'ce': crowding entropy
33
+ - 'mnn': M-Neaest Neighbors
34
+ - '2nn': 2-Neaest Neighbors
35
+
36
+ If callable, it has the form ``fun(F, filter_out_duplicates=None, n_remove=None, **kwargs)``
37
+ in which F (n, m) and must return metrics in a (n,) array.
38
+
39
+ The options 'pcd', 'cd', and 'ce' are recommended for two-objective problems, whereas 'mnn' and '2nn' for many objective.
40
+ When using 'pcd', 'mnn', or '2nn', individuals are already eliminated in a 'single' manner.
41
+ Due to Cython implementation, they are as fast as the corresponding 'cd', 'mnn-fast', or '2nn-fast',
42
+ although they can singnificantly improve diversity of solutions.
43
+ Defaults to 'cd'.
44
+ """
45
+
46
+ crowding_func_ = get_crowding_function(crowding_func)
47
+
48
+ super().__init__(filter_infeasible=True)
49
+ self.nds = nds if nds is not None else NonDominatedSorting()
50
+ self.crowding_func = crowding_func_
51
+
52
+
53
+ def _do(self,
54
+ problem,
55
+ pop,
56
+ *args,
57
+ random_state=None,
58
+ n_survive=None,
59
+ **kwargs):
60
+
61
+ # get the objective space values and objects
62
+ F = pop.get("F").astype(float, copy=False)
63
+
64
+ # the final indices of surviving individuals
65
+ survivors = []
66
+
67
+ # do the non-dominated sorting until splitting front
68
+ fronts = self.nds.do(F, n_stop_if_ranked=n_survive)
69
+
70
+ for k, front in enumerate(fronts):
71
+
72
+ I = np.arange(len(front))
73
+
74
+ # current front sorted by crowding distance if splitting
75
+ if len(survivors) + len(I) > n_survive:
76
+
77
+ # Define how many will be removed
78
+ n_remove = len(survivors) + len(front) - n_survive
79
+
80
+ # re-calculate the crowding distance of the front
81
+ crowding_of_front = \
82
+ self.crowding_func.do(
83
+ F[front, :],
84
+ n_remove=n_remove
85
+ )
86
+
87
+ I = randomized_argsort(crowding_of_front, order='descending', method='numpy', random_state=random_state)
88
+ I = I[:-n_remove]
89
+
90
+ # otherwise take the whole front unsorted
91
+ else:
92
+ # calculate the crowding distance of the front
93
+ crowding_of_front = \
94
+ self.crowding_func.do(
95
+ F[front, :],
96
+ n_remove=0
97
+ )
98
+
99
+ # save rank and crowding in the individual class
100
+ for j, i in enumerate(front):
101
+ pop[i].set("rank", k)
102
+ pop[i].set("crowding", crowding_of_front[j])
103
+
104
+ # extend the survivors by all or selected individuals
105
+ survivors.extend(front[I])
106
+
107
+ return pop[survivors]
108
+
109
+
110
+ class ConstrRankAndCrowding(Survival):
111
+
112
+ def __init__(self, nds=None, crowding_func="cd"):
113
+ """
114
+ The Rank and Crowding survival approach for handling constraints proposed on
115
+ GDE3 by Kukkonen, S. & Lampinen, J. (2005).
116
+
117
+ Parameters
118
+ ----------
119
+ nds : str or None, optional
120
+ Pymoo type of non-dominated sorting. Defaults to None.
121
+
122
+ crowding_func : str or callable, optional
123
+ Crowding metric. Options are:
124
+
125
+ - 'cd': crowding distances
126
+ - 'pcd' or 'pruning-cd': improved pruning based on crowding distances
127
+ - 'ce': crowding entropy
128
+ - 'mnn': M-Neaest Neighbors
129
+ - '2nn': 2-Neaest Neighbors
130
+
131
+ If callable, it has the form ``fun(F, filter_out_duplicates=None, n_remove=None, **kwargs)``
132
+ in which F (n, m) and must return metrics in a (n,) array.
133
+
134
+ The options 'pcd', 'cd', and 'ce' are recommended for two-objective problems, whereas 'mnn' and '2nn' for many objective.
135
+ When using 'pcd', 'mnn', or '2nn', individuals are already eliminated in a 'single' manner.
136
+ Due to Cython implementation, they are as fast as the corresponding 'cd', 'mnn-fast', or '2nn-fast',
137
+ although they can singnificantly improve diversity of solutions.
138
+ Defaults to 'cd'.
139
+ """
140
+
141
+ super().__init__(filter_infeasible=False)
142
+ self.nds = nds if nds is not None else NonDominatedSorting()
143
+ self.ranking = RankAndCrowding(nds=nds, crowding_func=crowding_func)
144
+
145
+ def _do(self,
146
+ problem,
147
+ pop,
148
+ *args,
149
+ n_survive=None,
150
+ **kwargs):
151
+
152
+ if n_survive is None:
153
+ n_survive = len(pop)
154
+
155
+ n_survive = min(n_survive, len(pop))
156
+
157
+ # If the split should be done beforehand
158
+ if problem.n_constr > 0:
159
+
160
+ # Split by feasibility
161
+ feas, infeas = split_by_feasibility(pop, sort_infeas_by_cv=True, sort_feas_by_obj=False, return_pop=False)
162
+
163
+ # Obtain len of feasible
164
+ n_feas = len(feas)
165
+
166
+ # Assure there is at least_one survivor
167
+ if n_feas == 0:
168
+ survivors = Population()
169
+ else:
170
+ survivors = self.ranking.do(problem, pop[feas], *args, n_survive=min(len(feas), n_survive), **kwargs)
171
+
172
+ # Calculate how many individuals are still remaining to be filled up with infeasible ones
173
+ n_remaining = n_survive - len(survivors)
174
+
175
+ # If infeasible solutions need to be added
176
+ if n_remaining > 0:
177
+
178
+ # Constraints to new ranking
179
+ G = pop[infeas].get("G")
180
+ G = np.maximum(G, 0)
181
+ H = pop[infeas].get("H")
182
+ H = np.absolute(H)
183
+ C = np.column_stack((G, H))
184
+
185
+ # Fronts in infeasible population
186
+ infeas_fronts = self.nds.do(C, n_stop_if_ranked=n_remaining)
187
+
188
+ # Iterate over fronts
189
+ for k, front in enumerate(infeas_fronts):
190
+
191
+ # Save ranks
192
+ pop[infeas][front].set("cv_rank", k)
193
+
194
+ # Current front sorted by CV
195
+ if len(survivors) + len(front) > n_survive:
196
+
197
+ # Obtain CV of front
198
+ CV = pop[infeas][front].get("CV").flatten()
199
+ I = randomized_argsort(CV, order='ascending', method='numpy')
200
+ I = I[:(n_survive - len(survivors))]
201
+
202
+ # Otherwise take the whole front unsorted
203
+ else:
204
+ I = np.arange(len(front))
205
+
206
+ # extend the survivors by all or selected individuals
207
+ survivors = Population.merge(survivors, pop[infeas][front[I]])
208
+
209
+ else:
210
+ survivors = self.ranking.do(problem, pop, *args, n_survive=n_survive, **kwargs)
211
+
212
+ return survivors
@@ -0,0 +1,208 @@
1
+ import numpy as np
2
+ from scipy.spatial.distance import pdist, squareform
3
+ from pymoo.util.misc import find_duplicates
4
+ from pymoo.functions import load_function
5
+
6
+
7
+ def get_crowding_function(label):
8
+
9
+ if label == "cd":
10
+ fun = FunctionalDiversity(calc_crowding_distance, filter_out_duplicates=False)
11
+ elif (label == "pcd") or (label == "pruning-cd"):
12
+ fun = FunctionalDiversity(load_function("calc_pcd"), filter_out_duplicates=True)
13
+ elif label == "ce":
14
+ fun = FunctionalDiversity(calc_crowding_entropy, filter_out_duplicates=True)
15
+ elif label == "mnn":
16
+ fun = FuncionalDiversityMNN(load_function("calc_mnn"), filter_out_duplicates=True)
17
+ elif label == "2nn":
18
+ fun = FuncionalDiversityMNN(load_function("calc_2nn"), filter_out_duplicates=True)
19
+ elif hasattr(label, "__call__"):
20
+ fun = FunctionalDiversity(label, filter_out_duplicates=True)
21
+ elif isinstance(label, CrowdingDiversity):
22
+ fun = label
23
+ else:
24
+ raise KeyError("Crowding function not defined")
25
+ return fun
26
+
27
+
28
+ class CrowdingDiversity:
29
+
30
+ def do(self, F, n_remove=0):
31
+ # Converting types Python int to Cython int would fail in some cases converting to long instead
32
+ n_remove = np.intc(n_remove)
33
+ F = np.array(F, dtype=np.double)
34
+ return self._do(F, n_remove=n_remove)
35
+
36
+ def _do(self, F, n_remove=None):
37
+ pass
38
+
39
+
40
+ class FunctionalDiversity(CrowdingDiversity):
41
+
42
+ def __init__(self, function=None, filter_out_duplicates=True):
43
+ self.function = function
44
+ self.filter_out_duplicates = filter_out_duplicates
45
+ super().__init__()
46
+
47
+ def _do(self, F, **kwargs):
48
+
49
+ n_points, n_obj = F.shape
50
+
51
+ if n_points <= 2:
52
+ return np.full(n_points, np.inf)
53
+
54
+ else:
55
+
56
+ if self.filter_out_duplicates:
57
+ # filter out solutions which are duplicates - duplicates get a zero finally
58
+ is_unique = np.where(np.logical_not(find_duplicates(F, epsilon=1e-32)))[0]
59
+ else:
60
+ # set every point to be unique without checking it
61
+ is_unique = np.arange(n_points)
62
+
63
+ # index the unique points of the array
64
+ _F = F[is_unique]
65
+
66
+ _d = self.function(_F, **kwargs)
67
+
68
+ d = np.zeros(n_points)
69
+ d[is_unique] = _d
70
+
71
+ return d
72
+
73
+
74
+ class FuncionalDiversityMNN(FunctionalDiversity):
75
+
76
+ def _do(self, F, **kwargs):
77
+
78
+ n_points, n_obj = F.shape
79
+
80
+ if n_points <= n_obj:
81
+ return np.full(n_points, np.inf)
82
+
83
+ else:
84
+ return super()._do(F, **kwargs)
85
+
86
+
87
+ def calc_crowding_distance(F, **kwargs):
88
+ n_points, n_obj = F.shape
89
+
90
+ # sort each column and get index
91
+ I = np.argsort(F, axis=0, kind='mergesort')
92
+
93
+ # sort the objective space values for the whole matrix
94
+ F = F[I, np.arange(n_obj)]
95
+
96
+ # calculate the distance from each point to the last and next
97
+ dist = np.vstack([F, np.full(n_obj, np.inf)]) - np.vstack([np.full(n_obj, -np.inf), F])
98
+
99
+ # calculate the norm for each objective - set to NaN if all values are equal
100
+ norm = np.max(F, axis=0) - np.min(F, axis=0)
101
+ norm[norm == 0] = np.nan
102
+
103
+ # prepare the distance to last and next vectors
104
+ dist_to_last, dist_to_next = dist, np.copy(dist)
105
+ dist_to_last, dist_to_next = dist_to_last[:-1] / norm, dist_to_next[1:] / norm
106
+
107
+ # if we divide by zero because all values in one columns are equal replace by none
108
+ dist_to_last[np.isnan(dist_to_last)] = 0.0
109
+ dist_to_next[np.isnan(dist_to_next)] = 0.0
110
+
111
+ # sum up the distance to next and last and norm by objectives - also reorder from sorted list
112
+ J = np.argsort(I, axis=0)
113
+ cd = np.sum(dist_to_last[J, np.arange(n_obj)] + dist_to_next[J, np.arange(n_obj)], axis=1) / n_obj
114
+
115
+ return cd
116
+
117
+
118
+ def calc_crowding_entropy(F, **kwargs):
119
+ """Wang, Y.-N., Wu, L.-H. & Yuan, X.-F., 2010. Multi-objective self-adaptive differential
120
+ evolution with elitist archive and crowding entropy-based diversity measure.
121
+ Soft Comput., 14(3), pp. 193-209.
122
+
123
+ Parameters
124
+ ----------
125
+ F : 2d array like
126
+ Objective functions.
127
+
128
+ Returns
129
+ -------
130
+ ce : 1d array
131
+ Crowding Entropies
132
+ """
133
+ n_points, n_obj = F.shape
134
+
135
+ # sort each column and get index
136
+ I = np.argsort(F, axis=0, kind='mergesort')
137
+
138
+ # sort the objective space values for the whole matrix
139
+ F = F[I, np.arange(n_obj)]
140
+
141
+ # calculate the distance from each point to the last and next
142
+ dist = np.vstack([F, np.full(n_obj, np.inf)]) - np.vstack([np.full(n_obj, -np.inf), F])
143
+
144
+ # calculate the norm for each objective - set to NaN if all values are equal
145
+ norm = np.max(F, axis=0) - np.min(F, axis=0)
146
+ norm[norm == 0] = np.nan
147
+
148
+ # prepare the distance to last and next vectors
149
+ dl = dist.copy()[:-1]
150
+ du = dist.copy()[1:]
151
+
152
+ # Fix nan
153
+ dl[np.isnan(dl)] = 0.0
154
+ du[np.isnan(du)] = 0.0
155
+
156
+ # Total distance
157
+ cd = dl + du
158
+
159
+ # Get relative positions
160
+ pl = (dl[1:-1] / cd[1:-1])
161
+ pu = (du[1:-1] / cd[1:-1])
162
+
163
+ # Entropy
164
+ entropy = np.vstack([np.full(n_obj, np.inf),
165
+ -(pl * np.log2(pl) + pu * np.log2(pu)),
166
+ np.full(n_obj, np.inf)])
167
+
168
+ # Crowding entropy
169
+ J = np.argsort(I, axis=0)
170
+ _cej = cd[J, np.arange(n_obj)] * entropy[J, np.arange(n_obj)] / norm
171
+ _cej[np.isnan(_cej)] = 0.0
172
+ ce = _cej.sum(axis=1)
173
+
174
+ return ce
175
+
176
+
177
+ def calc_mnn_fast(F, **kwargs):
178
+ return _calc_mnn_fast(F, F.shape[1], **kwargs)
179
+
180
+
181
+ def calc_2nn_fast(F, **kwargs):
182
+ return _calc_mnn_fast(F, 2, **kwargs)
183
+
184
+
185
+ def _calc_mnn_fast(F, n_neighbors, **kwargs):
186
+
187
+ # calculate the norm for each objective - set to NaN if all values are equal
188
+ norm = np.max(F, axis=0) - np.min(F, axis=0)
189
+ norm[norm == 0] = 1.0
190
+
191
+ # F normalized
192
+ F = (F - F.min(axis=0)) / norm
193
+
194
+ # Distances pairwise (Inefficient)
195
+ D = squareform(pdist(F, metric="sqeuclidean"))
196
+
197
+ # M neighbors
198
+ M = F.shape[1]
199
+ _D = np.partition(D, range(1, M+1), axis=1)[:, 1:M+1]
200
+
201
+ # Metric d
202
+ d = np.prod(_D, axis=1)
203
+
204
+ # Set top performers as np.inf
205
+ _extremes = np.concatenate((np.argmin(F, axis=0), np.argmax(F, axis=0)))
206
+ d[_extremes] = np.inf
207
+
208
+ return d
pymoo/optimize.py ADDED
@@ -0,0 +1,72 @@
1
+ import copy
2
+
3
+
4
+ def minimize(problem, algorithm, termination=None, copy_algorithm=True, copy_termination=True, **kwargs):
5
+ """
6
+
7
+ Minimization of function of one or more variables, objectives and constraints.
8
+
9
+ This is used as a convenience function to execute several algorithms with default settings which turned
10
+ out to work for a test single. However, evolutionary computations utilizes the idea of customizing a
11
+ meta-algorithm. Customizing the algorithm using the object-oriented interface is recommended to improve the
12
+ convergence.
13
+
14
+ Parameters
15
+ ----------
16
+
17
+ problem : :class:`~pymoo.core.problem.Problem`
18
+ A problem object which is defined using pymoo.
19
+
20
+ algorithm : :class:`~pymoo.core.algorithm.Algorithm`
21
+ The algorithm object that should be used for the optimization.
22
+
23
+ termination : :class:`~pymoo.core.termination.Termination` or tuple
24
+ The termination criterion that is used to stop the algorithm.
25
+
26
+ seed : integer
27
+ The random seed to be used.
28
+
29
+ verbose : bool
30
+ Whether output should be printed or not.
31
+
32
+ display : :class:`~pymoo.util.display.Display`
33
+ Each algorithm has a default display object for printouts. However, it can be overwritten if desired.
34
+
35
+ callback : :class:`~pymoo.core.callback.Callback`
36
+ A callback object which is called each iteration of the algorithm.
37
+
38
+ save_history : bool
39
+ Whether the history should be stored or not.
40
+
41
+ copy_algorithm : bool
42
+ Whether the algorithm object should be copied before optimization.
43
+
44
+ Returns
45
+ -------
46
+ res : :class:`~pymoo.core.result.Result`
47
+ The optimization result represented as an object.
48
+
49
+ """
50
+
51
+ # create a copy of the algorithm object to ensure no side effects
52
+ if copy_algorithm:
53
+ algorithm = copy.deepcopy(algorithm)
54
+
55
+ # initialize the algorithm object given a problem - if not set already
56
+ if algorithm.problem is None:
57
+ if termination is not None:
58
+
59
+ if copy_termination:
60
+ termination = copy.deepcopy(termination)
61
+
62
+ kwargs["termination"] = termination
63
+
64
+ algorithm.setup(problem, **kwargs)
65
+
66
+ # actually execute the algorithm
67
+ res = algorithm.run()
68
+
69
+ # store the deep copied algorithm in the result object
70
+ res.algorithm = algorithm
71
+
72
+ return res
@@ -0,0 +1,15 @@
1
+ """
2
+ Parallelization utilities for pymoo.
3
+ """
4
+
5
+ from .starmap import StarmapParallelization
6
+ from .dask import DaskParallelization
7
+ from .joblib import JoblibParallelization
8
+ from .ray import RayParallelization
9
+
10
+ __all__ = [
11
+ 'StarmapParallelization',
12
+ 'DaskParallelization',
13
+ 'JoblibParallelization',
14
+ 'RayParallelization'
15
+ ]
@@ -0,0 +1,25 @@
1
+ """
2
+ Dask-based parallelization for pymoo.
3
+ """
4
+
5
+
6
+ class DaskParallelization:
7
+ """Parallelization using Dask distributed client.
8
+
9
+ Parameters
10
+ ----------
11
+ client : dask.distributed.Client
12
+ Dask client for distributed computing
13
+ """
14
+
15
+ def __init__(self, client):
16
+ self.client = client
17
+
18
+ def __call__(self, f, X):
19
+ jobs = [self.client.submit(f, x) for x in X]
20
+ return [job.result() for job in jobs]
21
+
22
+ def __getstate__(self):
23
+ state = self.__dict__.copy()
24
+ state.pop("client", None)
25
+ return state
@@ -0,0 +1,28 @@
1
+
2
+ class JoblibParallelization:
3
+ """Parallelization using joblib.
4
+
5
+ Parameters
6
+ ----------
7
+ n_jobs : int, default=-1
8
+ Number of parallel jobs. -1 uses all available cores.
9
+ **kwargs
10
+ Additional arguments passed to joblib.Parallel
11
+ """
12
+
13
+ def __init__(self, n_jobs=-1, **kwargs):
14
+ try:
15
+ import joblib
16
+ except ImportError:
17
+ raise ImportError("joblib must be installed: pip install joblib")
18
+
19
+ self.joblib = joblib
20
+ self.n_jobs = n_jobs
21
+ self.kwargs = kwargs
22
+
23
+ def __call__(self, f, X):
24
+ with self.joblib.Parallel(n_jobs=self.n_jobs, **self.kwargs) as parallel:
25
+ return parallel(self.joblib.delayed(f)(x) for x in X)
26
+
27
+ def __getstate__(self):
28
+ return self.__dict__.copy()
@@ -0,0 +1,31 @@
1
+ """
2
+ Ray-based parallelization for pymoo.
3
+ """
4
+
5
+
6
+ class RayParallelization:
7
+ """Parallelization using Ray.
8
+
9
+ Parameters
10
+ ----------
11
+ job_resources : dict, default={'num_cpus': 1}
12
+ Ray resource requirements per job
13
+ """
14
+
15
+ def __init__(self, job_resources={'num_cpus': 1}):
16
+ try:
17
+ import ray
18
+ except ImportError:
19
+ raise ImportError("Ray must be installed: pip install ray")
20
+
21
+ self.ray = ray
22
+ self.job_resources = job_resources
23
+
24
+ def __call__(self, f, X):
25
+ runnable = self.ray.remote(f.__call__.__func__)
26
+ runnable = runnable.options(**self.job_resources)
27
+ futures = [runnable.remote(f, x) for x in X]
28
+ return self.ray.get(futures)
29
+
30
+ def __getstate__(self):
31
+ return self.__dict__.copy()
@@ -0,0 +1,24 @@
1
+ """
2
+ Starmap-based parallelization for pymoo.
3
+ """
4
+
5
+
6
+ class StarmapParallelization:
7
+ """Parallelization using a starmap function.
8
+
9
+ Parameters
10
+ ----------
11
+ starmap : callable
12
+ A starmap function like multiprocessing.Pool.starmap
13
+ """
14
+
15
+ def __init__(self, starmap):
16
+ self.starmap = starmap
17
+
18
+ def __call__(self, f, X):
19
+ return list(self.starmap(f, [[x] for x in X]))
20
+
21
+ def __getstate__(self):
22
+ state = self.__dict__.copy()
23
+ state.pop("starmap", None)
24
+ return state