00001
00002
00003
00004
00005
00006
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
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
00048
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
00056
00057
00058 double toler = 0.01;
00059
00060
00061
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
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
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
00198
00199
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 }
00218
00219 }