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,88 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.crossover import Crossover
4
+ from pymoo.util import default_random_state
5
+
6
+
7
+ @default_random_state
8
+ def random_sequence(n, random_state=None):
9
+ start, end = np.sort(random_state.choice(n, 2, replace=False))
10
+ return tuple([start, end])
11
+
12
+
13
+ @default_random_state
14
+ def ox(receiver, donor, seq=None, shift=False, random_state=None):
15
+ """
16
+ The Ordered Crossover (OX) as explained in http://www.dmi.unict.it/mpavone/nc-cs/materiale/moscato89.pdf.
17
+
18
+ Parameters
19
+ ----------
20
+ receiver : numpy.array
21
+ The receiver of the sequence. The array needs to be repaired after the donation took place.
22
+ donor : numpy.array
23
+ The donor of the sequence.
24
+ seq : tuple (optional)
25
+ Tuple with two problems defining the start and the end of the sequence. Please note in our implementation
26
+ the end of the sequence is included. The sequence is randomly chosen if not provided.
27
+
28
+ shift : bool
29
+ Whether during the repair the receiver should be shifted or not. Both version of it can be found in the
30
+ literature.
31
+
32
+ Returns
33
+ -------
34
+
35
+ y : numpy.array
36
+ The offspring which was created by the ordered crossover.
37
+
38
+ """
39
+ assert len(donor) == len(receiver)
40
+
41
+ # the sequence which shall be use for the crossover
42
+ seq = seq if seq is not None else random_sequence(len(receiver), random_state=random_state)
43
+ start, end = seq
44
+
45
+ # the donation and a set of it to allow a quick lookup
46
+ donation = np.copy(donor[start:end + 1])
47
+ donation_as_set = set(donation)
48
+
49
+ # the final value to be returned
50
+ y = []
51
+
52
+ for k in range(len(receiver)):
53
+
54
+ # do the shift starting from the swapped sequence - as proposed in the paper
55
+ i = k if not shift else (start + k) % len(receiver)
56
+ v = receiver[i]
57
+
58
+ if v not in donation_as_set:
59
+ y.append(v)
60
+
61
+ # now insert the donation at the right place
62
+ y = np.concatenate([y[:start], donation, y[start:]]).astype(copy=False, dtype=int)
63
+
64
+ return y
65
+
66
+
67
+ class OrderCrossover(Crossover):
68
+
69
+ def __init__(self, shift=False, **kwargs):
70
+ super().__init__(2, 2, **kwargs)
71
+ self.shift = shift
72
+
73
+ @default_random_state
74
+ def _do(self, problem, X, random_state=None, **kwargs):
75
+ _, n_matings, n_var = X.shape
76
+ Y = np.full((self.n_offsprings, n_matings, n_var), -1, dtype=int)
77
+
78
+ for i in range(n_matings):
79
+ a, b = X[:, i, :]
80
+ n = len(a)
81
+
82
+ # define the sequence to be used for crossover
83
+ start, end = random_sequence(n, random_state=random_state)
84
+
85
+ Y[0, i, :] = ox(a, b, seq=(start, end), shift=self.shift, random_state=random_state)
86
+ Y[1, i, :] = ox(b, a, seq=(start, end), shift=self.shift, random_state=random_state)
87
+
88
+ return Y
@@ -0,0 +1,84 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.crossover import Crossover
4
+ from pymoo.core.variable import Real, get
5
+ from pymoo.operators.repair.bounds_repair import repair_random_init
6
+ from pymoo.util import default_random_state
7
+
8
+
9
+ @default_random_state
10
+ def pcx(X, eta, zeta, index, random_state=None):
11
+ eps = 1e-32
12
+
13
+ # the number of parents to be considered
14
+ n_parents, n_matings, n_var = X.shape
15
+
16
+ # calculate the differences from all parents to index parent
17
+ diff_to_index = X - X[index]
18
+ dist_to_index = np.linalg.norm(diff_to_index, axis=-1)
19
+ dist_to_index = np.maximum(eps, dist_to_index)
20
+
21
+ # find the centroid of the parents
22
+ centroid = np.mean(X, axis=0)
23
+
24
+ # calculate the difference between the centroid and the k-th parent
25
+ diff_to_centroid = centroid - X[index]
26
+
27
+ dist_to_centroid = np.linalg.norm(diff_to_centroid, axis=-1)
28
+ dist_to_centroid = np.maximum(eps, dist_to_centroid)
29
+
30
+ # orthogonal directions are computed
31
+ orth_dir = np.zeros_like(dist_to_index)
32
+
33
+ for i in range(n_parents):
34
+ if i != index:
35
+ temp1 = (diff_to_index[i] * diff_to_centroid).sum(axis=-1)
36
+ temp2 = temp1 / (dist_to_index[i] * dist_to_centroid)
37
+ temp3 = np.maximum(0.0, 1.0 - temp2 ** 2)
38
+ orth_dir[i] = dist_to_index[i] * (temp3 ** 0.5)
39
+
40
+ # this is the avg of the perpendicular distances from other parents to the parent k
41
+ D_not = orth_dir.sum(axis=0) / (n_parents - 1)
42
+
43
+ # generating zero-mean normally distributed variables
44
+ sigma = D_not[:, None] * eta.repeat(n_var, axis=1)
45
+ rnd = random_state.normal(loc=0.0, scale=sigma)
46
+
47
+ # implemented just like the c code - generate_new.h file
48
+ inner_prod = np.sum(rnd * diff_to_centroid, axis=-1, keepdims=True)
49
+ noise = rnd - (inner_prod * diff_to_centroid) / dist_to_centroid[:, None] ** 2
50
+
51
+ bias_to_centroid = random_state.normal(0.0, zeta) * diff_to_centroid
52
+
53
+ # the array which is finally returned
54
+ Xp = X[index] + noise + bias_to_centroid
55
+
56
+ return Xp
57
+
58
+
59
+ class ParentCentricCrossover(Crossover):
60
+ def __init__(self,
61
+ eta=0.1,
62
+ zeta=0.1,
63
+ **kwargs):
64
+
65
+ super().__init__(n_parents=3, n_offsprings=1, **kwargs)
66
+ self.eta = Real(eta, bounds=(0.01, 0.3))
67
+ self.zeta = Real(zeta, bounds=(0.01, 0.3))
68
+
69
+ def _do(self, problem, X, params=None, random_state=None, **kwargs):
70
+ n_parents, n_matings, n_var = X.shape
71
+ zeta, eta = get(self.zeta, self.eta, size=(n_matings, 1))
72
+
73
+ index = 0
74
+
75
+ Xp = pcx(X, eta, zeta, index=index, random_state=random_state)
76
+
77
+ if problem.has_bounds():
78
+ Xp = repair_random_init(Xp, X[index], *problem.bounds(), random_state=random_state)
79
+
80
+ return Xp[None, :]
81
+
82
+
83
+ class PCX(ParentCentricCrossover):
84
+ pass
@@ -0,0 +1,49 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.crossover import Crossover
4
+ from pymoo.util.misc import crossover_mask
5
+
6
+
7
+ class PointCrossover(Crossover):
8
+
9
+ def __init__(self, n_points, **kwargs):
10
+ super().__init__(2, 2, **kwargs)
11
+ self.n_points = n_points
12
+
13
+ def _do(self, _, X, random_state=None, **kwargs):
14
+
15
+ # get the X of parents and count the matings
16
+ _, n_matings, n_var = X.shape
17
+
18
+ # start point of crossover
19
+ r = np.vstack([random_state.permutation(n_var - 1) + 1 for _ in range(n_matings)])[:, :self.n_points]
20
+ r.sort(axis=1)
21
+ r = np.column_stack([r, np.full(n_matings, n_var)])
22
+
23
+ # the mask do to the crossover
24
+ M = np.full((n_matings, n_var), False)
25
+
26
+ # create for each individual the crossover range
27
+ for i in range(n_matings):
28
+
29
+ j = 0
30
+ while j < r.shape[1] - 1:
31
+ a, b = r[i, j], r[i, j + 1]
32
+ M[i, a:b] = True
33
+ j += 2
34
+
35
+ Xp = crossover_mask(X, M)
36
+
37
+ return Xp
38
+
39
+
40
+ class SinglePointCrossover(PointCrossover):
41
+
42
+ def __init__(self, **kwargs):
43
+ super().__init__(n_points=1, **kwargs)
44
+
45
+
46
+ class TwoPointCrossover(PointCrossover):
47
+
48
+ def __init__(self, **kwargs):
49
+ super().__init__(n_points=2, **kwargs)
@@ -0,0 +1,137 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.crossover import Crossover
4
+ from pymoo.core.variable import Real, get
5
+ from pymoo.operators.repair.bounds_repair import repair_clamp
6
+ from pymoo.util import default_random_state
7
+
8
+
9
+ # ---------------------------------------------------------------------------------------------------------
10
+ # Function
11
+ # ---------------------------------------------------------------------------------------------------------
12
+
13
+
14
+ @default_random_state
15
+ def cross_sbx(X, xl, xu, eta, prob_var, prob_bin, eps=1.0e-14, random_state=None):
16
+ n_parents, n_matings, n_var = X.shape
17
+
18
+ # the probability of a crossover for each of the variables
19
+ cross = random_state.random((n_matings, n_var)) < prob_var
20
+
21
+ # when solutions are too close -> do not apply sbx crossover
22
+ too_close = np.abs(X[0] - X[1]) <= eps
23
+
24
+ # disable if two individuals are already too close
25
+ cross[too_close] = False
26
+
27
+ # disable crossover when lower and upper bound are identical
28
+ cross[:, xl == xu] = False
29
+
30
+ # preserve parent identity while getting values for SBX calculation
31
+ p1 = X[0][cross]
32
+ p2 = X[1][cross]
33
+
34
+ # assign y1 the smaller and y2 the larger value for SBX calculation
35
+ sm = p1 < p2
36
+ y1 = np.where(sm, p1, p2)
37
+ y2 = np.where(sm, p2, p1)
38
+
39
+ # mask all the values that should be crossovered
40
+ _xl = np.repeat(xl[None, :], n_matings, axis=0)[cross]
41
+ _xu = np.repeat(xu[None, :], n_matings, axis=0)[cross]
42
+ eta = eta.repeat(n_var, axis=1)[cross]
43
+ prob_bin = prob_bin.repeat(n_var, axis=1)[cross]
44
+
45
+ # random values for each individual
46
+ rand = random_state.random(len(eta))
47
+
48
+ def calc_betaq(beta):
49
+ alpha = 2.0 - np.power(beta, -(eta + 1.0))
50
+
51
+ mask, mask_not = (rand <= (1.0 / alpha)), (rand > (1.0 / alpha))
52
+
53
+ betaq = np.zeros(mask.shape)
54
+ betaq[mask] = np.power((rand * alpha), (1.0 / (eta + 1.0)))[mask]
55
+ betaq[mask_not] = np.power((1.0 / (2.0 - rand * alpha)), (1.0 / (eta + 1.0)))[mask_not]
56
+
57
+ return betaq
58
+
59
+ # difference between all variables
60
+ delta = (y2 - y1)
61
+
62
+ beta = 1.0 + (2.0 * (y1 - _xl) / delta)
63
+ betaq = calc_betaq(beta)
64
+ c1 = 0.5 * ((y1 + y2) - betaq * delta)
65
+
66
+ beta = 1.0 + (2.0 * (_xu - y2) / delta)
67
+ betaq = calc_betaq(beta)
68
+ c2 = 0.5 * ((y1 + y2) + betaq * delta)
69
+
70
+ # assign children based on parent position, then apply exchange probability
71
+ child1 = np.where(sm, c1, c2) # child for parent 1
72
+ child2 = np.where(sm, c2, c1) # child for parent 2
73
+
74
+ # exchange children with given probability
75
+ b = np.bitwise_xor(
76
+ random_state.random(len(prob_bin)) < prob_bin,
77
+ X[0, cross] > X[1, cross]
78
+ )
79
+ child1, child2 = np.where(b, (child2, child1), (child1, child2))
80
+
81
+ # first copy the unmodified parents
82
+ Q = np.copy(X)
83
+
84
+ # copy the positions where the crossover was done
85
+ Q[0, cross] = child1
86
+ Q[1, cross] = child2
87
+
88
+ Q[0] = repair_clamp(Q[0], xl, xu)
89
+ Q[1] = repair_clamp(Q[1], xl, xu)
90
+
91
+ return Q
92
+
93
+
94
+ # ---------------------------------------------------------------------------------------------------------
95
+ # Class
96
+ # ---------------------------------------------------------------------------------------------------------
97
+
98
+
99
+ class SimulatedBinaryCrossover(Crossover):
100
+
101
+ def __init__(self,
102
+ prob_var=0.5,
103
+ eta=15,
104
+ prob_exch=1.0,
105
+ prob_bin=0.5,
106
+ n_offsprings=2,
107
+ **kwargs):
108
+ super().__init__(2, n_offsprings, **kwargs)
109
+
110
+ self.prob_var = Real(prob_var, bounds=(0.1, 0.9))
111
+ self.eta = Real(eta, bounds=(3.0, 30.0), strict=(1.0, None))
112
+ self.prob_exch = Real(prob_exch, bounds=(0.0, 1.0), strict=(0.0, 1.0))
113
+ self.prob_bin = Real(prob_bin, bounds=(0.0, 1.0), strict=(0.0, 1.0))
114
+
115
+ def _do(self, problem, X, *args, random_state=None, **kwargs):
116
+ _, n_matings, _ = X.shape
117
+
118
+ # get the parameters required by SBX
119
+ eta, prob_var, prob_exch, prob_bin = get(self.eta, self.prob_var, self.prob_exch, self.prob_bin,
120
+ size=(n_matings, 1))
121
+
122
+ # set the binomial probability to zero if no exchange between individuals shall happen
123
+ rand = random_state.random((len(prob_bin), 1))
124
+ prob_bin[rand > prob_exch] = 0.0
125
+
126
+ Q = cross_sbx(X.astype(float), problem.xl, problem.xu, eta, prob_var, prob_bin, random_state=random_state)
127
+
128
+ if self.n_offsprings == 1:
129
+ rand = random_state.random(size=n_matings) < 0.5
130
+ Q[0, rand] = Q[1, rand]
131
+ Q = Q[[0]]
132
+
133
+ return Q
134
+
135
+
136
+ class SBX(SimulatedBinaryCrossover):
137
+ pass
@@ -0,0 +1,5 @@
1
+ from pymoo.operators.crossover.pntx import SinglePointCrossover
2
+
3
+
4
+ class SPX(SinglePointCrossover):
5
+ pass
@@ -0,0 +1,20 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.crossover import Crossover
4
+ from pymoo.util.misc import crossover_mask
5
+
6
+
7
+ class UniformCrossover(Crossover):
8
+
9
+ def __init__(self, **kwargs):
10
+ super().__init__(2, 2, **kwargs)
11
+
12
+ def _do(self, _, X, random_state=None, **kwargs):
13
+ _, n_matings, n_var = X.shape
14
+ M = random_state.random((n_matings, n_var)) < 0.5
15
+ _X = crossover_mask(X, M)
16
+ return _X
17
+
18
+
19
+ class UX(UniformCrossover):
20
+ pass
File without changes
@@ -0,0 +1,17 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.mutation import Mutation
4
+
5
+
6
+ class BitflipMutation(Mutation):
7
+
8
+ def _do(self, problem, X, random_state=None, **kwargs):
9
+ prob_var = self.get_prob_var(problem, size=(len(X), 1))
10
+ Xp = np.copy(X)
11
+ flip = random_state.random(X.shape) < prob_var
12
+ Xp[flip] = ~X[flip]
13
+ return Xp
14
+
15
+
16
+ class BFM(BitflipMutation):
17
+ pass
@@ -0,0 +1,60 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.mutation import Mutation
4
+ from pymoo.core.variable import Real, get
5
+ from pymoo.operators.repair.bounds_repair import repair_random_init
6
+ from pymoo.util import default_random_state
7
+
8
+
9
+ # ---------------------------------------------------------------------------------------------------------
10
+ # Function
11
+ # ---------------------------------------------------------------------------------------------------------
12
+
13
+
14
+ @default_random_state
15
+ def mut_gauss(X, xl, xu, sigma, prob, random_state=None):
16
+ n, n_var = X.shape
17
+ assert len(sigma) == n
18
+ assert len(prob) == n
19
+
20
+ Xp = np.full(X.shape, np.inf)
21
+
22
+ mut = random_state.random(X.shape) < prob[:, None]
23
+
24
+ Xp[:, :] = X
25
+
26
+ _xl = np.repeat(xl[None, :], X.shape[0], axis=0)[mut]
27
+ _xu = np.repeat(xu[None, :], X.shape[0], axis=0)[mut]
28
+ sigma = sigma[:, None].repeat(n_var, axis=1)[mut]
29
+
30
+ Xp[mut] = random_state.normal(X[mut], sigma * (_xu - _xl))
31
+
32
+ Xp = repair_random_init(Xp, X, xl, xu)
33
+
34
+ return Xp
35
+
36
+
37
+ # ---------------------------------------------------------------------------------------------------------
38
+ # Class
39
+ # ---------------------------------------------------------------------------------------------------------
40
+
41
+
42
+ class GaussianMutation(Mutation):
43
+
44
+ def __init__(self, sigma=0.1, **kwargs):
45
+ super().__init__(**kwargs)
46
+ self.sigma = Real(sigma, bounds=(0.01, 0.25), strict=(0.0, 1.0))
47
+
48
+ def _do(self, problem, X, random_state=None, **kwargs):
49
+ X = X.astype(float)
50
+
51
+ sigma = get(self.sigma, size=len(X))
52
+ prob_var = self.get_prob_var(problem, size=len(X))
53
+
54
+ Xp = mut_gauss(X, problem.xl, problem.xu, sigma, prob_var, random_state=random_state)
55
+
56
+ return Xp
57
+
58
+
59
+ class GM(GaussianMutation):
60
+ pass
@@ -0,0 +1,42 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.mutation import Mutation
4
+ from pymoo.operators.crossover.ox import random_sequence
5
+
6
+
7
+ def inversion_mutation(y, seq, inplace=True):
8
+ y = y if inplace else np.copy(y)
9
+
10
+ if seq is None:
11
+ seq = random_sequence(len(y))
12
+ start, end = seq
13
+
14
+ y[start:end + 1] = np.flip(y[start:end + 1])
15
+ return y
16
+
17
+
18
+ class InversionMutation(Mutation):
19
+
20
+ def __init__(self, prob=1.0):
21
+ """
22
+
23
+ This mutation is applied to permutations. It randomly selects a segment of a chromosome and reverse its order.
24
+ For instance, for the permutation `[1, 2, 3, 4, 5]` the segment can be `[2, 3, 4]` which results in `[1, 4, 3, 2, 5]`.
25
+
26
+ Parameters
27
+ ----------
28
+ prob : float
29
+ Probability to apply the mutation to the individual
30
+
31
+ """
32
+ super().__init__()
33
+ self.prob = prob
34
+
35
+ def _do(self, problem, X, random_state=None, **kwargs):
36
+ Y = X.copy()
37
+ for i, y in enumerate(X):
38
+ if random_state.random() < self.prob:
39
+ seq = random_sequence(len(y), random_state=random_state)
40
+ Y[i] = inversion_mutation(y, seq, inplace=True)
41
+
42
+ return Y
@@ -0,0 +1,7 @@
1
+ from pymoo.core.mutation import Mutation
2
+
3
+
4
+ class NoMutation(Mutation):
5
+
6
+ def do(self, problem, pop, **kwargs):
7
+ return pop
@@ -0,0 +1,96 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.mutation import Mutation
4
+ from pymoo.core.variable import get, Real
5
+ from pymoo.operators.crossover.binx import mut_binomial
6
+ from pymoo.operators.repair.to_bound import set_to_bounds_if_outside
7
+ from pymoo.util import default_random_state
8
+
9
+
10
+ # ---------------------------------------------------------------------------------------------------------
11
+ # Function
12
+ # ---------------------------------------------------------------------------------------------------------
13
+
14
+
15
+ @default_random_state
16
+ def mut_pm(X, xl, xu, eta, prob, at_least_once, random_state=None):
17
+ n, n_var = X.shape
18
+ assert len(eta) == n
19
+ assert len(prob) == n
20
+
21
+ Xp = np.full(X.shape, np.inf)
22
+
23
+ mut = mut_binomial(n, n_var, prob, at_least_once=at_least_once, random_state=random_state)
24
+ mut[:, xl == xu] = False
25
+
26
+ Xp[:, :] = X
27
+
28
+ _xl = np.repeat(xl[None, :], X.shape[0], axis=0)[mut]
29
+ _xu = np.repeat(xu[None, :], X.shape[0], axis=0)[mut]
30
+
31
+ X = X[mut]
32
+ eta = np.tile(eta[:, None], (1, n_var))[mut]
33
+
34
+ delta1 = (X - _xl) / (_xu - _xl)
35
+ delta2 = (_xu - X) / (_xu - _xl)
36
+
37
+ mut_pow = 1.0 / (eta + 1.0)
38
+
39
+ rand = random_state.random(X.shape)
40
+ mask = rand <= 0.5
41
+ mask_not = np.logical_not(mask)
42
+
43
+ deltaq = np.zeros(X.shape)
44
+
45
+ xy = 1.0 - delta1
46
+ val = 2.0 * rand + (1.0 - 2.0 * rand) * (np.power(xy, (eta + 1.0)))
47
+ d = np.power(val, mut_pow) - 1.0
48
+ deltaq[mask] = d[mask]
49
+
50
+ xy = 1.0 - delta2
51
+ val = 2.0 * (1.0 - rand) + 2.0 * (rand - 0.5) * (np.power(xy, (eta + 1.0)))
52
+ d = 1.0 - (np.power(val, mut_pow))
53
+ deltaq[mask_not] = d[mask_not]
54
+
55
+ # mutated values
56
+ _Y = X + deltaq * (_xu - _xl)
57
+
58
+ # back in bounds if necessary (floating point issues)
59
+ _Y[_Y < _xl] = _xl[_Y < _xl]
60
+ _Y[_Y > _xu] = _xu[_Y > _xu]
61
+
62
+ # set the values for output
63
+ Xp[mut] = _Y
64
+
65
+ # in case out of bounds repair (very unlikely)
66
+ Xp = set_to_bounds_if_outside(Xp, xl, xu)
67
+
68
+ return Xp
69
+
70
+
71
+ # ---------------------------------------------------------------------------------------------------------
72
+ # Class
73
+ # ---------------------------------------------------------------------------------------------------------
74
+
75
+
76
+ class PolynomialMutation(Mutation):
77
+
78
+ def __init__(self, prob=0.9, eta=20, at_least_once=False, **kwargs):
79
+ super().__init__(prob=prob, **kwargs)
80
+ self.at_least_once = at_least_once
81
+ self.eta = Real(eta, bounds=(3.0, 30.0), strict=(1.0, 100.0))
82
+
83
+ def _do(self, problem, X, params=None, *args, random_state=None, **kwargs):
84
+ X = X.astype(float)
85
+
86
+ eta = get(self.eta, size=len(X))
87
+ prob_var = self.get_prob_var(problem, size=len(X))
88
+
89
+ Xp = mut_pm(X, problem.xl, problem.xu, eta, prob_var, at_least_once=self.at_least_once, random_state=random_state)
90
+
91
+ return Xp
92
+
93
+
94
+ class PM(PolynomialMutation):
95
+ pass
96
+
@@ -0,0 +1,23 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.mutation import Mutation
4
+
5
+
6
+ class ChoiceRandomMutation(Mutation):
7
+
8
+ def _do(self, problem, X, random_state=None, **kwargs):
9
+ assert problem.vars is not None
10
+
11
+ # ensure the type object (fixed string length <UX can cause issues)
12
+ X = X.astype(object)
13
+
14
+ prob_var = self.get_prob_var(problem, size=len(X))
15
+
16
+ for k, (_, var) in enumerate(problem.vars.items()):
17
+ mut = np.where(random_state.random(len(X)) < prob_var)[0]
18
+
19
+ v = var.sample(len(mut), random_state=random_state)
20
+ X[mut, k] = v
21
+
22
+ return X
23
+
File without changes
@@ -0,0 +1,32 @@
1
+ import numpy as np
2
+
3
+ from pymoo.operators.repair.bounds_repair import BoundsRepair
4
+ from pymoo.util.misc import at_least_2d_array
5
+
6
+
7
+ def bounce_back(X, xl, xu):
8
+ only_1d = (X.ndim == 1)
9
+ X = at_least_2d_array(X)
10
+
11
+ xl = np.repeat(xl[None, :], X.shape[0], axis=0)
12
+ xu = np.repeat(xu[None, :], X.shape[0], axis=0)
13
+
14
+ # otherwise bounds back into the feasible space
15
+ _range = xu - xl
16
+ X[X < xl] = (xl + np.mod((xl - X), _range))[X < xl]
17
+ X[X > xu] = (xu - np.mod((X - xu), _range))[X > xu]
18
+
19
+ if only_1d:
20
+ return X[0, :]
21
+ else:
22
+ return X
23
+
24
+
25
+ def bounce_back_by_problem(problem, X):
26
+ return bounce_back(X, problem.xl, problem.xu)
27
+
28
+
29
+ class BounceBackOutOfBoundsRepair(BoundsRepair):
30
+
31
+ def repair_out_of_bounds(self, problem, X, **kwargs):
32
+ return bounce_back_by_problem(problem, X)