Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:14:02

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-in's 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    - Fumili (class TFumiliMinimizer)
0074 
0075    - Linear (see TLinearFitter and TLinearMinimizer) minimizer (fitter) working only for linear functions 
0076 
0077    - GSLMultiMin (class ROOT::Math::GSLMinimizer) available when ROOT is built with `mathmore` support
0078      - BFGS2 (Default)
0079      - BFGS
0080      - ConjugateFR
0081      - ConjugatePR
0082      - SteepestDescent
0083 
0084    - GSLMultiFit (class ROOT::Math::GSLNLMinimizer) available when ROOT is built `mathmore` support
0085 
0086    - GSLSimAn  (class ROOT::Math::GSLSimAnMinimizer) available when ROOT is built with `mathmore` support
0087 
0088    - Genetic  (class ROOT::Math::GeneticMinimizer)
0089 
0090    - RMinimizer (class ROOT::Math::RMinimizer)  available when ROOT is built with `r` support
0091      - BFGS (default)
0092      - L-BFGS-S
0093      - Nelder-Mead
0094      - CG
0095      - 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)
0096 
0097 
0098    The Minimizer class provides the interface to perform the minimization including
0099 
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    @ingroup MultiMin
0119 */
0120 
0121 class Minimizer {
0122 
0123 public:
0124 
0125    /// Default constructor.
0126    Minimizer () {}
0127 
0128    /// Destructor (no operations).
0129    virtual ~Minimizer ()  {}
0130 
0131    // usually copying is non trivial, so we delete this
0132    Minimizer(Minimizer const&) = delete;
0133    Minimizer &operator=(Minimizer const&) = delete;
0134    Minimizer(Minimizer &&) = delete;
0135    Minimizer &operator=(Minimizer &&) = delete;
0136 
0137    /// Reset for consecutive minimization - implement if needed.
0138    virtual void Clear() {}
0139 
0140    /// Set the function to minimize.
0141    virtual void SetFunction(const ROOT::Math::IMultiGenFunction & func) = 0;
0142 
0143    /// Set the function implementing Hessian computation (re-implemented by Minimizer using it).
0144    virtual void SetHessianFunction(std::function<bool(std::span<const double>, double *)> ) {}
0145 
0146    /// Add variables. @return number of variables successfully added
0147    template<class VariableIterator>
0148    int SetVariables(const VariableIterator & begin, const VariableIterator & end) {
0149       unsigned int ivar = 0;
0150       for ( VariableIterator vitr = begin; vitr != end; ++vitr) {
0151          bool iret = false;
0152          if (vitr->IsFixed() )
0153             iret = SetFixedVariable(ivar,  vitr->Name(), vitr->Value() );
0154          else if (vitr->IsDoubleBound() )
0155             iret = SetLimitedVariable(ivar,  vitr->Name(), vitr->Value(), vitr->StepSize(), vitr->LowerLimit(), vitr->UpperLimit() );
0156          else if (vitr->HasLowerLimit() )
0157             iret = SetLowerLimitedVariable(ivar,  vitr->Name(), vitr->Value(), vitr->StepSize(), vitr->LowerLimit() );
0158          else if (vitr->HasUpperLimit() )
0159             iret = SetUpperLimitedVariable(ivar,  vitr->Name(), vitr->Value(), vitr->StepSize(), vitr->UpperLimit() );
0160          else
0161             iret = SetVariable( ivar, vitr->Name(), vitr->Value(), vitr->StepSize() );
0162 
0163          if (iret) ivar++;
0164 
0165          // an error message should be eventually be reported in the virtual single SetVariable methods
0166       }
0167       return ivar;
0168    }
0169    /// Set a new free variable.
0170    virtual bool SetVariable(unsigned int ivar, const std::string & name, double val, double step) = 0;
0171    /// Set initial second derivatives.
0172    virtual bool SetCovarianceDiag(std::span<const double> d2, unsigned int n);
0173    /// Set initial covariance matrix.
0174    virtual bool SetCovariance(std::span<const double> cov, unsigned int nrow);
0175 
0176    /// Set a new lower limit variable (override if minimizer supports them), leave upper bound unlimited.
0177    /// @see Minimizer::SetLimitedVariable
0178    /// @param ivar the index of this variable in the array
0179    /// @param name the variable name
0180    /// @param val the value
0181    /// @param step the step size
0182    /// @param lower the lower bound
0183    virtual bool SetLowerLimitedVariable(unsigned int ivar, const std::string & name, double val, double step, double lower) {
0184       return SetLimitedVariable(ivar, name, val, step, lower, std::numeric_limits<double>::infinity());
0185    }
0186    /// Set a new upper limit variable (override if minimizer supports them), leave lower bound unlimited.
0187    /// @see Minimizer::SetLimitedVariable
0188    /// @param ivar the index of this variable in the array
0189    /// @param name the variable name
0190    /// @param val the value
0191    /// @param step the step size
0192    /// @param upper the upper bound
0193    virtual bool SetUpperLimitedVariable(unsigned int ivar, const std::string & name, double val, double step, double upper) {
0194       return SetLimitedVariable(ivar, name, val, step, - std::numeric_limits<double>::infinity(), upper);
0195    }
0196    virtual bool SetLimitedVariable(unsigned int ivar, const std::string & name, double val, double step,
0197                                    double lower, double upper);
0198    virtual bool SetFixedVariable(unsigned int  ivar, const std::string &  name, double val);
0199    virtual bool SetVariableValue(unsigned int ivar, double value);
0200    /// Set the values of all existing variables (array must be dimensioned to the size of the existing parameters).
0201    virtual bool SetVariableValues(const double * x) {
0202       bool ret = true;
0203       unsigned int i = 0;
0204       while ( i <= NDim() && ret) {
0205          ret &= SetVariableValue(i,x[i] ); i++;
0206       }
0207       return ret;
0208    }
0209    virtual bool SetVariableStepSize(unsigned int ivar, double value);
0210    virtual bool SetVariableLowerLimit(unsigned int ivar, double lower);
0211    virtual bool SetVariableUpperLimit(unsigned int ivar, double upper);
0212    /// Set the limits of an already existing variable.
0213    virtual bool SetVariableLimits(unsigned int ivar, double lower, double upper) {
0214       return SetVariableLowerLimit(ivar,lower) && SetVariableUpperLimit(ivar,upper);
0215    }
0216    virtual bool FixVariable(unsigned int ivar);
0217    virtual bool ReleaseVariable(unsigned int ivar);
0218    virtual bool IsFixedVariable(unsigned int ivar) const;
0219    virtual bool GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings & pars) const;
0220 
0221    /// Set the initial range of an existing variable.
0222    virtual bool SetVariableInitialRange(unsigned int /* ivar */, double /* mininitial */, double /* maxinitial */) {
0223      return false;
0224    }
0225 
0226    /// Method to perform the minimization.
0227    virtual  bool Minimize() = 0;
0228 
0229    /// @return minimum function value
0230    virtual double MinValue() const = 0;
0231 
0232    /// @return pointer to X values at the minimum
0233    virtual const double *  X() const = 0;
0234 
0235    /// @return expected distance reached from the minimum (re-implement if minimizer provides it
0236    virtual double Edm() const { return -1; }
0237 
0238    /// @return pointer to gradient values at the minimum
0239    virtual const double *  MinGradient() const { return nullptr; }
0240 
0241    /// Number of function calls to reach the minimum.
0242    virtual unsigned int NCalls() const { return 0; }
0243 
0244    /// Number of iterations to reach the minimum.
0245    virtual unsigned int NIterations() const { return NCalls(); }
0246 
0247    /// this is <= Function().NDim() which is the total
0248    /// number of variables (free+ constrained ones)
0249    virtual unsigned int NDim() const = 0;
0250 
0251    /// Number of free variables (real dimension of the problem).
0252    /// this is <= Function().NDim() which is the total
0253    /// (re-implement if minimizer supports bounded parameters)
0254    virtual unsigned int NFree() const { return NDim(); }
0255 
0256    /// Minimizer provides error and error matrix.
0257    virtual bool ProvidesError() const { return false; }
0258 
0259    /// @return errors at the minimum
0260    virtual const double * Errors() const { return nullptr; }
0261 
0262    virtual double CovMatrix(unsigned int  ivar , unsigned int jvar ) const;
0263    virtual bool GetCovMatrix(double * covMat) const;
0264    virtual bool GetHessianMatrix(double * hMat) const;
0265 
0266 
0267    /// @return status of covariance matrix
0268    /// using Minuit convention {0 not calculated 1 approximated 2 made pos def , 3 accurate}
0269    /// Minimizer who implements covariance matrix calculation will re-implement the method
0270    virtual int CovMatrixStatus() const {
0271       return 0;
0272    }
0273 
0274    /**
0275     * @return correlation coefficient between variable i and j.
0276     * If the variable is fixed or const the return value is zero
0277     */
0278    virtual double Correlation(unsigned int i, unsigned int j ) const {
0279       double tmp = CovMatrix(i,i) * CovMatrix(j,j);
0280       return ( tmp < 0) ? 0 : CovMatrix(i,j) / std::sqrt( tmp );
0281    }
0282 
0283    virtual double GlobalCC(unsigned int ivar) const;
0284 
0285    virtual bool GetMinosError(unsigned int ivar , double & errLow, double & errUp, int option = 0);
0286    virtual bool Hesse();
0287    virtual bool Scan(unsigned int ivar , unsigned int & nstep , double * x , double * y ,
0288                      double xmin = 0, double xmax = 0);
0289    virtual bool Contour(unsigned int ivar , unsigned int jvar, unsigned int & npoints,
0290                         double *  xi , double * xj );
0291 
0292    /// @return reference to the objective function
0293    /// virtual const ROOT::Math::IGenFunction & Function() const = 0;
0294 
0295    /// Print the result according to set level (implemented for TMinuit for maintaining Minuit-style printing).
0296    virtual void PrintResults() {}
0297 
0298    virtual std::string VariableName(unsigned int ivar) const;
0299 
0300    virtual int VariableIndex(const std::string & name) const;
0301 
0302    /* minimizer configuration parameters */
0303 
0304    /// Set print level.
0305    int PrintLevel() const { return fOptions.PrintLevel(); }
0306 
0307    /// Max number of function calls.
0308    unsigned int MaxFunctionCalls() const { return fOptions.MaxFunctionCalls(); }
0309 
0310    /// Max iterations.
0311    unsigned int MaxIterations() const { return fOptions.MaxIterations(); }
0312 
0313    /// Absolute tolerance.
0314    double Tolerance() const { return  fOptions.Tolerance(); }
0315 
0316    /// Precision of minimizer in the evaluation of the objective function.
0317    /// (a value <=0 corresponds to the let the minimizer choose its default one)
0318    double Precision() const { return fOptions.Precision(); }
0319 
0320    /// Strategy.
0321    int Strategy() const { return fOptions.Strategy(); }
0322 
0323    /// Status code of minimizer.
0324    int Status() const { return fStatus; }
0325 
0326    /// Status code of Minos (to be re-implemented by the minimizers supporting Minos).
0327    virtual int MinosStatus() const { return -1; }
0328 
0329    /// @return the statistical scale used for calculate the error
0330    /// is typically 1 for Chi2 and 0.5 for likelihood minimization
0331    double ErrorDef() const { return fOptions.ErrorDef(); }
0332 
0333    /// @return true if Minimizer has performed a detailed error validation (e.g. run Hesse for Minuit)
0334    bool IsValidError() const { return fValidError; }
0335 
0336    /// Retrieve the minimizer options (implement derived class if needed).
0337    virtual MinimizerOptions  Options() const {
0338       return fOptions;
0339    }
0340 
0341    /// Set print level.
0342    void SetPrintLevel(int level) { fOptions.SetPrintLevel(level); }
0343 
0344    /// Set maximum of function calls.
0345    void SetMaxFunctionCalls(unsigned int maxfcn) { if (maxfcn > 0) fOptions.SetMaxFunctionCalls(maxfcn); }
0346 
0347    /// Set maximum iterations (one iteration can have many function calls).
0348    void SetMaxIterations(unsigned int maxiter) { if (maxiter > 0) fOptions.SetMaxIterations(maxiter); }
0349 
0350    /// Set the tolerance.
0351    void SetTolerance(double tol) { fOptions.SetTolerance(tol); }
0352 
0353    /// Set in the minimizer the objective function evaluation precision.
0354    /// (a value <=0 means the minimizer will choose its optimal value automatically, i.e. default case)
0355    void SetPrecision(double prec) { fOptions.SetPrecision(prec); }
0356 
0357    /// Set the strategy.
0358    void SetStrategy(int strategyLevel) { fOptions.SetStrategy(strategyLevel); }
0359 
0360    /// Set scale for calculating the errors.
0361    void SetErrorDef(double up) { fOptions.SetErrorDef(up); }
0362 
0363    /// Flag to check if minimizer needs to perform accurate error analysis (e.g. run Hesse for Minuit).
0364    void SetValidError(bool on) { fValidError = on; }
0365 
0366    /// Set all options in one go.
0367    void SetOptions(const MinimizerOptions & opt) {
0368       fOptions = opt;
0369    }
0370 
0371    /// Set only the extra options.
0372    void SetExtraOptions(const IOptions & extraOptions) { fOptions.SetExtraOptions(extraOptions); }
0373 
0374    /// Reset the default options (defined in MinimizerOptions).
0375    void SetDefaultOptions() {
0376       fOptions.ResetToDefaultOptions();
0377    }
0378 
0379 protected:
0380 
0381    // keep protected to be accessible by the derived classes
0382 
0383    bool fValidError = false;    ///< flag to control if errors have been validated (Hesse has been run in case of Minuit)
0384    MinimizerOptions fOptions;   ///< minimizer options
0385    int fStatus = -1;            ///< status of minimizer
0386 };
0387 
0388    } // end namespace Math
0389 
0390 } // end namespace ROOT
0391 
0392 
0393 #endif /* ROOT_Math_Minimizer */