Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:29:40

0001 // @(#)root/minuit2:$Id$
0002 // Author: L. Moneta Wed Oct 18 11:48:00 2006
0003 
0004 /**********************************************************************
0005  *                                                                    *
0006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
0007  *                                                                    *
0008  *                                                                    *
0009  **********************************************************************/
0010 
0011 // Header file for class Minuit2Minimizer
0012 
0013 #ifndef ROOT_Minuit2_Minuit2Minimizer
0014 #define ROOT_Minuit2_Minuit2Minimizer
0015 
0016 #include "Math/Minimizer.h"
0017 
0018 #include "Minuit2/MnUserParameterState.h"
0019 
0020 #include "Math/IFunctionfwd.h"
0021 
0022 #include <vector>
0023 #include <string>
0024 #include <functional>
0025 
0026 namespace ROOT {
0027 
0028 namespace Minuit2 {
0029 
0030 class ModularFunctionMinimizer;
0031 class FCNBase;
0032 class FunctionMinimum;
0033 class MnTraceObject;
0034 
0035 // enumeration specifying the type of Minuit2 minimizers
0036 enum EMinimizerType { kMigrad, kSimplex, kCombined, kScan, kFumili, kMigradBFGS };
0037 
0038 } // namespace Minuit2
0039 
0040 namespace Minuit2 {
0041 //_____________________________________________________________________________________________________
0042 /**
0043    Minuit2Minimizer class implementing the ROOT::Math::Minimizer interface for
0044    Minuit2 minimization algorithm.
0045    In ROOT it can be instantiated using the plug-in manager (plug-in "Minuit2")
0046    Using a string  (used by the plugin manager) or via an enumeration
0047    an one can set all the possible minimization algorithms (Migrad, Simplex, Combined, Scan and Fumili).
0048 
0049    Refer to the [guide](https://root.cern.ch/doc/master/Minuit2Page.html) for an introduction how Minuit2
0050    works.
0051 
0052    \note Some gradient calculations, such as `Numerical2PGradientCalculator` support parallelization
0053    via OpenMP. To profit from this acceleration, one needs to build ROOT using `minuit2_omp=ON`
0054    and later call GradientCalculator::SetParallelOMP()
0055 
0056    @ingroup Minuit
0057 */
0058 class Minuit2Minimizer : public ROOT::Math::Minimizer {
0059 
0060 public:
0061    /**
0062       Default constructor
0063    */
0064    Minuit2Minimizer(ROOT::Minuit2::EMinimizerType type = ROOT::Minuit2::kMigrad);
0065 
0066    /**
0067       Constructor with a char (used by PM)
0068    */
0069    Minuit2Minimizer(const char *type);
0070 
0071    /**
0072       Destructor (no operations)
0073    */
0074    ~Minuit2Minimizer() override;
0075 
0076    // clear resources (parameters) for consecutives minimizations
0077    void Clear() override;
0078 
0079    /// set the function to minimize
0080    void SetFunction(const ROOT::Math::IMultiGenFunction &func) override;
0081 
0082    /// set the function implementing Hessian computation
0083    void SetHessianFunction(std::function<bool(std::span<const double>, double *)> hfunc) override;
0084 
0085    /// set free variable
0086    bool SetVariable(unsigned int ivar, const std::string &name, double val, double step) override;
0087 
0088    /// set lower limit variable  (override if minimizer supports them )
0089    bool
0090    SetLowerLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double lower) override;
0091    /// set upper limit variable (override if minimizer supports them )
0092    bool
0093    SetUpperLimitedVariable(unsigned int ivar, const std::string &name, double val, double step, double upper) override;
0094    /// set upper/lower limited variable (override if minimizer supports them )
0095    bool SetLimitedVariable(unsigned int ivar, const std::string &name, double val, double step,
0096                                    double /* lower */, double /* upper */) override;
0097    /// set fixed variable (override if minimizer supports them )
0098    bool SetFixedVariable(unsigned int /* ivar */, const std::string & /* name */, double /* val */) override;
0099    /// set variable
0100    bool SetVariableValue(unsigned int ivar, double val) override;
0101    // set variable values
0102    bool SetVariableValues(const double *val) override;
0103    /// set the step size of an already existing variable
0104    bool SetVariableStepSize(unsigned int ivar, double step) override;
0105    /// set the lower-limit of an already existing variable
0106    bool SetVariableLowerLimit(unsigned int ivar, double lower) override;
0107    /// set the upper-limit of an already existing variable
0108    bool SetVariableUpperLimit(unsigned int ivar, double upper) override;
0109    /// set the limits of an already existing variable
0110    bool SetVariableLimits(unsigned int ivar, double lower, double upper) override;
0111    /// fix an existing variable
0112    bool FixVariable(unsigned int ivar) override;
0113    /// release an existing variable
0114    bool ReleaseVariable(unsigned int ivar) override;
0115    /// query if an existing variable is fixed (i.e. considered constant in the minimization)
0116    /// note that by default all variables are not fixed
0117    bool IsFixedVariable(unsigned int ivar) const override;
0118    /// get variable settings in a variable object (like ROOT::Fit::ParamsSettings)
0119    bool GetVariableSettings(unsigned int ivar, ROOT::Fit::ParameterSettings &varObj) const override;
0120    /// get name of variables (override if minimizer support storing of variable names)
0121    std::string VariableName(unsigned int ivar) const override;
0122    /// get index of variable given a variable given a name
0123    /// return -1 if variable is not found
0124    int VariableIndex(const std::string &name) const override;
0125 
0126    /**
0127        method to perform the minimization.
0128        Return false in case the minimization did not converge. In this case a
0129        status code different than zero is set
0130        (retrieved by the derived method Minimizer::Status() )"
0131 
0132        status = 1    : Covariance was made pos defined
0133        status = 2    : Hesse is invalid
0134        status = 3    : Edm is above max
0135        status = 4    : Reached call limit
0136        status = 5    : Any other failure
0137    */
0138    bool Minimize() override;
0139 
0140    /// return minimum function value
0141    double MinValue() const override { return fState.Fval(); }
0142 
0143    /// return expected distance reached from the minimum
0144    double Edm() const override { return fState.Edm(); }
0145 
0146    /// return  pointer to X values at the minimum
0147    const double *X() const override { return &fValues.front(); }
0148 
0149    /// return pointer to gradient values at the minimum
0150    const double *MinGradient() const override { return nullptr; } // not available in Minuit2
0151 
0152    /// number of function calls to reach the minimum
0153    unsigned int NCalls() const override { return fState.NFcn(); }
0154 
0155    /// this is <= Function().NDim() which is the total
0156    /// number of variables (free+ constrained ones)
0157    unsigned int NDim() const override { return fDim; }
0158 
0159    /// number of free variables (real dimension of the problem)
0160    /// this is <= Function().NDim() which is the total
0161    unsigned int NFree() const override { return fState.VariableParameters(); }
0162 
0163    /// minimizer provides error and error matrix
0164    bool ProvidesError() const override { return true; }
0165 
0166    /// return errors at the minimum
0167    const double *Errors() const override;
0168 
0169    /**
0170        return covariance matrix elements
0171        if the variable is fixed or const the value is zero
0172        The ordering of the variables is the same as in errors and parameter value.
0173        This is different from the direct interface of Minuit2 or TMinuit where the
0174        values were obtained only to variable parameters
0175    */
0176    double CovMatrix(unsigned int i, unsigned int j) const override;
0177 
0178    /**
0179        Fill the passed array with the  covariance matrix elements
0180        if the variable is fixed or const the value is zero.
0181        The array will be filled as cov[i *ndim + j]
0182        The ordering of the variables is the same as in errors and parameter value.
0183        This is different from the direct interface of Minuit2 or TMinuit where the
0184        values were obtained only to variable parameters
0185    */
0186    bool GetCovMatrix(double *cov) const override;
0187 
0188    /**
0189        Fill the passed array with the Hessian matrix elements
0190        The Hessian matrix is the matrix of the second derivatives
0191        and is the inverse of the covariance matrix
0192        If the variable is fixed or const the values for that variables are zero.
0193        The array will be filled as h[i *ndim + j]
0194    */
0195    bool GetHessianMatrix(double *h) const override;
0196 
0197    /**
0198       return the status of the covariance matrix
0199        status = -1 :  not available (inversion failed or Hesse failed)
0200        status =  0 : available but not positive defined
0201        status =  1 : covariance only approximate
0202        status =  2 : full matrix but forced pos def
0203        status =  3 : full accurate matrix
0204 
0205     */
0206    int CovMatrixStatus() const override;
0207    /**
0208       return correlation coefficient between variable i and j.
0209       If the variable is fixed or const the return value is zero
0210     */
0211    double Correlation(unsigned int i, unsigned int j) const override;
0212 
0213    /**
0214       get global correlation coefficient for the variable i. This is a number between zero and one which gives
0215       the correlation between the i-th variable  and that linear combination of all other variables which
0216       is most strongly correlated with i.
0217       If the variable is fixed or const the return value is zero
0218     */
0219    std::vector<double> GlobalCC() const override;
0220 
0221    /**
0222       get the minos error for parameter i, return false if Minos failed
0223       A minimizaiton must be performed befre, return false if no minimization has been done
0224       In case of Minos failed the status error is updated as following
0225       status += 10 * minosStatus.
0226       The Minos status of last Minos run can also be retrieved by calling MinosStatus()
0227    */
0228    bool GetMinosError(unsigned int i, double &errLow, double &errUp, int = 0) override;
0229 
0230    /**
0231       MINOS status code of last Minos run
0232        `status & 1 > 0`  : invalid lower error
0233        `status & 2 > 0`  : invalid upper error
0234        `status & 4 > 0`  : invalid because maximum number of function calls exceeded
0235        `status & 8 > 0`  : a new minimum has been found
0236        `status & 16 > 0` : error is truncated because parameter is at lower/upper limit
0237    */
0238    int MinosStatus() const override { return fMinosStatus; }
0239 
0240    /**
0241       scan a parameter i around the minimum. A minimization must have been done before,
0242       return false if it is not the case
0243     */
0244    bool Scan(unsigned int i, unsigned int &nstep, double *x, double *y, double xmin = 0, double xmax = 0) override;
0245 
0246    /**
0247       find the contour points (xi,xj) of the function for parameter i and j around the minimum
0248       The contour will be find for value of the function = Min + ErrorUp();
0249     */
0250    bool Contour(unsigned int i, unsigned int j, unsigned int &npoints, double *xi, double *xj) override;
0251 
0252    /**
0253       perform a full calculation of the Hessian matrix for error calculation
0254       If a valid minimum exists the calculation is done on the minimum point otherwise is performed
0255       in the current set values of parameters
0256       Status code of minimizer is updated according to the following convention (in case Hesse failed)
0257       status += 100*hesseStatus where hesse status is:
0258       status = 1 : hesse failed
0259       status = 2 : matrix inversion failed
0260       status = 3 : matrix is not pos defined
0261     */
0262    bool Hesse() override;
0263 
0264    /// return reference to the objective function
0265    /// virtual const ROOT::Math::IGenFunction & Function() const;
0266 
0267    /// print result of minimization
0268    void PrintResults() override;
0269 
0270    /// set an object to trace operation for each iteration
0271    /// The object must be a (or inherit from) ROOT::Minuit2::MnTraceObject and implement operator() (int, const
0272    /// MinimumState & state)
0273    void SetTraceObject(MnTraceObject &obj);
0274 
0275    /// set storage level   = 1 : store all iteration states (default)
0276    ///                     = 0 : store only first and last state to save memory
0277    void SetStorageLevel(int level);
0278 
0279    /// return the minimizer state (containing values, step size , etc..)
0280    const ROOT::Minuit2::MnUserParameterState &State() { return fState; }
0281 
0282    /// To set the function directly to a Minuit 2 function.
0283    void SetFCN(unsigned int nDim, std::unique_ptr<ROOT::Minuit2::FCNBase> fcn);
0284 
0285    const ROOT::Minuit2::FCNBase *GetFCN() const { return fMinuitFCN.get(); }
0286    ROOT::Minuit2::FCNBase *GetFCN() { return fMinuitFCN.get(); }
0287 
0288 protected:
0289    // protected function for accessing the internal Minuit2 object. Needed for derived classes
0290 
0291    virtual const ROOT::Minuit2::ModularFunctionMinimizer *GetMinimizer() const { return fMinimizer.get(); }
0292 
0293    void SetMinimizerType(ROOT::Minuit2::EMinimizerType type);
0294 
0295    /// examine the minimum result
0296    bool ExamineMinimum(const ROOT::Minuit2::FunctionMinimum &min);
0297 
0298    // internal function to compute Minos errors
0299    int RunMinosError(unsigned int i, double &errLow, double &errUp, int runopt);
0300 
0301    /// set initial second derivatives
0302    virtual bool SetCovarianceDiag(std::span<const double> d2, unsigned int n) override;
0303 
0304    /// set initial covariance matrix
0305    bool SetCovariance(std::span<const double> cov, unsigned int nrow) override;
0306 
0307 private:
0308    unsigned int fDim; // dimension of the function to be minimized
0309    bool fUseFumili;
0310    int fMinosStatus = -1; // Minos status code
0311 
0312    ROOT::Minuit2::MnUserParameterState fState;
0313    std::unique_ptr<ROOT::Minuit2::ModularFunctionMinimizer> fMinimizer;
0314    std::unique_ptr<ROOT::Minuit2::FCNBase> fMinuitFCN;
0315    std::unique_ptr<ROOT::Minuit2::FunctionMinimum> fMinimum;
0316    mutable std::vector<double> fValues;
0317    mutable std::vector<double> fErrors;
0318 };
0319 
0320 } // namespace Minuit2
0321 
0322 } // end namespace ROOT
0323 
0324 #endif /* ROOT_Minuit2_Minuit2Minimizer */