Minuit2Minimizer.cxx

Go to the documentation of this file.
00001 // @(#)root/minuit2:$Id$
00002 // Author: L. Moneta Wed Oct 18 11:48:00 2006
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
00007  *                                                                    *
00008  *                                                                    *
00009  **********************************************************************/
00010 
00011 // Implementation file for class Minuit2Minimizer
00012 
00013 #include "Minuit2/Minuit2Minimizer.h"
00014 
00015 #include "Math/IFunction.h"
00016 
00017 #include "Minuit2/FCNAdapter.h"
00018 #include "Minuit2/FumiliFCNAdapter.h"
00019 #include "Minuit2/FCNGradAdapter.h"
00020 #include "Minuit2/FunctionMinimum.h"
00021 #include "Minuit2/MnMigrad.h"
00022 #include "Minuit2/MnMinos.h"
00023 #include "Minuit2/MinosError.h"
00024 #include "Minuit2/MnHesse.h"
00025 #include "Minuit2/MinuitParameter.h"
00026 #include "Minuit2/MnUserFcn.h"
00027 #include "Minuit2/MnPrint.h"
00028 #include "Minuit2/FunctionMinimum.h"
00029 #include "Minuit2/VariableMetricMinimizer.h"
00030 #include "Minuit2/SimplexMinimizer.h"
00031 #include "Minuit2/CombinedMinimizer.h"
00032 #include "Minuit2/ScanMinimizer.h"
00033 #include "Minuit2/FumiliMinimizer.h"
00034 #include "Minuit2/MnParameterScan.h"
00035 #include "Minuit2/MnContours.h"
00036  
00037 
00038 
00039 #include <cassert> 
00040 #include <iostream> 
00041 #include <algorithm>
00042 #include <functional>
00043 
00044 
00045 namespace ROOT { 
00046 
00047 namespace Minuit2 { 
00048 
00049 
00050    // functions needed to control siwthc off of Minuit2 printing level 
00051 #ifdef USE_ROOT_ERROR
00052    int TurnOffPrintInfoLevel() { 
00053    // switch off Minuit2 printing of INfo message (cut off is 1001) 
00054    int prevErrorIgnoreLevel = gErrorIgnoreLevel; 
00055    if (prevErrorIgnoreLevel < 1001) { 
00056       gErrorIgnoreLevel = 1001; 
00057       return prevErrorIgnoreLevel; 
00058    }
00059    return -2;  // no op in this case  
00060 }
00061 
00062 void RestoreGlobalPrintLevel(int value) { 
00063       gErrorIgnoreLevel = value; 
00064 }
00065 #else
00066    // dummy functions
00067 int ControlPrintLevel( ) { return -1;}
00068 void RestoreGlobalPrintLevel(int ) {} 
00069 #endif      
00070 
00071       
00072 
00073 
00074 Minuit2Minimizer::Minuit2Minimizer(ROOT::Minuit2::EMinimizerType type ) : 
00075    Minimizer(),
00076    fDim(0),
00077    fMinimizer(0),
00078    fMinuitFCN(0),
00079    fMinimum(0)   
00080 {
00081    // Default constructor implementation depending on minimizer type 
00082    SetMinimizerType(type); 
00083 }
00084 
00085 Minuit2Minimizer::Minuit2Minimizer(const char *  type ) : 
00086    Minimizer(),
00087    fDim(0),
00088    fMinimizer(0),
00089    fMinuitFCN(0),
00090    fMinimum(0)   
00091 {   
00092    // constructor from a string
00093 
00094    std::string algoname(type);
00095    // tolower() is not an  std function (Windows)
00096    std::transform(algoname.begin(), algoname.end(), algoname.begin(), (int(*)(int)) tolower ); 
00097 
00098    EMinimizerType algoType = kMigrad; 
00099    if (algoname == "simplex")   algoType = kSimplex; 
00100    if (algoname == "minimize" ) algoType = kCombined; 
00101    if (algoname == "scan" )     algoType = kScan; 
00102    if (algoname == "fumili" )   algoType = kFumili;
00103   
00104    SetMinimizerType(algoType);
00105 }
00106 
00107 void Minuit2Minimizer::SetMinimizerType(ROOT::Minuit2::EMinimizerType type) {
00108    // Set  minimizer algorithm type 
00109    fUseFumili = false;
00110    switch (type) { 
00111    case ROOT::Minuit2::kMigrad: 
00112       //std::cout << "Minuit2Minimizer: minimize using MIGRAD " << std::endl;
00113       SetMinimizer( new ROOT::Minuit2::VariableMetricMinimizer() );
00114       return;
00115    case ROOT::Minuit2::kSimplex: 
00116       //std::cout << "Minuit2Minimizer: minimize using SIMPLEX " << std::endl;
00117       SetMinimizer( new ROOT::Minuit2::SimplexMinimizer() );
00118       return;
00119    case ROOT::Minuit2::kCombined: 
00120       SetMinimizer( new ROOT::Minuit2::CombinedMinimizer() );
00121       return;
00122    case ROOT::Minuit2::kScan: 
00123       SetMinimizer( new ROOT::Minuit2::ScanMinimizer() );
00124       return;
00125    case ROOT::Minuit2::kFumili:          
00126       SetMinimizer( new ROOT::Minuit2::FumiliMinimizer() );
00127       fUseFumili = true;
00128       return;
00129    default: 
00130       //migrad minimizer
00131       SetMinimizer( new ROOT::Minuit2::VariableMetricMinimizer() );
00132 
00133    }
00134 }
00135 
00136 
00137 Minuit2Minimizer::~Minuit2Minimizer() 
00138 {
00139    // Destructor implementation.
00140    if (fMinimizer) delete fMinimizer; 
00141    if (fMinuitFCN) delete fMinuitFCN; 
00142    if (fMinimum)   delete fMinimum; 
00143 }
00144 
00145 Minuit2Minimizer::Minuit2Minimizer(const Minuit2Minimizer &) : 
00146    ROOT::Math::Minimizer()
00147 {
00148    // Implementation of copy constructor.
00149 }
00150 
00151 Minuit2Minimizer & Minuit2Minimizer::operator = (const Minuit2Minimizer &rhs) 
00152 {
00153    // Implementation of assignment operator.
00154    if (this == &rhs) return *this;  // time saving self-test
00155    return *this;
00156 }
00157 
00158 
00159 void Minuit2Minimizer::Clear() { 
00160    // delete the state in case of consecutive minimizations
00161    fState = MnUserParameterState();
00162    // clear also the function minimum
00163    if (fMinimum) delete fMinimum; 
00164    fMinimum = 0;
00165 }
00166 
00167 
00168 // set variables 
00169 
00170 bool Minuit2Minimizer::SetVariable(unsigned int ivar, const std::string & name, double val, double step) { 
00171    // set a free variable. 
00172    // Add the variable if not existing otherwise  set value if exists already
00173    // this is implemented in MnUserParameterState::Add
00174    // if index is wrong (i.e. variable already exists but with a different index return false) but 
00175    // value is set for corresponding variable name
00176 
00177 //    std::cout << " add parameter " << name << "  " <<  val << " step " << step << std::endl;
00178 
00179    if (step <= 0) { 
00180       std::string txtmsg = "Parameter " + name + "  has zero or invalid step size - consider it as constant ";
00181       MN_INFO_MSG2("Minuit2Minimizer::SetVariable",txtmsg);
00182       fState.Add(name.c_str(), val);
00183    }
00184    else 
00185       fState.Add(name.c_str(), val, step); 
00186 
00187    unsigned int minuit2Index = fState.Index(name.c_str() ); 
00188    if ( minuit2Index != ivar) {
00189       std::string txtmsg("Wrong index used for the variable " + name);
00190       MN_INFO_MSG2("Minuit2Minimizer::SetVariable",txtmsg);  
00191       MN_INFO_VAL2("Minuit2Minimizer::SetVariable",minuit2Index);  
00192       ivar = minuit2Index;
00193       return false;
00194    }
00195 
00196    return true; 
00197 }
00198 
00199 bool Minuit2Minimizer::SetLowerLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double lower ) {
00200    // add a lower bounded variable
00201    if (!SetVariable(ivar, name, val, step) ) return false;
00202    fState.SetLowerLimit(ivar, lower);
00203    return true;
00204 }
00205 
00206 bool Minuit2Minimizer::SetUpperLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double upper ) {
00207    // add a upper bounded variable
00208    if (!SetVariable(ivar, name, val, step) ) return false;
00209    fState.SetUpperLimit(ivar, upper);
00210    return true;
00211 }
00212 
00213 
00214 
00215 bool Minuit2Minimizer::SetLimitedVariable(unsigned int ivar , const std::string & name , double val , double step , double lower , double upper) {
00216    // add a double bound variable
00217    if (!SetVariable(ivar, name, val, step) ) return false;
00218    fState.SetLimits(ivar, lower, upper);
00219    return true;
00220 }
00221 
00222 bool Minuit2Minimizer::SetFixedVariable(unsigned int ivar , const std::string & name , double val ) {
00223    // add a fixed variable
00224    // need a step size otherwise treated as a constant 
00225    // use 10% 
00226    double step = ( val != 0) ? 0.1 * std::abs(val) : 0.1;
00227    if (!SetVariable(ivar, name, val, step ) ) { 
00228       ivar = fState.Index(name.c_str() );      
00229    }
00230    fState.Fix(ivar);
00231    return true;
00232 }
00233 
00234 std::string Minuit2Minimizer::VariableName(unsigned int ivar) const { 
00235    // return the variable name
00236    if (ivar >= fState.MinuitParameters().size() ) return std::string();
00237    return fState.GetName(ivar);
00238 }
00239 
00240 
00241 int Minuit2Minimizer::VariableIndex(const std::string & name) const { 
00242    // return the variable index
00243    // check if variable exist
00244    return fState.Trafo().FindIndex(name);
00245 }
00246 
00247 
00248 bool Minuit2Minimizer::SetVariableValue(unsigned int ivar, double val) { 
00249    // set value for variable ivar (only for existing parameters)
00250    if (ivar >= fState.MinuitParameters().size() ) return false; 
00251    fState.SetValue(ivar, val);
00252    return true; 
00253 }
00254 
00255 bool Minuit2Minimizer::SetVariableValues(const double * x)  { 
00256    // set value for variable ivar (only for existing parameters)
00257    unsigned int n =  fState.MinuitParameters().size(); 
00258    if (n== 0) return false; 
00259    for (unsigned int ivar = 0; ivar < n; ++ivar) 
00260       fState.SetValue(ivar, x[ivar]);
00261    return true; 
00262 }
00263 
00264 
00265 void Minuit2Minimizer::SetFunction(const  ROOT::Math::IMultiGenFunction & func) { 
00266    // set function to be minimized
00267    if (fMinuitFCN) delete fMinuitFCN;
00268    fDim = func.NDim(); 
00269    if (!fUseFumili) {
00270       fMinuitFCN = new ROOT::Minuit2::FCNAdapter<ROOT::Math::IMultiGenFunction> (func, ErrorDef() );
00271    }
00272    else { 
00273       // for Fumili the fit method function interface is required
00274       const ROOT::Math::FitMethodFunction * fcnfunc = dynamic_cast<const ROOT::Math::FitMethodFunction *>(&func);
00275       if (!fcnfunc) {
00276          MN_ERROR_MSG("Minuit2Minimizer: Wrong Fit method function for Fumili");
00277          return;
00278       }
00279       fMinuitFCN = new ROOT::Minuit2::FumiliFCNAdapter<ROOT::Math::FitMethodFunction> (*fcnfunc, fDim, ErrorDef() );
00280    }
00281 }
00282 
00283 void Minuit2Minimizer::SetFunction(const  ROOT::Math::IMultiGradFunction & func) { 
00284    // set function to be minimized
00285    fDim = func.NDim(); 
00286    if (fMinuitFCN) delete fMinuitFCN;
00287    if (!fUseFumili) { 
00288       fMinuitFCN = new ROOT::Minuit2::FCNGradAdapter<ROOT::Math::IMultiGradFunction> (func, ErrorDef() );
00289    }
00290    else { 
00291       // for Fumili the fit method function interface is required
00292       const ROOT::Math::FitMethodGradFunction * fcnfunc = dynamic_cast<const ROOT::Math::FitMethodGradFunction*>(&func);
00293       if (!fcnfunc) {
00294          MN_ERROR_MSG("Minuit2Minimizer: Wrong Fit method function for Fumili");
00295          return;
00296       }
00297       fMinuitFCN = new ROOT::Minuit2::FumiliFCNAdapter<ROOT::Math::FitMethodGradFunction> (*fcnfunc, fDim, ErrorDef() );
00298    }
00299 }
00300                                    
00301 bool Minuit2Minimizer::Minimize() { 
00302    // perform the minimization
00303    // store a copy of FunctionMinimum 
00304    if (!fMinuitFCN) { 
00305       MN_ERROR_MSG2("Minuit2Minimizer::Minimize","FCN function has not been set");
00306       return false; 
00307   }
00308 
00309    assert(GetMinimizer() != 0 );
00310 
00311    // delete result of previous minimization
00312    if (fMinimum) delete fMinimum; 
00313    fMinimum = 0;
00314 
00315 
00316    int maxfcn = MaxFunctionCalls(); 
00317    double tol = Tolerance();
00318    int strategy = Strategy(); 
00319    fMinuitFCN->SetErrorDef(ErrorDef() );
00320 
00321    if (PrintLevel() >=1)
00322       std::cout << "Minuit2Minimizer: Minimize with max iterations " << maxfcn << " edmval " << tol << " strategy " 
00323                 << strategy << std::endl; 
00324 
00325    // switch off Minuit2 printing
00326    int prev_level = (PrintLevel() == 0 ) ?   TurnOffPrintInfoLevel() : -1; 
00327 
00328    // set the precision if needed
00329    if (Precision() > 0) fState.SetPrecision(Precision());
00330       
00331    const ROOT::Minuit2::FCNGradientBase * gradFCN = dynamic_cast<const ROOT::Minuit2::FCNGradientBase *>( fMinuitFCN ); 
00332    if ( gradFCN != 0) {
00333       // use gradient
00334       //SetPrintLevel(3);
00335       ROOT::Minuit2::FunctionMinimum min =  GetMinimizer()->Minimize(*gradFCN, fState, ROOT::Minuit2::MnStrategy(strategy), maxfcn, tol);
00336       fMinimum = new ROOT::Minuit2::FunctionMinimum (min);    
00337    }
00338    else {
00339       ROOT::Minuit2::FunctionMinimum min = GetMinimizer()->Minimize(*GetFCN(), fState, ROOT::Minuit2::MnStrategy(strategy), maxfcn, tol);
00340       fMinimum = new ROOT::Minuit2::FunctionMinimum (min);    
00341    }
00342 
00343    // check if Hesse needs to be run 
00344    if (fMinimum->IsValid() && IsValidError() && fMinimum->State().Error().Dcovar() != 0 ) {
00345       // run Hesse (Hesse will add results in the last state of fMinimum
00346       ROOT::Minuit2::MnHesse hesse(strategy );
00347       hesse( *fMinuitFCN, *fMinimum, maxfcn); 
00348    }
00349 
00350    // -2 is the highest low invalid value for gErrorIgnoreLevel
00351    if (prev_level > -2) RestoreGlobalPrintLevel(prev_level);
00352    
00353    fState = fMinimum->UserState(); 
00354    bool ok =  ExamineMinimum(*fMinimum);
00355    //fMinimum = 0; 
00356    return ok; 
00357 }
00358 
00359 bool  Minuit2Minimizer::ExamineMinimum(const ROOT::Minuit2::FunctionMinimum & min) {  
00360    /// study the function minimum      
00361    
00362    // debug ( print all the states) 
00363    int debugLevel = PrintLevel(); 
00364    if (debugLevel >= 3) { 
00365       
00366       const std::vector<ROOT::Minuit2::MinimumState>& iterationStates = min.States();
00367       std::cout << "Number of iterations " << iterationStates.size() << std::endl;
00368       for (unsigned int i = 0; i <  iterationStates.size(); ++i) {
00369          //std::cout << iterationStates[i] << std::endl;                                                                       
00370          const ROOT::Minuit2::MinimumState & st =  iterationStates[i];
00371          std::cout << "----------> Iteration " << i << std::endl;
00372          int pr = std::cout.precision(12);
00373          std::cout << "            FVAL = " << st.Fval() << " Edm = " << st.Edm() << " Nfcn = " << st.NFcn() << std::endl;
00374          std::cout.precision(pr);
00375          std::cout << "            Error matrix change = " << st.Error().Dcovar() << std::endl;
00376          std::cout << "            Parameters : ";
00377          // need to transform from internal to external 
00378          for (int j = 0; j < st.size() ; ++j) std::cout << " p" << j << " = " << fState.Int2ext( j, st.Vec()(j) );
00379          std::cout << std::endl;
00380       }
00381    }
00382 
00383    fStatus = 0;
00384    std::string txt;
00385    if (min.HasMadePosDefCovar() ) { 
00386       txt = "Covar was made pos def";
00387       fStatus = 1; 
00388    }
00389    if (min.HesseFailed() ) { 
00390       txt = "Hesse is not valid";
00391       fStatus = 2; 
00392    }
00393    if (min.IsAboveMaxEdm() ) { 
00394       txt = "Edm is above max"; 
00395       fStatus = 3; 
00396    }
00397    if (min.HasReachedCallLimit() ) { 
00398       txt = "Reached call limit";
00399       fStatus = 4;
00400    }
00401 
00402    
00403    bool validMinimum = min.IsValid();
00404    if (validMinimum) { 
00405       // print a warning message in case something is not ok
00406       if (fStatus != 0)  MN_INFO_MSG2("Minuit2Minimizer::Minimize",txt);
00407    }
00408    else { 
00409       // minimum is not valid when state is not valid and edm is over max or has passed call limits
00410       if (fStatus == 0) { 
00411          // this should not happen
00412          txt = "unknown failure";  
00413          fStatus = 5;
00414       }
00415       std::string msg = "Minimization did NOT converge, " + txt;
00416       MN_INFO_MSG2("Minuit2Minimizer::Minimize",msg);                   
00417    }
00418 
00419    if (debugLevel >= 1) PrintResults(); 
00420    return validMinimum;
00421 }
00422 
00423 
00424 void Minuit2Minimizer::PrintResults() {
00425    // print results of minimization
00426    if (!fMinimum) return;
00427    if (fMinimum->IsValid() ) {
00428       // valid minimum
00429       std::cout << "Minuit2Minimizer : Valid minimum - status = " << fStatus  << std::endl; 
00430       int pr = std::cout.precision(18);
00431       std::cout << "FVAL  = " << fState.Fval() << std::endl;
00432       std::cout << "Edm   = " << fState.Edm() << std::endl;
00433       std::cout.precision(pr);
00434       std::cout << "Nfcn  = " << fState.NFcn() << std::endl;
00435       for (unsigned int i = 0; i < fState.MinuitParameters().size(); ++i) {
00436          const MinuitParameter & par = fState.Parameter(i); 
00437          std::cout << par.Name() << "\t  = " << par.Value() << "\t ";
00438          if (par.IsFixed() )      std::cout << "(fixed)" << std::endl;
00439          else if (par.IsConst() ) std::cout << "(const)" << std::endl;
00440          else if (par.HasLimits() ) 
00441             std::cout << "+/-  " << par.Error() << "\t(limited)"<< std::endl; 
00442          else 
00443             std::cout << "+/-  " << par.Error() << std::endl; 
00444       }
00445    }
00446    else { 
00447       std::cout << "Minuit2Minimizer : Invalid Minimum - status = " << fStatus << std::endl; 
00448       std::cout << "FVAL  = " << fState.Fval() << std::endl;
00449       std::cout << "Edm   = " << fState.Edm() << std::endl;
00450       std::cout << "Nfcn  = " << fState.NFcn() << std::endl;
00451    }
00452 }
00453 
00454 
00455 const double * Minuit2Minimizer::Errors() const { 
00456    // return error at minimum (set to zero for fixed and constant params)
00457    fErrors.resize(fState.MinuitParameters().size() );
00458    for (unsigned int i = 0; i < fErrors.size(); ++i) { 
00459       const MinuitParameter & par = fState.Parameter(i); 
00460       if (par.IsFixed() || par.IsConst() ) 
00461          fErrors[i] = 0; 
00462       else 
00463          fErrors[i] = par.Error();
00464    }
00465 
00466    return  (fErrors.size()) ? &fErrors.front() : 0; 
00467 }
00468 
00469 
00470 double Minuit2Minimizer::CovMatrix(unsigned int i, unsigned int j) const { 
00471    // get value of covariance matrices (transform from external to internal indices)
00472    if ( i >= fDim || i >= fDim) return 0;  
00473    if ( Status()  || !fState.HasCovariance()    ) return 0; // no info available when minimization has failed
00474    if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst() ) return 0; 
00475    if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst() ) return 0; 
00476    unsigned int k = fState.IntOfExt(i); 
00477    unsigned int l = fState.IntOfExt(j); 
00478    return fState.Covariance()(k,l); 
00479 }
00480 
00481 double Minuit2Minimizer::Correlation(unsigned int i, unsigned int j) const { 
00482    // get correlation between parameter i and j 
00483    if ( i >= fDim || i >= fDim) return 0;  
00484    if ( Status()  || !fState.HasCovariance()    ) return 0; // no info available when minimization has failed
00485    if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst() ) return 0; 
00486    if (fState.Parameter(j).IsFixed() || fState.Parameter(j).IsConst() ) return 0; 
00487    unsigned int k = fState.IntOfExt(i); 
00488    unsigned int l = fState.IntOfExt(j); 
00489    double cij =  fState.IntCovariance()(k,l); 
00490    double tmp =  std::sqrt( std::abs ( fState.IntCovariance()(k,k) * fState.IntCovariance()(l,l) ) );
00491    if (tmp > 0 ) return cij/tmp; 
00492    return 0; 
00493 }
00494 
00495 double Minuit2Minimizer::GlobalCC(unsigned int i) const { 
00496    // get global correlation coefficient for the parameter i. This is a number between zero and one which gives 
00497    // the correlation between the i-th parameter  and that linear combination of all other parameters which 
00498    // is most strongly correlated with i.
00499 
00500    if ( i >= fDim || i >= fDim) return 0;  
00501     // no info available when minimization has failed or has some problems
00502    if ( !fState.HasGlobalCC()    ) return 0; 
00503    if (fState.Parameter(i).IsFixed() || fState.Parameter(i).IsConst() ) return 0; 
00504    unsigned int k = fState.IntOfExt(i); 
00505    return fState.GlobalCC().GlobalCC()[k]; 
00506 }
00507 
00508 
00509 bool Minuit2Minimizer::GetMinosError(unsigned int i, double & errLow, double & errUp, int runopt) { 
00510    // return the minos error for parameter i
00511    // if a minimum does not exist an error is returned
00512    // runopt is a flag which specifies if only lower or upper error needs to be run
00513    // if runopt = 0 both, = 1 only lower, + 2 only upper errors
00514    errLow = 0; errUp = 0; 
00515    bool runLower = runopt != 2;
00516    bool runUpper = runopt != 1;
00517 
00518    assert( fMinuitFCN );
00519 
00520    // need to know if parameter is const or fixed 
00521    if ( fState.Parameter(i).IsConst() || fState.Parameter(i).IsFixed() ) { 
00522       return false; 
00523    }
00524 
00525    int debugLevel = PrintLevel(); 
00526 
00527    // to run minos I need function minimum class 
00528    // redo minimization from current state
00529 //    ROOT::Minuit2::FunctionMinimum min =  
00530 //       GetMinimizer()->Minimize(*GetFCN(),fState, ROOT::Minuit2::MnStrategy(strategy), MaxFunctionCalls(), Tolerance());
00531 //    fState = min.UserState();
00532    if (fMinimum == 0) { 
00533       MN_ERROR_MSG("Minuit2Minimizer::GetMinosErrors:  failed - no function minimum existing");
00534       return false;
00535    }
00536    
00537    if (!fMinimum->IsValid() ) { 
00538       MN_ERROR_MSG("Minuit2Minimizer::MINOS failed due to invalid function minimum");
00539       return false;
00540    }
00541 
00542    fMinuitFCN->SetErrorDef(ErrorDef() );
00543    // if error def has been changed update it in FunctionMinimum
00544    if (ErrorDef() != fMinimum->Up() ) 
00545       fMinimum->SetErrorDef(ErrorDef() );
00546 
00547    // switch off Minuit2 printing
00548    int prev_level = (PrintLevel() == 0 ) ?   TurnOffPrintInfoLevel() : -1; 
00549 
00550    // set the precision if needed
00551    if (Precision() > 0) fState.SetPrecision(Precision());
00552 
00553 
00554    ROOT::Minuit2::MnMinos minos( *fMinuitFCN, *fMinimum);
00555 
00556    // run MnCross 
00557    MnCross low;
00558    MnCross up;
00559    if (runLower) low = minos.Loval(i);
00560    if (runUpper) up  = minos.Upval(i);
00561  
00562    ROOT::Minuit2::MinosError me(i, fMinimum->UserState().Value(i),low, up);
00563 
00564    if (prev_level >= 0) RestoreGlobalPrintLevel(prev_level);
00565 
00566    // debug result of Minos 
00567    // print error message in Minos
00568 
00569    if (debugLevel >= 1) {
00570       if (runLower) { 
00571          if (!me.LowerValid() )  
00572             std::cout << "Minos:  Invalid lower error for parameter " << i << std::endl; 
00573          if(me.AtLowerLimit()) 
00574             std::cout << "Minos:  Parameter  is at Lower limit."<<std::endl;
00575          if(me.AtLowerMaxFcn())
00576             std::cout << "Minos:  Maximum number of function calls exceeded when running for lower error" <<std::endl;   
00577          if(me.LowerNewMin() )
00578             std::cout << "Minos:  New Minimum found while running Minos for lower error" <<std::endl;     
00579 
00580          if (debugLevel > 1)  std::cout << "Minos: Lower error for parameter " << i << "  :  " << me.Lower() << std::endl; 
00581 
00582       }
00583       if (runUpper) {          
00584          if (!me.UpperValid() )  
00585             std::cout << "Minos:  Invalid upper error for parameter " << i << std::endl; 
00586          if(me.AtUpperLimit()) 
00587             std::cout << "Minos:  Parameter  is at Upper limit."<<std::endl;
00588          if(me.AtUpperMaxFcn())
00589             std::cout << "Minos:  Maximum number of function calls exceeded when running for upper error" <<std::endl;   
00590          if(me.UpperNewMin() )
00591             std::cout << "Minos:  New Minimum found while running Minos for upper error" <<std::endl;              
00592 
00593          if (debugLevel > 1)  std::cout << "Minos: Upper error for parameter " << i << "  :  " << me.Upper() << std::endl;
00594       }
00595       
00596    }
00597 
00598    bool isValid = true; 
00599    if (runLower && !me.LowerValid() ) isValid = false; 
00600    if (runUpper && !me.UpperValid() ) isValid = false; 
00601    if ( !isValid ) { 
00602       //std::cout << "Error running Minos for parameter " << i << std::endl; 
00603       int mstatus = 5; 
00604       if (me.AtLowerMaxFcn() ) mstatus = 1; 
00605       if (me.AtUpperMaxFcn() ) mstatus = 2; 
00606       if (me.LowerNewMin() ) mstatus = 3; 
00607       if (me.UpperNewMin() ) mstatus = 4; 
00608       fStatus += 10*mstatus; 
00609       return false; 
00610    }
00611          
00612    errLow = me.Lower();
00613    errUp = me.Upper();
00614       
00615    return true;
00616 } 
00617 
00618 bool Minuit2Minimizer::Scan(unsigned int ipar, unsigned int & nstep, double * x, double * y, double xmin, double xmax) { 
00619    // scan a parameter (variable) around the minimum value
00620    // the parameters must have been set before 
00621    // if xmin=0 && xmax == 0  by default scan around 2 sigma of the error
00622    // if the errors  are also zero then scan from min and max of parameter range
00623 
00624    if (!fMinuitFCN) { 
00625       MN_ERROR_MSG2("Minuit2Minimizer::Scan"," Function must be set before using Scan");
00626       return false;
00627    }
00628    
00629    if ( ipar > fState.MinuitParameters().size() ) { 
00630       MN_ERROR_MSG2("Minuit2Minimizer::Scan"," Invalid number. Minimizer variables must be set before using Scan");
00631       return false;
00632    }
00633 
00634    // switch off Minuit2 printing
00635    int prev_level = (PrintLevel() == 0 ) ?   TurnOffPrintInfoLevel() : -1; 
00636 
00637    // set the precision if needed
00638    if (Precision() > 0) fState.SetPrecision(Precision());
00639 
00640    MnParameterScan scan( *fMinuitFCN, fState.Parameters() );
00641    double amin = scan.Fval(); // fcn value of the function before scan 
00642 
00643    // first value is param value
00644    std::vector<std::pair<double, double> > result = scan(ipar, nstep-1, xmin, xmax);
00645 
00646    if (prev_level >= 0) RestoreGlobalPrintLevel(prev_level);
00647 
00648    if (result.size() != nstep) { 
00649       MN_ERROR_MSG2("Minuit2Minimizer::Scan"," Invalid result from MnParameterScan");
00650       return false; 
00651    }
00652    // sort also the returned points in x
00653    std::sort(result.begin(), result.end() );
00654 
00655 
00656    for (unsigned int i = 0; i < nstep; ++i ) { 
00657       x[i] = result[i].first; 
00658       y[i] = result[i].second; 
00659    }
00660 
00661    // what to do if a new minimum has been found ? 
00662    // use that as new minimum
00663    if (scan.Fval() < amin ) { 
00664       MN_INFO_MSG2("Minuit2Minimizer::Scan","A new minimum has been found");
00665       fState.SetValue(ipar, scan.Parameters().Value(ipar) );
00666          
00667    }
00668 
00669 
00670    return true; 
00671 }
00672 
00673 bool Minuit2Minimizer::Contour(unsigned int ipar, unsigned int jpar, unsigned int & npoints, double * x, double * y) {
00674    // contour plot for parameter i and j
00675    // need a valid FunctionMinimum otherwise exits
00676    if (fMinimum == 0) { 
00677       MN_ERROR_MSG2("Minuit2Minimizer::Contour"," no function minimum existing. Must minimize function before");
00678       return false;
00679    }
00680 
00681    if (!fMinimum->IsValid() ) { 
00682       MN_ERROR_MSG2("Minuit2Minimizer::Contour","Invalid function minimum");
00683       return false;
00684    }
00685    assert(fMinuitFCN); 
00686 
00687    fMinuitFCN->SetErrorDef(ErrorDef() );
00688    // if error def has been changed update it in FunctionMinimum
00689    if (ErrorDef() != fMinimum->Up() ) 
00690       fMinimum->SetErrorDef(ErrorDef() );
00691 
00692    // switch off Minuit2 printing (for level of  0,1)
00693    int prev_level = (PrintLevel() <= 1 ) ?   TurnOffPrintInfoLevel() : -1; 
00694 
00695    // set the precision if needed
00696    if (Precision() > 0) fState.SetPrecision(Precision());
00697 
00698    // eventually one should specify tolerance in contours 
00699    MnContours contour(*fMinuitFCN, *fMinimum, Strategy() ); 
00700    
00701    if (prev_level >= 0) RestoreGlobalPrintLevel(prev_level);
00702 
00703    std::vector<std::pair<double,double> >  result = contour(ipar,jpar, npoints);
00704    if (result.size() != npoints) { 
00705       MN_ERROR_MSG2("Minuit2Minimizer::Contour"," Invalid result from MnContours");
00706       return false; 
00707    }
00708    for (unsigned int i = 0; i < npoints; ++i ) { 
00709       x[i] = result[i].first; 
00710       y[i] = result[i].second; 
00711    }
00712 
00713 
00714    return true;
00715    
00716 
00717 }
00718 
00719 bool Minuit2Minimizer::Hesse( ) { 
00720     // find Hessian (full second derivative calculations)
00721    // the contained state will be updated with the Hessian result
00722    // in case a function minimum exists and is valid the result will be 
00723    // appended in the function minimum
00724 
00725    if (!fMinuitFCN) { 
00726       MN_ERROR_MSG2("Minuit2Minimizer::Hesse","FCN function has not been set");
00727       return false; 
00728    }
00729 
00730    int strategy = Strategy();
00731    int maxfcn = MaxFunctionCalls(); 
00732 
00733    // switch off Minuit2 printing
00734    int prev_level = (PrintLevel() == 0 ) ?   TurnOffPrintInfoLevel() : -1; 
00735 
00736    // set the precision if needed
00737    if (Precision() > 0) fState.SetPrecision(Precision());
00738 
00739    ROOT::Minuit2::MnHesse hesse( strategy );
00740 
00741    // case when function minimum exists
00742    if (fMinimum  ) { 
00743       // run hesse and function minimum will be updated with Hesse result
00744       hesse( *fMinuitFCN, *fMinimum, maxfcn ); 
00745       fState = fMinimum->UserState(); 
00746    }
00747 
00748    else { 
00749       // run Hesse on point stored in current state (independent of function minimum validity)
00750       // (x == 0) 
00751       fState = hesse( *fMinuitFCN, fState, maxfcn); 
00752    }
00753 
00754    if (prev_level >= 0) RestoreGlobalPrintLevel(prev_level);
00755 
00756    if (PrintLevel() >= 3) { 
00757       std::cout << fState << std::endl; 
00758    }
00759 
00760    if (!fState.HasCovariance() ) { 
00761       // if false means error is not valid and this is due to a failure in Hesse
00762       if (PrintLevel() > 0) MN_INFO_MSG2("Minuit2Minimizer::Hesse","Hesse failed ");
00763       // update minimizer error status 
00764       int hstatus = 4;
00765       // informationon error state can be retrieved only if fMinimum is available
00766       if (fMinimum) { 
00767          if (fMinimum->Error().HesseFailed() ) hstatus = 1;
00768          if (fMinimum->Error().InvertFailed() ) hstatus = 2;
00769          else if (!(fMinimum->Error().IsPosDef()) ) hstatus = 3;
00770       }
00771       fStatus += 100*hstatus; 
00772       return false; 
00773    }
00774 
00775    return true;       
00776 }
00777 
00778 int Minuit2Minimizer::CovMatrixStatus() const { 
00779    // return status of covariance matrix 
00780    // 0 - no covariance available 
00781    // 1 - covariance only approximate
00782    // 2 full matrix but forced pos def 
00783    // 3 full accurate matrix 
00784 
00785    if (fMinimum) {
00786       // case a function minimum  is available 
00787       if (fMinimum->HasAccurateCovar() ) return 3; 
00788       else if (fMinimum->HasMadePosDefCovar() ) return 2; 
00789       else if (fMinimum->HasCovariance() ) return 1; 
00790    }
00791    else { 
00792       // case fMinimum is not available 
00793       if (fState.HasCovariance()) return 1; 
00794    }
00795    return 0; 
00796 }
00797 
00798 
00799    
00800 } // end namespace Minuit2
00801 
00802 } // end namespace ROOT
00803 

Generated on Tue Jul 5 14:37:09 2011 for ROOT_528-00b_version by  doxygen 1.5.1