import numpy as np
import matplotlib.pyplot as plt
from iwopy.core import Optimizer
from .problem import SingleObjProblemTemplate, MultiObjProblemTemplate
from .factory import Factory
from . import imports
[docs]
class DefaultCallbackTemplate:
"""
Template for the default callback
:group: interfaces.pymoo
"""
[docs]
def __init__(self):
"""
Constructor
"""
self.data["f_best"] = None
self.data["cv_best"] = None
[docs]
def notify(self, algorithm):
fvals = algorithm.pop.get("F")
cvals = algorithm.pop.get("CV")
n_obj = fvals.shape[1]
n_con = cvals.shape[1]
i = np.argmin(fvals, axis=0)
if self.data["f_best"] is None:
self.data["f_best"] = fvals[None, i, range(n_obj)]
self.data["cv_best"] = cvals[None, i, range(n_con)]
else:
self.data["f_best"] = np.append(
self.data["f_best"], fvals[None, i, range(n_obj)], axis=0
)
self.data["cv_best"] = np.append(
self.data["cv_best"], cvals[None, i, range(n_con)], axis=0
)
[docs]
@classmethod
def get_class(cls):
"""
Creates the class, dynamically derived from pymoo.Callback
"""
imports.load()
attrb = {v: d for v, d in cls.__dict__.items()}
init0 = cls.__init__
def init1(self):
imports.Callback.__init__(self)
init0(self)
attrb["__init__"] = init1
attrb["__doc__"] = "The default callback"
del attrb["get_class"]
return type("DefaultCallback", (imports.Callback,), attrb)()
[docs]
class Optimizer_pymoo(Optimizer):
"""
Interface to the pymoo optimization solver.
Attributes
----------
problem_pars: dict
Parameters for the problem
algo_pars: dict
Parameters for the alorithm
setup_pars: dict
Parameters for the calculation setup
term_pars: dict
Parameters for the termination conditions
pymoo_problem: iwopy.interfaces.pymoo.SingleObjProblem
The pygmo problem
algo: pygmo.algo
The pygmo algorithm
:group: interfaces.pymoo
"""
[docs]
def __init__(self, problem, problem_pars, algo_pars, setup_pars={}, term_pars={}):
"""
Constructor
Parameters
----------
problem: iwopy.Problem
The problem to optimize
problem_pars: dict
Parameters for the problem
algo_pars: dict
Parameters for the alorithm
setup_pars: dict
Parameters for the calculation setup
"""
super().__init__(problem)
self.problem_pars = problem_pars
self.algo_pars = algo_pars
self.setup_pars = setup_pars
self.term_pars = term_pars
self.pymoo_problem = None
self.algo = None
[docs]
def print_info(self):
"""
Print solver info, called before solving
"""
super().print_info()
if len(self.problem_pars):
print("\nProblem:")
print("--------")
for k, v in self.problem_pars.items():
if isinstance(v, int) or isinstance(v, float) or isinstance(v, str):
print(f" {k}: {v}")
if len(self.algo_pars):
print("\nAlgorithm:")
print("----------")
for k, v in self.algo_pars.items():
if isinstance(v, int) or isinstance(v, float) or isinstance(v, str):
print(f" {k}: {v}")
if len(self.setup_pars):
print("\nSetup:")
print("------")
for k, v in self.setup_pars.items():
if isinstance(v, int) or isinstance(v, float) or isinstance(v, str):
print(f" {k}: {v}")
if len(self.term_pars):
print("\nTermination:")
print("------------")
if isinstance(self.term_pars, (tuple, list)):
print(f" {self.term_pars[0]}: {self.term_pars[1]}")
else:
for k, v in self.term_pars.items():
if isinstance(v, int) or isinstance(v, float) or isinstance(v, str):
print(f" {k}: {v}")
print()
[docs]
def initialize(self, verbosity=1):
"""
Initialize the object.
Parameters
----------
verbosity: int
The verbosity level, 0 = silent
"""
if self.problem.n_objectives <= 1:
self.pymoo_problem = SingleObjProblemTemplate.get_class()(
self.problem, **self.problem_pars
)
else:
self.pymoo_problem = MultiObjProblemTemplate.get_class()(
self.problem, **self.problem_pars
)
if verbosity:
print("Initializing", type(self).__name__)
factory = Factory(self.pymoo_problem, verbosity)
self.algo = factory.get_algorithm(self.algo_pars)
self.term = factory.get_termination(self.term_pars)
super().initialize(verbosity)
[docs]
def solve(self, callback="default", verbosity=1):
"""
Run the optimization solver.
Parameters
----------
callback: pymoo.Callback, optional
The callback
verbosity: int
The verbosity level, 0 = silent
Returns
-------
results: iwopy.SingleObjOptResults or iwopy.MultiObjOptResults
The optimization results object
"""
if callback == "default":
callback = DefaultCallbackTemplate.get_class()
# check problem initialization:
super().solve()
# run pymoo solver:
self.callback = callback
self.results = imports.minimize(
self.pymoo_problem,
algorithm=self.algo,
termination=self.term,
verbose=verbosity > 0,
callback=self.callback,
**self.setup_pars,
)
# transfer callback:
if self.callback is not None:
self.callback = self.results.algorithm.callback
return self.pymoo_problem.finalize(self.results)