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,232 @@
|
|
|
1
|
+
|
|
2
|
+
from pymoo.core.termination import NoTermination
|
|
3
|
+
from pymoo.termination.max_eval import MaximumFunctionCallTermination
|
|
4
|
+
from pymoo.util.display.single import SingleObjectiveOutput
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
from scipy.optimize import minimize as scipy_minimize, NonlinearConstraint, LinearConstraint
|
|
8
|
+
except:
|
|
9
|
+
raise Exception("Please install SciPy: pip install scipy")
|
|
10
|
+
|
|
11
|
+
import warnings
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
|
|
15
|
+
from pymoo.algorithms.base.local import LocalSearch
|
|
16
|
+
from pymoo.core.individual import Individual, constr_to_cv
|
|
17
|
+
from pymoo.core.population import Population
|
|
18
|
+
|
|
19
|
+
from pymoo.termination.max_gen import MaximumGenerationTermination
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
24
|
+
# Interface
|
|
25
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Optimizer(LocalSearch):
|
|
29
|
+
|
|
30
|
+
def __init__(self, method, with_bounds=False, with_constr=False, require_jac=False,
|
|
31
|
+
use_bounds=True, use_constr=True, estm_gradients=True, disp=False, show_warnings=False, **kwargs):
|
|
32
|
+
|
|
33
|
+
super().__init__(output=SingleObjectiveOutput(), **kwargs)
|
|
34
|
+
|
|
35
|
+
self.method, self.with_bounds, self.with_constr, self.require_jac = method, with_bounds, with_constr, require_jac
|
|
36
|
+
self.show_warnings = show_warnings
|
|
37
|
+
self.use_bounds = use_bounds
|
|
38
|
+
self.use_constr = use_constr
|
|
39
|
+
self.estm_gradients = estm_gradients
|
|
40
|
+
|
|
41
|
+
self.options = {
|
|
42
|
+
'maxiter': int(1e8), # because of C code interfacing this can not be inf
|
|
43
|
+
'disp': disp}
|
|
44
|
+
|
|
45
|
+
def _setup(self, problem, **kwargs):
|
|
46
|
+
if isinstance(self.termination, MaximumGenerationTermination):
|
|
47
|
+
self.options["maxiter"] = self.termination.n_max_gen
|
|
48
|
+
elif isinstance(self.termination, MaximumFunctionCallTermination):
|
|
49
|
+
self.options["maxfev"] = self.termination.n_max_evals
|
|
50
|
+
|
|
51
|
+
self.termination = NoTermination()
|
|
52
|
+
self.return_least_infeasible = True
|
|
53
|
+
|
|
54
|
+
def _advance(self, **kwargs):
|
|
55
|
+
problem, evaluator = self.problem, self.evaluator
|
|
56
|
+
|
|
57
|
+
# add the box constraints defined in the problem
|
|
58
|
+
bounds = None
|
|
59
|
+
if self.use_bounds:
|
|
60
|
+
|
|
61
|
+
xl, xu = self.problem.bounds()
|
|
62
|
+
if self.with_bounds:
|
|
63
|
+
bounds = np.column_stack([xl, xu])
|
|
64
|
+
else:
|
|
65
|
+
if xl is not None or xu is not None:
|
|
66
|
+
raise Exception(f"Error: Boundary constraints can not be handled by {self.method}")
|
|
67
|
+
|
|
68
|
+
# define the actual constraints if supported by the algorithm
|
|
69
|
+
constr = []
|
|
70
|
+
if self.use_constr:
|
|
71
|
+
|
|
72
|
+
constr = [LinearConstraint(np.eye(self.problem.n_var), xl, xu)]
|
|
73
|
+
|
|
74
|
+
if problem.has_constraints():
|
|
75
|
+
|
|
76
|
+
if self.with_constr:
|
|
77
|
+
def fun_constr(x):
|
|
78
|
+
g = problem.evaluate(x, return_values_of=["G"])
|
|
79
|
+
cv = constr_to_cv(g)
|
|
80
|
+
return cv
|
|
81
|
+
|
|
82
|
+
non_lin_constr = NonlinearConstraint(fun_constr, -float("inf"), 0)
|
|
83
|
+
|
|
84
|
+
constr.append(non_lin_constr)
|
|
85
|
+
|
|
86
|
+
else:
|
|
87
|
+
raise Exception(f"Error: Constraint handling is not supported by {self.method}")
|
|
88
|
+
|
|
89
|
+
# the objective function to be optimized and add gradients if available
|
|
90
|
+
if self.estm_gradients:
|
|
91
|
+
jac = None
|
|
92
|
+
|
|
93
|
+
def fun_obj(x):
|
|
94
|
+
f = problem.evaluate(x, return_values_of=["F"])[0]
|
|
95
|
+
evaluator.n_eval += 1
|
|
96
|
+
return f
|
|
97
|
+
|
|
98
|
+
else:
|
|
99
|
+
jac = True
|
|
100
|
+
|
|
101
|
+
def fun_obj(x):
|
|
102
|
+
f, df = problem.evaluate(x, return_values_of=["F", "dF"])
|
|
103
|
+
|
|
104
|
+
if df is None:
|
|
105
|
+
raise Exception("If the gradient shall not be estimate, please set out['dF'] in _evaluate. ")
|
|
106
|
+
|
|
107
|
+
evaluator.n_eval += 1
|
|
108
|
+
return f[0], df[0]
|
|
109
|
+
|
|
110
|
+
# the arguments to be used
|
|
111
|
+
kwargs = dict(args=(), method=self.method, bounds=bounds, constraints=constr, jac=jac, options=self.options)
|
|
112
|
+
|
|
113
|
+
# the starting solution found by sampling beforehand
|
|
114
|
+
x0 = self.opt[0].X
|
|
115
|
+
|
|
116
|
+
# actually run the optimization
|
|
117
|
+
if not self.show_warnings:
|
|
118
|
+
warnings.simplefilter("ignore")
|
|
119
|
+
|
|
120
|
+
res = scipy_minimize(fun_obj, x0, **kwargs)
|
|
121
|
+
|
|
122
|
+
opt = Population.create(Individual(X=res.x))
|
|
123
|
+
self.evaluator.eval(self.problem, opt, algorithm=self)
|
|
124
|
+
|
|
125
|
+
self.pop, self.off = opt, opt
|
|
126
|
+
|
|
127
|
+
self.termination.force_termination = True
|
|
128
|
+
|
|
129
|
+
if hasattr("res", "nit"):
|
|
130
|
+
self.n_gen = res.nit + 1
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
134
|
+
# Object Oriented Interface
|
|
135
|
+
# ---------------------------------------------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
# +++++++++++++++++++++++++++++++++++++++++
|
|
138
|
+
# UNCONSTRAINED
|
|
139
|
+
# +++++++++++++++++++++++++++++++++++++++++
|
|
140
|
+
|
|
141
|
+
class NelderMead(Optimizer):
|
|
142
|
+
|
|
143
|
+
def __init__(self, **kwargs):
|
|
144
|
+
super().__init__("Nelder-Mead", **kwargs)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class CG(Optimizer):
|
|
148
|
+
|
|
149
|
+
def __init__(self, **kwargs):
|
|
150
|
+
super().__init__("CG", require_jac=True, **kwargs)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class NewtonCG(Optimizer):
|
|
154
|
+
|
|
155
|
+
def __init__(self, **kwargs):
|
|
156
|
+
super().__init__("Newton-CG", require_jac=True, **kwargs)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class BFGS(Optimizer):
|
|
160
|
+
|
|
161
|
+
def __init__(self, **kwargs):
|
|
162
|
+
super().__init__("BFGS", **kwargs)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class Powell(Optimizer):
|
|
166
|
+
|
|
167
|
+
def __init__(self, **kwargs):
|
|
168
|
+
super().__init__("Powell", **kwargs)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class Dogleg(Optimizer):
|
|
172
|
+
|
|
173
|
+
def __init__(self, **kwargs):
|
|
174
|
+
super().__init__("dogleg", require_jac=True, **kwargs)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class TrustNCG(Optimizer):
|
|
178
|
+
|
|
179
|
+
def __init__(self, **kwargs):
|
|
180
|
+
super().__init__("trust-ncg", require_jac=True, **kwargs)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class TrustExact(Optimizer):
|
|
184
|
+
|
|
185
|
+
def __init__(self, **kwargs):
|
|
186
|
+
super().__init__("trust-exact", require_jac=True, **kwargs)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class TrustKrylov(Optimizer):
|
|
190
|
+
|
|
191
|
+
def __init__(self, **kwargs):
|
|
192
|
+
super().__init__("trust-krylov", require_jac=True, **kwargs)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# +++++++++++++++++++++++++++++++++++++++++
|
|
196
|
+
# BOX CONSTRAINS
|
|
197
|
+
# +++++++++++++++++++++++++++++++++++++++++
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class LBFGSB(Optimizer):
|
|
201
|
+
|
|
202
|
+
def __init__(self, **kwargs):
|
|
203
|
+
super().__init__("L-BFGS-B", with_bounds=True, **kwargs)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class TNC(Optimizer):
|
|
207
|
+
|
|
208
|
+
def __init__(self, **kwargs):
|
|
209
|
+
super().__init__("TNC", with_bounds=True, **kwargs)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
# +++++++++++++++++++++++++++++++++++++++++
|
|
213
|
+
# NON-LINEAR CONSTRAINTS
|
|
214
|
+
# +++++++++++++++++++++++++++++++++++++++++
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class COBYLA(Optimizer):
|
|
218
|
+
|
|
219
|
+
def __init__(self, **kwargs):
|
|
220
|
+
super().__init__("COBYLA", with_bounds=False, with_constr=True, **kwargs)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class SLSQP(Optimizer):
|
|
224
|
+
|
|
225
|
+
def __init__(self, **kwargs):
|
|
226
|
+
super().__init__("SLSQP", with_bounds=True, with_constr=True, **kwargs)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class TrustConstr(Optimizer):
|
|
230
|
+
|
|
231
|
+
def __init__(self, **kwargs):
|
|
232
|
+
super().__init__("trust-constr", with_bounds=True, with_constr=True, **kwargs)
|
pymoo/version.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.6.1.6"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Visualization module for pymoo.
|
|
3
|
+
|
|
4
|
+
All matplotlib functionality should be accessed through:
|
|
5
|
+
from pymoo.visualization.matplotlib import plt, patches, etc.
|
|
6
|
+
|
|
7
|
+
This ensures proper handling when matplotlib is not available.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Import centralized matplotlib module
|
|
11
|
+
from . import matplotlib
|
|
12
|
+
|
|
13
|
+
__all__ = ["heatmap",
|
|
14
|
+
"pcp",
|
|
15
|
+
"petal",
|
|
16
|
+
"radar",
|
|
17
|
+
"radviz",
|
|
18
|
+
"scatter",
|
|
19
|
+
"star_coordinate",
|
|
20
|
+
"matplotlib"
|
|
21
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from pymoo.visualization.fitness_landscape import FitnessLandscape
|
|
2
|
+
from pymoo.visualization.video.callback_video import AnimationCallback
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class PSOAnimation(AnimationCallback):
|
|
6
|
+
|
|
7
|
+
def __init__(self,
|
|
8
|
+
nth_gen=1,
|
|
9
|
+
n_samples_for_surface=200,
|
|
10
|
+
dpi=200,
|
|
11
|
+
**kwargs):
|
|
12
|
+
|
|
13
|
+
super().__init__(nth_gen=nth_gen, dpi=dpi, **kwargs)
|
|
14
|
+
self.n_samples_for_surface = n_samples_for_surface
|
|
15
|
+
self.last_pop = None
|
|
16
|
+
|
|
17
|
+
def do(self, problem, algorithm, **kwargs):
|
|
18
|
+
from pymoo.visualization.matplotlib import plt
|
|
19
|
+
|
|
20
|
+
if problem.n_var != 2 or problem.n_obj != 1:
|
|
21
|
+
raise Exception(
|
|
22
|
+
"This visualization can only be used for problems with two variables and one objective!")
|
|
23
|
+
|
|
24
|
+
# draw the problem surface
|
|
25
|
+
FitnessLandscape(problem,
|
|
26
|
+
_type="contour",
|
|
27
|
+
kwargs_contour=dict(alpha=0.3),
|
|
28
|
+
n_samples=self.n_samples_for_surface,
|
|
29
|
+
close_on_destroy=False).do()
|
|
30
|
+
|
|
31
|
+
# get the population
|
|
32
|
+
off = algorithm.particles
|
|
33
|
+
pop = algorithm.particles if self.last_pop is None else self.last_pop
|
|
34
|
+
pbest = algorithm.pop
|
|
35
|
+
|
|
36
|
+
for i in range(len(pop)):
|
|
37
|
+
plt.plot([off[i].X[0], pop[i].X[0]], [off[i].X[1], pop[i].X[1]], color="blue", alpha=0.5)
|
|
38
|
+
plt.plot([pbest[i].X[0], pop[i].X[0]], [pbest[i].X[1], pop[i].X[1]], color="red", alpha=0.5)
|
|
39
|
+
plt.plot([pbest[i].X[0], off[i].X[0]], [pbest[i].X[1], off[i].X[1]], color="red", alpha=0.5)
|
|
40
|
+
|
|
41
|
+
X, F, CV = pbest.get("X", "F", "CV")
|
|
42
|
+
plt.scatter(X[:, 0], X[:, 1], edgecolors="red", marker="*", s=70, facecolors='none', label="pbest")
|
|
43
|
+
|
|
44
|
+
X, F, CV = off.get("X", "F", "CV")
|
|
45
|
+
plt.scatter(X[:, 0], X[:, 1], color="blue", marker="o", s=30, label="particle")
|
|
46
|
+
|
|
47
|
+
X, F, CV = pop.get("X", "F", "CV")
|
|
48
|
+
plt.scatter(X[:, 0], X[:, 1], color="blue", marker="o", s=30, alpha=0.5)
|
|
49
|
+
|
|
50
|
+
opt = algorithm.opt
|
|
51
|
+
X, F, CV = opt.get("X", "F", "CV")
|
|
52
|
+
plt.scatter(X[:, 0], X[:, 1], color="black", marker="x", s=100, label="gbest")
|
|
53
|
+
|
|
54
|
+
xl, xu = problem.bounds()
|
|
55
|
+
plt.xlim(xl[0], xu[0])
|
|
56
|
+
plt.ylim(xl[1], xu[1])
|
|
57
|
+
|
|
58
|
+
plt.title(f"Generation: %s \nf: %.5E" % (algorithm.n_gen, opt[0].F[0]))
|
|
59
|
+
plt.legend()
|
|
60
|
+
|
|
61
|
+
self.last_pop = off.copy(deep=True)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
import pymoo.visualization.util
|
|
4
|
+
from pymoo.docs import parse_doc_string
|
|
5
|
+
from pymoo.core.plot import Plot
|
|
6
|
+
from pymoo.util.misc import all_combinations
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FitnessLandscape(Plot):
|
|
10
|
+
|
|
11
|
+
def __init__(self,
|
|
12
|
+
problem,
|
|
13
|
+
_type="surface+contour",
|
|
14
|
+
n_samples=100,
|
|
15
|
+
colorbar=False,
|
|
16
|
+
contour_levels=30,
|
|
17
|
+
kwargs_surface=None,
|
|
18
|
+
kwargs_contour=None,
|
|
19
|
+
kwargs_contour_labels=None,
|
|
20
|
+
**kwargs):
|
|
21
|
+
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
Fitness Landscape
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------------
|
|
28
|
+
|
|
29
|
+
problem : The problem to be plotted
|
|
30
|
+
_type : str
|
|
31
|
+
Either "contour", "surface" or "contour+surface"
|
|
32
|
+
labels : {labels}
|
|
33
|
+
|
|
34
|
+
Other Parameters
|
|
35
|
+
----------------
|
|
36
|
+
|
|
37
|
+
figsize : {figsize}
|
|
38
|
+
title : {title}
|
|
39
|
+
legend : {legend}
|
|
40
|
+
tight_layout : {tight_layout}
|
|
41
|
+
cmap : {cmap}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
FitnessLandscape : :class:`~pymoo.core.analytics.visualization.fitness_landscape.FitnessLandscape`
|
|
47
|
+
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
super().__init__(**kwargs)
|
|
51
|
+
self.problem = problem
|
|
52
|
+
self.n_samples = n_samples
|
|
53
|
+
self._type = _type
|
|
54
|
+
self.colorbar = colorbar
|
|
55
|
+
|
|
56
|
+
self.contour_levels = contour_levels
|
|
57
|
+
|
|
58
|
+
self.kwargs_surface = kwargs_surface
|
|
59
|
+
if self.kwargs_surface is None:
|
|
60
|
+
self.kwargs_surface = dict(cmap="summer", rstride=1, cstride=1)
|
|
61
|
+
|
|
62
|
+
self.kwargs_contour = kwargs_contour
|
|
63
|
+
if self.kwargs_contour is None:
|
|
64
|
+
self.kwargs_contour = dict(linestyles="solid", offset=-1)
|
|
65
|
+
|
|
66
|
+
self.kwargs_contour_labels = kwargs_contour_labels
|
|
67
|
+
|
|
68
|
+
def _do(self):
|
|
69
|
+
|
|
70
|
+
problem, n_samples, _type = self.problem, self.n_samples, self._type
|
|
71
|
+
|
|
72
|
+
if problem.n_var == 1 and problem.n_obj == 1:
|
|
73
|
+
|
|
74
|
+
self.init_figure()
|
|
75
|
+
|
|
76
|
+
X = np.linspace(problem.xl[0], problem.xu[0], num=n_samples)[:, None]
|
|
77
|
+
Z = problem.evaluate(X, return_values_of=["F"])
|
|
78
|
+
pymoo.visualization.util.plot(X, Z)
|
|
79
|
+
self.ax.set_xlabel("x")
|
|
80
|
+
self.ax.set_ylabel("f(x)")
|
|
81
|
+
|
|
82
|
+
elif problem.n_var == 2 and problem.n_obj == 1:
|
|
83
|
+
|
|
84
|
+
A = np.linspace(problem.xl[0], problem.xu[0], n_samples)
|
|
85
|
+
B = np.linspace(problem.xl[1], problem.xu[1], n_samples)
|
|
86
|
+
X = all_combinations(A, B)
|
|
87
|
+
|
|
88
|
+
F = np.reshape(problem.evaluate(X, return_values_of=["F"]), (n_samples, n_samples))
|
|
89
|
+
|
|
90
|
+
_X = X[:, 0].reshape((n_samples, n_samples))
|
|
91
|
+
_Y = X[:, 1].reshape((n_samples, n_samples))
|
|
92
|
+
_Z = F.reshape((n_samples, n_samples))
|
|
93
|
+
|
|
94
|
+
def plot_surface():
|
|
95
|
+
surf = self.ax.plot_surface(_X, _Y, _Z, **self.kwargs_surface)
|
|
96
|
+
|
|
97
|
+
if self.colorbar:
|
|
98
|
+
self.fig.colorbar(surf)
|
|
99
|
+
|
|
100
|
+
def plot_contour():
|
|
101
|
+
CS = self.ax.contour(_X, _Y, _Z, self.contour_levels, **self.kwargs_contour)
|
|
102
|
+
if self.kwargs_contour_labels is not None:
|
|
103
|
+
self.ax.clabel(CS, **self.kwargs_contour_labels)
|
|
104
|
+
|
|
105
|
+
if self.colorbar:
|
|
106
|
+
self.fig.colorbar(CS)
|
|
107
|
+
|
|
108
|
+
if _type == "surface":
|
|
109
|
+
self.init_figure(plot_3D=True)
|
|
110
|
+
plot_surface()
|
|
111
|
+
elif _type == "contour":
|
|
112
|
+
self.init_figure(plot_3D=False)
|
|
113
|
+
|
|
114
|
+
if "offset" in self.kwargs_contour:
|
|
115
|
+
del self.kwargs_contour["offset"]
|
|
116
|
+
|
|
117
|
+
plot_contour()
|
|
118
|
+
elif _type == "surface+contour":
|
|
119
|
+
|
|
120
|
+
self.init_figure(plot_3D=True)
|
|
121
|
+
plot_surface()
|
|
122
|
+
plot_contour()
|
|
123
|
+
|
|
124
|
+
else:
|
|
125
|
+
raise Exception("Only landscapes of problems with one or two variables and one objective can be visualized.")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
parse_doc_string(FitnessLandscape.__init__)
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from pymoo.visualization.util import parse_bounds, normalize
|
|
4
|
+
from pymoo.docs import parse_doc_string
|
|
5
|
+
from pymoo.core.plot import Plot
|
|
6
|
+
from pymoo.util.misc import set_if_none_from_tuples
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Heatmap(Plot):
|
|
10
|
+
|
|
11
|
+
def __init__(self,
|
|
12
|
+
cmap="Blues",
|
|
13
|
+
order_by_objectives=False,
|
|
14
|
+
reverse=True,
|
|
15
|
+
solution_labels=True,
|
|
16
|
+
**kwargs):
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
Heatmap
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
|
|
24
|
+
cmap : str
|
|
25
|
+
The color map to be used.
|
|
26
|
+
|
|
27
|
+
order_by_objectives : int or list
|
|
28
|
+
Whether the result should be ordered by an objective. If false no order.
|
|
29
|
+
Otherwise, either supply just the objective or a list. (it is lexicographically sorted).
|
|
30
|
+
|
|
31
|
+
reverse : bool
|
|
32
|
+
If true large values are white and small values the corresponding color. Otherwise, the other way around.
|
|
33
|
+
|
|
34
|
+
solution_labels : bool or list
|
|
35
|
+
If False no labels are plotted in the y axis. If true just the corresponding index. Otherwise, the label provided.
|
|
36
|
+
|
|
37
|
+
bounds : {bounds}
|
|
38
|
+
|
|
39
|
+
labels : {labels}
|
|
40
|
+
|
|
41
|
+
Other Parameters
|
|
42
|
+
----------------
|
|
43
|
+
|
|
44
|
+
figsize : {figsize}
|
|
45
|
+
title : {title}
|
|
46
|
+
legend : {legend}
|
|
47
|
+
tight_layout : {tight_layout}
|
|
48
|
+
cmap : {cmap}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
super().__init__(cmap=cmap, reverse=reverse, **kwargs)
|
|
54
|
+
self.order_by_objectives = order_by_objectives
|
|
55
|
+
self.solution_labels = solution_labels
|
|
56
|
+
|
|
57
|
+
# set default style
|
|
58
|
+
set_if_none_from_tuples(self.axis_style, ("interpolation", "nearest"), ("vmin", 0), ("vmax", 1))
|
|
59
|
+
|
|
60
|
+
def _do(self):
|
|
61
|
+
|
|
62
|
+
if len(self.to_plot) != 1:
|
|
63
|
+
raise Exception("Only one element can be added to a heatmap.")
|
|
64
|
+
|
|
65
|
+
# initial a figure with a single plot
|
|
66
|
+
self.init_figure()
|
|
67
|
+
|
|
68
|
+
# normalize the input
|
|
69
|
+
bounds = parse_bounds(self.bounds, self.n_dim)
|
|
70
|
+
to_plot_norm = normalize(self.to_plot, bounds, reverse=self.reverse)
|
|
71
|
+
(F, kwargs) = to_plot_norm[0]
|
|
72
|
+
|
|
73
|
+
# dot the sorting if required
|
|
74
|
+
if self.order_by_objectives is not None and self.order_by_objectives is not False:
|
|
75
|
+
|
|
76
|
+
if isinstance(self.order_by_objectives, list) and len(self.order_by_objectives) == self.n_dim:
|
|
77
|
+
L = self.order_by_objectives
|
|
78
|
+
elif isinstance(self.order_by_objectives, int):
|
|
79
|
+
L = [i for i in range(F.shape[1]) if i != self.order_by_objectives]
|
|
80
|
+
L.insert(0, self.order_by_objectives)
|
|
81
|
+
else:
|
|
82
|
+
L = range(self.n_dim)
|
|
83
|
+
|
|
84
|
+
_F = [F[:, j] for j in L]
|
|
85
|
+
I = np.lexsort(_F[::-1])
|
|
86
|
+
else:
|
|
87
|
+
I = np.arange(len(F))
|
|
88
|
+
|
|
89
|
+
# plot the data
|
|
90
|
+
self.ax.imshow(F[I], cmap=self.cmap, **self.axis_style)
|
|
91
|
+
|
|
92
|
+
# set the x ticks and labels
|
|
93
|
+
self.ax.set_xticks(np.arange(self.n_dim))
|
|
94
|
+
self.ax.set_xticklabels(self.get_labels())
|
|
95
|
+
|
|
96
|
+
# no solution labels should be used
|
|
97
|
+
if self.solution_labels is None:
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
# if true, just use a number for each solution
|
|
101
|
+
elif isinstance(self.solution_labels, bool) and self.solution_labels:
|
|
102
|
+
self.solution_labels = np.arange(len(F)) + 1
|
|
103
|
+
|
|
104
|
+
# otherwise, use directly the label provided
|
|
105
|
+
else:
|
|
106
|
+
if len(self.solution_labels) != len(F):
|
|
107
|
+
raise Exception(
|
|
108
|
+
"The labels provided for each solution must be equal to the number of solutions being plotted.")
|
|
109
|
+
|
|
110
|
+
if self.solution_labels is None:
|
|
111
|
+
self.ax.set_yticks([])
|
|
112
|
+
self.ax.set_yticklabels([])
|
|
113
|
+
|
|
114
|
+
else:
|
|
115
|
+
|
|
116
|
+
# for ordered by objective apply it to labels
|
|
117
|
+
self.solution_labels = [self.solution_labels[i] for i in I]
|
|
118
|
+
|
|
119
|
+
self.ax.set_yticks(np.arange(len(F)))
|
|
120
|
+
self.ax.set_yticklabels(self.solution_labels)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
parse_doc_string(Heatmap.__init__)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Centralized matplotlib imports for pymoo visualization.
|
|
3
|
+
|
|
4
|
+
This module provides a single point of entry for all matplotlib functionality,
|
|
5
|
+
with graceful handling when matplotlib is not available.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
# Try to import matplotlib and related modules
|
|
9
|
+
try:
|
|
10
|
+
import matplotlib
|
|
11
|
+
import matplotlib.pyplot as plt
|
|
12
|
+
import matplotlib.patches as patches
|
|
13
|
+
import matplotlib.colors as colors
|
|
14
|
+
import matplotlib.cm as cm
|
|
15
|
+
from matplotlib import animation
|
|
16
|
+
from matplotlib.collections import LineCollection, PatchCollection
|
|
17
|
+
from matplotlib.colors import ListedColormap
|
|
18
|
+
|
|
19
|
+
_MATPLOTLIB_AVAILABLE = True
|
|
20
|
+
|
|
21
|
+
# Export all commonly used matplotlib objects
|
|
22
|
+
__all__ = [
|
|
23
|
+
'matplotlib', 'plt', 'patches', 'colors', 'cm', 'animation',
|
|
24
|
+
'LineCollection', 'PatchCollection', 'ListedColormap', 'is_available'
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
except ImportError:
|
|
28
|
+
_MATPLOTLIB_AVAILABLE = False
|
|
29
|
+
|
|
30
|
+
class _MatplotlibNotAvailable:
|
|
31
|
+
"""Helper class that raises informative errors when matplotlib is not available."""
|
|
32
|
+
|
|
33
|
+
def __getattr__(self, name):
|
|
34
|
+
raise ImportError(
|
|
35
|
+
"Visualization features require matplotlib.\n"
|
|
36
|
+
"Install with: pip install pymoo[visualization]"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def __call__(self, *args, **kwargs):
|
|
40
|
+
raise ImportError(
|
|
41
|
+
"Visualization features require matplotlib.\n"
|
|
42
|
+
"Install with: pip install pymoo[visualization]"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Create placeholder objects that give helpful errors
|
|
46
|
+
matplotlib = _MatplotlibNotAvailable()
|
|
47
|
+
plt = _MatplotlibNotAvailable()
|
|
48
|
+
patches = _MatplotlibNotAvailable()
|
|
49
|
+
colors = _MatplotlibNotAvailable()
|
|
50
|
+
cm = _MatplotlibNotAvailable()
|
|
51
|
+
animation = _MatplotlibNotAvailable()
|
|
52
|
+
LineCollection = _MatplotlibNotAvailable()
|
|
53
|
+
PatchCollection = _MatplotlibNotAvailable()
|
|
54
|
+
ListedColormap = _MatplotlibNotAvailable()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def is_available():
|
|
58
|
+
"""Check if matplotlib is available for visualization."""
|
|
59
|
+
return _MATPLOTLIB_AVAILABLE
|
|
60
|
+
|
|
61
|
+
|