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.
- pymoo/__init__.py +3 -0
- pymoo/algorithms/__init__.py +0 -0
- pymoo/algorithms/base/__init__.py +0 -0
- pymoo/algorithms/base/bracket.py +38 -0
- pymoo/algorithms/base/genetic.py +109 -0
- pymoo/algorithms/base/line.py +62 -0
- pymoo/algorithms/base/local.py +39 -0
- pymoo/algorithms/base/meta.py +79 -0
- pymoo/algorithms/hyperparameters.py +89 -0
- pymoo/algorithms/moo/__init__.py +0 -0
- pymoo/algorithms/moo/age.py +310 -0
- pymoo/algorithms/moo/age2.py +194 -0
- pymoo/algorithms/moo/ctaea.py +298 -0
- pymoo/algorithms/moo/dnsga2.py +76 -0
- pymoo/algorithms/moo/kgb.py +446 -0
- pymoo/algorithms/moo/moead.py +183 -0
- pymoo/algorithms/moo/nsga2.py +113 -0
- pymoo/algorithms/moo/nsga3.py +358 -0
- pymoo/algorithms/moo/pinsga2.py +370 -0
- pymoo/algorithms/moo/rnsga2.py +188 -0
- pymoo/algorithms/moo/rnsga3.py +246 -0
- pymoo/algorithms/moo/rvea.py +214 -0
- pymoo/algorithms/moo/sms.py +195 -0
- pymoo/algorithms/moo/spea2.py +190 -0
- pymoo/algorithms/moo/unsga3.py +47 -0
- pymoo/algorithms/soo/__init__.py +0 -0
- pymoo/algorithms/soo/convex/__init__.py +0 -0
- pymoo/algorithms/soo/nonconvex/__init__.py +0 -0
- pymoo/algorithms/soo/nonconvex/brkga.py +161 -0
- pymoo/algorithms/soo/nonconvex/cmaes.py +554 -0
- pymoo/algorithms/soo/nonconvex/de.py +279 -0
- pymoo/algorithms/soo/nonconvex/direct.py +149 -0
- pymoo/algorithms/soo/nonconvex/es.py +203 -0
- pymoo/algorithms/soo/nonconvex/g3pcx.py +94 -0
- pymoo/algorithms/soo/nonconvex/ga.py +93 -0
- pymoo/algorithms/soo/nonconvex/ga_niching.py +223 -0
- pymoo/algorithms/soo/nonconvex/isres.py +74 -0
- pymoo/algorithms/soo/nonconvex/nelder.py +251 -0
- pymoo/algorithms/soo/nonconvex/optuna.py +80 -0
- pymoo/algorithms/soo/nonconvex/pattern.py +183 -0
- pymoo/algorithms/soo/nonconvex/pso.py +399 -0
- pymoo/algorithms/soo/nonconvex/pso_ep.py +297 -0
- pymoo/algorithms/soo/nonconvex/random_search.py +25 -0
- pymoo/algorithms/soo/nonconvex/sres.py +56 -0
- pymoo/algorithms/soo/univariate/__init__.py +0 -0
- pymoo/algorithms/soo/univariate/backtracking.py +59 -0
- pymoo/algorithms/soo/univariate/exp.py +46 -0
- pymoo/algorithms/soo/univariate/golden.py +65 -0
- pymoo/algorithms/soo/univariate/quadr_interp.py +81 -0
- pymoo/algorithms/soo/univariate/wolfe.py +163 -0
- pymoo/config.py +33 -0
- pymoo/constraints/__init__.py +3 -0
- pymoo/constraints/adaptive.py +62 -0
- pymoo/constraints/as_obj.py +56 -0
- pymoo/constraints/as_penalty.py +41 -0
- pymoo/constraints/eps.py +26 -0
- pymoo/constraints/from_bounds.py +36 -0
- pymoo/core/__init__.py +0 -0
- pymoo/core/algorithm.py +394 -0
- pymoo/core/callback.py +38 -0
- pymoo/core/crossover.py +77 -0
- pymoo/core/decision_making.py +102 -0
- pymoo/core/decomposition.py +76 -0
- pymoo/core/duplicate.py +163 -0
- pymoo/core/evaluator.py +116 -0
- pymoo/core/indicator.py +34 -0
- pymoo/core/individual.py +784 -0
- pymoo/core/infill.py +64 -0
- pymoo/core/initialization.py +42 -0
- pymoo/core/mating.py +39 -0
- pymoo/core/meta.py +21 -0
- pymoo/core/mixed.py +165 -0
- pymoo/core/mutation.py +44 -0
- pymoo/core/operator.py +40 -0
- pymoo/core/parameters.py +134 -0
- pymoo/core/plot.py +210 -0
- pymoo/core/population.py +180 -0
- pymoo/core/problem.py +460 -0
- pymoo/core/recorder.py +99 -0
- pymoo/core/repair.py +23 -0
- pymoo/core/replacement.py +96 -0
- pymoo/core/result.py +52 -0
- pymoo/core/sampling.py +43 -0
- pymoo/core/selection.py +61 -0
- pymoo/core/solution.py +10 -0
- pymoo/core/survival.py +103 -0
- pymoo/core/termination.py +70 -0
- pymoo/core/variable.py +399 -0
- pymoo/cython/__init__.py +0 -0
- pymoo/cython/calc_perpendicular_distance.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/calc_perpendicular_distance.pyx +67 -0
- pymoo/cython/decomposition.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/decomposition.pyx +165 -0
- pymoo/cython/hv.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/hv.pyx +18 -0
- pymoo/cython/info.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/info.pyx +5 -0
- pymoo/cython/mnn.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/mnn.pyx +273 -0
- pymoo/cython/non_dominated_sorting.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/non_dominated_sorting.pyx +645 -0
- pymoo/cython/pruning_cd.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/pruning_cd.pyx +197 -0
- pymoo/cython/stochastic_ranking.cpython-311-x86_64-linux-musl.so +0 -0
- pymoo/cython/stochastic_ranking.pyx +49 -0
- pymoo/cython/utils.pxd +129 -0
- pymoo/cython/vendor/__init__.py +0 -0
- pymoo/cython/vendor/hypervolume.cpp +1621 -0
- pymoo/cython/vendor/hypervolume.h +63 -0
- pymoo/decomposition/__init__.py +0 -0
- pymoo/decomposition/aasf.py +24 -0
- pymoo/decomposition/asf.py +10 -0
- pymoo/decomposition/pbi.py +13 -0
- pymoo/decomposition/perp_dist.py +13 -0
- pymoo/decomposition/tchebicheff.py +11 -0
- pymoo/decomposition/util.py +13 -0
- pymoo/decomposition/weighted_sum.py +8 -0
- pymoo/docs.py +187 -0
- pymoo/experimental/__init__.py +0 -0
- pymoo/experimental/algorithms/__init__.py +0 -0
- pymoo/experimental/algorithms/gde3.py +57 -0
- pymoo/gradient/__init__.py +21 -0
- pymoo/gradient/automatic.py +57 -0
- pymoo/gradient/grad_autograd.py +105 -0
- pymoo/gradient/grad_complex.py +35 -0
- pymoo/gradient/grad_jax.py +51 -0
- pymoo/gradient/toolbox/__init__.py +6 -0
- pymoo/indicators/__init__.py +0 -0
- pymoo/indicators/distance_indicator.py +55 -0
- pymoo/indicators/gd.py +7 -0
- pymoo/indicators/gd_plus.py +7 -0
- pymoo/indicators/hv/__init__.py +63 -0
- pymoo/indicators/hv/exact.py +71 -0
- pymoo/indicators/hv/exact_2d.py +102 -0
- pymoo/indicators/hv/monte_carlo.py +74 -0
- pymoo/indicators/igd.py +7 -0
- pymoo/indicators/igd_plus.py +7 -0
- pymoo/indicators/kktpm.py +151 -0
- pymoo/indicators/migd.py +55 -0
- pymoo/indicators/rmetric.py +203 -0
- pymoo/indicators/spacing.py +52 -0
- pymoo/mcdm/__init__.py +0 -0
- pymoo/mcdm/compromise_programming.py +19 -0
- pymoo/mcdm/high_tradeoff.py +40 -0
- pymoo/mcdm/pseudo_weights.py +32 -0
- pymoo/operators/__init__.py +0 -0
- pymoo/operators/control.py +187 -0
- pymoo/operators/crossover/__init__.py +0 -0
- pymoo/operators/crossover/binx.py +45 -0
- pymoo/operators/crossover/dex.py +122 -0
- pymoo/operators/crossover/erx.py +162 -0
- pymoo/operators/crossover/expx.py +51 -0
- pymoo/operators/crossover/hux.py +37 -0
- pymoo/operators/crossover/nox.py +13 -0
- pymoo/operators/crossover/ox.py +84 -0
- pymoo/operators/crossover/pcx.py +82 -0
- pymoo/operators/crossover/pntx.py +49 -0
- pymoo/operators/crossover/sbx.py +125 -0
- pymoo/operators/crossover/spx.py +5 -0
- pymoo/operators/crossover/ux.py +20 -0
- pymoo/operators/mutation/__init__.py +0 -0
- pymoo/operators/mutation/bitflip.py +17 -0
- pymoo/operators/mutation/gauss.py +58 -0
- pymoo/operators/mutation/inversion.py +42 -0
- pymoo/operators/mutation/nom.py +7 -0
- pymoo/operators/mutation/pm.py +94 -0
- pymoo/operators/mutation/rm.py +23 -0
- pymoo/operators/repair/__init__.py +0 -0
- pymoo/operators/repair/bounce_back.py +32 -0
- pymoo/operators/repair/bounds_repair.py +95 -0
- pymoo/operators/repair/inverse_penalty.py +89 -0
- pymoo/operators/repair/rounding.py +18 -0
- pymoo/operators/repair/to_bound.py +31 -0
- pymoo/operators/repair/vtype.py +11 -0
- pymoo/operators/sampling/__init__.py +0 -0
- pymoo/operators/sampling/lhs.py +73 -0
- pymoo/operators/sampling/rnd.py +50 -0
- pymoo/operators/selection/__init__.py +0 -0
- pymoo/operators/selection/rnd.py +72 -0
- pymoo/operators/selection/tournament.py +76 -0
- pymoo/operators/survival/__init__.py +0 -0
- pymoo/operators/survival/rank_and_crowding/__init__.py +1 -0
- pymoo/operators/survival/rank_and_crowding/classes.py +209 -0
- pymoo/operators/survival/rank_and_crowding/metrics.py +208 -0
- pymoo/optimize.py +72 -0
- pymoo/problems/__init__.py +157 -0
- pymoo/problems/dyn.py +47 -0
- pymoo/problems/dynamic/__init__.py +0 -0
- pymoo/problems/dynamic/cec2015.py +108 -0
- pymoo/problems/dynamic/df.py +452 -0
- pymoo/problems/dynamic/misc.py +167 -0
- pymoo/problems/functional.py +48 -0
- pymoo/problems/many/__init__.py +5 -0
- pymoo/problems/many/cdtlz.py +159 -0
- pymoo/problems/many/dcdtlz.py +88 -0
- pymoo/problems/many/dtlz.py +264 -0
- pymoo/problems/many/wfg.py +550 -0
- pymoo/problems/multi/__init__.py +14 -0
- pymoo/problems/multi/bnh.py +34 -0
- pymoo/problems/multi/carside.py +48 -0
- pymoo/problems/multi/clutch.py +104 -0
- pymoo/problems/multi/csi.py +55 -0
- pymoo/problems/multi/ctp.py +198 -0
- pymoo/problems/multi/dascmop.py +213 -0
- pymoo/problems/multi/kursawe.py +25 -0
- pymoo/problems/multi/modact.py +68 -0
- pymoo/problems/multi/mw.py +400 -0
- pymoo/problems/multi/omnitest.py +48 -0
- pymoo/problems/multi/osy.py +32 -0
- pymoo/problems/multi/srn.py +28 -0
- pymoo/problems/multi/sympart.py +94 -0
- pymoo/problems/multi/tnk.py +24 -0
- pymoo/problems/multi/truss2d.py +83 -0
- pymoo/problems/multi/welded_beam.py +41 -0
- pymoo/problems/multi/wrm.py +36 -0
- pymoo/problems/multi/zdt.py +151 -0
- pymoo/problems/multi_to_single.py +22 -0
- pymoo/problems/single/__init__.py +12 -0
- pymoo/problems/single/ackley.py +24 -0
- pymoo/problems/single/cantilevered_beam.py +34 -0
- pymoo/problems/single/flowshop_scheduling.py +112 -0
- pymoo/problems/single/g.py +874 -0
- pymoo/problems/single/griewank.py +18 -0
- pymoo/problems/single/himmelblau.py +15 -0
- pymoo/problems/single/knapsack.py +48 -0
- pymoo/problems/single/mopta08.py +26 -0
- pymoo/problems/single/multimodal.py +20 -0
- pymoo/problems/single/pressure_vessel.py +30 -0
- pymoo/problems/single/rastrigin.py +20 -0
- pymoo/problems/single/rosenbrock.py +22 -0
- pymoo/problems/single/schwefel.py +18 -0
- pymoo/problems/single/simple.py +13 -0
- pymoo/problems/single/sphere.py +19 -0
- pymoo/problems/single/traveling_salesman.py +79 -0
- pymoo/problems/single/zakharov.py +19 -0
- pymoo/problems/static.py +14 -0
- pymoo/problems/util.py +42 -0
- pymoo/problems/zero_to_one.py +27 -0
- pymoo/termination/__init__.py +23 -0
- pymoo/termination/collection.py +12 -0
- pymoo/termination/cv.py +48 -0
- pymoo/termination/default.py +45 -0
- pymoo/termination/delta.py +64 -0
- pymoo/termination/fmin.py +16 -0
- pymoo/termination/ftol.py +144 -0
- pymoo/termination/indicator.py +49 -0
- pymoo/termination/max_eval.py +14 -0
- pymoo/termination/max_gen.py +15 -0
- pymoo/termination/max_time.py +20 -0
- pymoo/termination/robust.py +34 -0
- pymoo/termination/xtol.py +33 -0
- pymoo/util/__init__.py +0 -0
- pymoo/util/archive.py +150 -0
- pymoo/util/cache.py +29 -0
- pymoo/util/clearing.py +82 -0
- pymoo/util/display/__init__.py +0 -0
- pymoo/util/display/column.py +52 -0
- pymoo/util/display/display.py +34 -0
- pymoo/util/display/multi.py +96 -0
- pymoo/util/display/output.py +53 -0
- pymoo/util/display/progress.py +54 -0
- pymoo/util/display/single.py +67 -0
- pymoo/util/dominator.py +67 -0
- pymoo/util/function_loader.py +129 -0
- pymoo/util/hv.py +23 -0
- pymoo/util/matlab_engine.py +39 -0
- pymoo/util/misc.py +460 -0
- pymoo/util/mnn.py +70 -0
- pymoo/util/nds/__init__.py +0 -0
- pymoo/util/nds/dominance_degree_non_dominated_sort.py +159 -0
- pymoo/util/nds/efficient_non_dominated_sort.py +152 -0
- pymoo/util/nds/fast_non_dominated_sort.py +70 -0
- pymoo/util/nds/naive_non_dominated_sort.py +36 -0
- pymoo/util/nds/non_dominated_sorting.py +67 -0
- pymoo/util/nds/tree_based_non_dominated_sort.py +133 -0
- pymoo/util/normalization.py +312 -0
- pymoo/util/optimum.py +42 -0
- pymoo/util/plotting.py +177 -0
- pymoo/util/pruning_cd.py +89 -0
- pymoo/util/randomized_argsort.py +60 -0
- pymoo/util/ref_dirs/__init__.py +24 -0
- pymoo/util/ref_dirs/construction.py +88 -0
- pymoo/util/ref_dirs/das_dennis.py +52 -0
- pymoo/util/ref_dirs/energy.py +319 -0
- pymoo/util/ref_dirs/energy_layer.py +119 -0
- pymoo/util/ref_dirs/genetic_algorithm.py +63 -0
- pymoo/util/ref_dirs/incremental.py +68 -0
- pymoo/util/ref_dirs/misc.py +128 -0
- pymoo/util/ref_dirs/optimizer.py +59 -0
- pymoo/util/ref_dirs/performance.py +162 -0
- pymoo/util/ref_dirs/reduction.py +85 -0
- pymoo/util/ref_dirs/sample_and_map.py +24 -0
- pymoo/util/reference_direction.py +260 -0
- pymoo/util/remote.py +55 -0
- pymoo/util/roulette.py +27 -0
- pymoo/util/running_metric.py +128 -0
- pymoo/util/sliding_window.py +25 -0
- pymoo/util/stochastic_ranking.py +32 -0
- pymoo/util/value_functions.py +719 -0
- pymoo/util/vectors.py +40 -0
- pymoo/util/vf_dominator.py +99 -0
- pymoo/vendor/__init__.py +0 -0
- pymoo/vendor/cec2018.py +398 -0
- pymoo/vendor/gta.py +617 -0
- pymoo/vendor/hv.py +267 -0
- pymoo/vendor/vendor_cmaes.py +412 -0
- pymoo/vendor/vendor_coco.py +81 -0
- pymoo/vendor/vendor_scipy.py +232 -0
- pymoo/version.py +1 -0
- pymoo/visualization/__init__.py +8 -0
- pymoo/visualization/fitness_landscape.py +127 -0
- pymoo/visualization/heatmap.py +123 -0
- pymoo/visualization/pcp.py +120 -0
- pymoo/visualization/petal.py +91 -0
- pymoo/visualization/radar.py +108 -0
- pymoo/visualization/radviz.py +68 -0
- pymoo/visualization/scatter.py +150 -0
- pymoo/visualization/star_coordinate.py +75 -0
- pymoo/visualization/util.py +123 -0
- pymoo/visualization/video/__init__.py +0 -0
- pymoo/visualization/video/callback_video.py +82 -0
- pymoo/visualization/video/one_var_one_obj.py +57 -0
- pymoo/visualization/video/two_var_one_obj.py +62 -0
- pymoo-0.6.1.5.dev0.dist-info/METADATA +187 -0
- pymoo-0.6.1.5.dev0.dist-info/RECORD +330 -0
- pymoo-0.6.1.5.dev0.dist-info/WHEEL +5 -0
- pymoo-0.6.1.5.dev0.dist-info/licenses/LICENSE +191 -0
- pymoo-0.6.1.5.dev0.dist-info/top_level.txt +1 -0
- pymoo.libs/libgcc_s-2298274a.so.1 +0 -0
- pymoo.libs/libstdc++-08d5c7eb.so.6.0.33 +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
#ifndef HYPERVOLUME_H
|
|
4
|
+
#define HYPERVOLUME_H
|
|
5
|
+
|
|
6
|
+
/*!
|
|
7
|
+
*
|
|
8
|
+
* \brief Implementation of the Overmars-Yap Algorithm, originally provided by N. Beume.
|
|
9
|
+
*
|
|
10
|
+
* Applicable to points of dimension d >= 3. It is assumed that the array of points is sorted
|
|
11
|
+
* according to the 'last' objective.
|
|
12
|
+
*
|
|
13
|
+
* <PRE>
|
|
14
|
+
* author = {Nicola Beume and G\"unther Rudolph},
|
|
15
|
+
* title = {Faster {S}-Metric Calculation By Considering Dominated Hypervolume as {Klee}'s Measure Problem},
|
|
16
|
+
* booktitle = {IASTED International Conference on Computational Intelligence},
|
|
17
|
+
* publisher = {ACTA Press},
|
|
18
|
+
* pages = {231-236},
|
|
19
|
+
* year = {2006},
|
|
20
|
+
* </PRE>
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
double overmars_yap( double * points, double * referencePoint, unsigned noObjectives, unsigned noPoints );
|
|
24
|
+
|
|
25
|
+
/*!
|
|
26
|
+
*
|
|
27
|
+
* \brief Algorithm for the special case of d = 3 objectives.
|
|
28
|
+
*
|
|
29
|
+
* Applicable to points of dimension d = 3.
|
|
30
|
+
*
|
|
31
|
+
* Relevant literature:
|
|
32
|
+
*
|
|
33
|
+
* [1] C. M. Fonseca, L. Paquete, and M. Lopez-Ibanez. An
|
|
34
|
+
* improved dimension-sweep algorithm for the hypervolume
|
|
35
|
+
* indicator. In IEEE Congress on Evolutionary Computation,
|
|
36
|
+
* pages 1157-1163, Vancouver, Canada, July 2006.
|
|
37
|
+
*
|
|
38
|
+
* [2] L. Paquete, C. M. Fonseca and M. Lopez-Ibanez. An optimal
|
|
39
|
+
* algorithm for a special case of Klee's measure problem in three
|
|
40
|
+
* dimensions. Technical Report CSI-RT-I-01/2006, CSI, Universidade
|
|
41
|
+
* do Algarve, 2006.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
double fonseca( double * points, double * referencePoint, unsigned noObjectives, unsigned noPoints );
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
//!
|
|
48
|
+
//! \brief computation of the hypervolume
|
|
49
|
+
//!
|
|
50
|
+
//! \par
|
|
51
|
+
//! This function acts as a frontend to various algorithms
|
|
52
|
+
//! for the computation of the hypervolume.
|
|
53
|
+
//!
|
|
54
|
+
//! \param points the list containes the coordinates of all points in a single array
|
|
55
|
+
//! \param referencePoint the reference or nadir point
|
|
56
|
+
//! \param noObjectives number of coordinates per point
|
|
57
|
+
//! \param noPoints number of points in the list
|
|
58
|
+
//! \return dominated hypervolume
|
|
59
|
+
//!
|
|
60
|
+
double hypervolume(double* points, double* referencePoint, unsigned int noObjectives, unsigned int noPoints);
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
#endif // HYPERVOLUME_H
|
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.decomposition.asf import ASF
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AASF(ASF):
|
|
7
|
+
|
|
8
|
+
def __init__(self, eps=1e-10, _type="auto", rho=None, beta=None, **kwargs) -> None:
|
|
9
|
+
super().__init__(eps, _type, **kwargs)
|
|
10
|
+
if rho is None and beta is None:
|
|
11
|
+
raise Exception("Either provide rho or beta!")
|
|
12
|
+
elif rho is None:
|
|
13
|
+
self.rho = calc_rho(beta)
|
|
14
|
+
else:
|
|
15
|
+
self.rho = rho
|
|
16
|
+
|
|
17
|
+
def _do(self, F, weights, **kwargs):
|
|
18
|
+
asf = super()._do(F, weights, **kwargs)
|
|
19
|
+
augment = ((F - self.utopian_point) / np.clip(weights, 1e-12, np.inf)).sum(axis=1)
|
|
20
|
+
return asf + self.rho * augment
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def calc_rho(beta):
|
|
24
|
+
return 1 / (1 - np.tan(beta / 360 * 2 * np.pi)) - 1
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from pymoo.core.decomposition import Decomposition
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ASF(Decomposition):
|
|
5
|
+
|
|
6
|
+
def _do(self, F, weights, weight_0=1e-10, **kwargs):
|
|
7
|
+
_weights = weights.astype(float)
|
|
8
|
+
_weights[weights == 0] = weight_0
|
|
9
|
+
asf = ((F - self.utopian_point) / _weights).max(axis=1)
|
|
10
|
+
return asf
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from pymoo.core.decomposition import Decomposition
|
|
2
|
+
from pymoo.util.function_loader import load_function
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class PBI(Decomposition):
|
|
6
|
+
|
|
7
|
+
def __init__(self, theta=5, **kwargs) -> None:
|
|
8
|
+
super().__init__(**kwargs)
|
|
9
|
+
self.theta = theta
|
|
10
|
+
|
|
11
|
+
def _do(self, F, weights, **kwargs):
|
|
12
|
+
d1, d2 = load_function("calc_distance_to_weights")(F, weights, self.utopian_point)
|
|
13
|
+
return d1 + self.theta * d2
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from pymoo.core.decomposition import Decomposition
|
|
2
|
+
from pymoo.util.function_loader import load_function
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class PerpendicularDistance(Decomposition):
|
|
6
|
+
|
|
7
|
+
def __init__(self, theta=5, **kwargs) -> None:
|
|
8
|
+
super().__init__(**kwargs)
|
|
9
|
+
self.theta = theta
|
|
10
|
+
|
|
11
|
+
def _do(self, F, weights, **kwargs):
|
|
12
|
+
_, d2 = load_function("calc_distance_to_weights")(F, weights)
|
|
13
|
+
return d2
|
|
@@ -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
|
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.core import VJPNode, backward_pass
|
|
7
|
+
from autograd.tracer import new_box, isbox
|
|
8
|
+
except:
|
|
9
|
+
print("autograd only supports numpy < 2.0.0 versions.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def value_and_grad(*args, **kwargs):
|
|
13
|
+
from autograd import value_and_grad as vag
|
|
14
|
+
return vag(*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
|