Source code for minkit.minimization.scipy_api

########################################
# MIT License
#
# Copyright (c) 2020 Miguel Ramos Pernas
########################################
'''
Definition of the interface functions and classes with :mod:`scipy`.
'''
from . import core

import scipy.optimize as scipyopt
import warnings

__all__ = ['SciPyMinimizer']

# Choices and default method to minimize with SciPy
SCIPY_CHOICES = ('L-BFGS-B', 'TNC', 'SLSQP', 'trust-constr')


[docs]class SciPyMinimizer(core.Minimizer): def __init__(self, method, evaluator, **minimizer_config): ''' Interface with the :func:`scipy.optimize.minimize` function. :param method: method parsed by :func:`scipy.optimize.minimize`. :type method: str :param evaluator: evaluator to be used in the minimization. :type evaluator: UnbinnedEvaluator, BinnedEvaluator or SimultaneousEvaluator :param minimizer_config: configuration for the minimizer. :type minimizer_config: dict :raises ValueError: If the minimization method is unknown. ''' super().__init__(evaluator) if method not in SCIPY_CHOICES: raise ValueError(f'Unknown minimization method "{method}"') self.__method = method
[docs] def minimize(self, *args, **kwargs): ''' Minimize the FCN for the stored PDF and data sample. It returns a tuple with the information whether the minimization succeded and the covariance matrix. .. seealso:: :meth:`SciPyMinimizer.scipy_minimize` ''' res, cov = self.scipy_minimize(*args, **kwargs) return core.MinimizationResult(res.success, res.fun, cov)
[docs] def scipy_minimize(self, tol=None, hessian_opts=None): ''' Minimize the PDF. :param tol: tolerance to be used in the minimization. :type tol: float or None :param hessian_opts: options to be passed to :class:`numdifftools.core.Hessian`. :type hessian_opts: dict or None :returns: Result of the minimization and covariance matrix. :rtype: scipy.optimize.OptimizeResult, numpy.ndarray .. seealso:: :meth:`SciPyMinimizer.minimize` ''' varargs, values, varids = core.determine_varargs_values_varids( self.evaluator.args) initials = tuple(a.value for a in varargs) def _evaluate(*args): # set the non-constant argument values values[varids] = args return self.evaluator(*values) bounds = [p.bounds for p in varargs] with self.evaluator.using_caches(), warnings.catch_warnings(): warnings.filterwarnings( 'ignore', category=UserWarning, module=r'.*_hessian_update_strategy') warnings.filterwarnings('once', category=RuntimeWarning) result = scipyopt.minimize( _evaluate, initials, method=self.__method, bounds=bounds, tol=tol) with self.restoring_state(): errors, cov = core.errors_and_covariance_matrix( _evaluate, result.x) # Update the values and errors of the parameters for p, v, e in zip(varargs, result.x, errors): p.value, p.error = v, e return result, cov