RooMinimizerFcn.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooMinimizerFcn.cxx 36222 2010-10-09 18:27:06Z wouter $
00005  * Authors:                                                                  *
00006  *   AL, Alfio Lazzaro,   INFN Milan,        alfio.lazzaro@mi.infn.it        *
00007  *                                                                           *
00008  *                                                                           *
00009  * Redistribution and use in source and binary forms,                        *
00010  * with or without modification, are permitted according to the terms        *
00011  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00012  *****************************************************************************/
00013 
00014 #ifndef __ROOFIT_NOROOMINIMIZER
00015 
00016 //////////////////////////////////////////////////////////////////////////////
00017 //
00018 // RooMinimizerFcn is am interface class to the ROOT::Math function 
00019 // for minization.
00020 //                                                                                   
00021 
00022 #include <iostream>
00023 
00024 #include "RooFit.h"
00025 #include "RooMinimizerFcn.h"
00026 
00027 #include "Riostream.h"
00028 
00029 #include "TIterator.h"
00030 #include "TClass.h"
00031 
00032 #include "RooAbsArg.h"
00033 #include "RooAbsPdf.h"
00034 #include "RooArgSet.h"
00035 #include "RooRealVar.h"
00036 #include "RooAbsRealLValue.h"
00037 #include "RooMsgService.h"
00038 
00039 #include "RooMinimizer.h"
00040 
00041 RooMinimizerFcn::RooMinimizerFcn(RooAbsReal *funct, RooMinimizer* context,
00042                            bool verbose) :
00043   _funct(funct), _context(context),
00044   // Reset the *largest* negative log-likelihood value we have seen so far
00045   _maxFCN(-1e30), _numBadNLL(0),  
00046   _printEvalErrors(10), _doEvalErrorWall(kTRUE),
00047   _nDim(0), _logfile(0),
00048   _verbose(verbose)
00049 { 
00050 
00051   // Examine parameter list
00052   RooArgSet* paramSet = _funct->getParameters(RooArgSet());
00053   RooArgList paramList(*paramSet);
00054   delete paramSet;
00055 
00056   _floatParamList = (RooArgList*) paramList.selectByAttrib("Constant",kFALSE);
00057   if (_floatParamList->getSize()>1) {
00058     _floatParamList->sort();
00059   }
00060   _floatParamList->setName("floatParamList");
00061 
00062   _constParamList = (RooArgList*) paramList.selectByAttrib("Constant",kTRUE);
00063   if (_constParamList->getSize()>1) {
00064     _constParamList->sort();
00065   }
00066   _constParamList->setName("constParamList");
00067 
00068   // Remove all non-RooRealVar parameters from list (MINUIT cannot handle them)
00069   TIterator* pIter = _floatParamList->createIterator();
00070   RooAbsArg* arg;
00071   while ((arg=(RooAbsArg*)pIter->Next())) {
00072     if (!arg->IsA()->InheritsFrom(RooAbsRealLValue::Class())) {
00073       oocoutW(_context,Minimization) << "RooMinimizerFcn::RooMinimizerFcn: removing parameter " 
00074                                      << arg->GetName()
00075                                      << " from list because it is not of type RooRealVar" << endl;
00076       _floatParamList->remove(*arg);
00077     }
00078   }
00079   delete pIter;
00080 
00081   _nDim = _floatParamList->getSize();
00082   
00083   // Save snapshot of initial lists
00084   _initFloatParamList = (RooArgList*) _floatParamList->snapshot(kFALSE) ;
00085   _initConstParamList = (RooArgList*) _constParamList->snapshot(kFALSE) ;
00086 
00087 }
00088 
00089 RooMinimizerFcn::~RooMinimizerFcn()
00090 {
00091   delete _floatParamList;
00092   delete _initFloatParamList;
00093   delete _constParamList;
00094   delete _initConstParamList;
00095 }
00096 
00097 ROOT::Math::IBaseFunctionMultiDim* RooMinimizerFcn::Clone() const 
00098 {  
00099   return new RooMinimizerFcn(_funct,_context,_verbose);
00100 }
00101 
00102 Bool_t RooMinimizerFcn::Synchronize(std::vector<ROOT::Fit::ParameterSettings>& parameters, 
00103                                  Bool_t optConst, Bool_t verbose)
00104 {
00105 
00106   // Internal function to synchronize TMinimizer with current
00107   // information in RooAbsReal function parameters
00108   
00109   Bool_t constValChange(kFALSE) ;
00110   Bool_t constStatChange(kFALSE) ;
00111   
00112   Int_t index(0) ;
00113   
00114   // Handle eventual migrations from constParamList -> floatParamList
00115   for(index= 0; index < _constParamList->getSize() ; index++) {
00116 
00117     RooRealVar *par= dynamic_cast<RooRealVar*>(_constParamList->at(index)) ;
00118     if (!par) continue ;
00119 
00120     RooRealVar *oldpar= dynamic_cast<RooRealVar*>(_initConstParamList->at(index)) ;
00121     if (!oldpar) continue ;
00122 
00123     // Test if constness changed
00124     if (!par->isConstant()) {      
00125     
00126       // Remove from constList, add to floatList
00127       _constParamList->remove(*par) ;
00128       _floatParamList->add(*par) ;
00129       _initFloatParamList->addClone(*oldpar) ;      
00130       _initConstParamList->remove(*oldpar) ;
00131       constStatChange=kTRUE ;
00132       _nDim++ ;
00133 
00134       if (verbose) {
00135         oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: parameter " 
00136                                      << par->GetName() << " is now floating." << endl ;
00137       }
00138     } 
00139 
00140     // Test if value changed
00141     if (par->getVal()!= oldpar->getVal()) {
00142       constValChange=kTRUE ;      
00143       if (verbose) {
00144         oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: value of constant parameter " 
00145                                        << par->GetName() 
00146                                        << " changed from " << oldpar->getVal() << " to " 
00147                                        << par->getVal() << endl ;
00148       }
00149     }
00150 
00151   }
00152 
00153   // Update reference list
00154   *_initConstParamList = *_constParamList ;
00155   
00156   // Synchronize MINUIT with function state
00157   // Handle floatParamList
00158   for(index= 0; index < _floatParamList->getSize(); index++) {
00159     RooRealVar *par= dynamic_cast<RooRealVar*>(_floatParamList->at(index)) ;
00160     if (!par) continue ;
00161 
00162     Double_t pstep(0) ;
00163     Double_t pmin(0) ;
00164     Double_t pmax(0) ;
00165 
00166     if(!par->isConstant()) {
00167 
00168       // Verify that floating parameter is indeed of type RooRealVar 
00169       if (!par->IsA()->InheritsFrom(RooRealVar::Class())) {
00170         oocoutW(_context,Minimization) << "RooMinimizerFcn::fit: Error, non-constant parameter " 
00171                                        << par->GetName() 
00172                                        << " is not of type RooRealVar, skipping" << endl ;
00173         _floatParamList->remove(*par);
00174         index--;
00175         _nDim--;
00176         continue ;
00177       }
00178 
00179       // Set the limits, if not infinite
00180       if (par->hasMin() && par->hasMax()) {
00181         pmin = par->getMin();
00182         pmax = par->getMax();
00183       }
00184       
00185       // Calculate step size
00186       pstep = par->getError();
00187       if(pstep <= 0) {
00188         // Floating parameter without error estitimate
00189         if (par->hasMin() && par->hasMax()) {
00190           pstep= 0.1*(pmax-pmin);
00191 
00192           // Trim default choice of error if within 2 sigma of limit
00193           if (pmax - par->getVal() < 2*pstep) {
00194             pstep = (pmax - par->getVal())/2 ;
00195           } else if (par->getVal() - pmin < 2*pstep) {
00196             pstep = (par->getVal() - pmin )/2 ;     
00197           }       
00198 
00199           // If trimming results in zero error, restore default
00200           if (pstep==0) {
00201             pstep= 0.1*(pmax-pmin);
00202           }
00203 
00204         } else {
00205           pstep=1 ;
00206         }                                                 
00207         if(verbose) {
00208           oocoutW(_context,Minimization) << "RooMinimizerFcn::synchronize: WARNING: no initial error estimate available for "
00209                                          << par->GetName() << ": using " << pstep << endl;
00210         }
00211       }       
00212     } else {
00213       pmin = par->getVal() ;
00214       pmax = par->getVal() ;      
00215     }
00216 
00217     // new parameter
00218     if (index>=Int_t(parameters.size())) {
00219 
00220       if (par->hasMin() && par->hasMax()) {
00221         parameters.push_back(ROOT::Fit::ParameterSettings(par->GetName(),
00222                                                           par->getVal(),
00223                                                           pstep,
00224                                                           pmin,pmax));
00225       } else {
00226         parameters.push_back(ROOT::Fit::ParameterSettings(par->GetName(),
00227                                                           par->getVal(),
00228                                                           pstep));
00229       }
00230       
00231       continue;
00232 
00233     }
00234 
00235     Bool_t oldFixed = parameters[index].IsFixed();
00236     Double_t oldVar = parameters[index].Value();
00237     Double_t oldVerr = parameters[index].StepSize();
00238     Double_t oldVlo = parameters[index].LowerLimit();
00239     Double_t oldVhi = parameters[index].UpperLimit();
00240 
00241     if (par->isConstant() && !oldFixed) {
00242 
00243       // Parameter changes floating -> constant : update only value if necessary
00244       if (oldVar!=par->getVal()) {
00245         parameters[index].SetValue(par->getVal());
00246         if (verbose) {
00247           oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: value of parameter " 
00248                                          << par->GetName() << " changed from " << oldVar 
00249                                          << " to " << par->getVal() << endl ;
00250         }
00251       }
00252       parameters[index].Fix();
00253       constStatChange=kTRUE ;
00254       if (verbose) {
00255         oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: parameter " 
00256                                        << par->GetName() << " is now fixed." << endl ;
00257       }
00258 
00259     } else if (par->isConstant() && oldFixed) {
00260       
00261       // Parameter changes constant -> constant : update only value if necessary
00262       if (oldVar!=par->getVal()) {
00263         parameters[index].SetValue(par->getVal());
00264         constValChange=kTRUE ;
00265 
00266         if (verbose) {
00267           oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: value of fixed parameter " 
00268                                          << par->GetName() << " changed from " << oldVar 
00269                                          << " to " << par->getVal() << endl ;
00270         }
00271       }
00272 
00273     } else {
00274       // Parameter changes constant -> floating
00275       if (!par->isConstant() && oldFixed) {
00276         parameters[index].Release();
00277         constStatChange=kTRUE ;
00278         
00279         if (verbose) {
00280           oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: parameter " 
00281                                          << par->GetName() << " is now floating." << endl ;
00282         }
00283       } 
00284 
00285       // Parameter changes constant -> floating : update all if necessary      
00286       if (oldVar!=par->getVal() || oldVlo!=pmin || oldVhi != pmax || oldVerr!=pstep) {
00287         parameters[index].SetValue(par->getVal()); 
00288         parameters[index].SetStepSize(pstep);
00289         parameters[index].SetLimits(pmin,pmax);  
00290       }
00291 
00292       // Inform user about changes in verbose mode
00293       if (verbose) {
00294         // if ierr<0, par was moved from the const list and a message was already printed
00295 
00296         if (oldVar!=par->getVal()) {
00297           oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: value of parameter " 
00298                                          << par->GetName() << " changed from " << oldVar << " to " 
00299                                          << par->getVal() << endl ;
00300         }
00301         if (oldVlo!=pmin || oldVhi!=pmax) {
00302           oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: limits of parameter " 
00303                                          << par->GetName() << " changed from [" << oldVlo << "," << oldVhi 
00304                                          << "] to [" << pmin << "," << pmax << "]" << endl ;
00305         }
00306 
00307         // If oldVerr=0, then parameter was previously fixed
00308         if (oldVerr!=pstep && oldVerr!=0) {
00309           oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: error/step size of parameter " 
00310                                          << par->GetName() << " changed from " << oldVerr << " to " << pstep << endl ;
00311         }
00312       }      
00313     }
00314   }
00315 
00316   if (optConst) {
00317     if (constStatChange) {
00318 
00319       RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
00320 
00321       oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: set of constant parameters changed, rerunning const optimizer" << endl ;
00322       _funct->constOptimizeTestStatistic(RooAbsArg::ConfigChange) ;
00323     } else if (constValChange) {
00324       oocoutI(_context,Minimization) << "RooMinimizerFcn::synchronize: constant parameter values changed, rerunning const optimizer" << endl ;
00325       _funct->constOptimizeTestStatistic(RooAbsArg::ValueChange) ;
00326     }
00327     
00328     RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;  
00329 
00330   }
00331 
00332   return 0 ;  
00333 
00334 }
00335 
00336 Double_t RooMinimizerFcn::GetPdfParamVal(Int_t index)
00337 {
00338   // Access PDF parameter value by ordinal index (needed by MINUIT)
00339 
00340   return ((RooRealVar*)_floatParamList->at(index))->getVal() ;
00341 }
00342 
00343 Double_t RooMinimizerFcn::GetPdfParamErr(Int_t index)
00344 {
00345   // Access PDF parameter error by ordinal index (needed by MINUIT)
00346   return ((RooRealVar*)_floatParamList->at(index))->getError() ;
00347 }
00348 
00349 
00350 void RooMinimizerFcn::SetPdfParamErr(Int_t index, Double_t value)
00351 {
00352   // Modify PDF parameter error by ordinal index (needed by MINUIT)
00353 
00354   ((RooRealVar*)_floatParamList->at(index))->setError(value) ;
00355 }
00356 
00357 
00358 
00359 void RooMinimizerFcn::ClearPdfParamAsymErr(Int_t index)
00360 {
00361   // Modify PDF parameter error by ordinal index (needed by MINUIT)
00362 
00363   ((RooRealVar*)_floatParamList->at(index))->removeAsymError() ;
00364 }
00365 
00366 
00367 void RooMinimizerFcn::SetPdfParamErr(Int_t index, Double_t loVal, Double_t hiVal)
00368 {
00369   // Modify PDF parameter error by ordinal index (needed by MINUIT)
00370 
00371   ((RooRealVar*)_floatParamList->at(index))->setAsymError(loVal,hiVal) ;
00372 }
00373 
00374 
00375 void RooMinimizerFcn::BackProp(const ROOT::Fit::FitResult &results)
00376 {
00377   // Transfer MINUIT fit results back into RooFit objects
00378 
00379   for (Int_t index= 0; index < _nDim; index++) {
00380     Double_t value = results.Value(index);
00381     SetPdfParamVal(index, value);
00382 
00383     // Set the parabolic error    
00384     Double_t err = results.Error(index);
00385     SetPdfParamErr(index, err);
00386     
00387     Double_t eminus = results.LowerError(index);
00388     Double_t eplus = results.UpperError(index);
00389 
00390     if(eplus > 0 || eminus < 0) {
00391       // Store the asymmetric error, if it is available
00392       SetPdfParamErr(index, eminus,eplus);
00393     } else {
00394       // Clear the asymmetric error
00395       ClearPdfParamAsymErr(index) ;
00396     }
00397   }
00398 
00399 }
00400 
00401 Bool_t RooMinimizerFcn::SetLogFile(const char* inLogfile) 
00402 {
00403   // Change the file name for logging of a RooMinimizer of all MINUIT steppings
00404   // through the parameter space. If inLogfile is null, the current log file
00405   // is closed and logging is stopped.
00406 
00407   if (_logfile) {
00408     oocoutI(_context,Minimization) << "RooMinimizerFcn::setLogFile: closing previous log file" << endl ;
00409     _logfile->close() ;
00410     delete _logfile ;
00411     _logfile = 0 ;
00412   }
00413   _logfile = new ofstream(inLogfile) ;
00414   if (!_logfile->good()) {
00415     oocoutI(_context,Minimization) << "RooMinimizerFcn::setLogFile: cannot open file " << inLogfile << endl ;
00416     _logfile->close() ;
00417     delete _logfile ;
00418     _logfile= 0;
00419   }  
00420   
00421   return kFALSE ;
00422 
00423 }
00424 
00425 
00426 void RooMinimizerFcn::ApplyCovarianceMatrix(TMatrixDSym& V) 
00427 {
00428   // Apply results of given external covariance matrix. i.e. propagate its errors
00429   // to all RRV parameter representations and give this matrix instead of the
00430   // HESSE matrix at the next save() call
00431 
00432   for (Int_t i=0 ; i<_nDim ; i++) {
00433     // Skip fixed parameters
00434     if (_floatParamList->at(i)->isConstant()) {
00435       continue ;
00436     }
00437     SetPdfParamErr(i, sqrt(V(i,i))) ;             
00438   }
00439 
00440 }
00441 
00442 
00443 Bool_t RooMinimizerFcn::SetPdfParamVal(const Int_t &index, const Double_t &value) const
00444 {
00445   RooRealVar* par = (RooRealVar*)_floatParamList->at(index);
00446   if (par->getVal()!=value) {
00447     if (_verbose) oocxcoutD(_context,Minimization) << par->GetName() 
00448                                                    << "=" << value << ", ";
00449     par->setVal(value);
00450     return kTRUE;
00451   }
00452 
00453   return kFALSE;
00454 }
00455 
00456 
00457 double RooMinimizerFcn::DoEval(const double *x) const 
00458 {
00459 
00460   // Set the parameter values for this iteration
00461   for (int index = 0; index < _nDim; index++) {
00462     if (_logfile) (*_logfile) << x[index] << " " ;
00463     SetPdfParamVal(index,x[index]);
00464   }
00465 
00466   // Calculate the function for these parameters
00467   double fvalue = _funct->getVal();
00468   if (RooAbsPdf::evalError() || RooAbsReal::numEvalErrors()>0) {
00469 
00470     if (_printEvalErrors>=0) {
00471 
00472       if (_doEvalErrorWall) {
00473         oocoutW(_context,Minimization) << "RooMinimizerFcn: Minimized function has error status." << endl 
00474                                        << "Returning maximum FCN so far (" << _maxFCN 
00475                                        << ") to force MIGRAD to back out of this region. Error log follows" << endl ;
00476       } else {
00477         oocoutW(_context,Minimization) << "RooMinimizerFcn: Minimized function has error status but is ignored" << endl ;
00478       } 
00479 
00480       TIterator* iter = _floatParamList->createIterator() ;
00481       RooRealVar* var ;
00482       Bool_t first(kTRUE) ;
00483       ooccoutW(_context,Minimization) << "Parameter values: " ;
00484       while((var=(RooRealVar*)iter->Next())) {
00485         if (first) { first = kFALSE ; } else ooccoutW(_context,Minimization) << ", " ;
00486         ooccoutW(_context,Minimization) << var->GetName() << "=" << var->getVal() ;
00487       }
00488       delete iter ;
00489       ooccoutW(_context,Minimization) << endl ;
00490       
00491       RooAbsReal::printEvalErrors(ooccoutW(_context,Minimization),_printEvalErrors) ;
00492       ooccoutW(_context,Minimization) << endl ;
00493     } 
00494 
00495     if (_doEvalErrorWall) {
00496       fvalue = _maxFCN ;
00497     }
00498 
00499     RooAbsPdf::clearEvalError() ;
00500     RooAbsReal::clearEvalErrorLog() ;
00501     _numBadNLL++ ;
00502   } else if (fvalue>_maxFCN) {
00503     _maxFCN = fvalue ;
00504   }
00505       
00506   // Optional logging
00507   if (_logfile) 
00508     (*_logfile) << setprecision(15) << fvalue << setprecision(4) << endl;
00509   if (_verbose) {
00510     cout << "\nprevFCN = " << setprecision(10) 
00511          << fvalue << setprecision(4) << "  " ;
00512     cout.flush() ;
00513   }
00514 
00515   return fvalue;
00516 }
00517 
00518 #endif
00519 

Generated on Tue Jul 5 15:06:51 2011 for ROOT_528-00b_version by  doxygen 1.5.1