00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00051 #ifdef USE_ROOT_ERROR
00052 int TurnOffPrintInfoLevel() {
00053
00054 int prevErrorIgnoreLevel = gErrorIgnoreLevel;
00055 if (prevErrorIgnoreLevel < 1001) {
00056 gErrorIgnoreLevel = 1001;
00057 return prevErrorIgnoreLevel;
00058 }
00059 return -2;
00060 }
00061
00062 void RestoreGlobalPrintLevel(int value) {
00063 gErrorIgnoreLevel = value;
00064 }
00065 #else
00066
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
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
00093
00094 std::string algoname(type);
00095
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
00109 fUseFumili = false;
00110 switch (type) {
00111 case ROOT::Minuit2::kMigrad:
00112
00113 SetMinimizer( new ROOT::Minuit2::VariableMetricMinimizer() );
00114 return;
00115 case ROOT::Minuit2::kSimplex:
00116
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
00131 SetMinimizer( new ROOT::Minuit2::VariableMetricMinimizer() );
00132
00133 }
00134 }
00135
00136
00137 Minuit2Minimizer::~Minuit2Minimizer()
00138 {
00139
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
00149 }
00150
00151 Minuit2Minimizer & Minuit2Minimizer::operator = (const Minuit2Minimizer &rhs)
00152 {
00153
00154 if (this == &rhs) return *this;
00155 return *this;
00156 }
00157
00158
00159 void Minuit2Minimizer::Clear() {
00160
00161 fState = MnUserParameterState();
00162
00163 if (fMinimum) delete fMinimum;
00164 fMinimum = 0;
00165 }
00166
00167
00168
00169
00170 bool Minuit2Minimizer::SetVariable(unsigned int ivar, const std::string & name, double val, double step) {
00171
00172
00173
00174
00175
00176
00177
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
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
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
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
00224
00225
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
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
00243
00244 return fState.Trafo().FindIndex(name);
00245 }
00246
00247
00248 bool Minuit2Minimizer::SetVariableValue(unsigned int ivar, double val) {
00249
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
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
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
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
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
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
00303
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
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
00326 int prev_level = (PrintLevel() == 0 ) ? TurnOffPrintInfoLevel() : -1;
00327
00328
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
00334
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
00344 if (fMinimum->IsValid() && IsValidError() && fMinimum->State().Error().Dcovar() != 0 ) {
00345
00346 ROOT::Minuit2::MnHesse hesse(strategy );
00347 hesse( *fMinuitFCN, *fMinimum, maxfcn);
00348 }
00349
00350
00351 if (prev_level > -2) RestoreGlobalPrintLevel(prev_level);
00352
00353 fState = fMinimum->UserState();
00354 bool ok = ExamineMinimum(*fMinimum);
00355
00356 return ok;
00357 }
00358
00359 bool Minuit2Minimizer::ExamineMinimum(const ROOT::Minuit2::FunctionMinimum & min) {
00360
00361
00362
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
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
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
00406 if (fStatus != 0) MN_INFO_MSG2("Minuit2Minimizer::Minimize",txt);
00407 }
00408 else {
00409
00410 if (fStatus == 0) {
00411
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
00426 if (!fMinimum) return;
00427 if (fMinimum->IsValid() ) {
00428
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
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
00472 if ( i >= fDim || i >= fDim) return 0;
00473 if ( Status() || !fState.HasCovariance() ) return 0;
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
00483 if ( i >= fDim || i >= fDim) return 0;
00484 if ( Status() || !fState.HasCovariance() ) return 0;
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
00497
00498
00499
00500 if ( i >= fDim || i >= fDim) return 0;
00501
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
00511
00512
00513
00514 errLow = 0; errUp = 0;
00515 bool runLower = runopt != 2;
00516 bool runUpper = runopt != 1;
00517
00518 assert( fMinuitFCN );
00519
00520
00521 if ( fState.Parameter(i).IsConst() || fState.Parameter(i).IsFixed() ) {
00522 return false;
00523 }
00524
00525 int debugLevel = PrintLevel();
00526
00527
00528
00529
00530
00531
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
00544 if (ErrorDef() != fMinimum->Up() )
00545 fMinimum->SetErrorDef(ErrorDef() );
00546
00547
00548 int prev_level = (PrintLevel() == 0 ) ? TurnOffPrintInfoLevel() : -1;
00549
00550
00551 if (Precision() > 0) fState.SetPrecision(Precision());
00552
00553
00554 ROOT::Minuit2::MnMinos minos( *fMinuitFCN, *fMinimum);
00555
00556
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
00567
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
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
00620
00621
00622
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
00635 int prev_level = (PrintLevel() == 0 ) ? TurnOffPrintInfoLevel() : -1;
00636
00637
00638 if (Precision() > 0) fState.SetPrecision(Precision());
00639
00640 MnParameterScan scan( *fMinuitFCN, fState.Parameters() );
00641 double amin = scan.Fval();
00642
00643
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
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
00662
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
00675
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
00689 if (ErrorDef() != fMinimum->Up() )
00690 fMinimum->SetErrorDef(ErrorDef() );
00691
00692
00693 int prev_level = (PrintLevel() <= 1 ) ? TurnOffPrintInfoLevel() : -1;
00694
00695
00696 if (Precision() > 0) fState.SetPrecision(Precision());
00697
00698
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
00721
00722
00723
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
00734 int prev_level = (PrintLevel() == 0 ) ? TurnOffPrintInfoLevel() : -1;
00735
00736
00737 if (Precision() > 0) fState.SetPrecision(Precision());
00738
00739 ROOT::Minuit2::MnHesse hesse( strategy );
00740
00741
00742 if (fMinimum ) {
00743
00744 hesse( *fMinuitFCN, *fMinimum, maxfcn );
00745 fState = fMinimum->UserState();
00746 }
00747
00748 else {
00749
00750
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
00762 if (PrintLevel() > 0) MN_INFO_MSG2("Minuit2Minimizer::Hesse","Hesse failed ");
00763
00764 int hstatus = 4;
00765
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
00780
00781
00782
00783
00784
00785 if (fMinimum) {
00786
00787 if (fMinimum->HasAccurateCovar() ) return 3;
00788 else if (fMinimum->HasMadePosDefCovar() ) return 2;
00789 else if (fMinimum->HasCovariance() ) return 1;
00790 }
00791 else {
00792
00793 if (fState.HasCovariance()) return 1;
00794 }
00795 return 0;
00796 }
00797
00798
00799
00800 }
00801
00802 }
00803