"""Optimization algorithms.
This module includes the interface to implement any optimization algorithm as
well as several wrappers over optimization algorithms available on open-source
libraries (e.g., `SciPy <https://docs.scipy.org/doc/scipy/reference/generated/
scipy.optimize.minimize.html>`_) and others.
Classes
-------
Optimizer
Optimization algorithm interface.
SciPyMinimizer
SciPy minimization optimizer (wrapper).
"""
#
# Modules
# =============================================================================
# Standard
from abc import ABC, abstractmethod
# Third-party
import numpy as np
import scipy.optimize
#
# Authorship & Credits
# =============================================================================
__author__ = 'Bernardo Ferreira (bernardo_ferreira@brown.edu)'
__credits__ = ['Bernardo Ferreira', ]
__status__ = 'Alpha'
# =============================================================================
#
# =============================================================================
#
# Interface: Optimization algorithm
# =============================================================================
[docs]class Optimizer(ABC):
"""Optimization algorithm interface.
Methods
-------
solve_optimization(self, optimization_function, max_n_iter=None, \
verbose=False):
*abstract*: Solve optimization problem.
"""
[docs] @abstractmethod
def __init__(self):
"""Constructor."""
pass
# -------------------------------------------------------------------------
[docs] @abstractmethod
def solve_optimization(self, optimization_function, max_n_iter=None,
verbose=False):
"""Solve optimization problem.
Parameters
----------
optimization_function : OptimizationFunction
Instance of OptimizationFunction class.
max_n_iter : int, default=None
Maximum number of iterations.
verbose : bool, default=False
Enable verbose output.
Returns
-------
parameters : dict
Optimization parameters names (key, str) and values (item, float).
"""
pass
#
# Optimization algorithms
# =============================================================================
[docs]class SciPyMinimizer(Optimizer):
"""SciPy minimization optimizer (wrapper).
Documentation: see `here <https://docs.scipy.org/doc/scipy/reference/
generated/scipy.optimize.minimize.html>`_.
Methods
-------
solve_optimization(self, optimization_function, max_n_iter=None, \
verbose=False)
Solve optimization problem.
"""
[docs] def __init__(self, method='Powell'):
"""Constructor.
Parameters
----------
method : {'Nelder-Mead', 'Powell', 'CG', 'BFGS'}, default='Powell'
Optimization method.
"""
self._method = method
# -------------------------------------------------------------------------
[docs] def solve_optimization(self, optimization_function, max_n_iter=1,
verbose=False):
"""Solve optimization problem.
Parameters
----------
optimization_function : OptimizationFunction
Instance of OptimizationFunction class.
max_n_iter : int, default=1
Maximum number of iterations.
verbose : bool, default=False
Enable verbose output.
Returns
-------
parameters : dict
Optimization parameters names (key, str) and values (item, float).
"""
# Get optimization function with normalized parameters provided as
# sequence
norm_opt_function_seq = optimization_function.norm_opt_function_seq
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Get optimization function parameters names
parameters_names = optimization_function.get_parameters_names()
# Set number of optimization parameters
dimension = len(parameters_names)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Get optimization parameters initial guess
init_shot = optimization_function.get_init_shot(is_normalized=True)
x0 = np.array([init_shot[str(param)] for param in parameters_names])
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Get optimization parameters lower and upper bounds
lower_bounds, upper_bounds = \
optimization_function.get_bounds(is_normalized=True)
# Build optimization parameters bounds array
bounds = np.array([(lower_bounds[str(param)], upper_bounds[str(param)])
for param in parameters_names]).reshape(dimension,
2)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set algorithmic parameters
options = {'maxiter': max_n_iter, }
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Solve optimization problem
result = scipy.optimize.minimize(fun=norm_opt_function_seq,
x0=x0,
method=self._method,
bounds=bounds,
options=options)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Get optimization solution
parameters = {str(param): result.x[i]
for i, param in enumerate(parameters_names)}
# optimum = result.fun
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Return
return parameters