pymoo 0.6.1.2__cp312-cp312-macosx_10_9_universal2.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pymoo might be problematic. Click here for more details.

Files changed (316) 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 +304 -0
  12. pymoo/algorithms/moo/age2.py +164 -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 +117 -0
  18. pymoo/algorithms/moo/nsga3.py +358 -0
  19. pymoo/algorithms/moo/rnsga2.py +188 -0
  20. pymoo/algorithms/moo/rnsga3.py +246 -0
  21. pymoo/algorithms/moo/rvea.py +214 -0
  22. pymoo/algorithms/moo/sms.py +195 -0
  23. pymoo/algorithms/moo/spea2.py +190 -0
  24. pymoo/algorithms/moo/unsga3.py +47 -0
  25. pymoo/algorithms/soo/__init__.py +0 -0
  26. pymoo/algorithms/soo/convex/__init__.py +0 -0
  27. pymoo/algorithms/soo/nonconvex/__init__.py +0 -0
  28. pymoo/algorithms/soo/nonconvex/brkga.py +161 -0
  29. pymoo/algorithms/soo/nonconvex/cmaes.py +554 -0
  30. pymoo/algorithms/soo/nonconvex/de.py +279 -0
  31. pymoo/algorithms/soo/nonconvex/direct.py +149 -0
  32. pymoo/algorithms/soo/nonconvex/es.py +202 -0
  33. pymoo/algorithms/soo/nonconvex/g3pcx.py +94 -0
  34. pymoo/algorithms/soo/nonconvex/ga.py +93 -0
  35. pymoo/algorithms/soo/nonconvex/ga_niching.py +223 -0
  36. pymoo/algorithms/soo/nonconvex/isres.py +74 -0
  37. pymoo/algorithms/soo/nonconvex/nelder.py +251 -0
  38. pymoo/algorithms/soo/nonconvex/optuna.py +80 -0
  39. pymoo/algorithms/soo/nonconvex/pattern.py +183 -0
  40. pymoo/algorithms/soo/nonconvex/pso.py +399 -0
  41. pymoo/algorithms/soo/nonconvex/pso_ep.py +297 -0
  42. pymoo/algorithms/soo/nonconvex/random_search.py +25 -0
  43. pymoo/algorithms/soo/nonconvex/sres.py +56 -0
  44. pymoo/algorithms/soo/univariate/__init__.py +0 -0
  45. pymoo/algorithms/soo/univariate/backtracking.py +59 -0
  46. pymoo/algorithms/soo/univariate/exp.py +46 -0
  47. pymoo/algorithms/soo/univariate/golden.py +65 -0
  48. pymoo/algorithms/soo/univariate/quadr_interp.py +81 -0
  49. pymoo/algorithms/soo/univariate/wolfe.py +163 -0
  50. pymoo/config.py +33 -0
  51. pymoo/constraints/__init__.py +3 -0
  52. pymoo/constraints/adaptive.py +62 -0
  53. pymoo/constraints/as_obj.py +56 -0
  54. pymoo/constraints/as_penalty.py +41 -0
  55. pymoo/constraints/eps.py +26 -0
  56. pymoo/constraints/from_bounds.py +36 -0
  57. pymoo/core/__init__.py +0 -0
  58. pymoo/core/algorithm.py +394 -0
  59. pymoo/core/callback.py +38 -0
  60. pymoo/core/crossover.py +77 -0
  61. pymoo/core/decision_making.py +102 -0
  62. pymoo/core/decomposition.py +76 -0
  63. pymoo/core/duplicate.py +163 -0
  64. pymoo/core/evaluator.py +116 -0
  65. pymoo/core/indicator.py +34 -0
  66. pymoo/core/individual.py +783 -0
  67. pymoo/core/infill.py +64 -0
  68. pymoo/core/initialization.py +42 -0
  69. pymoo/core/mating.py +39 -0
  70. pymoo/core/meta.py +21 -0
  71. pymoo/core/mixed.py +165 -0
  72. pymoo/core/mutation.py +44 -0
  73. pymoo/core/operator.py +40 -0
  74. pymoo/core/parameters.py +134 -0
  75. pymoo/core/plot.py +210 -0
  76. pymoo/core/population.py +180 -0
  77. pymoo/core/problem.py +460 -0
  78. pymoo/core/recorder.py +99 -0
  79. pymoo/core/repair.py +23 -0
  80. pymoo/core/replacement.py +96 -0
  81. pymoo/core/result.py +52 -0
  82. pymoo/core/sampling.py +43 -0
  83. pymoo/core/selection.py +61 -0
  84. pymoo/core/solution.py +10 -0
  85. pymoo/core/survival.py +103 -0
  86. pymoo/core/termination.py +70 -0
  87. pymoo/core/variable.py +399 -0
  88. pymoo/cython/__init__.py +0 -0
  89. pymoo/cython/calc_perpendicular_distance.cpython-312-darwin.so +0 -0
  90. pymoo/cython/decomposition.cpython-312-darwin.so +0 -0
  91. pymoo/cython/hv.cpython-312-darwin.so +0 -0
  92. pymoo/cython/info.cpython-312-darwin.so +0 -0
  93. pymoo/cython/mnn.cpython-312-darwin.so +0 -0
  94. pymoo/cython/non_dominated_sorting.cpython-312-darwin.so +0 -0
  95. pymoo/cython/pruning_cd.cpython-312-darwin.so +0 -0
  96. pymoo/cython/stochastic_ranking.cpython-312-darwin.so +0 -0
  97. pymoo/cython/utils.pxd +129 -0
  98. pymoo/cython/vendor/__init__.py +0 -0
  99. pymoo/cython/vendor/hypervolume.h +63 -0
  100. pymoo/decomposition/__init__.py +0 -0
  101. pymoo/decomposition/aasf.py +24 -0
  102. pymoo/decomposition/asf.py +10 -0
  103. pymoo/decomposition/pbi.py +13 -0
  104. pymoo/decomposition/perp_dist.py +13 -0
  105. pymoo/decomposition/tchebicheff.py +11 -0
  106. pymoo/decomposition/util.py +13 -0
  107. pymoo/decomposition/weighted_sum.py +8 -0
  108. pymoo/docs.py +187 -0
  109. pymoo/experimental/__init__.py +0 -0
  110. pymoo/experimental/algorithms/__init__.py +0 -0
  111. pymoo/experimental/algorithms/gde3.py +57 -0
  112. pymoo/gradient/__init__.py +21 -0
  113. pymoo/gradient/automatic.py +57 -0
  114. pymoo/gradient/grad_autograd.py +105 -0
  115. pymoo/gradient/grad_complex.py +35 -0
  116. pymoo/gradient/grad_jax.py +51 -0
  117. pymoo/gradient/toolbox/__init__.py +6 -0
  118. pymoo/indicators/__init__.py +0 -0
  119. pymoo/indicators/distance_indicator.py +55 -0
  120. pymoo/indicators/gd.py +7 -0
  121. pymoo/indicators/gd_plus.py +7 -0
  122. pymoo/indicators/hv/__init__.py +63 -0
  123. pymoo/indicators/hv/exact.py +71 -0
  124. pymoo/indicators/hv/exact_2d.py +102 -0
  125. pymoo/indicators/hv/monte_carlo.py +74 -0
  126. pymoo/indicators/igd.py +7 -0
  127. pymoo/indicators/igd_plus.py +7 -0
  128. pymoo/indicators/kktpm.py +151 -0
  129. pymoo/indicators/migd.py +55 -0
  130. pymoo/indicators/rmetric.py +203 -0
  131. pymoo/indicators/spacing.py +52 -0
  132. pymoo/mcdm/__init__.py +0 -0
  133. pymoo/mcdm/compromise_programming.py +19 -0
  134. pymoo/mcdm/high_tradeoff.py +40 -0
  135. pymoo/mcdm/pseudo_weights.py +32 -0
  136. pymoo/operators/__init__.py +0 -0
  137. pymoo/operators/control.py +187 -0
  138. pymoo/operators/crossover/__init__.py +0 -0
  139. pymoo/operators/crossover/binx.py +45 -0
  140. pymoo/operators/crossover/dex.py +122 -0
  141. pymoo/operators/crossover/erx.py +162 -0
  142. pymoo/operators/crossover/expx.py +51 -0
  143. pymoo/operators/crossover/hux.py +37 -0
  144. pymoo/operators/crossover/nox.py +13 -0
  145. pymoo/operators/crossover/ox.py +84 -0
  146. pymoo/operators/crossover/pcx.py +82 -0
  147. pymoo/operators/crossover/pntx.py +49 -0
  148. pymoo/operators/crossover/sbx.py +125 -0
  149. pymoo/operators/crossover/spx.py +5 -0
  150. pymoo/operators/crossover/ux.py +20 -0
  151. pymoo/operators/mutation/__init__.py +0 -0
  152. pymoo/operators/mutation/bitflip.py +17 -0
  153. pymoo/operators/mutation/gauss.py +58 -0
  154. pymoo/operators/mutation/inversion.py +42 -0
  155. pymoo/operators/mutation/nom.py +7 -0
  156. pymoo/operators/mutation/pm.py +94 -0
  157. pymoo/operators/mutation/rm.py +23 -0
  158. pymoo/operators/repair/__init__.py +0 -0
  159. pymoo/operators/repair/bounce_back.py +32 -0
  160. pymoo/operators/repair/bounds_repair.py +95 -0
  161. pymoo/operators/repair/inverse_penalty.py +89 -0
  162. pymoo/operators/repair/rounding.py +18 -0
  163. pymoo/operators/repair/to_bound.py +31 -0
  164. pymoo/operators/repair/vtype.py +11 -0
  165. pymoo/operators/sampling/__init__.py +0 -0
  166. pymoo/operators/sampling/lhs.py +73 -0
  167. pymoo/operators/sampling/rnd.py +50 -0
  168. pymoo/operators/selection/__init__.py +0 -0
  169. pymoo/operators/selection/rnd.py +72 -0
  170. pymoo/operators/selection/tournament.py +76 -0
  171. pymoo/operators/survival/__init__.py +0 -0
  172. pymoo/operators/survival/rank_and_crowding/__init__.py +1 -0
  173. pymoo/operators/survival/rank_and_crowding/classes.py +209 -0
  174. pymoo/operators/survival/rank_and_crowding/metrics.py +208 -0
  175. pymoo/optimize.py +72 -0
  176. pymoo/problems/__init__.py +157 -0
  177. pymoo/problems/dyn.py +47 -0
  178. pymoo/problems/dynamic/__init__.py +0 -0
  179. pymoo/problems/dynamic/cec2015.py +108 -0
  180. pymoo/problems/dynamic/df.py +452 -0
  181. pymoo/problems/dynamic/misc.py +167 -0
  182. pymoo/problems/functional.py +48 -0
  183. pymoo/problems/many/__init__.py +5 -0
  184. pymoo/problems/many/cdtlz.py +159 -0
  185. pymoo/problems/many/dcdtlz.py +88 -0
  186. pymoo/problems/many/dtlz.py +264 -0
  187. pymoo/problems/many/wfg.py +550 -0
  188. pymoo/problems/multi/__init__.py +14 -0
  189. pymoo/problems/multi/bnh.py +34 -0
  190. pymoo/problems/multi/carside.py +48 -0
  191. pymoo/problems/multi/clutch.py +104 -0
  192. pymoo/problems/multi/csi.py +55 -0
  193. pymoo/problems/multi/ctp.py +198 -0
  194. pymoo/problems/multi/dascmop.py +213 -0
  195. pymoo/problems/multi/kursawe.py +25 -0
  196. pymoo/problems/multi/modact.py +68 -0
  197. pymoo/problems/multi/mw.py +400 -0
  198. pymoo/problems/multi/omnitest.py +48 -0
  199. pymoo/problems/multi/osy.py +32 -0
  200. pymoo/problems/multi/srn.py +28 -0
  201. pymoo/problems/multi/sympart.py +94 -0
  202. pymoo/problems/multi/tnk.py +24 -0
  203. pymoo/problems/multi/truss2d.py +83 -0
  204. pymoo/problems/multi/welded_beam.py +41 -0
  205. pymoo/problems/multi/wrm.py +36 -0
  206. pymoo/problems/multi/zdt.py +151 -0
  207. pymoo/problems/multi_to_single.py +22 -0
  208. pymoo/problems/single/__init__.py +12 -0
  209. pymoo/problems/single/ackley.py +24 -0
  210. pymoo/problems/single/cantilevered_beam.py +34 -0
  211. pymoo/problems/single/flowshop_scheduling.py +112 -0
  212. pymoo/problems/single/g.py +874 -0
  213. pymoo/problems/single/griewank.py +18 -0
  214. pymoo/problems/single/himmelblau.py +15 -0
  215. pymoo/problems/single/knapsack.py +48 -0
  216. pymoo/problems/single/mopta08.py +26 -0
  217. pymoo/problems/single/multimodal.py +20 -0
  218. pymoo/problems/single/pressure_vessel.py +30 -0
  219. pymoo/problems/single/rastrigin.py +20 -0
  220. pymoo/problems/single/rosenbrock.py +22 -0
  221. pymoo/problems/single/schwefel.py +18 -0
  222. pymoo/problems/single/simple.py +13 -0
  223. pymoo/problems/single/sphere.py +19 -0
  224. pymoo/problems/single/traveling_salesman.py +79 -0
  225. pymoo/problems/single/zakharov.py +19 -0
  226. pymoo/problems/static.py +14 -0
  227. pymoo/problems/util.py +42 -0
  228. pymoo/problems/zero_to_one.py +27 -0
  229. pymoo/termination/__init__.py +23 -0
  230. pymoo/termination/collection.py +12 -0
  231. pymoo/termination/cv.py +48 -0
  232. pymoo/termination/default.py +45 -0
  233. pymoo/termination/delta.py +64 -0
  234. pymoo/termination/fmin.py +16 -0
  235. pymoo/termination/ftol.py +144 -0
  236. pymoo/termination/indicator.py +49 -0
  237. pymoo/termination/max_eval.py +14 -0
  238. pymoo/termination/max_gen.py +15 -0
  239. pymoo/termination/max_time.py +20 -0
  240. pymoo/termination/robust.py +34 -0
  241. pymoo/termination/xtol.py +33 -0
  242. pymoo/util/__init__.py +0 -0
  243. pymoo/util/archive.py +150 -0
  244. pymoo/util/cache.py +29 -0
  245. pymoo/util/clearing.py +82 -0
  246. pymoo/util/display/__init__.py +0 -0
  247. pymoo/util/display/column.py +52 -0
  248. pymoo/util/display/display.py +34 -0
  249. pymoo/util/display/multi.py +96 -0
  250. pymoo/util/display/output.py +53 -0
  251. pymoo/util/display/progress.py +54 -0
  252. pymoo/util/display/single.py +67 -0
  253. pymoo/util/dominator.py +67 -0
  254. pymoo/util/function_loader.py +129 -0
  255. pymoo/util/hv.py +23 -0
  256. pymoo/util/matlab_engine.py +39 -0
  257. pymoo/util/misc.py +460 -0
  258. pymoo/util/mnn.py +70 -0
  259. pymoo/util/nds/__init__.py +0 -0
  260. pymoo/util/nds/dominance_degree_non_dominated_sort.py +159 -0
  261. pymoo/util/nds/efficient_non_dominated_sort.py +152 -0
  262. pymoo/util/nds/fast_non_dominated_sort.py +68 -0
  263. pymoo/util/nds/naive_non_dominated_sort.py +36 -0
  264. pymoo/util/nds/non_dominated_sorting.py +67 -0
  265. pymoo/util/nds/tree_based_non_dominated_sort.py +133 -0
  266. pymoo/util/normalization.py +315 -0
  267. pymoo/util/optimum.py +42 -0
  268. pymoo/util/plotting.py +177 -0
  269. pymoo/util/pruning_cd.py +89 -0
  270. pymoo/util/randomized_argsort.py +60 -0
  271. pymoo/util/ref_dirs/__init__.py +24 -0
  272. pymoo/util/ref_dirs/construction.py +88 -0
  273. pymoo/util/ref_dirs/das_dennis.py +52 -0
  274. pymoo/util/ref_dirs/energy.py +317 -0
  275. pymoo/util/ref_dirs/energy_layer.py +119 -0
  276. pymoo/util/ref_dirs/genetic_algorithm.py +63 -0
  277. pymoo/util/ref_dirs/incremental.py +68 -0
  278. pymoo/util/ref_dirs/misc.py +128 -0
  279. pymoo/util/ref_dirs/optimizer.py +59 -0
  280. pymoo/util/ref_dirs/performance.py +162 -0
  281. pymoo/util/ref_dirs/reduction.py +85 -0
  282. pymoo/util/ref_dirs/sample_and_map.py +24 -0
  283. pymoo/util/reference_direction.py +259 -0
  284. pymoo/util/remote.py +55 -0
  285. pymoo/util/roulette.py +27 -0
  286. pymoo/util/running_metric.py +128 -0
  287. pymoo/util/sliding_window.py +25 -0
  288. pymoo/util/stochastic_ranking.py +32 -0
  289. pymoo/util/vectors.py +40 -0
  290. pymoo/vendor/__init__.py +0 -0
  291. pymoo/vendor/cec2018.py +398 -0
  292. pymoo/vendor/gta.py +617 -0
  293. pymoo/vendor/hv.py +267 -0
  294. pymoo/vendor/vendor_cmaes.py +412 -0
  295. pymoo/vendor/vendor_coco.py +81 -0
  296. pymoo/vendor/vendor_scipy.py +232 -0
  297. pymoo/version.py +1 -0
  298. pymoo/visualization/__init__.py +8 -0
  299. pymoo/visualization/fitness_landscape.py +127 -0
  300. pymoo/visualization/heatmap.py +123 -0
  301. pymoo/visualization/pcp.py +120 -0
  302. pymoo/visualization/petal.py +91 -0
  303. pymoo/visualization/radar.py +108 -0
  304. pymoo/visualization/radviz.py +68 -0
  305. pymoo/visualization/scatter.py +150 -0
  306. pymoo/visualization/star_coordinate.py +75 -0
  307. pymoo/visualization/util.py +123 -0
  308. pymoo/visualization/video/__init__.py +0 -0
  309. pymoo/visualization/video/callback_video.py +82 -0
  310. pymoo/visualization/video/one_var_one_obj.py +57 -0
  311. pymoo/visualization/video/two_var_one_obj.py +62 -0
  312. pymoo-0.6.1.2.dist-info/LICENSE +191 -0
  313. pymoo-0.6.1.2.dist-info/METADATA +188 -0
  314. pymoo-0.6.1.2.dist-info/RECORD +316 -0
  315. pymoo-0.6.1.2.dist-info/WHEEL +5 -0
  316. pymoo-0.6.1.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,13 @@
