pymoo 0.6.1.5.dev0__cp311-cp311-musllinux_1_2_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 (330) 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-311-x86_64-linux-musl.so +0 -0
  91. pymoo/cython/calc_perpendicular_distance.pyx +67 -0
  92. pymoo/cython/decomposition.cpython-311-x86_64-linux-musl.so +0 -0
  93. pymoo/cython/decomposition.pyx +165 -0
  94. pymoo/cython/hv.cpython-311-x86_64-linux-musl.so +0 -0
  95. pymoo/cython/hv.pyx +18 -0
  96. pymoo/cython/info.cpython-311-x86_64-linux-musl.so +0 -0
  97. pymoo/cython/info.pyx +5 -0
  98. pymoo/cython/mnn.cpython-311-x86_64-linux-musl.so +0 -0
  99. pymoo/cython/mnn.pyx +273 -0
  100. pymoo/cython/non_dominated_sorting.cpython-311-x86_64-linux-musl.so +0 -0
  101. pymoo/cython/non_dominated_sorting.pyx +645 -0
  102. pymoo/cython/pruning_cd.cpython-311-x86_64-linux-musl.so +0 -0
  103. pymoo/cython/pruning_cd.pyx +197 -0
  104. pymoo/cython/stochastic_ranking.cpython-311-x86_64-linux-musl.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 +330 -0
  326. pymoo-0.6.1.5.dev0.dist-info/WHEEL +5 -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
  329. pymoo.libs/libgcc_s-2298274a.so.1 +0 -0
  330. pymoo.libs/libstdc++-08d5c7eb.so.6.0.33 +0 -0
