Source code for QHyper.optimizers.scipy_minimizer
# This work was supported by the EuroHPC PL infrastructure funded at the
# Smart Growth Operational Programme (2014-2020), Measure 4.2
# under the grant agreement no. POIR.04.02.00-00-D014/20-00
from numpy.typing import NDArray
from typing import Callable, Any
import scipy
import numpy as np
from QHyper.optimizers.base import (
Optimizer, OptimizationResult, OptimizerError, OptimizationParameter)
[docs]
class ScipyOptimizer(Optimizer):
"""
Class for the SciPy minimizer.
This class is a wrapper for the SciPy minimizer.
It requires the following parameters to be set:
- `init` initial values for each parameter
- `min` and `max` bounds for each parameter
Attributes
----------
verbose : bool, default False
Whether to print the optimization progress.
disable_tqdm : bool, default True
Whether to disable the tqdm progress bar.
maxfun : int
Maximum number of function evaluations.
kwargs : dict[str, Any]
Additional keyword arguments for the SciPy minimizer.
https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html
"""
verbose: bool
disable_tqdm: bool
maxfun: int
kwargs: dict[str, Any]
def __init__(
self,
verbose: bool = False,
disable_tqdm: bool = True,
maxfun: int = 200,
**kwargs: Any
) -> None:
self.verbose = verbose
self.disable_tqdm = disable_tqdm
self.maxfun = maxfun
self.kwargs = kwargs
[docs]
def minimize(
self,
func: Callable[[list[float]], OptimizationResult],
init: OptimizationParameter
) -> OptimizationResult:
"""
Minimize the given function using the SciPy minimize.
Parameters
----------
func : callable
The objective function to be minimized.
The function should take a single argument, which is a NumPy array
of type np.float64, and return a float value.
init : numpy.ndarray
The initial point for the optimization algorithm.
The array should have dtype np.float64.
Returns
-------
tuple
A tuple containing the minimum function value and the
corresponding optimal point.
"""
init.assert_bounds_init()
def wrapper(params: NDArray) -> float:
return func(params).value
history: list[OptimizationResult] = []
def callback(intermediate_result):
if self.verbose:
print(f"Step {len(history)+1}/{self.maxfun}: "
f"{float(intermediate_result.fun)}")
history.append(OptimizationResult(
intermediate_result.fun, np.copy(intermediate_result.x)))
if 'options' not in self.kwargs:
self.kwargs['options'] = {}
if 'maxfun' not in self.kwargs['options']:
self.kwargs['options']['maxfun'] = self.maxfun
result = scipy.optimize.minimize(
wrapper, init.init,
bounds=init.bounds,
callback=callback,
**self.kwargs
)
if self.verbose:
print(f"Success: {result.success}. Message: {result.message}")
return OptimizationResult(
result.fun, result.x, [history]
)