Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:19

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