Source code for lightwin.optimisation.algorithms.downhill_simplex

"""Define the Downhill simplex (or Nelder-Mead) algorihm."""

from typing import Any

import numpy as np
from scipy.optimize import Bounds, OptimizeResult, minimize

from lightwin.optimisation.algorithms.algorithm import (
    OptimisationAlgorithm,
    OptiSol,
)


[docs] class DownhillSimplex(OptimisationAlgorithm): """Downhill simplex method, which does not use derivatives. All the attributes but ``solution`` are inherited from the Abstract Base Class :class:`.OptimisationAlgorithm`. See also -------- :class:`.DownhillSimplexPenalty` """ supports_constraints = False
[docs] def optimize(self) -> OptiSol: """Set up the optimization and solve the problem. Returns ------- Gives list of solutions, corresponding objective, convergence violation if applicable, etc. """ x_0, bounds = self._format_variables() result = minimize( fun=self._norm_wrapper_residuals, x0=x_0, bounds=bounds, **self.optimisation_algorithm_kwargs, ) self.opti_sol = self._generate_opti_sol(result) self._finalize(self.opti_sol) return self.opti_sol
@property def _default_kwargs(self) -> dict[str, Any]: """Create the ``kwargs`` for the optimisation.""" kwargs = { "method": "Nelder-Mead", "options": { "adaptive": True, "disp": True, }, } return kwargs
[docs] def _generate_opti_sol(self, result: OptimizeResult) -> OptiSol: """Store the optimization results.""" cavity_settings = self._create_set_of_cavity_settings(result.x) opti_sol: OptiSol = { "var": result.x, "cavity_settings": cavity_settings, "fun": result.fun, "objectives": self._get_objective_values(result.x), "success": result.success, "info": [self.__class__.__name__, result.message], } return opti_sol
[docs] def _format_variables(self) -> tuple[np.ndarray, Bounds]: """Convert the :class:`.Variable` to an array and ``Bounds``.""" x_0 = np.array([var.x_0 for var in self._variables]) _bounds = np.array([var.limits for var in self._variables]) bounds = Bounds(_bounds[:, 0], _bounds[:, 1]) return x_0, bounds