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)