1
+ import numpy as np
2
+
3
+
4
+ def calc_distance_to_weights(F, weights, utopian_point=None):
5
+ norm = np.linalg.norm(weights, axis=1)
6
+
7
+ if utopian_point is not None:
8
+ F = F - utopian_point
9
+
10
+ d1 = (F * weights).sum(axis=1) / norm
11
+ d2 = np.linalg.norm(F - (d1[:, None] * weights / norm[:, None]), axis=1)
12
+
13
+ return d1, d2
@@ -0,0 +1,8 @@
1
+ from pymoo.core.decomposition import Decomposition
2
+ import numpy as np
3
+
4
+
5
+ class WeightedSum(Decomposition):
6
+
7
+ def _do(self, F, weights, **kwargs):
8
+ return np.sum(F * weights, axis=1)
pymoo/docs.py ADDED
@@ -0,0 +1,187 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ import inspect
4
+ import re
5
+ from pymoo.config import Config
6
+
7
+ # =========================================================================================================
8
+ # Docstrings Dictionary
9
+ # =========================================================================================================
10
+
11
+
12
+ algorithms = {
13
+ "pop_size": """ int
14
+ The population sized used by the algorithm.
15
+ """,
16
+
17
+ "n_offsprings": """ int
18
+ The number of offsprings that should be created in each generation.
19
+ """,
20
+
21
+ "sampling": """
22
+ :class:`~pymoo.core.sampling.Sampling`, :class:`~pymoo.core.population.Population`, :obj:`numpy.array`
23
+ The sampling process defines the initial set of solutions which are the starting point of the
24
+ optimization algorithm. Here, you have three different options by passing
25
+
26
+ (i) A :class:`~pymoo.core.sampling.Sampling` implementation which is an implementation of a
27
+ random sampling method.
28
+
29
+ (ii) A :class:`~pymoo.core.population.Population` object containing the variables to
30
+ be evaluated initially OR already evaluated solutions (F needs to be set in this case).
31
+
32
+ (iii) Pass a two dimensional :obj:`numpy.array` with (n_individuals, n_var) which contains the variable
33
+ space values for each individual.
34
+ """,
35
+
36
+ "selection": """:class:`~pymoo.core.selection.Selection`
37
+ This object defines the mating selection to be used.
38
+ In an evolutionary algorithm each generation parents need to be selected to produce new offsprings using
39
+ different recombination and mutation operators. Different strategies for selecting parents are possible e.g.
40
+ selecting them just randomly, only in the neighborhood, using a tournament selection to introduce some selection
41
+ pressure, ...
42
+ """,
43
+ "crossover": """:class:`~pymoo.core.crossover.Crossover`
44
+ The crossover has the purpose of create offsprings during the evolution. After the mating selection
45
+ the parents are passed to the crossover operator which will dependent on the implementation create
46
+ a different number of offsprings.
47
+ """,
48
+
49
+ "mutation": """:class:`~pymoo.core.mutation.Mutation`
50
+ Some genetic algorithms rely only on the mutation operation. However, it has shown that increases
51
+ the performance to perform a mutation after creating the offsprings through crossover as well.
52
+ Usually the mutation operator needs to be initialized with a probability to be executed.
53
+ Having a high probability of mutation will most of the time increase the diversity in the population.
54
+ """,
55
+
56
+ "survival": """:class:`~pymoo.core.survival.Survival`
57
+ The survival selection is the key for many genetic algorithms. It is responsible to define the
58
+ goal of convergence by choosing the individual to survive or be truncated each generation.
59
+ For single-objective single a selection based on the fitness is used commonly. However, for
60
+ multi-objective single different concepts are introduced.
61
+ """,
62
+
63
+ "ref_points": """:obj:`numpy.array`
64
+ Reference Points (or also called Aspiration Points) as a :obj:`numpy.array` where each row
65
+ represents a point and each column a variable (must be equal to the objective dimension of the problem)
66
+ """,
67
+
68
+ "eliminate_duplicates": """bool
69
+ The genetic algorithm implementation has a built in feature that eliminates duplicates after merging
70
+ the parent and the offspring population. If there are duplicates with respect to the current
71
+ population or in the offsprings itself they are removed and the mating process is repeated to
72
+ fill up the offsprings until the desired number of unique offsprings is met.
73
+ """,
74
+
75
+ "n_offsprings": """int (default: None)
76
+ Number of offspring that are created through mating. By default *n_offsprings=None* which
77
+ sets the number of offsprings equal to the population size. By setting *n_offsprings=1* a, so called,
78
+ steady-state version of an algorithm can be achieved.
79
+ """,
80
+
81
+ "ref_dirs": """:obj:`numpy.array`
82
+ The reference direction that should be used during the optimization. Each row represents a reference line
83
+ and each column a variable.
84
+ """
85
+
86
+ }
87
+
88
+ visualization = {
89
+ "figsize": """tuple
90
+ The figure size. Default (figsize=(8, 6)). For some plots changing the size might have side-effects for position.
91
+ """,
92
+
93
+ "title": """str or tuple
94
+ The title of the figure. If some additional kwargs should be provided this can be achieved by providing a tuple
95
+ ("name", {"key" : val}).
96
+ """,
97
+
98
+ "legend": """str
99
+ Whether a legend should be shown or not.
100
+ """,
101
+
102
+ "tight_layout": """bool
103
+ Whether tight layout should be used.
104
+ """,
105
+
106
+ "bounds": """tuple
107
+ If plot requires normalization, it might be necessary to supply the boundaries. (Otherwise they might be
108
+ approximate by the minimum and maximum of the provided data). The boundaries should be provided as a list/tuple or
109
+ 2D numpy array, where the first element represents the minimum, second the second the maximum values.
110
+ If only an integer or float is supplied, the boundaries apply for each variable.
111
+ """,
112
+
113
+ "reverse": """bool
114
+ If plot requires normalization, then the reverse values can be plotted (1 - Input). For some plots
115
+ it can be useful to interpret a larger area as better regarding a value. If minimization applies, a smaller
116
+ area means better, which can be misleading.
117
+ """,
118
+
119
+ "axis_style": """dict
120
+ Most of the plots consists of an axis. The style of the axis, e.g. color, alpha, ..., can be changed to
121
+ further modify the plot appealing.
122
+ """,
123
+
124
+ "cmap": """colormap
125
+ For some plots different kind of colors are used. The colormap can be changed to modify the color sequence
126
+ for the plots.
127
+ """,
128
+
129
+ "labels": """str or list
130
+ The labels to be used for each variable provided in the plot. If a string is used, then they will
131
+ be enumerated. Otherwise, a list equal to the number of variables can be provided directly.
132
+ """,
133
+
134
+ "func_number_to_text": """func
135
+ A function which defines how numerical values should be represented if present in the plot
136
+ for instance scientific notation, rounding and so on.
137
+ """,
138
+
139
+ }
140
+
141
+ docs = {**algorithms, **visualization}
142
+
143
+
144
+ # =========================================================================================================
145
+ # Util for docstrings
146
+ # =========================================================================================================
147
+
148
+ def parse_doc_string(source, dest=None, other={}):
149
+ if not Config.parse_custom_docs:
150
+ return
151
+
152
+ if dest is None:
153
+ dest = source
154
+
155
+ D = {k: v.strip() for k, v in docs.items()}
156
+
157
+ doc = source.__doc__
158
+
159
+
160
+ lines = inspect.getsource(source)
161
+ if doc is not None:
162
+
163
+ doc = doc.format(**{**D, **other})
164
+
165
+ lines = inspect.getsource(source)
166
+
167
+ cnt = 0
168
+ b = False
169
+
170
+ for i, c in enumerate(lines):
171
+
172
+ if b and cnt == 0:
173
+ break
174
+ if c == "(":
175
+ cnt += 1
176
+ b = True
177
+ elif c == ")":
178
+ cnt -= 1
179
+
180
+ signature = lines[:i]
181
+ signature = re.sub(r"[\n\t]*", "", signature)
182
+ signature = re.sub(r"\s+", " ", signature)
183
+ signature = re.sub(r"def\s*", "", signature)
184
+ signature = signature.strip()
185
+
186
+ if dest is not None:
187
+ dest.__doc__ = signature + "\n" + doc
File without changes
File without changes
@@ -0,0 +1,57 @@
1
+ from pymoo.algorithms.moo.nsga2 import RankAndCrowdingSurvival
2
+ from pymoo.algorithms.soo.nonconvex.de import DE, Variant
3
+ from pymoo.core.population import Population
4
+
5
+ from pymoo.docs import parse_doc_string
6
+ from pymoo.operators.control import NoParameterControl
7
+ from pymoo.util.display.multi import MultiObjectiveOutput
8
+ from pymoo.util.dominator import get_relation
9
+ from pymoo.termination.default import DefaultMultiObjectiveTermination
10
+
11
+
12
+ class GDE3(DE):
13
+
14
+ def __init__(self, variant=None, **kwargs):
15
+
16
+ if variant is None:
17
+
18
+ if "control" not in kwargs:
19
+ kwargs["control"] = NoParameterControl
20
+
21
+ # the setting as proposed in the paper
22
+ variant = Variant(selection="rand", F=0.1, CR=0.9, **kwargs)
23
+
24
+ super().__init__(variant=variant, output=MultiObjectiveOutput(), **kwargs)
25
+ self.termination = DefaultMultiObjectiveTermination()
26
+
27
+ def _initialize_advance(self, infills=None, **kwargs):
28
+ RankAndCrowdingSurvival().do(self.problem, infills, return_indices=True)
29
+
30
+ def _advance(self, infills=None, **kwargs):
31
+ assert infills is not None, "This algorithms uses the AskAndTell interface thus 'infills' must to be provided."
32
+ pop = self.pop
33
+
34
+ # the pool of solutions considered to survive
35
+ pool = pop.tolist()
36
+
37
+ # now do the replacement of individuals
38
+ for infill in infills:
39
+ k = infill.get("index")
40
+
41
+ # get the relation between the infill and the solution from the population
42
+ rel = get_relation(infill, pop[k])
43
+
44
+ # if the new solution is not dominated by the individual
45
+ if rel <= 0:
46
+ pool.append(infill)
47
+
48
+ # if the individual is not dominated by the new solution
49
+ if rel >= 0:
50
+ pool.append(pop[k])
51
+
52
+ # set the rank and crowding in the current population
53
+ pool = Population.create(*pool)
54
+ self.pop = RankAndCrowdingSurvival().do(self.problem, pool, n_survive=self.pop_size)
55
+
56
+
57
+ parse_doc_string(GDE3.__init__)
@@ -0,0 +1,21 @@
1
+ import sys
2
+ import importlib
3
+
4
+ GRADIENT_MODULE = "pymoo.gradient.toolbox"
5
+
6
+ TOOLBOX = "numpy"
7
+
8
+
9
+ def activate(name):
10
+ global TOOLBOX
11
+ TOOLBOX = name
12
+
13
+ if GRADIENT_MODULE in sys.modules:
14
+ del sys.modules[GRADIENT_MODULE]
15
+ importlib.import_module(GRADIENT_MODULE)
16
+
17
+
18
+ def deactivate():
19
+ activate("numpy")
20
+
21
+
@@ -0,0 +1,57 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.meta import Meta
4
+ from pymoo.core.problem import Problem, ElementwiseEvaluationFunction
5
+
6
+
7
+ class ElementwiseEvaluationFunctionWithGradient(ElementwiseEvaluationFunction):
8
+
9
+ def __call__(self, x):
10
+ f = super().__call__
11
+
12
+ from pymoo.gradient import TOOLBOX
13
+
14
+ if TOOLBOX == "jax.numpy":
15
+ from pymoo.gradient.grad_jax import jax_elementwise_value_and_grad
16
+ out, grad = jax_elementwise_value_and_grad(f, x)
17
+
18
+ elif TOOLBOX == "autograd.numpy":
19
+ from pymoo.gradient.grad_autograd import autograd_elementwise_value_and_grad
20
+ out, grad = autograd_elementwise_value_and_grad(f, x)
21
+
22
+ for k, v in grad.items():
23
+ out["d" + k] = np.array(v)
24
+
25
+ return out
26
+
27
+
28
+ class ElementwiseAutomaticDifferentiation(Meta, Problem):
29
+
30
+ def __init__(self, problem, copy=True):
31
+ if not problem.elementwise:
32
+ raise Exception("Elementwise automatic differentiation can only be applied to elementwise problems.")
33
+
34
+ super().__init__(problem, copy)
35
+ self.elementwise_func = ElementwiseEvaluationFunctionWithGradient
36
+
37
+
38
+ class AutomaticDifferentiation(Meta, Problem):
39
+
40
+ def do(self, x, return_values_of, *args, **kwargs):
41
+ from pymoo.gradient import TOOLBOX
42
+
43
+ vals_not_grad = [v for v in return_values_of if not v.startswith("d")]
44
+ f = lambda xp: self.__object__.do(xp, vals_not_grad, *args, **kwargs)
45
+
46
+ if TOOLBOX == "jax.numpy":
47
+ from pymoo.gradient.grad_jax import jax_vectorized_value_and_grad
48
+ out, grad = jax_vectorized_value_and_grad(f, x)
49
+
50
+ elif TOOLBOX == "autograd.numpy":
51
+ from pymoo.gradient.grad_autograd import autograd_vectorized_value_and_grad
52
+ out, grad = autograd_vectorized_value_and_grad(f, x)
53
+
54
+ for k, v in grad.items():
55
+ out["d" + k] = v
56
+
57
+ return out
@@ -0,0 +1,105 @@
1
+ import warnings
2
+ import numpy as np
3
+
4
+ try:
5
+ import autograd.numpy as anp
6
+ from autograd import value_and_grad
7
+ from autograd.core import VJPNode, backward_pass
8
+ from autograd.tracer import new_box, isbox
9
+ except:
10
+ print("autograd only supports numpy < 2.0.0 versions.")
11
+
12
+
13
+ def value_and_grad(*args, **kwargs):
14
+ return value_and_grad(*args, **kwargs)
15
+
16
+
17
+ def log(*args, **kwargs):
18
+ return anp.log(*args, **kwargs)
19
+
20
+
21
+ def sqrt(*args, **kwargs):
22
+ return anp.sqrt(*args, **kwargs)
23
+
24
+
25
+ def row_stack(*args, **kwargs):
26
+ return anp.row_stack(*args, **kwargs)
27
+
28
+
29
+ def triu_indices(*args, **kwargs):
30
+ return anp.triu_indices(*args, **kwargs)
31
+
32
+
33
+ def run_and_trace(f, x):
34
+ start_node = VJPNode.new_root()
35
+
36
+ start_box = new_box(x, 0, start_node)
37
+ out = f(start_box)
38
+
39
+ return out, start_box
40
+
41
+
42
+ def autograd_elementwise_value_and_grad(f, x):
43
+ out, pullback = run_and_trace(f, x)
44
+
45
+ jac = dict()
46
+ for name in out:
47
+ val = out[name]
48
+
49
+ if val is not None:
50
+
51
+ if len(val.shape) == 0:
52
+ val = anp.array([val])
53
+
54
+ with warnings.catch_warnings():
55
+ warnings.simplefilter("ignore")
56
+
57
+ # the backward pass is done for each objective function once
58
+ grad = []
59
+ for j in range(len(val)):
60
+ b = np.zeros(val.shape)
61
+ b[j] = 1
62
+
63
+ n = new_box(b, 0, VJPNode.new_root())
64
+ _grad = backward_pass(n, val._node)
65
+ grad.append(_grad)
66
+
67
+ out[name] = np.array(val._value)
68
+ jac[name] = anp.stack(grad, axis=0)._value
69
+
70
+ return out, jac
71
+
72
+
73
+ def autograd_vectorized_value_and_grad(f, x):
74
+ end, start = run_and_trace(f, x)
75
+
76
+ out, jac = dict(), dict()
77
+
78
+ end = {k: v for k, v in end.items() if v is not None}
79
+
80
+ for name, val in end.items():
81
+
82
+ v = val
83
+ if hasattr(v, "_value"):
84
+ v = np.array(v._value)
85
+ out[name] = v
86
+
87
+ # if the end_box is not a box - autograd can not track back
88
+ if not isbox(val):
89
+ n, m = val.shape
90
+ jac[name] = np.zeros((n, m, x.shape[1]))
91
+
92
+ else:
93
+
94
+ # the backward pass is done for each objective function once
95
+ grad = []
96
+ for j in range(val.shape[1]):
97
+ b = anp.zeros(val.shape)
98
+ b[:, j] = 1
99
+ n = new_box(b, 0, VJPNode.new_root())
100
+ _grad = backward_pass(n, val._node)
101
+ grad.append(_grad)
102
+
103
+ jac[name] = anp.stack(grad, axis=1)._value
104
+
105
+ return out, jac
@@ -0,0 +1,35 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.meta import Meta
4
+ from pymoo.core.problem import Problem
5
+
6
+
7
+ def calc_complex_gradient(problem, return_values_of, x, eps, *args, **kwargs):
8
+ xp = x + np.eye(len(x)) * complex(0, eps)
9
+ out = problem.do(xp, return_values_of, *args, **kwargs)
10
+
11
+ grad = {}
12
+ for name, value in out.items():
13
+ grad[name] = np.imag(value / eps).T
14
+
15
+ return grad
16
+
17
+
18
+ class ComplexNumberGradient(Meta, Problem):
19
+
20
+ def __init__(self, object, eps=1e-8, **kwargs):
21
+ super().__init__(object, **kwargs)
22
+ self.eps = eps
23
+
24
+ def do(self, X, return_values_of, *args, **kwargs):
25
+ out = self.__object__.do(X, return_values_of, *args, **kwargs)
26
+
27
+ vals_not_grad = [v for v in return_values_of if not v.startswith("d")]
28
+
29
+ for i, x in enumerate(X):
30
+ grad = calc_complex_gradient(self.__object__, vals_not_grad, x, self.eps, *args, **kwargs)
31
+
32
+ for name, value in grad.items():
33
+ out['d' + name][i] = value
34
+
35
+ return out
@@ -0,0 +1,51 @@
1
+ from functools import partial
2
+
3
+ from jax.config import config
4
+
5
+ config.update("jax_enable_x64", True)
6
+
7
+ import pymoo.gradient.toolbox as anp
8
+ import numpy as np
9
+ from jax import vjp
10
+ from jax import vmap
11
+ from jax._src.api import _jacrev_unravel, _std_basis
12
+ from jax.tree_util import (tree_map)
13
+
14
+
15
+ def jax_elementwise_value_and_grad(f, x):
16
+ out, pullback = vjp(f, x)
17
+ u = _std_basis(out)
18
+ jac, = vmap(pullback, in_axes=0)(u)
19
+
20
+ grad = tree_map(partial(_jacrev_unravel, out), x, jac)
21
+
22
+ return out, grad
23
+
24
+
25
+ def jax_vectorized_value_and_grad(f, x):
26
+ out, pullback = vjp(f, x)
27
+
28
+ ncols = sum([v.shape[1] for v in out.values()])
29
+
30
+ u = dict()
31
+ cols = dict()
32
+ cnt = 0
33
+ for k, v in out.items():
34
+ if k not in cols:
35
+ cols[k] = []
36
+
37
+ n, m = v.shape
38
+ a = np.zeros((ncols, n, m))
39
+ for i in range(m):
40
+ cols[k].append(cnt)
41
+ a[cnt, :, i] = 1.0
42
+ cnt += 1
43
+
44
+ u[k] = anp.array(a)
45
+
46
+ jac, = vmap(pullback, in_axes=0)(u)
47
+ jac = np.array(jac)
48
+
49
+ grad = {k: np.swapaxes(jac[I], 0, 1) for k, I in cols.items()}
50
+
51
+ return out, grad
@@ -0,0 +1,6 @@
1
+ import importlib
2
+ import sys
3
+
4
+ from pymoo.gradient import TOOLBOX
5
+
6
+ sys.modules[__name__] = importlib.import_module(TOOLBOX)
File without changes
@@ -0,0 +1,55 @@
1
+ import numpy as np
2
+
3
+ from pymoo.core.indicator import Indicator
4
+ from pymoo.util.misc import vectorized_cdist, at_least_2d_array
5
+
6
+
7
+ def euclidean_distance(a, b, norm=None):
8
+ return np.sqrt((((a - b) / norm) ** 2).sum(axis=1))
9
+
10
+
11
+ def modified_distance(z, a, norm=None):
12
+ d = a - z
13
+ d[d < 0] = 0
14
+ d = d / norm
15
+ return np.sqrt((d ** 2).sum(axis=1))
16
+
17
+
18
+ def derive_ideal_and_nadir_from_pf(pf, ideal=None, nadir=None):
19
+
20
+ # try to derive ideal and nadir if not already set and pf provided
21
+ if pf is not None:
22
+ if ideal is None:
23
+ ideal = np.min(pf, axis=0)
24
+ if nadir is None:
25
+ nadir = np.max(pf, axis=0)
26
+
27
+ return ideal, nadir
28
+
29
+
30
+ class DistanceIndicator(Indicator):
31
+
32
+ def __init__(self, pf, dist_func, axis, zero_to_one=False, ideal=None, nadir=None, norm_by_dist=False, **kwargs):
33
+
34
+ # the pareto front if necessary to calculate the indicator
35
+ pf = at_least_2d_array(pf, extend_as="row")
36
+ ideal, nadir = derive_ideal_and_nadir_from_pf(pf, ideal=ideal, nadir=nadir)
37
+
38
+ super().__init__(zero_to_one=zero_to_one, ideal=ideal, nadir=nadir, **kwargs)
39
+ self.dist_func = dist_func
40
+ self.axis = axis
41
+ self.norm_by_dist = norm_by_dist
42
+ self.pf = self.normalization.forward(pf)
43
+
44
+ def _do(self, F):
45
+
46
+ # a factor to normalize the distances by (1.0 disables that by default)
47
+ norm = 1.0
48
+
49
+ # if zero_to_one is disabled this can be used to normalize the distance calculation itself
50
+ if self.norm_by_dist:
51
+ assert self.ideal is not None and self.nadir is not None, "If norm_by_dist is enabled ideal and nadir must be set!"
52
+ norm = self.nadir - self.ideal
53
+
54
+ D = vectorized_cdist(self.pf, F, func_dist=self.dist_func, norm=norm)
55
+ return np.mean(np.min(D, axis=self.axis))
pymoo/indicators/gd.py ADDED
@@ -0,0 +1,7 @@
1
+ from pymoo.indicators.distance_indicator import DistanceIndicator, euclidean_distance
2
+
3
+
4
+ class GD(DistanceIndicator):
5
+
6
+ def __init__(self, pf, **kwargs):
7
+ super().__init__(pf, euclidean_distance, 0, **kwargs)
@@ -0,0 +1,7 @@
1
+ from pymoo.indicators.distance_indicator import DistanceIndicator, modified_distance
2
+
3
+
4
+ class GDPlus(DistanceIndicator):
5
+
6
+ def __init__(self, pf, **kwargs):
7
+ super().__init__(pf, modified_distance, 0, **kwargs)