MnContours.cxx

Go to the documentation of this file.
00001 // @(#)root/minuit2:$Id: MnContours.cxx 34256 2010-06-30 21:07:32Z moneta $
00002 // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei   2003-2005  
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2005 LCG ROOT Math team,  CERN/PH-SFT                *
00007  *                                                                    *
00008  **********************************************************************/
00009 
00010 #include "Minuit2/MnContours.h"
00011 #include "Minuit2/MnMinos.h"
00012 #include "Minuit2/MnMigrad.h"
00013 #include "Minuit2/MnFunctionCross.h"
00014 #include "Minuit2/FunctionMinimum.h"
00015 #include "Minuit2/FCNBase.h"
00016 #include "Minuit2/MnCross.h"
00017 #include "Minuit2/MinosError.h"
00018 #include "Minuit2/ContoursError.h"
00019 
00020 #include "Minuit2/MnPrint.h" 
00021 
00022 
00023 
00024 namespace ROOT {
00025 
00026    namespace Minuit2 {
00027 
00028 
00029 void PrintContourPoint(const std::pair<double,double> & point)  { 
00030 #ifdef WARNINGMSG 
00031 #ifdef USE_ROOT_ERROR
00032    std::string msg = "\tx = " + ROOT::Math::Util::ToString(point.first) + "\ty = " + ROOT::Math::Util::ToString(point.first);
00033    MN_INFO_MSG2("MnContour",msg.c_str());
00034 #else
00035    std::cout << " x  = " << point.first << "  y = " << point.second << std::endl;
00036 #endif
00037 #endif
00038 }
00039 
00040 std::vector<std::pair<double,double> > MnContours::operator()(unsigned int px, unsigned int py, unsigned int npoints) const {
00041    // get contour as a pair of (x,y) points passing the parameter index (px, py)  and the number of requested points (>=4)
00042    ContoursError cont = Contour(px, py, npoints);
00043    return cont();
00044 }
00045 
00046 ContoursError MnContours::Contour(unsigned int px, unsigned int py, unsigned int npoints) const {
00047    // calculate the contour passing the parameter index (px, py)  and the number of requested points (>=4)
00048    // the fcn.UP() has to be set to the rquired value (see Minuit document on errors)
00049    assert(npoints > 3);
00050    unsigned int maxcalls = 100*(npoints+5)*(fMinimum.UserState().VariableParameters()+1);
00051    unsigned int nfcn = 0;
00052    
00053    std::vector<std::pair<double,double> > result; result.reserve(npoints);
00054    std::vector<MnUserParameterState> states;
00055    //   double edmmax = 0.5*0.05*fFCN.Up()*1.e-3;    
00056 
00057    //double toler = 0.05;    
00058    double toler = 0.01; // use same value as in Minos    
00059    
00060    //get first four points
00061    //   std::cout<<"MnContours: get first 4 params."<<std::endl;
00062    MnMinos minos(fFCN, fMinimum, fStrategy);
00063    
00064    double valx = fMinimum.UserState().Value(px);
00065    double valy = fMinimum.UserState().Value(py);
00066    
00067    MinosError mex = minos.Minos(px);
00068    nfcn += mex.NFcn();
00069    if(!mex.IsValid()) {
00070       MN_ERROR_MSG("MnContours is unable to find first two points.");
00071       return ContoursError(px, py, result, mex, mex, nfcn);
00072    }
00073    std::pair<double,double> ex = mex();
00074    
00075    MinosError mey = minos.Minos(py);
00076    nfcn += mey.NFcn();
00077    if(!mey.IsValid()) {
00078       MN_ERROR_MSG("MnContours is unable to find second two points.");
00079       return ContoursError(px, py, result, mex, mey, nfcn);
00080    }
00081    std::pair<double,double> ey = mey();
00082    
00083    MnMigrad migrad(fFCN, fMinimum.UserState(), MnStrategy(std::max(0, int(fStrategy.Strategy()-1))));
00084    
00085    migrad.Fix(px);
00086    migrad.SetValue(px, valx + ex.second);
00087    FunctionMinimum exy_up = migrad();
00088    nfcn += exy_up.NFcn();
00089    if(!exy_up.IsValid()) {
00090       MN_ERROR_VAL2("MnContours: unable to find Upper y Value for x Parameter",px);
00091       return ContoursError(px, py, result, mex, mey, nfcn);
00092    }
00093    
00094    migrad.SetValue(px, valx + ex.first);
00095    FunctionMinimum exy_lo = migrad();
00096    nfcn += exy_lo.NFcn();
00097    if(!exy_lo.IsValid()) {
00098       MN_ERROR_VAL2("MnContours: unable to find Lower y Value for x Parameter",px);
00099       return ContoursError(px, py, result, mex, mey, nfcn);
00100    }
00101    
00102    
00103    MnMigrad migrad1(fFCN, fMinimum.UserState(), MnStrategy(std::max(0, int(fStrategy.Strategy()-1))));
00104    migrad1.Fix(py);
00105    migrad1.SetValue(py, valy + ey.second);
00106    FunctionMinimum eyx_up = migrad1();
00107    nfcn += eyx_up.NFcn();
00108    if(!eyx_up.IsValid()) {
00109       MN_ERROR_VAL2("MnContours: unable to find Upper x Value for y Parameter",py);
00110       return ContoursError(px, py, result, mex, mey, nfcn);
00111    }
00112    
00113    migrad1.SetValue(py, valy + ey.first);
00114    FunctionMinimum eyx_lo = migrad1();
00115    nfcn += eyx_lo.NFcn();
00116    if(!eyx_lo.IsValid()) {
00117       MN_ERROR_VAL2("MnContours: unable to find Lower x Value for y Parameter",py);
00118       return ContoursError(px, py, result, mex, mey, nfcn);
00119    }
00120    
00121    double scalx = 1./(ex.second - ex.first);
00122    double scaly = 1./(ey.second - ey.first);
00123    
00124    result.push_back(std::pair<double,double>(valx + ex.first, exy_lo.UserState().Value(py)));
00125    result.push_back(std::pair<double,double>(eyx_lo.UserState().Value(px), valy + ey.first));
00126    result.push_back(std::pair<double,double>(valx + ex.second, exy_up.UserState().Value(py)));
00127    result.push_back(std::pair<double,double>(eyx_up.UserState().Value(px), valy + ey.second));
00128 
00129    
00130    
00131    //   std::cout<<"MnContours: first 4 params finished."<<std::endl;
00132 #ifdef WARNINGMSG
00133    MN_INFO_MSG("Minuit2::MnContour : List of  found points");
00134    MN_INFO_VAL2("Minuit2::MnContour : parameter number x",px);
00135    MN_INFO_VAL2("Minuit2::MnContour : parameter number y",py);
00136 #endif
00137 
00138    for (unsigned int i = 0; i < 4; ++i)
00139       PrintContourPoint(result[i] ); 
00140  
00141    MnUserParameterState upar = fMinimum.UserState();
00142    upar.Fix(px);
00143    upar.Fix(py);
00144    
00145    std::vector<unsigned int> par(2); par[0] = px; par[1] = py;
00146    MnFunctionCross cross(fFCN, upar, fMinimum.Fval(), fStrategy);
00147    
00148    for(unsigned int i = 4; i < npoints; i++) {
00149       
00150       std::vector<std::pair<double,double> >::iterator idist1 = result.end()-1;
00151       std::vector<std::pair<double,double> >::iterator idist2 = result.begin();
00152       double dx = idist1->first - (idist2)->first;
00153       double dy = idist1->second - (idist2)->second;
00154       double bigdis = scalx*scalx*dx*dx + scaly*scaly*dy*dy;
00155       
00156       for(std::vector<std::pair<double,double> >::iterator ipair = result.begin(); ipair != result.end()-1; ipair++) {
00157          double distx = ipair->first - (ipair+1)->first;
00158          double disty = ipair->second - (ipair+1)->second;
00159          double dist = scalx*scalx*distx*distx + scaly*scaly*disty*disty;
00160          if(dist > bigdis) {
00161             bigdis = dist;
00162             idist1 = ipair;
00163             idist2 = ipair+1;
00164          }
00165       }
00166       
00167       double a1 = 0.5;
00168       double a2 = 0.5;
00169       double sca = 1.;
00170       
00171 L300:
00172          
00173       if(nfcn > maxcalls) {
00174          MN_ERROR_MSG("MnContours: maximum number of function calls exhausted.");
00175          return ContoursError(px, py, result, mex, mey, nfcn);
00176       }
00177       
00178       double xmidcr = a1*idist1->first + a2*(idist2)->first;
00179       double ymidcr = a1*idist1->second + a2*(idist2)->second;
00180       double xdir = (idist2)->second - idist1->second;
00181       double ydir = idist1->first - (idist2)->first;
00182       double scalfac = sca*std::max(fabs(xdir*scalx), fabs(ydir*scaly));
00183       double xdircr = xdir/scalfac;
00184       double ydircr = ydir/scalfac;
00185       std::vector<double> pmid(2); pmid[0] = xmidcr; pmid[1] = ymidcr;
00186       std::vector<double> pdir(2); pdir[0] = xdircr; pdir[1] = ydircr;
00187       
00188       MnCross opt = cross(par, pmid, pdir, toler, maxcalls);
00189       nfcn += opt.NFcn();
00190       if(!opt.IsValid()) {
00191          //       if(a1 > 0.5) {
00192          if(sca < 0.) {
00193             MN_ERROR_VAL2("MnContours : unable to find point on Contour",i+1);
00194             MN_ERROR_VAL2("MnContours : found  only i points",i);
00195             return ContoursError(px, py, result, mex, mey, nfcn);
00196          }
00197          //       a1 = 0.75;
00198          //       a2 = 0.25;
00199          //       std::cout<<"*****switch direction"<<std::endl;
00200          sca = -1.;
00201          goto L300;
00202          }
00203       double aopt = opt.Value();
00204       if(idist2 == result.begin()) { 
00205          result.push_back(std::pair<double,double>(xmidcr+(aopt)*xdircr, ymidcr + (aopt)*ydircr));
00206          PrintContourPoint( result.back() );
00207       }
00208       else {
00209          result.insert(idist2, std::pair<double,double>(xmidcr+(aopt)*xdircr, ymidcr + (aopt)*ydircr));
00210          PrintContourPoint( *idist2 );
00211       }
00212    }   
00213    return ContoursError(px, py, result, mex, mey, nfcn);
00214 }
00215 
00216 
00217    }  // namespace Minuit2
00218 
00219 }  // namespace ROOT

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