00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "Minuit2/MnMinos.h"
00011 #include "Minuit2/FunctionMinimum.h"
00012 #include "Minuit2/FCNBase.h"
00013 #include "Minuit2/MnFunctionCross.h"
00014 #include "Minuit2/MnCross.h"
00015 #include "Minuit2/MinosError.h"
00016
00017
00018
00019 #if defined(DEBUG) || defined(WARNINGMSG)
00020 #include "Minuit2/MnPrint.h"
00021 #endif
00022
00023
00024 namespace ROOT {
00025
00026 namespace Minuit2 {
00027
00028
00029 MnMinos::MnMinos(const FCNBase& fcn, const FunctionMinimum& min, unsigned int stra ) :
00030 fFCN(fcn),
00031 fMinimum(min),
00032 fStrategy(MnStrategy(stra))
00033 {
00034
00035
00036 if (fcn.Up() != min.Up() ) {
00037 #ifdef WARNINGMSG
00038 MN_INFO_MSG("MnMinos UP value has changed, need to update FunctionMinimum class");
00039 #endif
00040 }
00041 }
00042
00043 MnMinos::MnMinos(const FCNBase& fcn, const FunctionMinimum& min, const MnStrategy& stra) :
00044 fFCN(fcn),
00045 fMinimum(min),
00046 fStrategy(stra)
00047 {
00048
00049
00050 if (fcn.Up() != min.Up() ) {
00051 #ifdef WARNINGMSG
00052 MN_INFO_MSG("MnMinos UP value has changed, need to update FunctionMinimum class");
00053 #endif
00054 }
00055 }
00056
00057
00058 std::pair<double,double> MnMinos::operator()(unsigned int par, unsigned int maxcalls) const {
00059
00060 MinosError mnerr = Minos(par, maxcalls);
00061 return mnerr();
00062 }
00063
00064 double MnMinos::Lower(unsigned int par, unsigned int maxcalls) const {
00065
00066 MnUserParameterState upar = fMinimum.UserState();
00067 double err = fMinimum.UserState().Error(par);
00068
00069 MnCross aopt = Loval(par, maxcalls);
00070
00071 double lower = aopt.IsValid() ? -1.*err*(1.+ aopt.Value()) : (aopt.AtLimit() ? upar.Parameter(par).LowerLimit() : upar.Value(par));
00072
00073 return lower;
00074 }
00075
00076 double MnMinos::Upper(unsigned int par, unsigned int maxcalls) const {
00077
00078 MnCross aopt = Upval(par, maxcalls);
00079
00080 MnUserParameterState upar = fMinimum.UserState();
00081 double err = fMinimum.UserState().Error(par);
00082
00083 double upper = aopt.IsValid() ? err*(1.+ aopt.Value()) : (aopt.AtLimit() ? upar.Parameter(par).UpperLimit() : upar.Value(par));
00084
00085 return upper;
00086 }
00087
00088 MinosError MnMinos::Minos(unsigned int par, unsigned int maxcalls) const {
00089
00090 assert(fMinimum.IsValid());
00091 assert(!fMinimum.UserState().Parameter(par).IsFixed());
00092 assert(!fMinimum.UserState().Parameter(par).IsConst());
00093
00094 MnCross up = Upval(par, maxcalls);
00095 #ifdef DEBUG
00096 std::cout << "Function calls to find upper error " << up.NFcn() << std::endl;
00097 #endif
00098
00099 MnCross lo = Loval(par, maxcalls);
00100
00101 #ifdef DEBUG
00102 std::cout << "Function calls to find lower error " << lo.NFcn() << std::endl;
00103 #endif
00104
00105 return MinosError(par, fMinimum.UserState().Value(par), lo, up);
00106 }
00107
00108
00109 MnCross MnMinos::FindCrossValue(int direction, unsigned int par, unsigned int maxcalls) const {
00110
00111
00112
00113
00114 assert(direction == 1 || direction == -1);
00115 #ifdef DEBUG
00116 if (direction == 1)
00117 std::cout << "\n--------- MnMinos --------- \n Determination of positive Minos error for parameter "
00118 << par << std::endl;
00119 else
00120 std::cout << "\n--------- MnMinos --------- \n Determination of positive Minos error for parameter "
00121 << par << std::endl;
00122 #endif
00123
00124 assert(fMinimum.IsValid());
00125 assert(!fMinimum.UserState().Parameter(par).IsFixed());
00126 assert(!fMinimum.UserState().Parameter(par).IsConst());
00127 if(maxcalls == 0) {
00128 unsigned int nvar = fMinimum.UserState().VariableParameters();
00129 maxcalls = 2*(nvar+1)*(200 + 100*nvar + 5*nvar*nvar);
00130 }
00131
00132 std::vector<unsigned int> para(1, par);
00133
00134 MnUserParameterState upar = fMinimum.UserState();
00135 double err = direction * upar.Error(par);
00136 double val = upar.Value(par) + err;
00137 std::vector<double> xmid(1, val);
00138 std::vector<double> xdir(1, err);
00139
00140 double up = fFCN.Up();
00141 unsigned int ind = upar.IntOfExt(par);
00142
00143 MnAlgebraicSymMatrix m = fMinimum.Error().Matrix();
00144
00145 const MnAlgebraicVector & xt = fMinimum.Parameters().Vec();
00146
00147 double xunit = sqrt(up/m(ind,ind));
00148
00149 for(unsigned int i = 0; i < m.Nrow(); i++) {
00150 if(i == ind) continue;
00151 double xdev = xunit*m(ind,i);
00152 double xnew = xt(i) + direction * xdev;
00153
00154
00155 unsigned int ext = upar.ExtOfInt(i);
00156
00157 double unew = upar.Int2ext(i, xnew);
00158
00159 #ifdef DEBUG
00160 std::cout << "Parameter " << ext << " is set from " << upar.Value(ext) << " to " << unew << std::endl;
00161 #endif
00162 upar.SetValue(ext, unew);
00163 }
00164
00165 upar.Fix(par);
00166 upar.SetValue(par, val);
00167
00168 #ifdef DEBUG
00169 std::cout << "Parameter " << par << " is fixed and set from " << fMinimum.UserState().Value(par) << " to " << val << std::endl;
00170 #endif
00171
00172
00173 double toler = 0.01;
00174 MnFunctionCross cross(fFCN, upar, fMinimum.Fval(), fStrategy);
00175
00176 MnCross aopt = cross(para, xmid, xdir, toler, maxcalls);
00177
00178 #ifdef DEBUG
00179 std::cout<<"----- MnMinos: aopt found from MnFunctionCross = "<<aopt.Value()<<std::endl << std::endl;
00180 #endif
00181
00182 #ifdef WARNINGMSG
00183 if(aopt.AtMaxFcn())
00184 MN_INFO_VAL2("MnMinos maximum number of function calls exceeded for Parameter ",par);
00185 if(aopt.NewMinimum())
00186 MN_INFO_VAL2("MnMinos new Minimum found while looking for Parameter ",par);
00187 if (direction ==1) {
00188 if(aopt.AtLimit())
00189 MN_INFO_VAL2("MnMinos Parameter is at Upper limit.",par);
00190 if(!aopt.IsValid())
00191 MN_INFO_VAL2("MnMinos could not find Upper Value for Parameter ",par);
00192 }
00193 else {
00194 if(aopt.AtLimit())
00195 MN_INFO_VAL2("MnMinos Parameter is at Lower limit.",par);
00196 if(!aopt.IsValid())
00197 MN_INFO_VAL2("MnMinos could not find Lower Value for Parameter ",par);
00198 }
00199 #endif
00200
00201 return aopt;
00202 }
00203
00204 MnCross MnMinos::Upval(unsigned int par, unsigned int maxcalls) const {
00205
00206 return FindCrossValue(1,par,maxcalls);
00207 }
00208
00209 MnCross MnMinos::Loval(unsigned int par, unsigned int maxcalls) const {
00210
00211 return FindCrossValue(-1,par,maxcalls);
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 }
00292
00293 }