pymoo 0.6.1.5.dev0__cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.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-312-x86_64-linux-gnu.so +0 -0
  91. pymoo/cython/calc_perpendicular_distance.pyx +67 -0
  92. pymoo/cython/decomposition.cpython-312-x86_64-linux-gnu.so +0 -0
  93. pymoo/cython/decomposition.pyx +165 -0
  94. pymoo/cython/hv.cpython-312-x86_64-linux-gnu.so +0 -0
  95. pymoo/cython/hv.pyx +18 -0
  96. pymoo/cython/info.cpython-312-x86_64-linux-gnu.so +0 -0
  97. pymoo/cython/info.pyx +5 -0
  98. pymoo/cython/mnn.cpython-312-x86_64-linux-gnu.so +0 -0
  99. pymoo/cython/mnn.pyx +273 -0
  100. pymoo/cython/non_dominated_sorting.cpython-312-x86_64-linux-gnu.so +0 -0
  101. pymoo/cython/non_dominated_sorting.pyx +645 -0
  102. pymoo/cython/pruning_cd.cpython-312-x86_64-linux-gnu.so +0 -0
  103. pymoo/cython/pruning_cd.pyx +197 -0
  104. pymoo/cython/stochastic_ranking.cpython-312-x86_64-linux-gnu.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,399 @@
