Source code for iwopy.core.optimizer
import numpy as np
from abc import ABCMeta, abstractmethod
from iwopy.utils import new_instance
from .base import Base
[docs]
class Optimizer(Base, metaclass=ABCMeta):
"""
Abstract base class for optimization solvers.
Attributes
----------
problem: iwopy.Problem
The problem to optimize
name: str
The name
:group: core
"""
[docs]
def __init__(self, problem, name="optimizer"):
"""
Constructor
Parameters
----------
problem: iwopy.Problem
The problem to optimize
name: str
The name
"""
super().__init__(name)
self.problem = problem
self.name = name
[docs]
def print_info(self):
"""
Print solver info, called before solving
"""
pass
[docs]
@abstractmethod
def solve(self, verbosity=1):
"""
Run the optimization solver.
Parameters
----------
verbosity: int
The verbosity level, 0 = silent
Returns
-------
results: iwopy.core.OptResults
The optimization results object
"""
# check problem initialization:
if not self.problem.initialized:
raise ValueError(
f"Optimizer called for problem '{self.problem.name}'"
+ " before problem initialization"
)
# check solver initialization:
if not self.initialized:
raise ValueError(
f"Optimizer called for problem '{self.problem.name}'"
+ " before solver initialization"
)
return None
[docs]
def finalize(self, opt_results, verbosity=1):
"""
This function may be called after finishing
the optimization.
Parameters
----------
opt_results: iwopy.OptResults
The optimization results object
verbosity: int
The verbosity level, 0 = silent
"""
if verbosity:
print(f"{type(self).__name__}: Optimization run finished")
if (
isinstance(opt_results.success, bool)
or len(opt_results.success.flat) == 1
):
print(f" Success: {opt_results.success}")
else:
v = np.sum(opt_results.success) / len(opt_results.success.flat)
print(f" Success: {100*v:.2f} %")
if opt_results is not None and opt_results.objs is not None:
if self.problem.n_objectives == 1:
i0 = 0
for o in self.problem.objs.functions:
n = o.n_components()
i1 = i0 + n
names = o.component_names
if n == 1:
val = opt_results.objs[i0]
print(f" Best {o.name} = {val}")
else:
for i in range(n):
val = opt_results.objs[i0 + i]
print(f" Best {names[i]} = {val}")
i0 = i1
else:
i0 = 0
for o in self.problem.objs.functions:
n = o.n_components()
i1 = i0 + n
names = o.component_names
if n == 1:
if self.problem.maximize_objs[i0]:
val = np.max(opt_results.objs[:, i0])
else:
val = np.min(opt_results.objs[:, i0])
print(f" Best {o.name} = {val}")
else:
for i in range(n):
if self.problem.maximize_objs[i0 + 1]:
val = np.max(opt_results.objs[:, i0 + i])
else:
val = np.min(opt_results.objs[:, i0 + i])
print(f" Best {names[i]} = {val}")
i0 = i1
[docs]
@classmethod
def new(cls, optimizer_type, *args, **kwargs):
"""
Run-time optimizer factory.
Parameters
----------
optimizer_type: str
The selected derived class name
args: tuple, optional
Additional parameters for constructor
kwargs: dict, optional
Additional parameters for constructor
"""
return new_instance(cls, optimizer_type, *args, **kwargs)