Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-13 10:26:33

0001 // @(#)root/mathcore:$Id$
0002 // Author: L. Moneta Fri Sep 22 15:06:47 2006
0003 
0004 /**********************************************************************
0005  *                                                                    *
0006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
0007  *                                                                    *
0008  *                                                                    *
0009  **********************************************************************/
0010 
0011 // Header file for class Minimizer
0012 
0013 #ifndef ROOT_Math_Minimizer
0014 #define ROOT_Math_Minimizer
0015 
0016 #include "Math/IFunction.h"
0017 #include "Math/MinimizerOptions.h"
0018 
0019 #include <ROOT/RSpan.hxx>
0020 
0021 #include <string>
0022 #include <limits>
0023 #include <cmath>
0024 #include <vector>
0025 #include <functional>
0026 
0027 
0028 
0029 namespace ROOT {
0030 
0031    namespace Fit {
0032       class ParameterSettings;
0033    }
0034 
0035 
0036    namespace Math {
0037 
0038 /**
0039    @defgroup MultiMin Multi-dimensional Minimization
0040    @ingroup NumAlgo
0041 
0042    Classes implementing algorithms for multi-dimensional minimization
0043  */
0044 
0045 
0046 
0047 //_______________________________________________________________________________
0048 /**
0049    Abstract Minimizer class, defining  the interface for the various minimizer
0050    (like Minuit2, Minuit, GSL, etc..) in ROOT.
0051    Plug-ins exist in ROOT to be able to instantiate the derived classes without linking the library
0052    using the static function ROOT::Math::Factory::CreateMinimizer.
0053 
0054    Here is the list of all possible minimizers and their respective methods (algorithms) that can be instantiated:
0055    The name shown below can be used to create them. More documentation can be found in the respective class
0056 
0057    - Minuit   (class TMinuitMinimizer)
0058       - Migrad (default)
0059       - MigradImproved  (Migrad with adding a method to improve minimization when ends-up in a local minimum, see par. 6.3 of [Minuit tutorial on Function Minimization](https://seal.web.cern.ch/documents/minuit/mntutorial.pdf))
0060       - Simplex
0061       - Minimize (a combination of Simplex + Migrad)
0062       - Minimize
0063       - Scan
0064       - Seek
0065 
0066    - Minuit2 (class ROOT::Minuit2::Minuit2Minimizer)
0067      - Migrad (default)
0068      - Simplex
0069      - Minimize
0070      - Fumili (Fumili2)
0071      - Scan
0072 
0073    \note Some Minuit2 gradient calculations, such as `Numerical2PGradientCalculator` support parallelization
0074    via OpenMP. To profit from this acceleration, one needs to build ROOT using `minuit2_omp=ON`
0075    and later call GradientCalculator::SetParallelOMP()
0076 
0077    - Fumili (class TFumiliMinimizer)
0078 
0079    - Linear (see TLinearFitter and TLinearMinimizer) minimizer (fitter) working only for linear functions 
0080 
0081    - GSLMultiMin (class ROOT::Math::GSLMinimizer) available when ROOT is built with `mathmore` support
0082      - BFGS2 (Default)
0083      - BFGS
0084      - ConjugateFR
0085      - ConjugatePR
0086      - SteepestDescent
0087 
0088    - GSLMultiFit (class ROOT::Math::GSLNLMinimizer) available when ROOT is built `mathmore` support
0089 
0090    - GSLSimAn  (class ROOT::Math::GSLSimAnMinimizer) available when ROOT is built with `mathmore` support
0091 
0092    - Genetic  (class ROOT::Math::GeneticMinimizer)
0093 
0094    - RMinimizer (class ROOT::Math::RMinimizer)  available when ROOT is built with `r` support
0095      - BFGS (default)
0096      - L-BFGS-S
0097      - Nelder-Mead
0098      - CG
0099      - and more methods, see the Details in the documentation of the function `optimix` of the [optmix R package](https://cran.r-project.org/web/packages/optimx/optimx.pdf)
0100 
0101    In addition to provide the API for function minimization (via ROOT::Math::Minimizer::Minimize) the Minimizer class  provides:
0102    - the interface for setting the function to be minimized. The objective function passed to the Minimizer must  implement the multi-dimensional generic interface
0103    ROOT::Math::IBaseFunctionMultiDim. If the function provides gradient calculation (e.g. implementing the ROOT::Math::IGradientFunctionMultiDim interface)
0104    the gradient will be used by the Minimizer class, when needed. There are convenient classes for the users to wrap their own functions in this required interface for minimization.
0105    These are the `ROOT::Math::Functor` class and the `ROOT::Math::GradFunctor` class for wrapping functions providing both evaluation and gradient. Some methods, like Fumili, Fumili2 and GSLMultiFit are
0106    specialized method for least-square and also likelihood minimizations. They require then that the given function implements in addition
0107    the `ROOT::Math::FitMethodFunction` interface.
0108    - The interface for setting the initial values for the function variables (which are the parameters in
0109    of the model function in case of solving for fitting) and specifying their limits.
0110    - The interface to set and retrieve basic minimization parameters. These parameter are controlled by the class `ROOT::Math::MinimizerOptions`.
0111    When no parameters are specified the default ones are used. Specific Minimizer options can also be passed via the `MinimizerOptions` class.
0112    For the list of the available option parameter one must look at the documentation of the corresponding derived class.
0113    - The interface to retrieve the result of minimization ( minimum X values, function value, gradient, error on the minimum, etc...)
0114    - The interface to perform a Scan, Hesse or a Contour plot (for the minimizers that support this, i.e. Minuit and Minuit2)
0115 
0116    An example on how to use this interface is the tutorial NumericalMinimization.C in the tutorials/math directory.
0117 
0118    To get an overview of the default minimizer, tolerance, precision, maximum number of function calls, etc., use:
0119    `ROOT::Math::MinimizerOptions::PrintDefault()`
0120 
0121    @ingroup MultiMin
0122 */
0123 
0124 class Minimizer {
0125 
0126 public:
0127 
0128    /// Default constructor.
0129    Minimizer () {}
0130 
0131    /// Destructor (no operations).
0132    virtual ~Minimizer ()  {}
0133 
0134    // usually copying is non trivial, so we delete this
0135    Minimizer(Minimizer const&) = delete;
0136    Minimizer &operator=(Minimizer const&) = delete;
0137    Minimizer(Minimizer &&) = delete;
0138    Minimizer &operator=(Minimizer &&) = delete;
0139 
0140    /// Reset for consecutive minimization - implement if needed.
0141    virtual void Clear() {}
0142 
0143    /// Set the function to minimize.
0144    virtual void SetFunction(const ROOT::Math::IMultiGenFunction & func) = 0;
0145 
0146    /// Set the function implementing Hessian computation (re-implemented by Minimizer using it).
0147    virtual void SetHessianFunction(std::function<bool(std::span<const double>, double *)> ) {}
0148 
0149    /// Add variables. @return number of variables successfully added
0150    template<class VariableIterator>
0151    int SetVariables(const VariableIterator & begin, const VariableIterator & end) {
0152       unsigned int ivar = 0;
0153       for ( VariableIterator vitr = begin; vitr != end; ++vitr) {
0154          bool iret = false;
0155          if (vitr->IsFixed() )
0156             iret = SetFixedVariable(ivar,  vitr->Name(), vitr->Value() );
0157          else if (vitr->IsDoubleBound() )
0158             iret = SetLimitedVariable(ivar,  vitr->Name(), vitr->Value(), vitr->StepSize(), vitr->LowerLimit(), vitr->UpperLimit() );
0159          else if (vitr->HasLowerLimit() )
0160             iret = SetLowerLimitedVariable(ivar,  vitr->Name(), vitr->Value(), vitr->StepSize(), vitr->LowerLimit() );
0161          else if (vitr->HasUpperLimit() )
0162             iret = SetUpperLimitedVariable(ivar,  vitr->Name(), vitr->Value(), vitr->StepSize(), vitr->UpperLimit() );
0163          else
0164             iret = SetVariable( ivar, vitr->Name(), vitr->Value(), vitr->StepSize() );
0165 
0166          if (iret) ivar++;
0167 
0168          // an error message should be eventually be reported in the virtual single SetVariable methods
0169       }
0170       return ivar;
0171    }
0172    /// Set a new free variable.
0173    virtual bool SetVariable(unsigned int ivar, const std::string & name, double val, double step) = 0;
0174    /// Set initial second derivatives.
0175    virtual bool SetCovarianceDiag(std::span<const double> d2, unsigned int n);
0176    /// Set initial covariance matrix.
0177    virtual bool SetCovariance(std::span<const double> cov, unsigned int nrow);
0178 
0179    /// Set a new lower limit variable (override if minimizer supports them), leave upper bound unlimited.
0180    /// @see Minimizer::SetLimitedVariable
0181    /// @param ivar the index of this variable in the array
0182    /// @param name the variable name
0183    /// @param val the value
0184    /// @param step the step size
0185    /// @param lower the lower bound
0186    virtual bool SetLowerLimitedVariable(unsigned int ivar, const std::string & name, double val, double step, double lower) {
0187       return SetLimitedVariable(ivar, name, val, step, lower, std::numeric_limits<double>::infinity());
0188    }
0189    /// Set a new upper limit variable (override if minimizer supports them), leave lower bound unlimited.
0190    /// @see Minimizer::SetLimitedVariable
0191    /// @param ivar the index of this variable in the array
0192    /// @param name the variable name
0193    /// @param val the value
0194    /// @param step the step size
0195    /// @param upper the upper bound
0196    virtual bool SetUpperLimitedVariable(unsigned int ivar, const std::string & name, double val, double step, double upper) {
0197       return SetLimitedVariable(ivar, name, val, step, - std::numeric_limits<double>::infinity(), upper);
0198    }
0199    virtual bool SetLimitedVariable(unsigned int ivar, const std::string & name, double val, double step,
0200                                    double lower, double upper);
0201    virtual bool SetFixedVariable(unsigned int  ivar, const std::string &  name, double val);
0202    virtual bool SetVariableValue(unsigned int ivar, double value);
0203    /// Set the values of all existing variables (array must be dimensioned to the size of the existing parameters).
0204    virtual bool SetVariableValues(const double * x) {
0205       bool ret = true;
0206       unsigned int i = 0;
0207       while ( i <= NDim() && ret) {
0208          ret &= SetVariableValue(i,x[i] ); i++;
0209       }
0210       return ret;
0211    }
0212    virtual bool SetVariableStepSize(unsigned int ivar, double value);
0213    virtual bool SetVariableLowerLimit(unsigned int ivar, double lower);
0214    virtual bool SetVariableUpperLimit(unsigned int ivar, double upper);
0215    /// Set the limits of an already existing variable.
0216    virtual bool SetVariableLimits(unsigned int ivar, double lower, double upper) {
0217       return SetVariableLowerLimit(ivar,lower) && SetVariableUpperLimit(ivar,upper);
0218    }
0219    virtual bool FixVariable(unsigned int ivar);
0220    virtual bool ReleaseVariable(unsigned int ivar);
0221    virtual bool IsFixedVariable(unsigned int ivar) const;
0222    virtual bool GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings & pars) const;
0223 
0224    /// Set the initial range of an existing variable.
0225    virtual bool SetVariableInitialRange(unsigned int /* ivar */, double /* mininitial */, double /* maxinitial */) {
0226      return false;
0227    }
0228 
0229    /// Method to perform the minimization.
0230    virtual  bool Minimize() = 0;
0231 
0232    /// @return minimum function value
0233    virtual double MinValue() const = 0;
0234 
0235    /// @return pointer to X values at the minimum
0236    virtual const double *  X() const = 0;
0237 
0238    /// @return expected distance reached from the minimum (re-implement if minimizer provides it
0239    virtual double Edm() const { return -1; }
0240 
0241    /// @return pointer to gradient values at the minimum
0242    virtual const double *  MinGradient() const { return nullptr; }
0243 
0244    /// Number of function calls to reach the minimum.
0245    virtual unsigned int NCalls() const { return 0; }
0246 
0247    /// Number of iterations to reach the minimum.
0248    virtual unsigned int NIterations() const { return NCalls(); }
0249 
0250    /// this is <= Function().NDim() which is the total
0251    /// number of variables (free+ constrained ones)
0252    virtual unsigned int NDim() const = 0;
0253 
0254    /// Number of free variables (real dimension of the problem).
0255    /// this is <= Function().NDim() which is the total
0256    /// (re-implement if minimizer supports bounded parameters)
0257    virtual unsigned int NFree() const { return NDim(); }
0258 
0259    /// Minimizer provides error and error matrix.
0260    virtual bool ProvidesError() const { return false; }
0261 
0262    /// @return errors at the minimum
0263    virtual const double * Errors() const { return nullptr; }
0264 
0265    virtual double CovMatrix(unsigned int  ivar , unsigned int jvar ) const;
0266    virtual bool GetCovMatrix(double * covMat) const;
0267    virtual bool GetHessianMatrix(double * hMat) const;
0268 
0269 
0270    /// @return status of covariance matrix
0271    /// using Minuit convention {0 not calculated 1 approximated 2 made pos def , 3 accurate}
0272    /// Minimizer who implements covariance matrix calculation will re-implement the method
0273    virtual int CovMatrixStatus() const {
0274       return 0;
0275    }
0276 
0277    /**
0278     * @return correlation coefficient between variable i and j.
0279     * If the variable is fixed or const the return value is zero
0280     */
0281    virtual double Correlation(unsigned int i, unsigned int j ) const {
0282       double tmp = CovMatrix(i,i) * CovMatrix(j,j);
0283       return ( tmp < 0) ? 0 : CovMatrix(i,j) / std::sqrt( tmp );
0284    }
0285 
0286    virtual std::vector<double> GlobalCC() const;
0287 
0288    virtual bool GetMinosError(unsigned int ivar , double & errLow, double & errUp, int option = 0);
0289    virtual bool Hesse();
0290    virtual bool Scan(unsigned int ivar , unsigned int & nstep , double * x , double * y ,
0291                      double xmin = 0, double xmax = 0);
0292    virtual bool Contour(unsigned int ivar , unsigned int jvar, unsigned int & npoints,
0293                         double *  xi , double * xj );
0294 
0295    /// @return reference to the objective function
0296    /// virtual const ROOT::Math::IGenFunction & Function() const = 0;
0297 
0298    /// Print the result according to set level (implemented for TMinuit for maintaining Minuit-style printing).
0299    virtual void PrintResults() {}
0300 
0301    virtual std::string VariableName(unsigned int ivar) const;
0302 
0303    virtual int VariableIndex(const std::string & name) const;
0304 
0305    /* minimizer configuration parameters */
0306 
0307    /// Set print level.
0308    int PrintLevel() const { return fOptions.PrintLevel(); }
0309 
0310    /// Max number of function calls.
0311    unsigned int MaxFunctionCalls() const { return fOptions.MaxFunctionCalls(); }
0312 
0313    /// Max iterations.
0314    unsigned int MaxIterations() const { return fOptions.MaxIterations(); }
0315 
0316    /// Absolute tolerance.
0317    double Tolerance() const { return  fOptions.Tolerance(); }
0318 
0319    /// Precision of minimizer in the evaluation of the objective function.
0320    /// (a value <=0 corresponds to the let the minimizer choose its default one)
0321    double Precision() const { return fOptions.Precision(); }
0322 
0323    /// Strategy.
0324    int Strategy() const { return fOptions.Strategy(); }
0325 
0326    /// Status code of minimizer.
0327    int Status() const { return fStatus; }
0328 
0329    /// Status code of Minos (to be re-implemented by the minimizers supporting Minos).
0330    virtual int MinosStatus() const { return -1; }
0331 
0332    /// @return the statistical scale used for calculate the error
0333    /// is typically 1 for Chi2 and 0.5 for likelihood minimization
0334    double ErrorDef() const { return fOptions.ErrorDef(); }
0335 
0336    /// @return true if Minimizer has performed a detailed error validation (e.g. run Hesse for Minuit)
0337    bool IsValidError() const { return fValidError; }
0338 
0339    /// Retrieve the minimizer options (implement derived class if needed).
0340    virtual MinimizerOptions  Options() const {
0341       return fOptions;
0342    }
0343 
0344    /// Set print level.
0345    void SetPrintLevel(int level) { fOptions.SetPrintLevel(level); }
0346 
0347    /// Set maximum of function calls.
0348    void SetMaxFunctionCalls(unsigned int maxfcn) { if (maxfcn > 0) fOptions.SetMaxFunctionCalls(maxfcn); }
0349 
0350    /// Set maximum iterations (one iteration can have many function calls).
0351    void SetMaxIterations(unsigned int maxiter) { if (maxiter > 0) fOptions.SetMaxIterations(maxiter); }
0352 
0353    /// Set the tolerance.
0354    void SetTolerance(double tol) { fOptions.SetTolerance(tol); }
0355 
0356    /// Set in the minimizer the objective function evaluation precision.
0357    /// (a value <=0 means the minimizer will choose its optimal value automatically, i.e. default case)
0358    void SetPrecision(double prec) { fOptions.SetPrecision(prec); }
0359 
0360    /// Set the strategy.
0361    void SetStrategy(int strategyLevel) { fOptions.SetStrategy(strategyLevel); }
0362 
0363    /// Set scale for calculating the errors.
0364    void SetErrorDef(double up) { fOptions.SetErrorDef(up); }
0365 
0366    /// Flag to check if minimizer needs to perform accurate error analysis (e.g. run Hesse for Minuit).
0367    void SetValidError(bool on) { fValidError = on; }
0368 
0369    /// Set all options in one go.
0370    void SetOptions(const MinimizerOptions & opt) {
0371       fOptions = opt;
0372    }
0373 
0374    /// Set only the extra options.
0375    void SetExtraOptions(const IOptions & extraOptions) { fOptions.SetExtraOptions(extraOptions); }
0376 
0377    /// Reset the default options (defined in MinimizerOptions).
0378    void SetDefaultOptions() {
0379       fOptions.ResetToDefaultOptions();
0380    }
0381 
0382 protected:
0383 
0384    // keep protected to be accessible by the derived classes
0385 
0386    bool fValidError = false;    ///< flag to control if errors have been validated (Hesse has been run in case of Minuit)
0387    MinimizerOptions fOptions;   ///< minimizer options
0388    int fStatus = -1;            ///< status of minimizer
0389 };
0390 
0391    } // end namespace Math
0392 
0393 } // end namespace ROOT
0394 
0395 
0396 #endif /* ROOT_Math_Minimizer */