@@ -0,0 +1,251 @@
1
+ import numpy as np
2
+
3
+ from pymoo.algorithms.base.local import LocalSearch
4
+ from pymoo.algorithms.soo.nonconvex.ga import FitnessSurvival
5
+ from pymoo.core.individual import Individual
6
+ from pymoo.core.population import Population
7
+ from pymoo.core.population import pop_from_array_or_individual
8
+ from pymoo.core.replacement import is_better
9
+ from pymoo.core.termination import Termination
10
+ from pymoo.docs import parse_doc_string
11
+ from pymoo.operators.repair.to_bound import set_to_bounds_if_outside_by_problem
12
+ from pymoo.util.display.single import SingleObjectiveOutput
13
+ from pymoo.util.misc import vectorized_cdist
14
+ from pymoo.util.vectors import max_alpha
15
+
16
+
17
+ # =========================================================================================================
18
+ # Implementation
19
+ # =========================================================================================================
20
+
21
+
22
+ class NelderAndMeadTermination(Termination):
23
+
24
+ def __init__(self,
25
+ x_tol=1e-6,
26
+ f_tol=1e-6,
27
+ n_max_iter=1e6,
28
+ n_max_evals=1e6):
29
+
30
+ super().__init__()
31
+ self.x_tol = x_tol
32
+ self.f_tol = f_tol
33
+ self.n_max_iter = n_max_iter
34
+ self.n_max_evals = n_max_evals
35
+
36
+ def _update(self, algorithm):
37
+ pop, problem = algorithm.pop, algorithm.problem
38
+
39
+ if len(pop) <= 1:
40
+ return 0.0
41
+
42
+ X, F = pop.get("X", "F")
43
+
44
+ f_delta = np.abs(F[1:] - F[0]).max()
45
+ f_tol = 1 / (1 + (f_delta - self.f_tol))
46
+
47
+ # if the problem has bounds we can normalize the x space to to be more accurate
48
+ if problem.has_bounds():
49
+ x_delta = np.abs((X[1:] - X[0]) / (problem.xu - problem.xl)).max()
50
+ else:
51
+ x_delta = np.abs(X[1:] - X[0]).max()
52
+
53
+ x_tol = 1 / (1 + (x_delta - self.x_tol))
54
+
55
+ # degenerated simplex - get all edges and minimum and maximum length
56
+ D = vectorized_cdist(X, X)
57
+ val = D[np.triu_indices(len(pop), 1)]
58
+ min_e, max_e = val.min(), val.max()
59
+
60
+ # either if the maximum length is very small or the ratio is degenerated
61
+ is_degenerated = int(max_e < 1e-16 or min_e / max_e < 1e-16)
62
+
63
+ max_iter = algorithm.n_iter / self.n_max_iter
64
+ max_evals = algorithm.evaluator.n_eval / self.n_max_evals
65
+
66
+ return max(f_tol, x_tol, max_iter, max_evals, is_degenerated)
67
+
68
+
69
+ def adaptive_params(problem):
70
+ n = problem.n_var
71
+ alpha = 1
72
+ beta = 1 + 2 / n
73
+ gamma = 0.75 - 1 / (2 * n)
74
+ delta = 1 - 1 / n
75
+ return alpha, beta, gamma, delta
76
+
77
+
78
+ def default_params(_):
79
+ alpha = 1
80
+ beta = 2.0
81
+ gamma = 0.5
82
+ delta = 0.05
83
+ return alpha, beta, gamma, delta
84
+
85
+
86
+ def initialize_simplex(problem, x0, scale=0.05):
87
+ n = len(x0)
88
+
89
+ if problem.has_bounds():
90
+ delta = scale * (problem.xu - problem.xl)
91
+ else:
92
+ delta = scale * x0
93
+ delta[delta == 0] = 0.00025
94
+
95
+ # repeat the x0 already and add the values
96
+ X = x0[None, :].repeat(n, axis=0)
97
+
98
+ for k in range(n):
99
+
100
+ # if the problem has bounds do the check
101
+ if problem.has_bounds():
102
+ if X[k, k] + delta[k] < problem.xu[k]:
103
+ X[k, k] = X[k, k] + delta[k]
104
+ else:
105
+ X[k, k] = X[k, k] - delta[k]
106
+
107
+ # otherwise just add the init_simplex_scale
108
+ else:
109
+ X[k, k] = X[k, k] + delta[k]
110
+
111
+ return X
112
+
113
+
114
+ class NelderMead(LocalSearch):
115
+
116
+ def __init__(self,
117
+ init_simplex_scale=0.05,
118
+ func_params=adaptive_params,
119
+ output=SingleObjectiveOutput(),
120
+ **kwargs):
121
+
122
+ super().__init__(output=output, **kwargs)
123
+
124
+ # the function to return the parameter
125
+ self.func_params = func_params
126
+
127
+ # the attributes for the simplex operations
128
+ self.alpha = None
129
+ self.beta = None
130
+ self.gamma = None
131
+ self.delta = None
132
+
133
+ # whether the simplex has been initialized or not
134
+ self.is_simplex_initialized = False
135
+
136
+ # the initial simplex scale used
137
+ self.init_simplex_scale = init_simplex_scale
138
+
139
+ # the termination used for nelder and mead if nothing else provided
140
+ self.termination = NelderAndMeadTermination()
141
+
142
+ def _setup(self, problem, **kwargs):
143
+ self.alpha, self.beta, self.gamma, self.delta = self.func_params(self.problem)
144
+
145
+ def _initialize_simplex(self):
146
+ simplex = pop_from_array_or_individual(initialize_simplex(self.problem, self.x0.X, scale=0.05))
147
+ return Population.merge(self.x0, simplex)
148
+
149
+ def _next(self):
150
+ if not self.is_simplex_initialized:
151
+ self.pop = yield self._initialize_simplex()
152
+ self.is_simplex_initialized = True
153
+ else:
154
+ yield from self._step()
155
+
156
+ def _step(self):
157
+
158
+ # number of variables increased by one - matches equations in the paper
159
+ xl, xu = self.problem.bounds()
160
+ pop, n = self.pop, self.problem.n_var - 1
161
+
162
+ # calculate the centroid
163
+ centroid = pop[:n + 1].get("X").mean(axis=0)
164
+
165
+ # -------------------------------------------------------------------------------------------
166
+ # REFLECT
167
+ # -------------------------------------------------------------------------------------------
168
+
169
+ # check the maximum alpha until the bounds are hit
170
+ alphaU = max_alpha(centroid, (centroid - pop[n + 1].X), xl, xu)
171
+
172
+ # reflect the point, consider factor if bounds are there, make sure in bounds (floating point) evaluate
173
+ x_reflect = centroid + min(self.alpha, alphaU) * (centroid - pop[n + 1].X)
174
+ x_reflect = set_to_bounds_if_outside_by_problem(self.problem, x_reflect)
175
+ reflect = yield Individual(X=x_reflect)
176
+
177
+ # whether a shrink is necessary or not - decided during this step
178
+ shrink = False
179
+
180
+ better_than_current_best = is_better(reflect, pop[0])
181
+ better_than_second_worst = is_better(reflect, pop[n])
182
+ better_than_worst = is_better(reflect, pop[n + 1])
183
+
184
+ # if better than the current best - check for expansion
185
+ if better_than_current_best:
186
+
187
+ # -------------------------------------------------------------------------------------------
188
+ # EXPAND
189
+ # -------------------------------------------------------------------------------------------
190
+
191
+ # the maximum expansion until the bounds are hit
192
+ betaU = max_alpha(centroid, (x_reflect - centroid), xl, xu)
193
+
194
+ # expand using the factor, consider bounds, make sure in case of floating point issues
195
+ x_expand = centroid + min(self.beta, betaU) * (x_reflect - centroid)
196
+ x_expand = set_to_bounds_if_outside_by_problem(self.problem, x_expand)
197
+ expand = yield Individual(X=x_expand)
198
+
199
+ # if the expansion further improved take it - otherwise use expansion
200
+ if is_better(expand, reflect):
201
+ pop[n + 1] = expand
202
+ else:
203
+ pop[n + 1] = reflect
204
+
205
+ # if the new point is not better than the best, but better than second worst - just keep it
206
+ elif not better_than_current_best and better_than_second_worst:
207
+ pop[n + 1] = reflect
208
+
209
+ # if not worse than the worst - outside contraction
210
+ elif not better_than_second_worst and better_than_worst:
211
+
212
+ # -------------------------------------------------------------------------------------------
213
+ # Outside Contraction
214
+ # -------------------------------------------------------------------------------------------
215
+
216
+ x_contract_outside = centroid + self.gamma * (x_reflect - centroid)
217
+ contract_outside = yield Individual(X=x_contract_outside)
218
+
219
+ if is_better(contract_outside, reflect):
220
+ pop[n + 1] = contract_outside
221
+ else:
222
+ shrink = True
223
+
224
+ # if the reflection was worse than the worst - inside contraction
225
+ else:
226
+
227
+ # -------------------------------------------------------------------------------------------
228
+ # Inside Contraction
229
+ # -------------------------------------------------------------------------------------------
230
+
231
+ x_contract_inside = centroid - self.gamma * (x_reflect - centroid)
232
+ contract_inside = yield Individual(X=x_contract_inside)
233
+
234
+ if is_better(contract_inside, pop[n + 1]):
235
+ pop[n + 1] = contract_inside
236
+ else:
237
+ shrink = True
238
+
239
+ # -------------------------------------------------------------------------------------------
240
+ # Shrink (only if necessary)
241
+ # -------------------------------------------------------------------------------------------
242
+
243
+ if shrink:
244
+ x_best, x_others = pop[0].X, pop[1:].get("X")
245
+ x_shrink = x_best + self.delta * (x_others - x_best)
246
+ pop[1:] = yield Population.new(X=x_shrink)
247
+
248
+ self.pop = FitnessSurvival().do(self.problem, pop, n_survive=len(pop))
249
+
250
+
251
+ parse_doc_string(NelderMead.__init__)
@@ -0,0 +1,80 @@
1
+ from pymoo.util.optimum import filter_optimum
2
+
3
+ try:
4
+ import optuna
5
+ from optuna.samplers import TPESampler
6
+ from optuna.logging import get_logger
7
+ except:
8
+ raise Exception("Please install optuna: pip install optuna")
9
+
10
+ from pymoo.core.algorithm import Algorithm
11
+ from pymoo.core.individual import Individual
12
+ from pymoo.core.population import Population
13
+ from pymoo.core.variable import Real, Integer, Choice, Binary
14
+ from pymoo.util.display.single import SingleObjectiveOutput
15
+
16
+
17
+ class Optuna(Algorithm):
18
+
19
+ def __init__(self, sampler=None, output=SingleObjectiveOutput(), **kwargs):
20
+ super().__init__(output=output, **kwargs)
21
+ self.sampler = sampler
22
+
23
+ def _setup(self, problem, **kwargs):
24
+
25
+ sampler = self.sampler
26
+ if sampler is None:
27
+ sampler = TPESampler(seed=self.seed)
28
+
29
+ # that disables the warning in the very beginning
30
+ get_logger('optuna.storages._in_memory').disabled = True
31
+
32
+ # create a new study
33
+ self.study = optuna.create_study(study_name=f"Study@{id(self)}", sampler=sampler, direction='minimize')
34
+
35
+ # the current trial for an individual
36
+ self.trial = None
37
+
38
+ def _infill(self):
39
+ self.trial = self.study.ask()
40
+
41
+ vars = self.problem.vars
42
+ assert vars is not None, "Optuna needs explicitly defined variables."
43
+
44
+ x = {}
45
+ for name, param in vars.items():
46
+ if isinstance(param, Real):
47
+ lower, upper = param.bounds
48
+ v = self.trial.suggest_float(name, lower, upper)
49
+ elif isinstance(param, Integer):
50
+ lower, upper = param.bounds
51
+ v = self.trial.suggest_int(name, lower, upper)
52
+ elif isinstance(param, Choice):
53
+ options = param.options
54
+ v = self.trial.suggest_categorical(name, options)
55
+ elif isinstance(param, Binary):
56
+ v = self.trial.suggest_categorical(name, [False, True])
57
+ else:
58
+ raise Exception("Type not supported yet.")
59
+ x[name] = v
60
+
61
+ return Individual(X=x)
62
+
63
+ def _advance(self, infills=None, **kwargs):
64
+ self.pop = Population.create(infills)
65
+ self.study.tell(self.trial, infills.f)
66
+
67
+ def _initialize_infill(self):
68
+ return self._infill()
69
+
70
+ def _initialize_advance(self, **kwargs):
71
+ return self._advance(**kwargs)
72
+
73
+ def _set_optimum(self):
74
+ pop = self.pop
75
+ if self.opt is not None:
76
+ pop = Population.merge(self.opt, pop)
77
+ self.opt = filter_optimum(pop, least_infeasible=True)
78
+
79
+
80
+
@@ -0,0 +1,183 @@
1
+ import numpy as np
2
+
3
+ from pymoo.algorithms.base.local import LocalSearch
4
+ from pymoo.core.individual import Individual
5
+ from pymoo.core.population import Population
6
+ from pymoo.core.replacement import is_better
7
+ from pymoo.docs import parse_doc_string
8
+ from pymoo.operators.repair.to_bound import set_to_bounds_if_outside_by_problem
9
+ from pymoo.util.display.single import SingleObjectiveOutput
10
+ from pymoo.util.optimum import filter_optimum
11
+
12
+
13
+ # =========================================================================================================
14
+ # Implementation
15
+ # =========================================================================================================
16
+
17
+
18
+ class PatternSearch(LocalSearch):
19
+ def __init__(self,
20
+ init_delta=0.25,
21
+ init_rho=0.5,
22
+ step_size=1.0,
23
+ output=SingleObjectiveOutput(),
24
+ **kwargs):
25
+ """
26
+ An implementation of well-known Hooke and Jeeves Pattern Search.
27
+
28
+ Parameters
29
+ ----------
30
+
31
+ x0 : numpy.array
32
+ The initial value where the local search should be initiated. If not provided `n_sample_points` are
33
+ created using latin hypercube sampling and the best solution found is set to `x0`.
34
+
35
+ n_sample_points : int
36
+ Number of sample points to be used to determine the initial search point. (Only used of `x0` is not provided)
37
+
38
+ delta : float
39
+ The `delta` values which is used for the exploration move. If lower and upper bounds are provided the
40
+ value is in relation to the overall search space. For instance, a value of 0.25 means that initially the
41
+ pattern is created in 25% distance of the initial search point.
42
+
43
+ rho : float
44
+ If the move was unsuccessful then the `delta` value is reduced by multiplying it with the value provided.
45
+ For instance, `explr_rho` implies that with a value of `delta/2` is continued.
46
+
47
+ step_size : float
48
+ After the exploration move the new center is determined by following a promising direction.
49
+ This value defines how large to step on this direction will be.
50
+
51
+ """
52
+
53
+ super().__init__(output=output, **kwargs)
54
+ self.init_rho = init_rho
55
+ self.init_delta = init_delta
56
+ self.step_size = step_size
57
+
58
+ self.n_not_improved = 0
59
+
60
+ self._rho = init_rho
61
+ self._delta = None
62
+ self._center = None
63
+ self._current = None
64
+ self._trial = None
65
+ self._direction = None
66
+ self._sign = None
67
+
68
+ def _initialize_advance(self, infills=None, **kwargs):
69
+ super()._initialize_advance(infills=infills, **kwargs)
70
+ self._center, self._explr = self.x0, self.x0
71
+ self._sign = np.ones(self.problem.n_var)
72
+
73
+ if self.problem.has_bounds():
74
+ xl, xu = self.problem.bounds()
75
+ self._delta = self.init_delta * (xu - xl)
76
+ else:
77
+ self._delta = np.abs(self.x0.X) / 2.0
78
+ self._delta[self._delta <= 1.0] = 1.0
79
+
80
+ def _next(self):
81
+
82
+ # whether the last iteration has resulted in a new optimum or not
83
+ has_improved = is_better(self._explr, self._center)
84
+
85
+ # that means that the exploration did not find any new point and was thus unsuccessful
86
+ if not has_improved:
87
+
88
+ # increase the counter (by default this will be initialized to 0 and directly increased to 1)
89
+ self.n_not_improved += 1
90
+
91
+ # keep track of the rho values in the normalized space
92
+ self._rho = self.init_rho ** self.n_not_improved
93
+
94
+ # explore around the current center - try finding a suitable direction
95
+ self._explr = yield from exploration_move(self.problem, self._center, self._sign, self._delta, self._rho)
96
+
97
+ # if we have found a direction in the last iteration to be worth following
98
+ else:
99
+
100
+ # get the direction which was successful in the last move
101
+ self._direction = (self._explr.X - self._center.X)
102
+
103
+ # declare the exploration point the new center (it has led to an improvement in the last iteration!)
104
+ self._center = self._explr
105
+
106
+ # use the pattern move to get a new trial vector along that given direction
107
+ self._trial = yield pattern_move(self.problem, self._center, self._direction, self.step_size)
108
+
109
+ # get the delta sign adjusted for the exploration
110
+ self._sign = calc_sign(self._direction)
111
+
112
+ # explore around the current center to try finding a suitable direction
113
+ self._explr = yield from exploration_move(self.problem, self._trial, self._sign, self._delta, self._rho)
114
+
115
+ self.pop = Population.create(self._center, self._explr)
116
+
117
+ def _set_optimum(self):
118
+ pop = self.pop if self.opt is None else Population.merge(self.opt, self.pop)
119
+ self.opt = filter_optimum(pop, least_infeasible=True)
120
+
121
+
122
+ def exploration_move(problem, center, sign, delta, rho, randomize=True):
123
+ n_var = problem.n_var
124
+
125
+ # the order for the variable iteration
126
+ if randomize:
127
+ K = np.random.permutation(n_var)
128
+ else:
129
+ K = np.arange(n_var)
130
+
131
+ # iterate over each variable
132
+ for k in K:
133
+
134
+ # the value to be tried first is given by the amount times the sign
135
+ _delta = sign[k] * rho * delta
136
+
137
+ # make a step of delta on the k-th variable
138
+ _explr = yield step_along_axis(problem, center.X, _delta, k)
139
+
140
+ if is_better(_explr, center, eps=0.0):
141
+ center = _explr
142
+
143
+ # if not successful try the other direction
144
+ else:
145
+
146
+ # now try the negative value of delta and see if we can improve
147
+ _explr = yield step_along_axis(problem, center.X, -1 * _delta, k)
148
+
149
+ if is_better(_explr, center, eps=0.0):
150
+ center = _explr
151
+
152
+ return center
153
+
154
+
155
+ def pattern_move(problem, current, direction, step_size):
156
+ # calculate the new X and repair out of bounds if necessary
157
+ X = current.X + step_size * direction
158
+ set_to_bounds_if_outside_by_problem(problem, X)
159
+
160
+ # create the new center individual
161
+ return Individual(X=X)
162
+
163
+
164
+ def calc_sign(direction):
165
+ sign = np.sign(direction)
166
+ sign[sign == 0] = -1
167
+ return sign
168
+
169
+
170
+ def step_along_axis(problem, x, delta, axis):
171
+ # copy and add delta to the new point
172
+ X = np.copy(x)
173
+
174
+ # now add to the current solution
175
+ X[axis] = X[axis] + delta[axis]
176
+
177
+ # repair if out of bounds if necessary
178
+ X = set_to_bounds_if_outside_by_problem(problem, X)
179
+
180
+ return Individual(X=X)
181
+
182
+
183
+ parse_doc_string(PatternSearch.__init__)