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,191 @@
1
+ import numpy as np
2
+
3
+ from pymoo.algorithms.base.genetic import GeneticAlgorithm
4
+ from pymoo.algorithms.moo.nsga3 import HyperplaneNormalization
5
+ from pymoo.core.survival import Survival
6
+ from pymoo.docs import parse_doc_string
7
+ from pymoo.operators.crossover.sbx import SBX
8
+ from pymoo.operators.mutation.pm import PM
9
+ from pymoo.operators.sampling.rnd import FloatRandomSampling
10
+ from pymoo.operators.selection.tournament import TournamentSelection, compare
11
+ from pymoo.termination.default import DefaultMultiObjectiveTermination
12
+ from pymoo.util.display.multi import MultiObjectiveOutput
13
+ from pymoo.util.dominator import Dominator
14
+ from pymoo.util.misc import vectorized_cdist
15
+
16
+
17
+ # ---------------------------------------------------------------------------------------------------------
18
+ # Environmental Survival (in the original paper it is referred to as archiving)
19
+ # ---------------------------------------------------------------------------------------------------------
20
+
21
+
22
+ class SPEA2Survival(Survival):
23
+
24
+ def __init__(self, normalize=False, filter_infeasible=True):
25
+ super().__init__(filter_infeasible)
26
+
27
+ # whether the survival should considered normalized distance or just raw
28
+ self.normalize = normalize
29
+
30
+ # an object keeping track of normalization points
31
+ self.norm = None
32
+
33
+ def _do(self, problem, pop, *args, n_survive=None, **kwargs):
34
+
35
+ # get the objective space values and objects
36
+ F = pop.get("F").astype(float, copy=False)
37
+
38
+ # the domination matrix to see the relation for each solution to another
39
+ M = Dominator().calc_domination_matrix(F)
40
+
41
+ # the number of solutions each individual dominates
42
+ S = (M == 1).sum(axis=1)
43
+
44
+ # the raw fitness of each solution - strength of its dominators
45
+ R = ((M == -1) * S).sum(axis=1)
46
+
47
+ # determine what k-th nearest neighbor to consider
48
+ k = int(np.sqrt(len(pop)))
49
+ if k >= len(pop):
50
+ k = len(pop) - 1
51
+
52
+ # if normalization is enabled keep track of ideal and nadir
53
+ if self.normalize:
54
+
55
+ # initialize the first time and then always update the boundary points
56
+ if self.norm is None:
57
+ self.norm = HyperplaneNormalization(F.shape[1])
58
+ self.norm.update(F)
59
+
60
+ ideal, nadir = self.norm.ideal_point, self.norm.nadir_point
61
+
62
+ _F = (F - ideal) / (nadir - ideal)
63
+ dists = vectorized_cdist(_F, _F, fill_diag_with_inf=True)
64
+
65
+ # if no normalize is required simply use the F values from the population
66
+ else:
67
+ dists = vectorized_cdist(F, F, fill_diag_with_inf=True)
68
+
69
+ # the distances sorted for each individual
70
+ sdists = np.sort(dists, axis=1)
71
+
72
+ # inverse distance as part of the fitness
73
+ D = 1 / (sdists[:, k] + 2)
74
+
75
+ # the actual fitness value used to determine who survives
76
+ SPEA_F = R + D
77
+
78
+ # set all the attributes to the population
79
+ pop.set(SPEA_F=SPEA_F, SPEA_R=R, SPEA_D=D)
80
+
81
+ # get all the non-dominated solutions
82
+ survivors = list(np.where(np.all(M >= 0, axis=1))[0])
83
+
84
+ # if we normalize give boundary points most importance - give the boundary points in the nds set the lowest fit.
85
+ if self.normalize:
86
+ I = vectorized_cdist(self.norm.extreme_points, F[survivors]).argmin(axis=1)
87
+ pop[survivors][I].set("SPEA_F", -1.0)
88
+
89
+ # identify the remaining individuals to choose from
90
+ H = set(survivors)
91
+ rem = np.array([k for k in range(len(pop)) if k not in H])
92
+
93
+ # if not enough solutions, will up by F
94
+ if len(survivors) < n_survive:
95
+
96
+ # sort them by the fitness values (lower is better) and append them
97
+ rem_by_F = rem[SPEA_F[rem].argsort()]
98
+ survivors.extend(rem_by_F[:n_survive - len(survivors)])
99
+
100
+ # if too many, delete based on distances
101
+ elif len(survivors) > n_survive:
102
+
103
+ # remove one individual per loop, until we hit n_survive
104
+ while len(survivors) > n_survive:
105
+ i = dists[survivors][:, survivors].min(axis=1).argmin()
106
+ survivors = [survivors[j] for j in range(len(survivors)) if j != i]
107
+
108
+ return pop[survivors]
109
+
110
+
111
+ # ---------------------------------------------------------------------------------------------------------
112
+ # Binary Tournament Selection
113
+ # ---------------------------------------------------------------------------------------------------------
114
+
115
+
116
+ def spea_binary_tournament(pop, P, algorithm, random_state=None, **kwargs):
117
+ n_tournaments, n_parents = P.shape
118
+
119
+ if n_parents != 2:
120
+ raise ValueError("Only implemented for binary tournament!")
121
+
122
+ S = np.full(n_tournaments, np.nan)
123
+
124
+ for i in range(n_tournaments):
125
+
126
+ a, b = P[i, 0], P[i, 1]
127
+ a_cv, a_f, b_cv, b_f, = pop[a].CV[0], pop[a].F, pop[b].CV[0], pop[b].F
128
+
129
+ # if at least one solution is infeasible
130
+ if a_cv > 0.0 or b_cv > 0.0:
131
+ S[i] = compare(a, a_cv, b, b_cv, method='smaller_is_better',
132
+ return_random_if_equal=True, random_state=random_state)
133
+
134
+ # both solutions are feasible
135
+ else:
136
+ S[i] = compare(a, pop[a].get("SPEA_F"), b, pop[b].get("SPEA_F"), method='smaller_is_better',
137
+ return_random_if_equal=True, random_state=random_state)
138
+
139
+ return S[:, None].astype(int, copy=False)
140
+
141
+
142
+ # ---------------------------------------------------------------------------------------------------------
143
+ # Algorithm
144
+ # ---------------------------------------------------------------------------------------------------------
145
+
146
+
147
+ class SPEA2(GeneticAlgorithm):
148
+
149
+ def __init__(self,
150
+ pop_size=100,
151
+ sampling=FloatRandomSampling(),
152
+ selection=TournamentSelection(spea_binary_tournament),
153
+ crossover=SBX(),
154
+ mutation=PM(),
155
+ survival=SPEA2Survival(normalize=True),
156
+ eliminate_duplicates=True,
157
+ n_offsprings=None,
158
+ output=MultiObjectiveOutput(),
159
+ **kwargs):
160
+ """
161
+
162
+ SPEA2 - Strength Pareto EA 2
163
+
164
+ Parameters
165
+ ----------
166
+ pop_size : {pop_size}
167
+ sampling : {sampling}
168
+ selection : {selection}
169
+ crossover : {crossover}
170
+ mutation : {mutation}
171
+ eliminate_duplicates : {eliminate_duplicates}
172
+ n_offsprings : {n_offsprings}
173
+
174
+ """
175
+
176
+ super().__init__(pop_size=pop_size,
177
+ sampling=sampling,
178
+ selection=selection,
179
+ crossover=crossover,
180
+ mutation=mutation,
181
+ survival=survival,
182
+ eliminate_duplicates=eliminate_duplicates,
183
+ n_offsprings=n_offsprings,
184
+ output=output,
185
+ advance_after_initial_infill=True,
186
+ **kwargs)
187
+ self.termination = DefaultMultiObjectiveTermination()
188
+
189
+
190
+ parse_doc_string(SPEA2.__init__)
191
+
@@ -0,0 +1,49 @@
1
+ import numpy as np
2
+
3
+ from pymoo.algorithms.moo.nsga3 import NSGA3
4
+ from pymoo.util import default_random_state
5
+ from pymoo.operators.selection.tournament import compare, TournamentSelection
6
+
7
+
8
+ # =========================================================================================================
9
+ # Implementation
10
+ # =========================================================================================================
11
+
12
+
13
+ @default_random_state
14
+ def comp_by_rank_and_ref_line_dist(pop, P, random_state=None, **kwargs):
15
+ S = np.full(P.shape[0], np.nan)
16
+
17
+ for i in range(P.shape[0]):
18
+ a, b = P[i, 0], P[i, 1]
19
+
20
+ # if at least one solution is infeasible
21
+ if pop[a].CV > 0.0 or pop[b].CV > 0.0:
22
+ S[i] = compare(a, pop[a].CV, b, pop[b].CV, method='smaller_is_better', return_random_if_equal=True)
23
+
24
+ # both solutions are feasible
25
+ else:
26
+
27
+ # if in the same niche select by rank
28
+ if pop[a].get("niche") == pop[b].get("niche"):
29
+
30
+ if pop[a].get("rank") != pop[b].get("rank"):
31
+ S[i] = compare(a, pop[a].get("rank"), b, pop[b].get("rank"), method='smaller_is_better')
32
+
33
+ else:
34
+ S[i] = compare(a, pop[a].get("dist_to_niche"), b, pop[b].get("dist_to_niche"),
35
+ method='smaller_is_better')
36
+
37
+ if np.isnan(S[i]):
38
+ S[i] = random_state.choice([a, b])
39
+
40
+ return S[:, None].astype(int)
41
+
42
+
43
+ class UNSGA3(NSGA3):
44
+
45
+ def __init__(self,
46
+ ref_dirs,
47
+ selection=TournamentSelection(func_comp=comp_by_rank_and_ref_line_dist),
48
+ **kwargs):
49
+ super().__init__(ref_dirs, selection=selection, **kwargs)
File without changes
File without changes
File without changes
@@ -0,0 +1,162 @@
1
+ import numpy as np
2
+
3
+ from pymoo.algorithms.base.genetic import GeneticAlgorithm
4
+ from pymoo.algorithms.soo.nonconvex.ga import FitnessSurvival
5
+ from pymoo.core.duplicate import DefaultDuplicateElimination, DuplicateElimination
6
+ from pymoo.core.population import Population
7
+ from pymoo.core.selection import Selection
8
+ from pymoo.core.survival import Survival
9
+ from pymoo.docs import parse_doc_string
10
+ from pymoo.operators.crossover.binx import BinomialCrossover
11
+ from pymoo.operators.mutation.nom import NoMutation
12
+ from pymoo.operators.sampling.rnd import FloatRandomSampling
13
+ from pymoo.termination.default import DefaultSingleObjectiveTermination
14
+ from pymoo.util.display.single import SingleObjectiveOutput
15
+ from pymoo.util.nds.non_dominated_sorting import NonDominatedSorting
16
+
17
+
18
+ # =========================================================================================================
19
+ # Implementation
20
+ # =========================================================================================================
21
+
22
+
23
+ class EliteSurvival(Survival):
24
+
25
+ def __init__(self, n_elites, eliminate_duplicates=None):
26
+ super().__init__(False)
27
+ self.n_elites = n_elites
28
+ self.eliminate_duplicates = eliminate_duplicates
29
+
30
+ def _do(self, problem, pop, n_survive=None, algorithm=None, **kwargs):
31
+
32
+ if isinstance(self.eliminate_duplicates, bool) and self.eliminate_duplicates:
33
+ pop = DefaultDuplicateElimination(func=lambda p: p.get("F")).do(pop)
34
+
35
+ elif isinstance(self.eliminate_duplicates, DuplicateElimination):
36
+ _, no_candidates, candidates = DefaultDuplicateElimination(func=lambda pop: pop.get("F")).do(pop,
37
+ return_indices=True)
38
+ _, _, is_duplicate = self.eliminate_duplicates.do(pop[candidates], pop[no_candidates], return_indices=True,
39
+ to_itself=False)
40
+ elim = set(np.array(candidates)[is_duplicate])
41
+ pop = pop[[k for k in range(len(pop)) if k not in elim]]
42
+
43
+ if problem.n_obj == 1:
44
+ pop = FitnessSurvival().do(problem, pop, n_survive=len(pop))
45
+ elites = pop[:self.n_elites]
46
+ non_elites = pop[self.n_elites:]
47
+ else:
48
+ I = NonDominatedSorting().do(pop.get("F"), only_non_dominated_front=True)
49
+ elites = pop[I]
50
+ non_elites = pop[[k for k in range(len(pop)) if k not in I]]
51
+
52
+ elites.set("type", ["elite"] * len(elites))
53
+ non_elites.set("type", ["non_elite"] * len(non_elites))
54
+
55
+ return pop
56
+
57
+
58
+ class EliteBiasedSelection(Selection):
59
+
60
+ def _do(self, problem, pop, n_select, n_parents, **kwargs):
61
+ random_state = kwargs.get('random_state')
62
+ _type = pop.get("type")
63
+ elites = np.where(_type == "elite")[0].astype(int)
64
+ non_elites = np.where(_type == "non_elite")[0].astype(int)
65
+
66
+ # if through duplicate elimination no non-elites exist
67
+ if len(non_elites) == 0:
68
+ non_elites = elites
69
+
70
+ # do the mating selection - always one elite and one non-elites
71
+ s_elite = random_state.choice(elites, size=n_select)
72
+ s_non_elite = random_state.choice(non_elites, size=n_select)
73
+
74
+ return np.column_stack([s_elite, s_non_elite])
75
+
76
+
77
+ class BRKGA(GeneticAlgorithm):
78
+
79
+ def __init__(self,
80
+ n_elites=200,
81
+ n_offsprings=700,
82
+ n_mutants=100,
83
+ bias=0.7,
84
+ sampling=FloatRandomSampling(),
85
+ survival=None,
86
+ output=SingleObjectiveOutput(),
87
+ eliminate_duplicates=False,
88
+ **kwargs
89
+ ):
90
+ """
91
+
92
+
93
+ Parameters
94
+ ----------
95
+
96
+ n_elites : int
97
+ Number of elite individuals
98
+
99
+ n_offsprings : int
100
+ Number of offsprings to be generated through mating of an elite and a non-elite individual
101
+
102
+ n_mutants : int
103
+ Number of mutations to be introduced each generation
104
+
105
+ bias : float
106
+ Bias of an offspring inheriting the allele of its elite parent
107
+
108
+ eliminate_duplicates : bool or class
109
+ The duplicate elimination is more important if a decoding is used. The duplicate check has to be
110
+ performed on the decoded variable and not on the real values. Therefore, we recommend passing
111
+ a DuplicateElimination object.
112
+ If eliminate_duplicates is simply set to `True`, then duplicates are filtered out whenever the
113
+ objective values are equal.
114
+
115
+ """
116
+
117
+ if survival is None:
118
+ survival = EliteSurvival(n_elites, eliminate_duplicates=eliminate_duplicates)
119
+
120
+ super().__init__(pop_size=n_elites + n_offsprings + n_mutants,
121
+ n_offsprings=n_offsprings,
122
+ sampling=sampling,
123
+ selection=EliteBiasedSelection(),
124
+ crossover=BinomialCrossover(bias, prob=1.0, n_offsprings=1),
125
+ mutation=NoMutation(),
126
+ survival=survival,
127
+ output=output,
128
+ eliminate_duplicates=True,
129
+ advance_after_initial_infill=True,
130
+ **kwargs)
131
+
132
+ self.n_elites = n_elites
133
+ self.n_mutants = n_mutants
134
+ self.bias = bias
135
+ self.termination = DefaultSingleObjectiveTermination()
136
+
137
+ def _infill(self):
138
+ pop = self.pop
139
+
140
+ # actually do the mating given the elite selection and biased crossover
141
+ off = self.mating.do(self.problem, pop, n_offsprings=self.n_offsprings, algorithm=self, random_state=self.random_state)
142
+
143
+ # create the mutants randomly to fill the population with
144
+ mutants = FloatRandomSampling().do(self.problem, self.n_mutants, algorithm=self, random_state=self.random_state)
145
+
146
+ # evaluate all the new solutions
147
+ return Population.merge(off, mutants)
148
+
149
+ def _advance(self, infills=None, **kwargs):
150
+ pop = self.pop
151
+
152
+ # get all the elites from the current population
153
+ elites = np.where(pop.get("type") == "elite")[0]
154
+
155
+ # finally merge everything together and sort by fitness
156
+ pop = Population.merge(pop[elites], infills)
157
+
158
+ # the do survival selection - set the elites for the next round
159
+ self.pop = self.survival.do(self.problem, pop, n_survive=len(pop), algorithm=self)
160
+
161
+
162
+ parse_doc_string(BRKGA.__init__)