Source code for optimization.optimizer.scipy.dual_annealing

from __future__ import annotations

import warnings
from typing import TYPE_CHECKING

import optiland.backend as be
from scipy import optimize

from .base import OptimizerGeneric

if TYPE_CHECKING:
    from ...problem import OptimizationProblem


[docs] class DualAnnealing(OptimizerGeneric): """DualAnnealing is an optimizer that uses the dual annealing algorithm to find the minimum of an optimization problem. Args: problem (OptimizationProblem): The optimization problem to be solved. Methods: optimize(maxiter=1000, disp=True): Runs the dual annealing algorithm to optimize the problem and returns the result. """ def __init__(self, problem: OptimizationProblem): super().__init__(problem)
[docs] def optimize(self, maxiter=1000, disp=True, callback=None): """Runs the dual annealing algorithm to optimize the problem. Args: maxiter (int): Maximum number of iterations. disp (bool): Whether to display the optimization process. callback (callable): A callable called after each iteration. Returns: result: The result of the optimization. """ # Get initial values in backend format x0_backend = [var.value for var in self.problem.variables] self._x.append(x0_backend) # Store backend values # Convert x0 to NumPy for SciPy x0_numpy = be.to_numpy(x0_backend) bounds = tuple([var.bounds for var in self.problem.variables]) if any(None in bound for bound in bounds): raise ValueError("Dual annealing requires all variables have bounds.") with warnings.catch_warnings(): warnings.simplefilter("ignore", category=RuntimeWarning) result = optimize.dual_annealing( self._fun, bounds=bounds, maxiter=maxiter, x0=x0_numpy, callback=callback, ) for idvar, var in enumerate(self.problem.variables): var.update(result.x[idvar]) self.problem.update_optics() return result