|
|
|||
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 */
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|