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,190 @@
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=0)
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, **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', return_random_if_equal=True)
132
+
133
+ # both solutions are feasible
134
+ else:
135
+ S[i] = compare(a, pop[a].get("SPEA_F"), b, pop[b].get("SPEA_F"), method='smaller_is_better',
136
+ return_random_if_equal=True)
137
+
138
+ return S[:, None].astype(int, copy=False)
139
+
140
+
141
+ # ---------------------------------------------------------------------------------------------------------
142
+ # Algorithm
143
+ # ---------------------------------------------------------------------------------------------------------
144
+
145
+
146
+ class SPEA2(GeneticAlgorithm):
147
+
148
+ def __init__(self,
149
+ pop_size=100,
150
+ sampling=FloatRandomSampling(),
151
+ selection=TournamentSelection(spea_binary_tournament),
152
+ crossover=SBX(),
153
+ mutation=PM(),
154
+ survival=SPEA2Survival(normalize=True),
155
+ eliminate_duplicates=True,
156
+ n_offsprings=None,
157
+ output=MultiObjectiveOutput(),
158
+ **kwargs):
159
+ """
160
+
161
+ SPEA2 - Strength Pareto EA 2
162
+
163
+ Parameters
164
+ ----------
165
+ pop_size : {pop_size}
166
+ sampling : {sampling}
167
+ selection : {selection}
168
+ crossover : {crossover}
169
+ mutation : {mutation}
170
+ eliminate_duplicates : {eliminate_duplicates}
171
+ n_offsprings : {n_offsprings}
172
+
173
+ """
174
+
175
+ super().__init__(pop_size=pop_size,
176
+ sampling=sampling,
177
+ selection=selection,
178
+ crossover=crossover,
179
+ mutation=mutation,
180
+ survival=survival,
181
+ eliminate_duplicates=eliminate_duplicates,
182
+ n_offsprings=n_offsprings,
183
+ output=output,
184
+ advance_after_initial_infill=True,
185
+ **kwargs)
186
+ self.termination = DefaultMultiObjectiveTermination()
187
+
188
+
189
+ parse_doc_string(SPEA2.__init__)
190
+
@@ -0,0 +1,47 @@
1
+ import numpy as np
2
+
3
+ from pymoo.algorithms.moo.nsga3 import NSGA3
4
+ from pymoo.operators.selection.tournament import compare, TournamentSelection
5
+
6
+
7
+ # =========================================================================================================
8
+ # Implementation
9
+ # =========================================================================================================
10
+
11
+
12
+ def comp_by_rank_and_ref_line_dist(pop, P, **kwargs):
13
+ S = np.full(P.shape[0], np.nan)
14
+
15
+ for i in range(P.shape[0]):
16
+ a, b = P[i, 0], P[i, 1]
17
+
18
+ # if at least one solution is infeasible
19
+ if pop[a].CV > 0.0 or pop[b].CV > 0.0:
20
+ S[i] = compare(a, pop[a].CV, b, pop[b].CV, method='smaller_is_better', return_random_if_equal=True)
21
+
22
+ # both solutions are feasible
23
+ else:
24
+
25
+ # if in the same niche select by rank
26
+ if pop[a].get("niche") == pop[b].get("niche"):
27
+
28
+ if pop[a].get("rank") != pop[b].get("rank"):
29
+ S[i] = compare(a, pop[a].get("rank"), b, pop[b].get("rank"), method='smaller_is_better')
30
+
31
+ else:
32
+ S[i] = compare(a, pop[a].get("dist_to_niche"), b, pop[b].get("dist_to_niche"),
33
+ method='smaller_is_better')
34
+
35
+ if np.isnan(S[i]):
36
+ S[i] = np.random.choice([a, b])
37
+
38
+ return S[:, None].astype(int)
39
+
40
+
41
+ class UNSGA3(NSGA3):
42
+
43
+ def __init__(self,
44
+ ref_dirs,
45
+ selection=TournamentSelection(func_comp=comp_by_rank_and_ref_line_dist),
46
+ **kwargs):
47
+ super().__init__(ref_dirs, selection=selection, **kwargs)
File without changes
File without changes
File without changes
@@ -0,0 +1,161 @@
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
+ _type = pop.get("type")
62
+ elites = np.where(_type == "elite")[0].astype(int)
63
+ non_elites = np.where(_type == "non_elite")[0].astype(int)
64
+
65
+ # if through duplicate elimination no non-elites exist
66
+ if len(non_elites) == 0:
67
+ non_elites = elites
68
+
69
+ # do the mating selection - always one elite and one non-elites
70
+ s_elite = np.random.choice(elites, size=n_select)
71
+ s_non_elite = np.random.choice(non_elites, size=n_select)
72
+
73
+ return np.column_stack([s_elite, s_non_elite])
74
+
75
+
76
+ class BRKGA(GeneticAlgorithm):
77
+
78
+ def __init__(self,
79
+ n_elites=200,
80
+ n_offsprings=700,
81
+ n_mutants=100,
82
+ bias=0.7,
83
+ sampling=FloatRandomSampling(),
84
+ survival=None,
85
+ output=SingleObjectiveOutput(),
86
+ eliminate_duplicates=False,
87
+ **kwargs
88
+ ):
89
+ """
90
+
91
+
92
+ Parameters
93
+ ----------
94
+
95
+ n_elites : int
96
+ Number of elite individuals
97
+
98
+ n_offsprings : int
99
+ Number of offsprings to be generated through mating of an elite and a non-elite individual
100
+
101
+ n_mutants : int
102
+ Number of mutations to be introduced each generation
103
+
104
+ bias : float
105
+ Bias of an offspring inheriting the allele of its elite parent
106
+
107
+ eliminate_duplicates : bool or class
108
+ The duplicate elimination is more important if a decoding is used. The duplicate check has to be
109
+ performed on the decoded variable and not on the real values. Therefore, we recommend passing
110
+ a DuplicateElimination object.
111
+ If eliminate_duplicates is simply set to `True`, then duplicates are filtered out whenever the
112
+ objective values are equal.
113
+
114
+ """
115
+
116
+ if survival is None:
117
+ survival = EliteSurvival(n_elites, eliminate_duplicates=eliminate_duplicates)
118
+
119
+ super().__init__(pop_size=n_elites + n_offsprings + n_mutants,
120
+ n_offsprings=n_offsprings,
121
+ sampling=sampling,
122
+ selection=EliteBiasedSelection(),
123
+ crossover=BinomialCrossover(bias, prob=1.0, n_offsprings=1),
124
+ mutation=NoMutation(),
125
+ survival=survival,
126
+ output=output,
127
+ eliminate_duplicates=True,
128
+ advance_after_initial_infill=True,
129
+ **kwargs)
130
+
131
+ self.n_elites = n_elites
132
+ self.n_mutants = n_mutants
133
+ self.bias = bias
134
+ self.termination = DefaultSingleObjectiveTermination()
135
+
136
+ def _infill(self):
137
+ pop = self.pop
138
+
139
+ # actually do the mating given the elite selection and biased crossover
140
+ off = self.mating.do(self.problem, pop, n_offsprings=self.n_offsprings, algorithm=self)
141
+
142
+ # create the mutants randomly to fill the population with
143
+ mutants = FloatRandomSampling().do(self.problem, self.n_mutants, algorithm=self)
144
+
145
+ # evaluate all the new solutions
146
+ return Population.merge(off, mutants)
147
+
148
+ def _advance(self, infills=None, **kwargs):
149
+ pop = self.pop
150
+
151
+ # get all the elites from the current population
152
+ elites = np.where(pop.get("type") == "elite")[0]
153
+
154
+ # finally merge everything together and sort by fitness
155
+ pop = Population.merge(pop[elites], infills)
156
+
157
+ # the do survival selection - set the elites for the next round
158
+ self.pop = self.survival.do(self.problem, pop, n_survive=len(pop), algorithm=self)
159
+
160
+
161
+ parse_doc_string(BRKGA.__init__)