pymoo 0.6.1.6__cp312-cp312-macosx_10_13_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +110 -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 +91 -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/cmopso.py +239 -0
- pymoo/algorithms/moo/ctaea.py +305 -0
- pymoo/algorithms/moo/dnsga2.py +80 -0
- pymoo/algorithms/moo/kgb.py +450 -0
- pymoo/algorithms/moo/moead.py +183 -0
- pymoo/algorithms/moo/mopso_cd.py +309 -0
- pymoo/algorithms/moo/nsga2.py +113 -0
- pymoo/algorithms/moo/nsga3.py +361 -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 +196 -0
- pymoo/algorithms/moo/spea2.py +191 -0
- pymoo/algorithms/moo/unsga3.py +49 -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 +162 -0
- pymoo/algorithms/soo/nonconvex/cmaes.py +556 -0
- pymoo/algorithms/soo/nonconvex/de.py +283 -0
- pymoo/algorithms/soo/nonconvex/direct.py +148 -0
- pymoo/algorithms/soo/nonconvex/es.py +213 -0
- pymoo/algorithms/soo/nonconvex/g3pcx.py +94 -0
- pymoo/algorithms/soo/nonconvex/ga.py +95 -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/nrbo.py +191 -0
- pymoo/algorithms/soo/nonconvex/optuna.py +80 -0
- pymoo/algorithms/soo/nonconvex/pattern.py +185 -0
- pymoo/algorithms/soo/nonconvex/pso.py +337 -0
- pymoo/algorithms/soo/nonconvex/pso_ep.py +307 -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/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 +66 -0
- pymoo/constraints/as_obj.py +56 -0
- pymoo/constraints/as_penalty.py +41 -0
- pymoo/constraints/eps.py +34 -0
- pymoo/constraints/from_bounds.py +36 -0
- pymoo/core/__init__.py +0 -0
- pymoo/core/algorithm.py +408 -0
- pymoo/core/callback.py +38 -0
- pymoo/core/crossover.py +79 -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 +65 -0
- pymoo/core/initialization.py +44 -0
- pymoo/core/mating.py +39 -0
- pymoo/core/meta.py +21 -0
- pymoo/core/mixed.py +164 -0
- pymoo/core/mutation.py +44 -0
- pymoo/core/operator.py +46 -0
- pymoo/core/parameters.py +134 -0
- pymoo/core/plot.py +208 -0
- pymoo/core/population.py +180 -0
- pymoo/core/problem.py +373 -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 +45 -0
- pymoo/core/selection.py +61 -0
- pymoo/core/solution.py +10 -0
- pymoo/core/survival.py +107 -0
- pymoo/core/termination.py +70 -0
- pymoo/core/variable.py +415 -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/functions/__init__.py +135 -0
- pymoo/functions/compiled/__init__.py +0 -0
- pymoo/functions/compiled/calc_perpendicular_distance.cpp +27464 -0
- pymoo/functions/compiled/calc_perpendicular_distance.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/decomposition.cpp +28853 -0
- pymoo/functions/compiled/decomposition.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/info.cpp +7058 -0
- pymoo/functions/compiled/info.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/mnn.cpp +30095 -0
- pymoo/functions/compiled/mnn.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/non_dominated_sorting.cpp +35692 -0
- pymoo/functions/compiled/non_dominated_sorting.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/pruning_cd.cpp +29248 -0
- pymoo/functions/compiled/pruning_cd.cpython-312-darwin.so +0 -0
- pymoo/functions/compiled/stochastic_ranking.cpp +28042 -0
- pymoo/functions/compiled/stochastic_ranking.cpython-312-darwin.so +0 -0
- pymoo/functions/standard/__init__.py +1 -0
- pymoo/functions/standard/calc_perpendicular_distance.py +20 -0
- pymoo/functions/standard/decomposition.py +18 -0
- pymoo/functions/standard/hv.py +5 -0
- pymoo/functions/standard/mnn.py +78 -0
- pymoo/functions/standard/non_dominated_sorting.py +474 -0
- pymoo/functions/standard/pruning_cd.py +93 -0
- pymoo/functions/standard/stochastic_ranking.py +42 -0
- pymoo/gradient/__init__.py +24 -0
- pymoo/gradient/automatic.py +85 -0
- pymoo/gradient/grad_autograd.py +105 -0
- pymoo/gradient/grad_complex.py +35 -0
- pymoo/gradient/grad_jax.py +51 -0
- pymoo/gradient/numpy.py +22 -0
- pymoo/gradient/toolbox/__init__.py +19 -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 +59 -0
- pymoo/indicators/hv/approximate.py +105 -0
- pymoo/indicators/hv/exact.py +68 -0
- pymoo/indicators/hv/exact_2d.py +102 -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 +190 -0
- pymoo/operators/crossover/__init__.py +0 -0
- pymoo/operators/crossover/binx.py +47 -0
- pymoo/operators/crossover/dex.py +125 -0
- pymoo/operators/crossover/erx.py +164 -0
- pymoo/operators/crossover/expx.py +53 -0
- pymoo/operators/crossover/hux.py +37 -0
- pymoo/operators/crossover/nox.py +25 -0
- pymoo/operators/crossover/ox.py +88 -0
- pymoo/operators/crossover/pcx.py +84 -0
- pymoo/operators/crossover/pntx.py +49 -0
- pymoo/operators/crossover/sbx.py +137 -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 +60 -0
- pymoo/operators/mutation/inversion.py +42 -0
- pymoo/operators/mutation/nom.py +7 -0
- pymoo/operators/mutation/pm.py +96 -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 +97 -0
- pymoo/operators/repair/inverse_penalty.py +91 -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 +76 -0
- pymoo/operators/sampling/rnd.py +52 -0
- pymoo/operators/selection/__init__.py +0 -0
- pymoo/operators/selection/rnd.py +75 -0
- pymoo/operators/selection/tournament.py +78 -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 +212 -0
- pymoo/operators/survival/rank_and_crowding/metrics.py +208 -0
- pymoo/optimize.py +72 -0
- pymoo/parallelization/__init__.py +15 -0
- pymoo/parallelization/dask.py +25 -0
- pymoo/parallelization/joblib.py +28 -0
- pymoo/parallelization/ray.py +31 -0
- pymoo/parallelization/starmap.py +24 -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 +451 -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 +553 -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 +113 -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 +49 -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 +33 -0
- pymoo/util/archive.py +152 -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 +100 -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/hv.py +21 -0
- pymoo/util/matlab_engine.py +39 -0
- pymoo/util/misc.py +447 -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/find_non_dominated.py +54 -0
- pymoo/util/nds/naive_non_dominated_sort.py +36 -0
- pymoo/util/nds/non_dominated_sorting.py +94 -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/randomized_argsort.py +63 -0
- pymoo/util/ref_dirs/__init__.py +24 -0
- pymoo/util/ref_dirs/construction.py +89 -0
- pymoo/util/ref_dirs/das_dennis.py +52 -0
- pymoo/util/ref_dirs/energy.py +317 -0
- pymoo/util/ref_dirs/energy_layer.py +119 -0
- pymoo/util/ref_dirs/genetic_algorithm.py +64 -0
- pymoo/util/ref_dirs/incremental.py +69 -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 +258 -0
- pymoo/util/remote.py +55 -0
- pymoo/util/roulette.py +29 -0
- pymoo/util/running_metric.py +128 -0
- pymoo/util/sliding_window.py +25 -0
- pymoo/util/value_functions.py +720 -0
- pymoo/util/vectors.py +40 -0
- pymoo/util/vf_dominator.py +102 -0
- pymoo/vendor/__init__.py +0 -0
- pymoo/vendor/cec2018.py +398 -0
- pymoo/vendor/gta.py +617 -0
- pymoo/vendor/vendor_cmaes.py +421 -0
- pymoo/vendor/vendor_coco.py +81 -0
- pymoo/vendor/vendor_scipy.py +232 -0
- pymoo/version.py +1 -0
- pymoo/visualization/__init__.py +21 -0
- pymoo/visualization/app/__init__.py +0 -0
- pymoo/visualization/app/pso.py +61 -0
- pymoo/visualization/fitness_landscape.py +128 -0
- pymoo/visualization/heatmap.py +123 -0
- pymoo/visualization/matplotlib.py +61 -0
- pymoo/visualization/pcp.py +121 -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 +296 -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.6.dist-info/METADATA +209 -0
- pymoo-0.6.1.6.dist-info/RECORD +337 -0
- pymoo-0.6.1.6.dist-info/WHEEL +6 -0
- pymoo-0.6.1.6.dist-info/licenses/LICENSE +191 -0
- pymoo-0.6.1.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.algorithms.soo.nonconvex.es import ES
|
|
4
|
+
from pymoo.core.population import Population, calc_cv
|
|
5
|
+
from pymoo.core.survival import Survival
|
|
6
|
+
from pymoo.docs import parse_doc_string
|
|
7
|
+
from pymoo.functions import load_function
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class StochasticRankingSurvival(Survival):
|
|
11
|
+
|
|
12
|
+
def __init__(self, PR):
|
|
13
|
+
super().__init__(filter_infeasible=False)
|
|
14
|
+
self.PR = PR
|
|
15
|
+
|
|
16
|
+
def _do(self, problem, pop, *args, n_survive=None, tcv=None, random_state=None, **kwargs):
|
|
17
|
+
assert problem.n_obj == 1, "This stochastic ranking implementation only works for single-objective problems."
|
|
18
|
+
|
|
19
|
+
F, G = pop.get("F", "G")
|
|
20
|
+
f = F[:, 0]
|
|
21
|
+
|
|
22
|
+
if not problem.has_constraints():
|
|
23
|
+
I = f.argsort()
|
|
24
|
+
|
|
25
|
+
else:
|
|
26
|
+
phi = calc_cv(pop)
|
|
27
|
+
J = np.arange(len(phi))
|
|
28
|
+
I = load_function("stochastic_ranking")(f, phi, self.PR, J, random_state=random_state)
|
|
29
|
+
|
|
30
|
+
return pop[I][:n_survive]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class SRES(ES):
|
|
34
|
+
|
|
35
|
+
def __init__(self, PF=0.45, **kwargs):
|
|
36
|
+
"""
|
|
37
|
+
Stochastic Ranking Evolutionary Strategy (SRES)
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
PF: float
|
|
42
|
+
The stochastic ranking weight for choosing a random decision while doing the modified bubble sort.
|
|
43
|
+
"""
|
|
44
|
+
super().__init__(survival=StochasticRankingSurvival(PF), **kwargs)
|
|
45
|
+
self.PF = PF
|
|
46
|
+
|
|
47
|
+
def _advance(self, infills=None, **kwargs):
|
|
48
|
+
|
|
49
|
+
# if not all solutions suggested by infill() are evaluated we create a more semi (mu+lambda) algorithm
|
|
50
|
+
if len(infills) < self.pop_size:
|
|
51
|
+
infills = Population.merge(infills, self.pop)
|
|
52
|
+
|
|
53
|
+
self.pop = self.survival.do(self.problem, infills, n_survive=self.pop_size)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
parse_doc_string(SRES.__init__)
|
|
File without changes
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.core.algorithm import Algorithm
|
|
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.termination.default import DefaultSingleObjectiveTermination
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ExponentialSearch(Algorithm):
|
|
11
|
+
|
|
12
|
+
def __init__(self, delta=0.05, **kwargs):
|
|
13
|
+
super().__init__(**kwargs)
|
|
14
|
+
self.termination = DefaultSingleObjectiveTermination()
|
|
15
|
+
self.alpha = delta
|
|
16
|
+
self.point = None
|
|
17
|
+
|
|
18
|
+
def _setup(self, problem, x0=None, **kwargs):
|
|
19
|
+
msg = "Only problems with one variable, one objective and no constraints can be solved!"
|
|
20
|
+
assert problem.n_var == 1 and not problem.has_constraints() and problem.n_obj == 1, msg
|
|
21
|
+
self.point = x0
|
|
22
|
+
|
|
23
|
+
def _initialize_infill(self):
|
|
24
|
+
self.step_size = self.alpha
|
|
25
|
+
|
|
26
|
+
if self.point is None:
|
|
27
|
+
return Population.new(X=np.copy(self.problem.xl[None, :]))
|
|
28
|
+
else:
|
|
29
|
+
return Population.create(self.point)
|
|
30
|
+
|
|
31
|
+
def step(self):
|
|
32
|
+
alpha, max_alpha = self.alpha, self.problem.xu[0]
|
|
33
|
+
|
|
34
|
+
if alpha > max_alpha:
|
|
35
|
+
alpha = max_alpha
|
|
36
|
+
|
|
37
|
+
infill = Individual(X=np.array([alpha]))
|
|
38
|
+
self.evaluator.eval(self.problem, infill)
|
|
39
|
+
self.pop = Population.merge(self.pop, infill)[-10:]
|
|
40
|
+
|
|
41
|
+
if is_better(self.point, infill, eps=0.0) or alpha == max_alpha:
|
|
42
|
+
self.termination.force_termination = True
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
self.point = infill
|
|
46
|
+
self.alpha *= 2
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from pymoo.algorithms.base.bracket import BracketSearch
|
|
2
|
+
from pymoo.core.individual import Individual
|
|
3
|
+
from pymoo.core.population import Population
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class GoldenSectionSearch(BracketSearch):
|
|
7
|
+
|
|
8
|
+
def __init__(self, **kwargs):
|
|
9
|
+
super().__init__(**kwargs)
|
|
10
|
+
self.left, self.right = None, None
|
|
11
|
+
self.R = (5 ** 0.5 - 1) / 2
|
|
12
|
+
|
|
13
|
+
def _initialize_infill(self):
|
|
14
|
+
super()._initialize_infill()
|
|
15
|
+
a, b = self.a, self.b
|
|
16
|
+
|
|
17
|
+
# the golden ratio (precomputed constant)
|
|
18
|
+
R = self.R
|
|
19
|
+
|
|
20
|
+
# create the left and right in the interval itself
|
|
21
|
+
c, d = Individual(X=b.X - R * (b.X - a.X)), Individual(X=a.X + R * (b.X - a.X))
|
|
22
|
+
|
|
23
|
+
# create a population with all four individuals
|
|
24
|
+
pop = Population.create(a, c, d, b)
|
|
25
|
+
|
|
26
|
+
self.pop, self.infills = pop, pop
|
|
27
|
+
|
|
28
|
+
return pop
|
|
29
|
+
|
|
30
|
+
def _advance(self, **kwargs):
|
|
31
|
+
|
|
32
|
+
# all the elements in the interval
|
|
33
|
+
a, c, d, b = self.pop
|
|
34
|
+
|
|
35
|
+
# the golden ratio (precomputed constant)
|
|
36
|
+
R = self.R
|
|
37
|
+
|
|
38
|
+
# if the left solution is better than the right
|
|
39
|
+
if c.F[0] < d.F[0]:
|
|
40
|
+
|
|
41
|
+
# make the right to be the new right bound and the left becomes the right
|
|
42
|
+
a, b = a, d
|
|
43
|
+
d = c
|
|
44
|
+
|
|
45
|
+
# create a new left individual and evaluate
|
|
46
|
+
c = Individual(X=b.X - R * (b.X - a.X))
|
|
47
|
+
self.evaluator.eval(self.problem, c, algorithm=self)
|
|
48
|
+
self.infills = c
|
|
49
|
+
|
|
50
|
+
# if the right solution is better than the left
|
|
51
|
+
else:
|
|
52
|
+
|
|
53
|
+
# make the left to be the new left bound and the right becomes the left
|
|
54
|
+
a, b = c, b
|
|
55
|
+
c = d
|
|
56
|
+
|
|
57
|
+
# create a new right individual and evaluate
|
|
58
|
+
d = Individual(X=a.X + R * (b.X - a.X))
|
|
59
|
+
self.evaluator.eval(self.problem, d, algorithm=self)
|
|
60
|
+
self.infills = d
|
|
61
|
+
|
|
62
|
+
# update the population with all the four individuals
|
|
63
|
+
self.pop = Population.create(a, c, d, b)
|
|
64
|
+
|
|
65
|
+
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from pymoo.algorithms.base.bracket import BracketSearch
|
|
2
|
+
from pymoo.core.individual import Individual
|
|
3
|
+
from pymoo.core.population import Population
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def quadr_interp_equ(xa, fa, xb, fb, xc, fc):
|
|
7
|
+
g1 = (fc - fa) / (xc - xa)
|
|
8
|
+
g2 = ((fb - fc) / (xb - xc) - g1) * (xb - xa)
|
|
9
|
+
xd = 0.5 * ((xa - xb) - g1 / g2)
|
|
10
|
+
return xd
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def quadr_interp(a, b, c):
|
|
14
|
+
return Individual(X=quadr_interp_equ(a.X, a.F, b.X, b.F, c.X, c.F))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class QuadraticInterpolationSearch(BracketSearch):
|
|
18
|
+
|
|
19
|
+
def __init__(self, a=None, b=None, **kwargs):
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
7.1.2 Quadratic Interpolation Search
|
|
23
|
+
http://www.mathcs.emory.edu/~haber/math315/chap7.pdf
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
a
|
|
28
|
+
b
|
|
29
|
+
kwargs
|
|
30
|
+
"""
|
|
31
|
+
super().__init__(a, b, **kwargs)
|
|
32
|
+
|
|
33
|
+
def _initialize_infill(self):
|
|
34
|
+
super()._initialize_infill()
|
|
35
|
+
a, b = self.a, self.b
|
|
36
|
+
|
|
37
|
+
# set c to be directly in the middle between the two brackets
|
|
38
|
+
c = Individual(X=(b.X - a.X) / 2)
|
|
39
|
+
|
|
40
|
+
# create a population with all three individuals
|
|
41
|
+
pop = Population.create(a, b, c)
|
|
42
|
+
|
|
43
|
+
return pop
|
|
44
|
+
|
|
45
|
+
def _advance(self, **kwargs):
|
|
46
|
+
|
|
47
|
+
# all the elements in the interval
|
|
48
|
+
a, b, c = self.pop
|
|
49
|
+
|
|
50
|
+
# if this is the case then the function is not convex (which means U shaped)
|
|
51
|
+
if c.F[0] >= a.F[0] or c.F[0] >= b.F[0]:
|
|
52
|
+
|
|
53
|
+
# choose the left side if a smaller than b, or the right side otherwise
|
|
54
|
+
if a.F[0] <= b.F[0]:
|
|
55
|
+
a = c
|
|
56
|
+
else:
|
|
57
|
+
b = c
|
|
58
|
+
|
|
59
|
+
c = Individual(X=(b.X - a.X) / 2)
|
|
60
|
+
self.evaluator.eval(self.problem, c, algorithm=self)
|
|
61
|
+
self.infills = c
|
|
62
|
+
|
|
63
|
+
else:
|
|
64
|
+
|
|
65
|
+
d = quadr_interp(a, b, c)
|
|
66
|
+
self.evaluator.eval(self.problem, d, algorithm=self)
|
|
67
|
+
self.infills = d
|
|
68
|
+
|
|
69
|
+
# swap c and d -> make sure d is always on the right of c -> a, c, d, b
|
|
70
|
+
if c.X[0] > d.X[0]:
|
|
71
|
+
c, d = d, c
|
|
72
|
+
|
|
73
|
+
# if c is better than d, then d becomes the new right bound
|
|
74
|
+
if c.F[0] <= d.F[0]:
|
|
75
|
+
b = d
|
|
76
|
+
|
|
77
|
+
# if d is better than c, then c becomes the new left bound and d the new right bound
|
|
78
|
+
else:
|
|
79
|
+
a, c = c, d
|
|
80
|
+
|
|
81
|
+
self.pop = Population.create(a, b, c)
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.algorithms.base.line import LineSearchProblem
|
|
4
|
+
from pymoo.core.algorithm import Algorithm
|
|
5
|
+
from pymoo.core.evaluator import Evaluator
|
|
6
|
+
from pymoo.core.individual import Individual
|
|
7
|
+
from pymoo.core.solution import SolutionSet
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class WolfeSearch(Algorithm):
|
|
11
|
+
|
|
12
|
+
def __init__(self, c1=1e-4, c2=0.9, max_iter=10, **kwargs):
|
|
13
|
+
|
|
14
|
+
super().__init__(**kwargs)
|
|
15
|
+
self.c1 = c1
|
|
16
|
+
self.c2 = c2
|
|
17
|
+
self.max_iter = max_iter
|
|
18
|
+
|
|
19
|
+
def _setup(self, problem, **kwargs):
|
|
20
|
+
assert isinstance(problem,
|
|
21
|
+
LineSearchProblem), "The wolfe search only purpose is to solve a line search problem!"
|
|
22
|
+
self.pop = SolutionSet.create(problem.point)
|
|
23
|
+
self.opt = self.pop
|
|
24
|
+
|
|
25
|
+
def _set_optimum(self, force=False):
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
def step(self):
|
|
29
|
+
sol = self._infill()
|
|
30
|
+
|
|
31
|
+
self.opt = sol
|
|
32
|
+
self.termination.force_termination = True
|
|
33
|
+
|
|
34
|
+
def _infill(self):
|
|
35
|
+
|
|
36
|
+
problem, evaluator = self.problem, self.evaluator
|
|
37
|
+
evaluator.skip_already_evaluated = False
|
|
38
|
+
|
|
39
|
+
sol, direction = self.problem.point, self.problem.direction
|
|
40
|
+
|
|
41
|
+
# the function value and gradient of the initial solution
|
|
42
|
+
sol.set("alpha", 0.0)
|
|
43
|
+
sol_F, sol_dF = sol.F[0], sol.get("dF")[0]
|
|
44
|
+
|
|
45
|
+
def zoom(alpha_low, alpha_high, max_iter=100):
|
|
46
|
+
|
|
47
|
+
while True:
|
|
48
|
+
|
|
49
|
+
_alpha = (alpha_high.get("alpha") + alpha_low.get("alpha")) / 2
|
|
50
|
+
_point = Individual(X=_alpha)
|
|
51
|
+
evaluator.eval(problem, _point, evaluate_values_of=["F", "CV"])
|
|
52
|
+
|
|
53
|
+
if _point.F[0] > sol_F + self.c1 * _alpha * sol_dF @ direction or _point.F[0] > alpha_low.F[0]:
|
|
54
|
+
alpha_high = _point
|
|
55
|
+
else:
|
|
56
|
+
evaluator.eval(problem, _point, evaluate_values_of=["dF"])
|
|
57
|
+
point_dF = _point.get("dF")[0]
|
|
58
|
+
|
|
59
|
+
if np.abs(point_dF @ direction) <= -self.c2 * sol_dF @ direction:
|
|
60
|
+
return _point
|
|
61
|
+
|
|
62
|
+
if (point_dF @ direction) * (alpha_high.get("alpha") - alpha_low.get("alpha")) >= 0:
|
|
63
|
+
alpha_high = alpha_low
|
|
64
|
+
|
|
65
|
+
alpha_low = _point
|
|
66
|
+
|
|
67
|
+
last = sol
|
|
68
|
+
|
|
69
|
+
alpha = 1.0
|
|
70
|
+
current = Individual(X=alpha)
|
|
71
|
+
|
|
72
|
+
for i in range(1, self.max_iter + 1):
|
|
73
|
+
|
|
74
|
+
# evaluate the solutions
|
|
75
|
+
evaluator.eval(problem, current, evaluate_values_of=["F", "CV"])
|
|
76
|
+
|
|
77
|
+
# get the values from the solution to be used to evaluate the conditions
|
|
78
|
+
F, dF, _F = last.F[0], last.get("dF")[0], current.F[0]
|
|
79
|
+
|
|
80
|
+
# if the wolfe condition is violate we have found our upper bound
|
|
81
|
+
if _F > sol_F + self.c1 * sol_dF @ direction or (i > 1 and F >= _F):
|
|
82
|
+
return zoom(last, current)
|
|
83
|
+
|
|
84
|
+
# for the other condition we need the gradient information
|
|
85
|
+
evaluator.eval(problem, current, evaluate_values_of=["dF"])
|
|
86
|
+
_dF = current.get("dF")[0]
|
|
87
|
+
|
|
88
|
+
if np.abs(_dF @ direction) <= -self.c2 * sol_dF @ direction:
|
|
89
|
+
return current
|
|
90
|
+
|
|
91
|
+
if _dF @ direction >= 0:
|
|
92
|
+
return zoom(current, last)
|
|
93
|
+
|
|
94
|
+
alpha = 2 * alpha
|
|
95
|
+
last = current
|
|
96
|
+
current = Individual(X=alpha)
|
|
97
|
+
|
|
98
|
+
return current
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def wolfe_line_search(problem, sol, direction, c1=1e-4, c2=0.9, max_iter=10, evaluator=None):
|
|
102
|
+
# initialize the evaluator to be used (this will make sure evaluations are counted)
|
|
103
|
+
evaluator = evaluator if evaluator is not None else Evaluator()
|
|
104
|
+
evaluator.skip_already_evaluated = False
|
|
105
|
+
|
|
106
|
+
# the function value and gradient of the initial solution
|
|
107
|
+
sol.set("alpha", 0.0)
|
|
108
|
+
sol_F, sol_dF = sol.F[0], sol.get("dF")[0]
|
|
109
|
+
|
|
110
|
+
def zoom(alpha_low, alpha_high, max_iter=100):
|
|
111
|
+
|
|
112
|
+
while True:
|
|
113
|
+
|
|
114
|
+
_alpha = (alpha_high.get("alpha") + alpha_low.get("alpha")) / 2
|
|
115
|
+
_point = Individual(X=sol.X + _alpha * direction, alpha=_alpha)
|
|
116
|
+
evaluator.eval(problem, _point, evaluate_values_of=["F", "CV"])
|
|
117
|
+
|
|
118
|
+
if _point.F[0] > sol_F + c1 * _alpha * sol_dF @ direction or _point.F[0] > alpha_low.F[0]:
|
|
119
|
+
alpha_high = _point
|
|
120
|
+
else:
|
|
121
|
+
evaluator.eval(problem, _point, evaluate_values_of=["dF"])
|
|
122
|
+
point_dF = _point.get("dF")[0]
|
|
123
|
+
|
|
124
|
+
if np.abs(point_dF @ direction) <= -c2 * sol_dF @ direction:
|
|
125
|
+
return _point
|
|
126
|
+
|
|
127
|
+
if (point_dF @ direction) * (alpha_high.get("alpha") - alpha_low.get("alpha")) >= 0:
|
|
128
|
+
alpha_high = alpha_low
|
|
129
|
+
|
|
130
|
+
alpha_low = _point
|
|
131
|
+
|
|
132
|
+
last = sol
|
|
133
|
+
|
|
134
|
+
alpha = 1.0
|
|
135
|
+
current = Individual(X=sol.X + alpha * direction, alpha=alpha)
|
|
136
|
+
|
|
137
|
+
for i in range(1, max_iter + 1):
|
|
138
|
+
|
|
139
|
+
# evaluate the solutions
|
|
140
|
+
evaluator.eval(problem, current, evaluate_values_of=["F", "CV"])
|
|
141
|
+
|
|
142
|
+
# get the values from the solution to be used to evaluate the conditions
|
|
143
|
+
F, dF, _F = last.F[0], last.get("dF")[0], current.F[0]
|
|
144
|
+
|
|
145
|
+
# if the wolfe condition is violate we have found our upper bound
|
|
146
|
+
if _F > sol_F + c1 * sol_dF @ direction or (i > 1 and F >= _F):
|
|
147
|
+
return zoom(last, current)
|
|
148
|
+
|
|
149
|
+
# for the other condition we need the gradient information
|
|
150
|
+
evaluator.eval(problem, current, evaluate_values_of=["dF"])
|
|
151
|
+
_dF = current.get("dF")[0]
|
|
152
|
+
|
|
153
|
+
if np.abs(_dF @ direction) <= -c2 * sol_dF @ direction:
|
|
154
|
+
return current
|
|
155
|
+
|
|
156
|
+
if _dF @ direction >= 0:
|
|
157
|
+
return zoom(current, last)
|
|
158
|
+
|
|
159
|
+
alpha = 2 * alpha
|
|
160
|
+
last = current
|
|
161
|
+
current = Individual(X=sol.X + alpha * direction, alpha=alpha)
|
|
162
|
+
|
|
163
|
+
return current
|
pymoo/config.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from os.path import dirname, realpath
|
|
2
|
+
|
|
3
|
+
from pymoo.version import __version__
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Config:
|
|
7
|
+
"""
|
|
8
|
+
The configuration of this package in general providing the place
|
|
9
|
+
for declaring global variables.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
# the root directory where the package is located at
|
|
13
|
+
root = dirname(realpath(__file__))
|
|
14
|
+
|
|
15
|
+
warnings = {
|
|
16
|
+
"not_compiled": True
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# whether a warning should be printed if compiled modules are not available
|
|
20
|
+
show_compile_hint = True
|
|
21
|
+
|
|
22
|
+
# whether when import a file the doc should be parsed - only activate when creating doc files
|
|
23
|
+
parse_custom_docs = False
|
|
24
|
+
|
|
25
|
+
# a method defining the endpoint to load data remotely - default from GitHub repo
|
|
26
|
+
@classmethod
|
|
27
|
+
def data(cls):
|
|
28
|
+
return f"https://raw.githubusercontent.com/anyoptimization/pymoo-data/main/"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# returns the directory to be used for imports
|
|
32
|
+
def get_pymoo():
|
|
33
|
+
return dirname(Config.root)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from copy import deepcopy
|
|
2
|
+
|
|
3
|
+
from pymoo.core.algorithm import MetaAlgorithm
|
|
4
|
+
from pymoo.core.evaluator import Evaluator
|
|
5
|
+
from pymoo.core.individual import Individual
|
|
6
|
+
from pymoo.core.population import Population
|
|
7
|
+
from pymoo.core.problem import Problem
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AttachConfigEvaluator(Evaluator):
|
|
11
|
+
|
|
12
|
+
def __init__(self, wrapped, config):
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.wrapped = wrapped
|
|
15
|
+
self.config = config
|
|
16
|
+
|
|
17
|
+
# Copy all attributes from wrapped evaluator
|
|
18
|
+
for attr_name in ['evaluate_values_of', 'skip_already_evaluated', 'callback', 'n_eval']:
|
|
19
|
+
if hasattr(wrapped, attr_name):
|
|
20
|
+
setattr(self, attr_name, getattr(wrapped, attr_name))
|
|
21
|
+
|
|
22
|
+
def eval(self, problem: Problem, pop: Population, **kwargs):
|
|
23
|
+
pop = self.wrapped.eval(problem, pop, **kwargs)
|
|
24
|
+
pop.apply(lambda ind: ind.set("config", self.config))
|
|
25
|
+
return pop
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def copy_to_dict(src, dest):
|
|
29
|
+
dest.clear()
|
|
30
|
+
dest.update(**src)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class AdaptiveConstraintHandling(MetaAlgorithm):
|
|
34
|
+
|
|
35
|
+
def __init__(self, algorithm):
|
|
36
|
+
super().__init__(algorithm)
|
|
37
|
+
|
|
38
|
+
self.config = Individual.default_config()
|
|
39
|
+
self.config["cache"] = False
|
|
40
|
+
|
|
41
|
+
self.default_config = deepcopy(self.config)
|
|
42
|
+
self.adapted_config = deepcopy(self.config)
|
|
43
|
+
|
|
44
|
+
def _setup(self, _, **kwargs):
|
|
45
|
+
self.evaluator = AttachConfigEvaluator(self.evaluator, self.config)
|
|
46
|
+
|
|
47
|
+
def _adapt_constraint_handling(self, config, infills=None, **kwargs):
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
def _initialize_advance(self, infills=None, **kwargs):
|
|
51
|
+
copy_to_dict(self.adapted_config, self.config)
|
|
52
|
+
super()._initialize_advance(infills=infills, **kwargs)
|
|
53
|
+
copy_to_dict(self.default_config, self.config)
|
|
54
|
+
|
|
55
|
+
def _advance(self, infills=None, **kwargs):
|
|
56
|
+
copy_to_dict(self.adapted_config, self.config)
|
|
57
|
+
super()._advance(infills=infills, **kwargs)
|
|
58
|
+
copy_to_dict(self.default_config, self.config)
|
|
59
|
+
|
|
60
|
+
self._adapt_constraint_handling(self.adapted_config, infills=infills, **kwargs)
|
|
61
|
+
|
|
62
|
+
def _infill(self):
|
|
63
|
+
copy_to_dict(self.adapted_config, self.config)
|
|
64
|
+
pop = super()._infill()
|
|
65
|
+
copy_to_dict(self.default_config, self.config)
|
|
66
|
+
return pop
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import pymoo.gradient.toolbox as anp
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from pymoo.core.individual import calc_cv
|
|
5
|
+
from pymoo.core.meta import Meta
|
|
6
|
+
from pymoo.core.problem import Problem
|
|
7
|
+
from pymoo.util.misc import from_dict
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ConstraintsAsObjective(Meta, Problem):
|
|
11
|
+
|
|
12
|
+
def __init__(self,
|
|
13
|
+
problem,
|
|
14
|
+
config=None,
|
|
15
|
+
append=True):
|
|
16
|
+
|
|
17
|
+
super().__init__(problem)
|
|
18
|
+
self.config = config
|
|
19
|
+
self.append = append
|
|
20
|
+
|
|
21
|
+
if append:
|
|
22
|
+
self.n_obj = problem.n_obj + 1
|
|
23
|
+
else:
|
|
24
|
+
self.n_obj = 1
|
|
25
|
+
|
|
26
|
+
self.n_ieq_constr = 0
|
|
27
|
+
self.n_eq_constr = 0
|
|
28
|
+
|
|
29
|
+
def do(self, X, return_values_of, *args, **kwargs):
|
|
30
|
+
out = self.__object__.do(X, return_values_of, *args, **kwargs)
|
|
31
|
+
|
|
32
|
+
# get at the values from the output
|
|
33
|
+
F, G, H = from_dict(out, "F", "G", "H")
|
|
34
|
+
|
|
35
|
+
# store a backup of the values in out
|
|
36
|
+
out["__F__"], out["__G__"], out["__H__"] = F, G, H
|
|
37
|
+
|
|
38
|
+
# calculate the total constraint violation (here normalization shall be already included)
|
|
39
|
+
CV = calc_cv(G=G, H=H, config=self.config)
|
|
40
|
+
|
|
41
|
+
# append the constraint violation as objective
|
|
42
|
+
if self.append:
|
|
43
|
+
out["F"] = anp.column_stack([CV, F])
|
|
44
|
+
else:
|
|
45
|
+
out["F"] = CV
|
|
46
|
+
|
|
47
|
+
del out["G"]
|
|
48
|
+
del out["H"]
|
|
49
|
+
|
|
50
|
+
return out
|
|
51
|
+
|
|
52
|
+
def pareto_front(self, *args, **kwargs):
|
|
53
|
+
pf = super().pareto_front(*args, **kwargs)
|
|
54
|
+
if pf is not None:
|
|
55
|
+
pf = np.column_stack([np.zeros(len(pf)), pf])
|
|
56
|
+
return pf
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from pymoo.core.individual import calc_cv
|
|
2
|
+
from pymoo.core.meta import Meta
|
|
3
|
+
from pymoo.core.problem import Problem
|
|
4
|
+
from pymoo.util.misc import from_dict
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ConstraintsAsPenalty(Meta, Problem):
|
|
10
|
+
|
|
11
|
+
def __init__(self,
|
|
12
|
+
problem,
|
|
13
|
+
penalty: float = 0.1):
|
|
14
|
+
super().__init__(problem)
|
|
15
|
+
|
|
16
|
+
# the amount of penalty to add for this type
|
|
17
|
+
self.penalty = penalty
|
|
18
|
+
|
|
19
|
+
# set ieq and eq to zero (because it became now a penalty)
|
|
20
|
+
self.n_ieq_constr = 0
|
|
21
|
+
self.n_eq_constr = 0
|
|
22
|
+
|
|
23
|
+
def do(self, X, return_values_of, *args, **kwargs):
|
|
24
|
+
out = self.__object__.do(X, return_values_of, *args, **kwargs)
|
|
25
|
+
|
|
26
|
+
# get at the values from the output
|
|
27
|
+
F, G, H = from_dict(out, "F", "G", "H")
|
|
28
|
+
|
|
29
|
+
# store a backup of the values in out
|
|
30
|
+
out["__F__"], out["__G__"], out["__H__"] = F, G, H
|
|
31
|
+
|
|
32
|
+
# calculate the total constraint violation (here normalization shall be already included)
|
|
33
|
+
CV = calc_cv(G=G, H=H)
|
|
34
|
+
|
|
35
|
+
# set the penalized objective values
|
|
36
|
+
out["F"] = F + self.penalty * np.reshape(CV, F.shape)
|
|
37
|
+
|
|
38
|
+
del out["G"]
|
|
39
|
+
del out["H"]
|
|
40
|
+
|
|
41
|
+
return out
|
pymoo/constraints/eps.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.constraints.adaptive import AdaptiveConstraintHandling
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AdaptiveEpsilonConstraintHandling(AdaptiveConstraintHandling):
|
|
7
|
+
|
|
8
|
+
def __init__(self, algorithm, perc_eps_until=0.5):
|
|
9
|
+
super().__init__(algorithm)
|
|
10
|
+
self.perc_eps_until = perc_eps_until
|
|
11
|
+
self.max_cv = None
|
|
12
|
+
|
|
13
|
+
def _adapt_constraint_handling(self, config, **kwargs):
|
|
14
|
+
t = self.termination.perc
|
|
15
|
+
alpha = np.maximum(0.0, 1 - 1 / self.perc_eps_until * t)
|
|
16
|
+
eps = alpha * self.max_cv
|
|
17
|
+
|
|
18
|
+
config["cv_eps"] = eps
|
|
19
|
+
|
|
20
|
+
def _initialize_advance(self, infills=None, **kwargs):
|
|
21
|
+
|
|
22
|
+
# get the average constraint violation in the current generation
|
|
23
|
+
if infills is not None and infills.has("cv"):
|
|
24
|
+
cv = infills.get("cv")
|
|
25
|
+
self.max_cv = np.mean(cv)
|
|
26
|
+
elif self.pop is not None and self.pop.has("cv"):
|
|
27
|
+
# Use current population if available
|
|
28
|
+
cv = self.pop.get("cv")
|
|
29
|
+
self.max_cv = np.mean(cv)
|
|
30
|
+
else:
|
|
31
|
+
# Default value during initialization
|
|
32
|
+
self.max_cv = 1.0
|
|
33
|
+
|
|
34
|
+
return super()._initialize_advance(infills, **kwargs)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
import pymoo.gradient.toolbox as anp
|
|
4
|
+
|
|
5
|
+
from pymoo.core.meta import Meta
|
|
6
|
+
from pymoo.core.problem import Problem
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ConstraintsFromBounds(Meta, Problem):
|
|
10
|
+
|
|
11
|
+
def __init__(self, problem, remove_bonds=False):
|
|
12
|
+
super().__init__(problem)
|
|
13
|
+
self.n_ieq_constr += 2 * self.n_var
|
|
14
|
+
|
|
15
|
+
if remove_bonds:
|
|
16
|
+
self.xl, self.xu = None, None
|
|
17
|
+
|
|
18
|
+
def do(self, X, return_values_of, *args, **kwargs):
|
|
19
|
+
|
|
20
|
+
out = self.__object__.do(X, return_values_of, *args, **kwargs)
|
|
21
|
+
|
|
22
|
+
# get the boundaries for normalization
|
|
23
|
+
xl, xu = self.bounds()
|
|
24
|
+
|
|
25
|
+
# add the boundary constraint if enabled
|
|
26
|
+
_G = anp.column_stack([xl - X, X - xu])
|
|
27
|
+
|
|
28
|
+
out["G"] = anp.column_stack([out["G"], _G])
|
|
29
|
+
|
|
30
|
+
if "dG" in out:
|
|
31
|
+
_dG = np.zeros((len(X), 2 * self.n_var, self.n_var))
|
|
32
|
+
_dG[:, :self.n_var, :] = - np.eye(self.n_var)
|
|
33
|
+
_dG[:, self.n_var:, :] = np.eye(self.n_var)
|
|
34
|
+
out["dG"] = np.column_stack([out["dG"], _dG])
|
|
35
|
+
|
|
36
|
+
return out
|
pymoo/core/__init__.py
ADDED
|
File without changes
|