1
+ import numpy as np
2
+
3
+ from pymoo.algorithms.soo.nonconvex.ga import FitnessSurvival
4
+ from pymoo.core.algorithm import Algorithm
5
+ from pymoo.core.individual import Individual
6
+ from pymoo.core.initialization import Initialization
7
+ from pymoo.core.population import Population
8
+ from pymoo.core.repair import NoRepair
9
+ from pymoo.core.replacement import ImprovementReplacement
10
+ from pymoo.docs import parse_doc_string
11
+ from pymoo.operators.crossover.dex import repair_random_init
12
+ from pymoo.operators.mutation.pm import PM
13
+ from pymoo.operators.repair.bounds_repair import is_out_of_bounds_by_problem
14
+ from pymoo.operators.repair.to_bound import set_to_bounds_if_outside
15
+ from pymoo.operators.sampling.lhs import LHS
16
+ from pymoo.util.display.column import Column
17
+ from pymoo.util.display.single import SingleObjectiveOutput
18
+ from pymoo.util.misc import norm_eucl_dist
19
+ from pymoo.visualization.fitness_landscape import FitnessLandscape
20
+ from pymoo.visualization.video.callback_video import AnimationCallback
21
+
22
+
23
+ # =========================================================================================================
24
+ # Display
25
+ # =========================================================================================================
26
+
27
+ class PSOFuzzyOutput(SingleObjectiveOutput):
28
+
29
+ def __init__(self):
30
+ super().__init__()
31
+
32
+ self.f = Column(name="f", width=8)
33
+ self.S = Column(name="S", width=7)
34
+ self.w = Column(name="w", width=7)
35
+ self.c1 = Column(name="c1", width=8)
36
+ self.c2 = Column(name="c2", width=8)
37
+
38
+ self.columns += [self.f, self.S, self.w, self.c1, self.c2]
39
+
40
+ def update(self, algorithm):
41
+ super().update(algorithm)
42
+
43
+ self.f.set(algorithm.f)
44
+ self.S.set(algorithm.strategy)
45
+ self.w.set(algorithm.w)
46
+ self.c1.set(algorithm.c1)
47
+ self.c2.set(algorithm.c2)
48
+
49
+
50
+ # =========================================================================================================
51
+ # Adaptation Constants
52
+ # =========================================================================================================
53
+
54
+
55
+ def S1_exploration(f):
56
+ if f <= 0.4:
57
+ return 0
58
+ elif 0.4 < f <= 0.6:
59
+ return 5 * f - 2
60
+ elif 0.6 < f <= 0.7:
61
+ return 1
62
+ elif 0.7 < f <= 0.8:
63
+ return -10 * f + 8
64
+ elif 0.8 < f:
65
+ return 0
66
+
67
+
68
+ def S2_exploitation(f):
69
+ if f <= 0.2:
70
+ return 0
71
+ elif 0.2 < f <= 0.3:
72
+ return 10 * f - 2
73
+ elif 0.3 < f <= 0.4:
74
+ return 1
75
+ elif 0.4 < f <= 0.6:
76
+ return -5 * f + 3
77
+ elif 0.6 < f:
78
+ return 0
79
+
80
+
81
+ def S3_convergence(f):
82
+ if f <= 0.1:
83
+ return 1
84
+ elif 0.1 < f <= 0.3:
85
+ return -5 * f + 1.5
86
+ elif 0.3 < f:
87
+ return 0
88
+
89
+
90
+ def S4_jumping_out(f):
91
+ if f <= 0.7:
92
+ return 0
93
+ elif 0.7 < f <= 0.9:
94
+ return 5 * f - 3.5
95
+ elif 0.9 < f:
96
+ return 1
97
+
98
+
99
+ # =========================================================================================================
100
+ # Equation
101
+ # =========================================================================================================
102
+
103
+ def pso_equation(X, P_X, S_X, V, V_max, w, c1, c2, r1=None, r2=None):
104
+ n_particles, n_var = X.shape
105
+
106
+ if r1 is None:
107
+ r1 = np.random.random((n_particles, n_var))
108
+
109
+ if r2 is None:
110
+ r2 = np.random.random((n_particles, n_var))
111
+
112
+ inerta = w * V
113
+ cognitive = c1 * r1 * (P_X - X)
114
+ social = c2 * r2 * (S_X - X)
115
+
116
+ # calculate the velocity vector
117
+ Vp = inerta + cognitive + social
118
+ Vp = set_to_bounds_if_outside(Vp, - V_max, V_max)
119
+
120
+ Xp = X + Vp
121
+
122
+ return Xp, Vp
123
+
124
+
125
+ # =========================================================================================================
126
+ # Implementation
127
+ # =========================================================================================================
128
+
129
+
130
+ class PSO(Algorithm):
131
+
132
+ def __init__(self,
133
+ pop_size=25,
134
+ sampling=LHS(),
135
+ w=0.9,
136
+ c1=2.0,
137
+ c2=2.0,
138
+ adaptive=True,
139
+ initial_velocity="random",
140
+ max_velocity_rate=0.20,
141
+ pertube_best=True,
142
+ repair=NoRepair(),
143
+ output=PSOFuzzyOutput(),
144
+ **kwargs):
145
+ """
146
+
147
+ Parameters
148
+ ----------
149
+ pop_size : The size of the swarm being used.
150
+
151
+ sampling : {sampling}
152
+
153
+ adaptive : bool
154
+ Whether w, c1, and c2 are changed dynamically over time. The update uses the spread from the global
155
+ optimum to determine suitable values.
156
+
157
+ w : float
158
+ The inertia F to be used in each iteration for the velocity update. This can be interpreted
159
+ as the momentum term regarding the velocity. If `adaptive=True` this is only the
160
+ initially used value.
161
+
162
+ c1 : float
163
+ The cognitive impact (personal best) during the velocity update. If `adaptive=True` this is only the
164
+ initially used value.
165
+ c2 : float
166
+ The social impact (global best) during the velocity update. If `adaptive=True` this is only the
167
+ initially used value.
168
+
169
+ initial_velocity : str - ('random', or 'zero')
170
+ How the initial velocity of each particle should be assigned. Either 'random' which creates a
171
+ random velocity vector or 'zero' which makes the particles start to find the direction through the
172
+ velocity update equation.
173
+
174
+ max_velocity_rate : float
175
+ The maximum velocity rate. It is determined variable (and not vector) wise. We consider the rate here
176
+ since the value is normalized regarding the `xl` and `xu` defined in the problem.
177
+
178
+ pertube_best : bool
179
+ Some studies have proposed to mutate the global best because it has been found to converge better.
180
+ Which means the population size is reduced by one particle and one function evaluation is spend
181
+ additionally to permute the best found solution so far.
182
+
183
+ """
184
+
185
+ super().__init__(output=output, **kwargs)
186
+
187
+ self.initialization = Initialization(sampling)
188
+
189
+ self.pop_size = pop_size
190
+ self.adaptive = adaptive
191
+ self.pertube_best = pertube_best
192
+ self.V_max = None
193
+ self.initial_velocity = initial_velocity
194
+ self.max_velocity_rate = max_velocity_rate
195
+ self.repair = repair
196
+
197
+ self.w = w
198
+ self.c1 = c1
199
+ self.c2 = c2
200
+
201
+ self.particles = None
202
+ self.sbest = None
203
+
204
+ def _setup(self, problem, **kwargs):
205
+ self.V_max = self.max_velocity_rate * (problem.xu - problem.xl)
206
+ self.f, self.strategy = None, None
207
+
208
+ def _initialize_infill(self):
209
+ return self.initialization.do(self.problem, self.pop_size, algorithm=self)
210
+
211
+ def _initialize_advance(self, infills=None, **kwargs):
212
+ particles = self.pop
213
+
214
+ if self.initial_velocity == "random":
215
+ init_V = np.random.random((len(particles), self.problem.n_var)) * self.V_max[None, :]
216
+ elif self.initial_velocity == "zero":
217
+ init_V = np.zeros((len(particles), self.problem.n_var))
218
+ else:
219
+ raise Exception("Unknown velocity initialization.")
220
+
221
+ particles.set("V", init_V)
222
+ self.particles = particles
223
+
224
+ super()._initialize_advance(infills=infills, **kwargs)
225
+
226
+ def _infill(self):
227
+ problem, particles, pbest = self.problem, self.particles, self.pop
228
+
229
+ (X, V) = particles.get("X", "V")
230
+ P_X = pbest.get("X")
231
+
232
+ sbest = self._social_best()
233
+ S_X = sbest.get("X")
234
+
235
+ Xp, Vp = pso_equation(X, P_X, S_X, V, self.V_max, self.w, self.c1, self.c2)
236
+
237
+ # if the problem has boundaries to be considered
238
+ if problem.has_bounds():
239
+
240
+ for k in range(20):
241
+ # find the individuals which are still infeasible
242
+ m = is_out_of_bounds_by_problem(problem, Xp)
243
+
244
+ if len(m) == 0:
245
+ break
246
+
247
+ # actually execute the differential equation
248
+ Xp[m], Vp[m] = pso_equation(X[m], P_X[m], S_X[m], V[m], self.V_max, self.w, self.c1, self.c2)
249
+
250
+ # if still infeasible do a random initialization
251
+ Xp = repair_random_init(Xp, X, *problem.bounds())
252
+
253
+ # create the offspring population
254
+ off = Population.new(X=Xp, V=Vp)
255
+
256
+ # try to improve the current best with a pertubation
257
+ if self.pertube_best:
258
+ k = FitnessSurvival().do(problem, pbest, n_survive=1, return_indices=True)[0]
259
+ mut = PM(prob=0.9, eta=np.random.uniform(5, 30), at_least_once=False)
260
+ mutant = mut(problem, Population(Individual(X=pbest[k].X)))[0]
261
+ off[k].set("X", mutant.X)
262
+
263
+ self.repair(problem, off)
264
+ self.sbest = sbest
265
+
266
+ return off
267
+
268
+ def _advance(self, infills=None, **kwargs):
269
+ assert infills is not None, "This algorithms uses the AskAndTell interface thus 'infills' must to be provided."
270
+
271
+ # set the new population to be equal to the offsprings
272
+ self.particles = infills
273
+
274
+ # if an offspring has improved the personal store that index
275
+ has_improved = ImprovementReplacement().do(self.problem, self.pop, infills, return_indices=True)
276
+
277
+ # set the personal best which have been improved
278
+ self.pop[has_improved] = infills[has_improved]
279
+
280
+ if self.adaptive:
281
+ self._adapt()
282
+
283
+ def _social_best(self):
284
+ return Population([self.opt[0]] * len(self.pop))
285
+
286
+ def _adapt(self):
287
+ pop = self.pop
288
+
289
+ X, F = pop.get("X", "F")
290
+ sbest = self.sbest
291
+ w, c1, c2, = self.w, self.c1, self.c2
292
+
293
+ # get the average distance from one to another for normalization
294
+ D = norm_eucl_dist(self.problem, X, X)
295
+ mD = D.sum(axis=1) / (len(pop) - 1)
296
+ _min, _max = mD.min(), mD.max()
297
+
298
+ # get the average distance to the best
299
+ g_D = norm_eucl_dist(self.problem, sbest.get("X"), X).mean()
300
+ f = (g_D - _min) / (_max - _min + 1e-32)
301
+
302
+ S = np.array([S1_exploration(f), S2_exploitation(f), S3_convergence(f), S4_jumping_out(f)])
303
+ strategy = S.argmax() + 1
304
+
305
+ delta = 0.05 + (np.random.random() * 0.05)
306
+
307
+ if strategy == 1:
308
+ c1 += delta
309
+ c2 -= delta
310
+ elif strategy == 2:
311
+ c1 += 0.5 * delta
312
+ c2 -= 0.5 * delta
313
+ elif strategy == 3:
314
+ c1 += 0.5 * delta
315
+ c2 += 0.5 * delta
316
+ elif strategy == 4:
317
+ c1 -= delta
318
+ c2 += delta
319
+
320
+ c1 = max(1.5, min(2.5, c1))
321
+ c2 = max(1.5, min(2.5, c2))
322
+
323
+ if c1 + c2 > 4.0:
324
+ c1 = 4.0 * (c1 / (c1 + c2))
325
+ c2 = 4.0 * (c2 / (c1 + c2))
326
+
327
+ w = 1 / (1 + 1.5 * np.exp(-2.6 * f))
328
+
329
+ self.f = f
330
+ self.strategy = strategy
331
+ self.c1 = c1
332
+ self.c2 = c2
333
+ self.w = w
334
+
335
+
336
+ # =========================================================================================================
337
+ # Animation
338
+ # =========================================================================================================
339
+
340
+ class PSOAnimation(AnimationCallback):
341
+
342
+ def __init__(self,
343
+ nth_gen=1,
344
+ n_samples_for_surface=200,
345
+ dpi=200,
346
+ **kwargs):
347
+
348
+ super().__init__(nth_gen=nth_gen, dpi=dpi, **kwargs)
349
+ self.n_samples_for_surface = n_samples_for_surface
350
+ self.last_pop = None
351
+
352
+ def do(self, problem, algorithm):
353
+ import matplotlib.pyplot as plt
354
+
355
+ if problem.n_var != 2 or problem.n_obj != 1:
356
+ raise Exception(
357
+ "This visualization can only be used for problems with two variables and one objective!")
358
+
359
+ # draw the problem surface
360
+ FitnessLandscape(problem,
361
+ _type="contour",
362
+ kwargs_contour=dict(alpha=0.3),
363
+ n_samples=self.n_samples_for_surface,
364
+ close_on_destroy=False).do()
365
+
366
+ # get the population
367
+ off = algorithm.particles
368
+ pop = algorithm.particles if self.last_pop is None else self.last_pop
369
+ pbest = algorithm.pop
370
+
371
+ for i in range(len(pop)):
372
+ plt.plot([off[i].X[0], pop[i].X[0]], [off[i].X[1], pop[i].X[1]], color="blue", alpha=0.5)
373
+ plt.plot([pbest[i].X[0], pop[i].X[0]], [pbest[i].X[1], pop[i].X[1]], color="red", alpha=0.5)
374
+ plt.plot([pbest[i].X[0], off[i].X[0]], [pbest[i].X[1], off[i].X[1]], color="red", alpha=0.5)
375
+
376
+ X, F, CV = pbest.get("X", "F", "CV")
377
+ plt.scatter(X[:, 0], X[:, 1], edgecolors="red", marker="*", s=70, facecolors='none', label="pbest")
378
+
379
+ X, F, CV = off.get("X", "F", "CV")
380
+ plt.scatter(X[:, 0], X[:, 1], color="blue", marker="o", s=30, label="particle")
381
+
382
+ X, F, CV = pop.get("X", "F", "CV")
383
+ plt.scatter(X[:, 0], X[:, 1], color="blue", marker="o", s=30, alpha=0.5)
384
+
385
+ opt = algorithm.opt
386
+ X, F, CV = opt.get("X", "F", "CV")
387
+ plt.scatter(X[:, 0], X[:, 1], color="black", marker="x", s=100, label="gbest")
388
+
389
+ xl, xu = problem.bounds()
390
+ plt.xlim(xl[0], xu[0])
391
+ plt.ylim(xl[1], xu[1])
392
+
393
+ plt.title(f"Generation: %s \nf: %.5E" % (algorithm.n_gen, opt[0].F[0]))
394
+ plt.legend()
395
+
396
+ self.last_pop = off.copy(deep=True)
397
+
398
+
399
+ parse_doc_string(PSO.__init__)
@@ -0,0 +1,297 @@
1
+ """
2
+
3
+ Particle Swarm Optimization (PSO)
4
+
5
+ -------------------------------- Description -------------------------------
6
+
7
+
8
+
9
+ -------------------------------- References --------------------------------
10
+
11
+ [1] J. Blank and K. Deb, pymoo: Multi-Objective Optimization in Python, in IEEE Access,
12
+ vol. 8, pp. 89497-89509, 2020, DOI: 10.1109/ACCESS.2020.2990567
13
+
14
+ -------------------------------- License -----------------------------------
15
+
16
+
17
+ ----------------------------------------------------------------------------
18
+ """
19
+
20
+ import numpy as np
21
+
22
+ from pymoo.algorithms.base.genetic import GeneticAlgorithm
23
+ from pymoo.algorithms.soo.nonconvex.ga import FitnessSurvival
24
+ from pymoo.core.duplicate import NoDuplicateElimination
25
+ from pymoo.core.infill import InfillCriterion
26
+ from pymoo.core.population import Population
27
+ from pymoo.core.replacement import ImprovementReplacement, is_better
28
+ from pymoo.core.variable import Real, Choice, get
29
+ from pymoo.docs import parse_doc_string
30
+ from pymoo.operators.control import EvolutionaryParameterControl
31
+ from pymoo.operators.repair.bounds_repair import repair_random_init, repair_clamp
32
+ from pymoo.operators.sampling.rnd import FloatRandomSampling, random
33
+ from pymoo.termination.default import DefaultSingleObjectiveTermination
34
+ from pymoo.util.display.single import SingleObjectiveOutput
35
+ from pymoo.util.sliding_window import SlidingWindow
36
+
37
+
38
+ # =========================================================================================================
39
+ # Mating
40
+ # =========================================================================================================
41
+
42
+
43
+ def pso_canonical(V, X, P_X, L_X, w, c1, c2):
44
+ n_particles, n_var = X.shape
45
+ r1, r2 = np.random.random((n_particles, n_var)), np.random.random((n_particles, n_var))
46
+ Vp = w * V + c1 * r1 * (P_X - X) + c2 * r2 * (L_X - X)
47
+ return Vp
48
+
49
+
50
+ def pso_rotation_invariant(V, X, P_X, L_X, inertia, c1, c2):
51
+ n_particles, n_var = X.shape
52
+
53
+ r1 = np.random.random((n_particles, n_var))
54
+ p = X + c1 * r1 * (P_X - X)
55
+
56
+ r2 = np.random.random((n_particles, n_var))
57
+ l = X + c2 * r2 * (L_X - X)
58
+
59
+ G = (X + p + l) / 3
60
+ r = np.linalg.norm(G - X, axis=1, keepdims=True)
61
+
62
+ Vp = inertia * V + alea_sphere(G, r) - X
63
+
64
+ return Vp
65
+
66
+
67
+ def alea_sphere(G, radius):
68
+ n, m = G.shape
69
+
70
+ x = np.random.normal(size=(n, m))
71
+ l = np.sqrt(np.sum(x ** 2, axis=1, keepdims=True))
72
+
73
+ r = np.random.random(size=(n, 1))
74
+ x = r * radius * x / l
75
+ return x + G
76
+
77
+
78
+ class Swarm(InfillCriterion):
79
+
80
+ def __init__(self,
81
+ w=0.7,
82
+ c1=1.4,
83
+ c2=1.4,
84
+ V_max=0.2,
85
+ prob_mut=0.33,
86
+ control=EvolutionaryParameterControl,
87
+ **kwargs):
88
+
89
+ super().__init__(**kwargs)
90
+ self.w = Real(w, bounds=(0.7, 0.9), strict=(0.0, 1.0))
91
+ self.c1 = Real(c1, bounds=(1.2, 1.6), strict=(0.0, None))
92
+ self.c2 = Real(c2, bounds=(1.2, 1.6), strict=(0.0, None))
93
+ self.V_max = V_max
94
+ self.prob_mut = prob_mut
95
+
96
+ # of parameter control should be applied on the mating level
97
+ self.control = control(self)
98
+
99
+ def do(self, problem, pop, n_offsprings, algorithm=None, **kwargs):
100
+ control = self.control
101
+
102
+ # let the parameter control now some information
103
+ control.tell(pop=pop)
104
+
105
+ # set the controlled parameter for the desired number of offsprings
106
+ control.do(n_offsprings)
107
+
108
+ # get the parameters that will be used
109
+ w, c1, c2 = get(self.w, self.c1, self.c2, size=(len(pop), 1))
110
+
111
+ # get all the population that play a role for the mating
112
+ swarm, pbest, lbest = algorithm.swarm, algorithm.pbest, algorithm.lbest
113
+
114
+ V, X, P_X, L_X = swarm.get("V"), swarm.get("X"), pbest.get("X"), lbest.get("X")
115
+
116
+ Vp = pso_canonical(V, X, P_X, L_X, w, c1, c2)
117
+ # Vp = pso_rotation_invariant(V, X, P_X, L_X, w, c1, c2)
118
+
119
+ # if a maximum velocity has been defined
120
+ V_max = self.V_max
121
+ if V_max is not None:
122
+ xl, xu = problem.bounds()
123
+ Vp = repair_clamp(Vp, -V_max * (xu - xl), V_max * (xu - xl))
124
+
125
+ # the position of the new swarm particles
126
+ Xp = X + Vp
127
+
128
+ # if adding the velocity has brought them out of bounds -> bring them back
129
+ if problem.has_bounds():
130
+ Xp = repair_random_init(Xp, X, *problem.bounds())
131
+
132
+ # do a mutation of the global best solution (helps to keep some diversity)
133
+ # Xm = PM(prob=1.0, eta=20).do(problem, swarm).get("X")
134
+ # mut = pbest.get("rank") == 0
135
+ # Xp[mut] = Xm[mut]
136
+
137
+ # recalculate the velocity after the repair has happened
138
+ Vp = Xp - X
139
+
140
+ # create the population
141
+ off = Population.new(X=Xp, V=Vp)
142
+
143
+ # do the reset of particles if their personal bests have not moved much
144
+ # for k, ind in enumerate(pbest):
145
+ # delta = algorithm.delta[k]
146
+ #
147
+ # if k != algorithm.best and delta.is_full() and np.array(delta).mean() < 0.001:
148
+ # particle = FloatRandomSampling().do(problem, 1)[0]
149
+ # particle.set("V", np.zeros(problem.n_var))
150
+ # off[k], pbest[k], lbest[k] = particle, particle, particle
151
+ # delta.clear()
152
+
153
+ # repair the individuals if necessary - disabled if repair is NoRepair
154
+ off = self.repair(problem, off, **kwargs)
155
+
156
+ # advance the parameter control by attaching them to the offsprings
157
+ control.advance(off)
158
+
159
+ return off
160
+
161
+
162
+ def get_neighbors(name, N):
163
+ if name == "star":
164
+ return np.tile(np.arange(N), (N, 1))
165
+ elif name == "ring":
166
+ return (np.array([np.arange(3) for _ in range(N)]) + np.arange(N)[:, None] - 1) % N
167
+ elif name.startswith("random"):
168
+ K = 3
169
+ neighbors = []
170
+ for i in range(N):
171
+ vals = np.random.permutation(N)[:K]
172
+ neighbors.append([i] + vals.tolist())
173
+ return neighbors
174
+ else:
175
+ raise Exception(f"Unknown topology: {name}")
176
+
177
+
178
+ # =========================================================================================================
179
+ # Implementation
180
+ # =========================================================================================================
181
+
182
+
183
+ class EPPSO(GeneticAlgorithm):
184
+
185
+ def __init__(self,
186
+ pop_size=100,
187
+ sampling=FloatRandomSampling(),
188
+ swarm=Swarm(),
189
+ topology="star",
190
+ init_V="zero",
191
+ output=SingleObjectiveOutput(),
192
+ **kwargs):
193
+
194
+ super().__init__(pop_size=pop_size,
195
+ sampling=sampling,
196
+ mating=swarm,
197
+ init_V=init_V,
198
+ n_offsprings=None,
199
+ eliminate_duplicates=NoDuplicateElimination(),
200
+ output=output,
201
+ **kwargs)
202
+
203
+ # how the initial weights should be created
204
+ self.init_V = Choice(init_V, options=["zero", "random"])
205
+
206
+ # how the individual are connected to determine the local (or also global) best
207
+ self.topology = Choice(topology, options=["star", "ring"])
208
+
209
+ # create the neighbors of each particle given the topology
210
+ self.neighbors = get_neighbors(get(self.topology), pop_size)
211
+
212
+ # choose the single-objective default termination
213
+ self.termination = DefaultSingleObjectiveTermination()
214
+
215
+ # the particles that fly around to find good solutions (pop is the pbest)
216
+ self.swarm = None
217
+
218
+ # the personal and local best solution
219
+ self.lbest = None
220
+ self.pbest = None
221
+
222
+ # the integer of the currently best individual
223
+ self.best = None
224
+
225
+ def _initialize_infill(self):
226
+ swarm = super()._initialize_infill()
227
+
228
+ n_var = self.problem.n_var
229
+ init_V = get(self.init_V)
230
+ if init_V == "zero":
231
+ V = np.zeros((len(swarm), n_var))
232
+ elif init_V == "random":
233
+ Xp = random(self.problem, len(swarm))
234
+ V = (swarm.get("X") - Xp) / 2
235
+ else:
236
+ raise Exception("Unknown velocity initialization.")
237
+ swarm.set("V", V)
238
+
239
+ return swarm
240
+
241
+ def _initialize_advance(self, infills=None, **kwargs):
242
+ self.swarm = infills
243
+ self.pbest = self.pop
244
+ self.lbest = Population.create(*self.pbest)
245
+ self.delta = [SlidingWindow(30) for _ in range(len(infills))]
246
+
247
+ FitnessSurvival().do(self.problem, self.pbest, return_indices=True)
248
+
249
+ def _advance(self, infills=None, **kwargs):
250
+ assert infills is not None, "This algorithms uses the AskAndTell interface thus 'infills' must to be provided."
251
+
252
+ X = self.pbest.get("X")
253
+
254
+ self.swarm = infills
255
+ ImprovementReplacement().do(self.problem, self.pbest, infills, inplace=True)
256
+ Xp = self.pbest.get("X")
257
+
258
+ xl, xu = self.problem.bounds()
259
+ delta = np.max(np.abs(X - Xp) / (xu - xl), axis=1)
260
+ [self.delta[k].append(delta[k]) for k in range(len(delta))]
261
+
262
+ pbest = self.pbest
263
+ S = FitnessSurvival().do(self.problem, pbest, return_indices=True)
264
+ rank = pbest.get("rank")
265
+ self.best = S[0]
266
+
267
+ if get(self.topology) == "random-adaptive" and pbest[self.best].get("n_gen") != self.n_gen:
268
+ self.neighbors = get_neighbors(get(self.topology), len(pbest))
269
+
270
+ # send the message from each particle to all its neighbors
271
+ msgs = [[] for _ in range(len(pbest))]
272
+ for k, neighbors in enumerate(self.neighbors):
273
+ for neighbor in neighbors:
274
+ msgs[neighbor].append(k)
275
+
276
+ # now receive the messages and set the new local best (if an improvement has been found)
277
+ for k, msg in enumerate(msgs):
278
+
279
+ # if messages have been received
280
+ if len(msg) > 0:
281
+
282
+ # find the best one from the swarm that have been send
283
+ i = msg[rank[msg].argmin()]
284
+
285
+ # if the best from the message is better than the current local best
286
+ if is_better(pbest[i], self.lbest[k]):
287
+ self.lbest[k] = pbest[i]
288
+
289
+ self.pop = self.pbest
290
+
291
+ def _set_optimum(self, **kwargs):
292
+ k = self.pop.get("rank") == 0
293
+ self.opt = self.pop[k]
294
+
295
+
296
+ parse_doc_string(EPPSO.__init__)
297
+