inlib
1.2.0
|
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved. 00002 // See the file inlib.license for terms. 00003 00004 #ifndef inlib_f2cmn 00005 #define inlib_f2cmn 00006 00007 // The below code is a modified version of the ROOT/TMinuit class 00008 // in order to have a stand alone C++ version of the Minuit package. 00009 // 00010 // The usage of TString has been replaced by the usage of std::string 00011 // The reference to TNamed, TObject and TMethods has been removed. 00012 // In "the ROOT of everything" it could be reintroduced through a 00013 // class TMinuit that could inherit the Midnight one (we can dream no ?). 00014 // 00015 // G.Barrand 00016 00017 /************************************************************************* 00018 * Copyright(c) 1995-1998, The ROOT System, All rights reserved. * 00019 * Authors: Rene Brun, Nenad Buncic, Valery Fine, Fons Rademakers. * 00020 * * 00021 * Permission to use, copy, modify and distribute this software and its * 00022 * documentation for non-commercial purposes is hereby granted without * 00023 * fee, provided that the above copyright notice appears in all copies * 00024 * and that both the copyright notice and this permission notice appear * 00025 * in the supporting documentation. The authors make no claims about the * 00026 * suitability of this software for any purpose. * 00027 * It is provided "as is" without express or implied warranty. * 00028 *************************************************************************/ 00029 00030 //*-*-*-*-*-*-*-*-*-*-*-*The Minimization package*-*--*-*-*-*-*-*-*-*-*-*-* 00031 //*-* ======================== * 00032 //*-* * 00033 //*-* This package was originally written in Fortran by Fred James * 00034 //*-* and part of PACKLIB (patch D506) * 00035 //*-* * 00036 //*-* It has been converted to a C++ class by R.Brun * 00037 //*-* The current implementation in C++ is a straightforward conversion * 00038 //*-* of the original Fortran version: The main changes are: * 00039 //*-* * 00040 //*-* - The variables in the various Minuit labelled common blocks * 00041 //*-* have been changed to the Minuit class data members. * 00042 //*-* - The include file Minuit.h has been commented as much as possible* 00043 //*-* using existing comments in the code or the printed documentation* 00044 //*-* - The original Minuit subroutines are now member functions. * 00045 //*-* - Constructors and destructor have been added. * 00046 //*-* - Instead of passing the FCN function in the argument * 00047 //*-* list, the addresses of this function is stored as pointer * 00048 //*-* in the data members of the class. This is by far more elegant * 00049 //*-* and flexible in an interactive environment. * 00050 //*-* The member function SetFCN can be used to define this pointer. * 00051 //*-* - The ROOT static function Printf is provided to replace all * 00052 //*-* format statements and to print on currently defined output file.* 00053 //*-* - The derived class MinuitOld contains obsolete routines from * 00054 //*-* the Fortran based version. * 00055 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00056 00057 #include <string> 00058 #include <ostream> 00059 00060 namespace inlib { 00061 namespace f2cmn { 00062 00063 class fitter { 00064 public: 00065 typedef bool(*Function_t)(int&,double*,double&,double*,int,void*); 00066 enum {kMAXDIM = 50}; 00067 private: 00068 int fEmpty; //Initialization flag (1 = initialized) 00069 int fMaxpar; //Maximum number of parameters 00070 std::string *fCpnam; //Array of parameters names 00071 double *fU; //External (visible to user in FCN) value of parameters 00072 double *fAlim; //Lower limits for parameters. If zero no limits 00073 double *fBlim; //Upper limits for parameters 00074 double *fErp; //Positive Minos errors if calculated 00075 double *fErn; //Negative Minos errors if calculated 00076 double *fWerr; //External parameters error (standard deviation, defined by UP) 00077 double *fGlobcc; //Global Correlation Coefficients 00078 int *fNvarl; //parameters flag (-1=undefined, 0=constant..) 00079 int *fNiofex; //Internal parameters number, or zero if not currently variable 00080 int *fNexofi; //External parameters number for currently variable parameters 00081 double *fX; //Internal parameters values 00082 double *fXt; //Internal parameters values X saved as Xt 00083 double *fDirin; //(Internal) step sizes for current step 00084 double *fXs; //Internal parameters values saved for fixed params 00085 double *fXts; //Internal parameters values X saved as Xt for fixed params 00086 double *fDirins; //(Internal) step sizes for current step for fixed params 00087 double *fGrd; //First derivatives 00088 double *fG2; // 00089 double *fGstep; //Step sizes 00090 double *fGin; // 00091 double *fDgrd; //Uncertainties 00092 double *fGrds; // 00093 double *fG2s; // 00094 double *fGsteps; // 00095 int *fIpfix; //List of fixed parameters 00096 int fNpfix; //Number of fixed parameters 00097 double *fVhmat; //(Internal) error matrix stored as Half MATrix, since it is symmetric 00098 double *fVthmat; //VHMAT is sometimes saved in VTHMAT, especially in MNMNOT 00099 double *fP; // 00100 double *fPstar; // 00101 double *fPstst; // 00102 double *fPbar; // 00103 double *fPrho; //Minimum point of parabola 00104 int fMaxint; //Maximum number of internal parameters 00105 int fNpar; //Number of parameters 00106 int fMaxext; //Maximum number of external parameters 00107 int fNu; // 00108 int fIsysrd; //standardInput unit 00109 int fIsyswr; //standard output unit 00110 int fIsyssa; // 00111 int fNpagwd; //Page width 00112 int fNpagln; //Number of lines per page 00113 int fNewpag; // 00114 int fIstkrd[10]; // 00115 int fNstkrd; // 00116 int fIstkwr[10]; // 00117 int fNstkwr; // 00118 std::string fCfrom; // 00119 std::string fCstatu; // 00120 std::string fCtitl; // 00121 std::string fCword; // 00122 std::string fCundef; // 00123 std::string fCvrsn; // 00124 std::string fCovmes[4]; // 00125 int fISW[7]; //Array of switches 00126 int fIdbg[11]; //Array of internal debug switches 00127 int fNblock; //Number of Minuit data blocks 00128 int fIcomnd; //Number of commands 00129 double fAmin; //Minimum value found for FCN 00130 double fUp; //FCN+-UP defines errors (for chisquare fits UP=1) 00131 double fEDM; //Estimated vertical distance to the minimum 00132 double fFval3; // 00133 double fEpsi; // 00134 double fApsi; // 00135 double fDcovar; //Relative change in covariance matrix 00136 int fNfcn; //Number of calls to FCN 00137 int fNfcnmx; //Maximum number of calls to FCN 00138 int fNfcnlc; // 00139 int fNfcnfr; // 00140 int fItaur; // 00141 int fIstrat; // 00142 int fNwrmes[2]; // 00143 double *fWord7; // 00144 bool fLwarn; //true if warning messges are to be put out (default=true) 00145 bool fLrepor; //true if exceptional conditions are put out (default=false) 00146 bool fLimset; //true if a parameter is up against limits (for MINOS) 00147 bool fLnolim; //true if there are no limits on any parameters (not yet used) 00148 bool fLnewmn; //true if the previous process has unexpectedly improved FCN 00149 bool fLphead; //true if a heading should be put out for the next parameter definition 00150 double fEpsmac; //machine precision for floating points: 00151 double fEpsma2; //sqrt(fEpsmac) 00152 double fVlimlo; // 00153 double fVlimhi; // 00154 double fUndefi; //Undefined number = -54321 00155 double fBigedm; //Big EDM = 123456 00156 double fUpdflt; // 00157 double *fXpt; //X array of points for contours 00158 double *fYpt; //Y array of points for contours 00159 std::string *fChpt; //Character to be plotted at the X,Y contour positions 00160 double fXmidcr; // 00161 double fYmidcr; // 00162 double fXdircr; // 00163 double fYdircr; // 00164 int fKe1cr; // 00165 int fKe2cr; // 00166 std::string *fOrigin; // 00167 std::string *fWarmes; // 00168 int fNfcwar[20]; // 00169 int fIcirc[2]; // 00170 Function_t fFCN; 00171 void* fTag; 00172 std::ostream* f_out; 00173 00174 00175 private: 00176 fitter(const fitter &m); 00177 void BuildArrays(int maxpar=15); 00178 void DeleteArrays(); 00179 public: 00180 fitter(); 00181 fitter(int maxpar); 00182 virtual ~fitter(){DeleteArrays();} 00183 public: 00184 void SetFCN(Function_t,void*); 00185 void SetOut(std::ostream*); 00186 // 00187 void mnamin(); 00188 void mnbins(double a1, double a2, int naa, double &bl, double &bh, int &nb, double &bwid); 00189 void mncalf(double *pvec, double &ycalf); 00190 void mncler(); 00191 void mncntr(int ke1, int ke2, int &ierrf); 00192 void mncomd(const std::string& crdbin, int &icondn); 00193 void mncont(int ke1, int ke2, int nptu, double *xptu, double *yptu, int &ierrf); 00194 void mncrck(const std::string &crdbuf, int maxcwd, std::string &comand, int &lnc, int mxp, double *plist, int &llist, int &ierr, int isyswr); 00195 void mncros(double &aopt, int &iercr); 00196 void mncuve(); 00197 bool mnderi(); //GB 00198 void mndxdi(double pint, int ipar, double &dxdi); 00199 void mneig(double *a, int ndima, int n, int mits, double *work, double precis, int &ifault); 00200 void mnemat(double *emat, int ndim); 00201 void mnerrs(int number, double &eplus, double &eminus, double &eparab, double &gcc); 00202 void mneval(double anext, double &fnext, int &ierev); 00203 void mnexcm(const std::string& comand, const double *plist, int llist, int &ierflg) ; 00204 void mnexin(double *pint); 00205 void mnfixp(int iint, int &ierr); 00206 void mnfree(int k); 00207 void mngrad(); 00208 void mnhelp(const std::string& comd); 00209 void mnhess(); 00210 void mnhes1(); 00211 void mnimpr(); 00212 void mninex(double *pint); 00213 void mninit(int i1, int i2, int i3); 00214 void mnlims(); 00215 void mnline(double *start, double fstart, double *step, double slope, double toler); 00216 void mnmatu(int kode); 00217 bool mnmigr(); //G.Barrand : return a bool. 00218 void mnmnos(); 00219 void mnmnot(int ilax, int ilax2, double &val2pl, double &val2mi); 00220 void mnparm(int k, const std::string& cnamj, double uk, double wk, double a, double b, int &ierflg); 00221 void mnpars(const std::string& crdbuf, int &icondn); 00222 void mnpfit(double *parx2p, double *pary2p, int npar2p, double *coef2p, double &sdev2p); 00223 void mnpint(double &pexti, int i, double &pinti); 00224 void mnplot(double *xpt, double *ypt, std::string *chpt, int nxypt, int npagwd, int npagln); 00225 void mnpout(int iuext, std::string& chnam, double &val, double &err, double &xlolim, double &xuplim, int &iuint); 00226 void mnprin(int inkode, double fval); 00227 void mnpsdf(); 00228 void mnrazz(double ynew, double *pnew, double *y, int &jh, int &jl); 00229 void mnrn15(double &val, int &inseed); 00230 void mnrset(int iopt); 00231 void mnsave(); 00232 void mnscan(); 00233 void mnseek(); 00234 void mnset(); 00235 void mnsimp(); 00236 void mnstat(double &fmin, double &fedm, double &errdef, int &npari, int &nparx, int &istat); 00237 void mntiny(double epsp1, double &epsbak); 00238 bool mnunpt(const std::string &cfname); 00239 void mnvert(double *a, int l, int m, int n, int &ifail); 00240 void mnwarn(const std::string& copt, const std::string& corg, const std::string& cmes); 00241 void mnwerr(); 00242 private: 00243 static std::string msubstr(const std::string&, 00244 std::string::size_type, 00245 std::string::size_type); 00246 static std::string& mreplace(std::string&, 00247 std::string::size_type, 00248 std::string::size_type, 00249 const std::string&); 00250 }; 00251 00252 }} 00253 00254 #include <cstdlib> 00255 #include <cstdio> 00256 #include <cstring> 00257 #include <cstdarg> 00258 #include <cmath> 00259 00260 namespace inlib { 00261 namespace f2cmn { 00262 00263 template <class T> 00264 inline T TMath_Min(const T& a,const T& b) { 00265 return (a<b?a:b); 00266 } 00267 00268 template <class T> 00269 inline T TMath_Max(const T& a,const T& b) { 00270 return (a>b?a:b); 00271 } 00272 00273 00274 inline double TMath_Log(double a){return ::log(a);} 00275 inline double TMath_Log10(double a){return ::log10(a);} 00276 inline double TMath_Sqrt(double a){return ::sqrt(a);} 00277 inline double TMath_Power(double a,double b) {return ::pow(a,b);} 00278 inline double TMath_Abs(double a){return ::fabs(a);} 00279 inline double TMath_Sin(double a){return ::sin(a);} 00280 inline double TMath_Cos(double a){return ::cos(a);} 00281 inline double TMath_ATan(double a){return ::atan(a);} 00282 inline double TMath_ASin(double a){return ::asin(a);} 00283 00284 inline int TMath_int_abs(int a){return a>=0?a:-a;} /*G.Barrand*/ 00285 00286 inline std::string Form(const char* aFormat,...){ 00287 char sBuffer[1024]; 00288 va_list args; 00289 va_start(args,aFormat); 00290 #ifdef WIN32 00291 _vsnprintf(sBuffer,sizeof(sBuffer),aFormat,args); 00292 #else 00293 ::vsnprintf(sBuffer,sizeof(sBuffer),aFormat,args); 00294 #endif 00295 va_end(args); 00296 return sBuffer; 00297 } 00298 00299 inline void Printf(std::ostream* a_out,const char* aFormat,...){ 00300 char s[2048]; 00301 va_list args; 00302 va_start(args,aFormat); 00303 #ifdef WIN32 00304 _vsnprintf(s,sizeof(s),aFormat,args); 00305 #else 00306 ::vsnprintf(s,sizeof(s),aFormat,args); 00307 #endif 00308 va_end(args); 00309 if(a_out) { 00310 (*a_out) << s << std::endl; 00311 } else { 00312 ::printf("%s\n",s); 00313 } 00314 } 00315 00316 // Some substr start outside string, crash with std::string.substr. 00317 // Instead we use the below : 00318 inline 00319 std::string fitter::msubstr(const std::string& aString, 00320 std::string::size_type aStart, 00321 std::string::size_type aLength ) { 00322 if(aStart>=aString.length()) return aString; 00323 return aString.substr(aStart,aLength); 00324 } 00325 // std::string.replace is not protected against outside start position. 00326 inline 00327 std::string& fitter::mreplace(std::string& aString, 00328 std::string::size_type aStart, 00329 std::string::size_type aLength, 00330 const std::string& aNew) { 00331 if(aStart>=aString.length()) return aString; 00332 return aString.replace(aStart,aLength,aNew); 00333 } 00334 00335 00336 //______________________________________________________________________________ 00337 inline 00338 fitter::fitter() 00339 { 00340 //*-*-*-*-*-*-*-*-*-*-*Minuit normal constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00341 //*-* ======================== 00342 00343 fEmpty = 1; 00344 f_out = 0; 00345 fFCN = 0; 00346 fTag = 0; 00347 00348 } 00349 00350 //______________________________________________________________________________ 00351 inline 00352 fitter::fitter(int maxpar) 00353 { 00354 //*-*-*-*-*-*-*-*-*-*-*Minuit normal constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00355 //*-* ======================== 00356 00357 BuildArrays(maxpar); 00358 00359 fEmpty = 0; 00360 f_out = 0; 00361 fFCN = 0; 00362 fTag = 0; 00363 00364 mninit(5,6,7); 00365 } 00366 00367 //______________________________________________________________________________ 00368 inline 00369 fitter::fitter(const fitter &) 00370 { 00371 // Private copy ctor. This object can not be copied. 00372 00373 //debug Error("Midnight", "can not copy construct Midnight"); 00374 Printf(f_out,"Midnight can not copy construct Midnight"); 00375 } 00376 00377 //______________________________________________________________________________ 00378 inline 00379 void fitter::BuildArrays(int maxpar) 00380 { 00381 //*-*-*-*-*-*-*Create internal Minuit arrays for the maxpar parameters*-*-*-* 00382 //*-* ======================================================= 00383 00384 int mni = 25; 00385 if (maxpar > 10 && maxpar < 200) mni = maxpar; 00386 fMaxpar = mni; 00387 int mnihl = mni*(mni+1)/2; 00388 int maxcpt = 101; 00389 int mne = 2*mni; 00390 fCpnam = new std::string[mne]; 00391 fU = new double[mne]; 00392 fAlim = new double[mne]; 00393 fBlim = new double[mne]; 00394 fErp = new double[mni]; 00395 fErn = new double[mni]; 00396 fWerr = new double[mni]; 00397 fGlobcc = new double[mni]; 00398 fNvarl = new int[mne]; 00399 fNiofex = new int[mne]; 00400 fNexofi = new int[mne]; 00401 fX = new double[mni]; 00402 fXt = new double[mni]; 00403 fDirin = new double[mni]; 00404 fXs = new double[mni]; 00405 fXts = new double[mni]; 00406 fDirins = new double[mni]; 00407 fGrd = new double[mni]; 00408 fG2 = new double[mni]; 00409 fGstep = new double[mni]; 00410 fGin = new double[mni]; 00411 fDgrd = new double[mni]; 00412 fGrds = new double[mni]; 00413 fG2s = new double[mni]; 00414 fGsteps = new double[mni]; 00415 fIpfix = new int[mni]; 00416 fVhmat = new double[mnihl]; 00417 fVthmat = new double[mnihl]; 00418 fP = new double[mni*(mni+1)]; 00419 fPstar = new double[mni*2]; 00420 fPstst = new double[mni]; 00421 fPbar = new double[mni]; 00422 fPrho = new double[mni]; 00423 fWord7 = new double[30]; 00424 fXpt = new double[maxcpt]; 00425 fYpt = new double[maxcpt]; 00426 fChpt = new std::string[maxcpt]; 00427 fOrigin = new std::string[100]; 00428 fWarmes = new std::string[100]; 00429 00430 for (int i = 0; i < fMaxpar; i++) { 00431 fErp[i] = 0; 00432 fErn[i] = 0; 00433 } 00434 } 00435 00436 //______________________________________________________________________________ 00437 inline 00438 void fitter::DeleteArrays() 00439 { 00440 //*-*-*-*-*-*-*-*-*-*-*-*Delete internal Minuit arrays*-*-*-*-*-*-*-*-* 00441 //*-* ============================= 00442 if (fEmpty) return; 00443 delete [] fCpnam; 00444 delete [] fU; 00445 delete [] fAlim; 00446 delete [] fBlim; 00447 delete [] fErp; 00448 delete [] fErn; 00449 delete [] fWerr; 00450 delete [] fGlobcc; 00451 delete [] fNvarl; 00452 delete [] fNiofex; 00453 delete [] fNexofi; 00454 delete [] fX; 00455 delete [] fXt; 00456 delete [] fDirin; 00457 delete [] fXs; 00458 delete [] fXts; 00459 delete [] fDirins; 00460 delete [] fGrd; 00461 delete [] fG2; 00462 delete [] fGstep; 00463 delete [] fGin; 00464 delete [] fDgrd; 00465 delete [] fGrds; 00466 delete [] fG2s; 00467 delete [] fGsteps; 00468 delete [] fIpfix; 00469 delete [] fVhmat; 00470 delete [] fVthmat; 00471 delete [] fP; 00472 delete [] fPstar; 00473 delete [] fPstst; 00474 delete [] fPbar; 00475 delete [] fPrho; 00476 delete [] fWord7; 00477 delete [] fXpt; 00478 delete [] fYpt; 00479 delete [] fChpt; 00480 delete [] fOrigin; 00481 delete [] fWarmes; 00482 fEmpty = 1; 00483 } 00484 00485 //______________________________________________________________________________ 00486 inline 00487 void fitter::SetFCN(Function_t fcn,void* aTag) 00488 { 00489 //*-*-*-*-*-*-*To set the address of the minimization function*-*-*-*-*-*-*-* 00490 //*-* =============================================== 00491 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00492 fFCN = fcn; 00493 fTag = aTag; 00494 } 00495 00496 inline 00497 void fitter::SetOut(std::ostream* a_out) 00498 { 00499 f_out = a_out; 00500 } 00501 00502 //______________________________________________________________________________ 00503 inline 00504 void fitter::mnamin() 00505 { 00506 //*-*-*-*-*-*-*-*-*-*-*-*-*Initialize AMIN*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00507 //*-* =============== 00508 //*-*C Called from many places. Initializes the value of AMIN by 00509 //*-*C calling the user function. Prints out the function value and 00510 //*-*C parameter values if Print Flag value is high enough. 00511 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00512 00513 /* Local variables */ 00514 /*static*/ double fnew; 00515 /*static*/ int nparx; 00516 00517 nparx = fNpar; 00518 if (fISW[4] >= 1) { 00519 Printf(f_out," FIRST CALL TO USER FUNCTION AT NEW START POINT, WITH IFLAG=4."); 00520 } 00521 mnexin(fX); 00522 //Printf(f_out,"debug : FCN : 000"); 00523 (*fFCN)(nparx, fGin, fnew, fU, 4,fTag); ++fNfcn; 00524 fAmin = fnew; 00525 fEDM = fBigedm; 00526 } /* mnamin_ */ 00527 00528 //______________________________________________________________________________ 00529 inline 00530 void fitter::mnbins(double a1, double a2, int naa, double &bl, double &bh, int &nb, double &bwid) 00531 { 00532 //*-*-*-*-*-*-*-*-*-*-*Compute reasonable histogram intervals*-*-*-*-*-*-*-*-* 00533 //*-* ====================================== 00534 //*-* Function TO DETERMINE REASONABLE HISTOGRAM INTERVALS 00535 //*-* GIVEN ABSOLUTE UPPER AND LOWER BOUNDS A1 AND A2 00536 //*-* AND DESIRED MAXIMUM NUMBER OF BINS NAA 00537 //*-* PROGRAM MAKES REASONABLE BINNING FROM BL TO BH OF WIDTH BWID 00538 //*-* F. JAMES, AUGUST, 1974 , stolen for Minuit, 1988 00539 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00540 00541 /* Local variables */ 00542 double awid,ah, al, sigfig, sigrnd, alb; 00543 /*static*/ int kwid, lwid, na, log_; 00544 na = 0; //GB 00545 00546 al = TMath_Min(a1,a2); 00547 ah = TMath_Max(a1,a2); 00548 if (al == ah) ah = al + 1; 00549 00550 //*-*- IF NAA .EQ. -1 , PROGRAM USES BWID INPUT FROM CALLING ROUTINE 00551 if (naa == -1) goto L150; 00552 L10: 00553 na = naa - 1; 00554 if (na < 1) na = 1; 00555 00556 //*-*- GET NOMINAL BIN WIDTH IN EXPON FORM 00557 L20: 00558 awid = (ah-al) / double(na); 00559 log_ = int(TMath_Log10(awid)); 00560 if (awid <= 1) --log_; 00561 sigfig = awid*TMath_Power(10., -log_); 00562 //*-*- ROUND MANTISSA UP TO 2, 2.5, 5, OR 10 00563 if (sigfig > 2) goto L40; 00564 sigrnd = 2; 00565 goto L100; 00566 L40: 00567 if (sigfig > 2.5) goto L50; 00568 sigrnd = 2.5; 00569 goto L100; 00570 L50: 00571 if (sigfig > 5) goto L60; 00572 sigrnd = 5; 00573 goto L100; 00574 L60: 00575 sigrnd = 1; 00576 ++log_; 00577 L100: 00578 bwid = sigrnd*TMath_Power(10., log_); 00579 goto L200; 00580 //*-*- GET NEW BOUNDS FROM NEW WIDTH BWID 00581 L150: 00582 if (bwid <= 0) goto L10; 00583 L200: 00584 alb = al / bwid; 00585 lwid = int(alb); 00586 if (alb < 0) --lwid; 00587 bl = bwid*double(lwid); 00588 alb = ah / bwid + 1; 00589 kwid = int(alb); 00590 if (alb < 0) --kwid; 00591 bh = bwid*double(kwid); 00592 nb = kwid - lwid; 00593 if (naa > 5) goto L240; 00594 if (naa == -1) return; 00595 //*-*- REQUEST FOR ONE BIN IS DIFFICULT CASE 00596 if (naa > 1 || nb == 1) return; 00597 bwid *= 2; 00598 nb = 1; 00599 return; 00600 L240: 00601 if (nb << 1 != naa) return; 00602 ++na; 00603 goto L20; 00604 } /* mnbins_ */ 00605 00606 //______________________________________________________________________________ 00607 inline 00608 void fitter::mncalf(double *pvec, double &ycalf) 00609 { 00610 //*-*-*-*-*-*-*-*-*-*Transform FCN to find further minima*-*-*-*-*-*-*-*-*-* 00611 //*-* ==================================== 00612 //*-* Called only from MNIMPR. Transforms the function FCN 00613 //*-* by dividing out the quadratic part in order to find further 00614 //*-* minima. Calculates ycalf = (f-fmin)/(x-xmin)*v*(x-xmin) 00615 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00616 00617 /* Local variables */ 00618 /*static*/ int ndex, i, j, m, n, nparx; 00619 /*static*/ double denom, f; 00620 00621 nparx = fNpar; 00622 mninex(&pvec[0]); 00623 //Printf(f_out,"debug : FCN : 001"); 00624 (*fFCN)(nparx, fGin, f, fU, 4,fTag); ++fNfcn; 00625 for (i = 1; i <= fNpar; ++i) { 00626 fGrd[i-1] = 0; 00627 for (j = 1; j <= fNpar; ++j) { 00628 m = TMath_Max(i,j); 00629 n = TMath_Min(i,j); 00630 ndex = m*(m-1) / 2 + n; 00631 fGrd[i-1] += fVthmat[ndex-1]*(fXt[j-1] - pvec[j-1]); 00632 } 00633 } 00634 denom = 0; 00635 for (i = 1; i <= fNpar; ++i) {denom += fGrd[i-1]*(fXt[i-1] - pvec[i-1]); } 00636 if (denom <= 0) { 00637 fDcovar = 1; 00638 fISW[1] = 0; 00639 denom = 1; 00640 } 00641 ycalf = (f - fApsi) / denom; 00642 } /* mncalf_ */ 00643 00644 //______________________________________________________________________________ 00645 inline 00646 void fitter::mncler() 00647 { 00648 //*-*-*-*-*-*-*-*-*-*-*Resets the parameter list to UNDEFINED*-*-*-*-*-*-*-* 00649 //*-* ====================================== 00650 //*-* Called from MINUIT and by option from MNEXCM 00651 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00652 00653 int i; 00654 00655 fNpfix = 0; 00656 fNu = 0; 00657 fNpar = 0; 00658 fNfcn = 0; 00659 fNwrmes[0] = 0; 00660 fNwrmes[1] = 0; 00661 for (i = 1; i <= fMaxext; ++i) { 00662 fU[i-1] = 0; 00663 fCpnam[i-1] = fCundef; 00664 fNvarl[i-1] = -1; 00665 fNiofex[i-1] = 0; 00666 } 00667 mnrset(1); 00668 fCfrom = "CLEAR "; 00669 fNfcnfr = fNfcn; 00670 fCstatu = "UNDEFINED "; 00671 fLnolim = true; 00672 fLphead = true; 00673 } /* mncler_ */ 00674 00675 //______________________________________________________________________________ 00676 inline 00677 void fitter::mncntr(int ke1, int ke2, int &ierrf) 00678 { 00679 //*-*-*-*-*Print function contours in two variables, on line printer*-*-*-*-* 00680 //*-* ========================================================= 00681 //*-* 00682 //*-* input arguments: parx, pary, devs, ngrid 00683 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00684 00685 static const std::string clabel = "0123456789ABCDEFGHIJ"; 00686 00687 /* Local variables */ 00688 double d__1, d__2; 00689 double fcna[115], fcnb[115], contur[20]; 00690 double ylabel, fmn, fmx, xlo, ylo, xup, yup; 00691 double devs, xsav, ysav, bwidx, bwidy, unext, ff, xb4; 00692 00693 /*static*/ int i, ngrid, ixmid, nparx, ix, nx, ny, ki1, ki2, ixzero, iy, ics; 00694 /*static*/ std::string chmid, chln, chzero; 00695 00696 if (ke1 <= 0 || ke2 <= 0) goto L1350; 00697 if (ke1 > fNu || ke2 > fNu) goto L1350; 00698 ki1 = fNiofex[ke1-1]; 00699 ki2 = fNiofex[ke2-1]; 00700 if (ki1 <= 0 || ki2 <= 0) goto L1350; 00701 if (ki1 == ki2) goto L1350; 00702 00703 if (fISW[1] < 1) { 00704 mnhess(); 00705 mnwerr(); 00706 } 00707 nparx = fNpar; 00708 xsav = fU[ke1-1]; 00709 ysav = fU[ke2-1]; 00710 devs = fWord7[2]; 00711 if (devs <= 0) devs = 2; 00712 xlo = fU[ke1-1] - devs*fWerr[ki1-1]; 00713 xup = fU[ke1-1] + devs*fWerr[ki1-1]; 00714 ylo = fU[ke2-1] - devs*fWerr[ki2-1]; 00715 yup = fU[ke2-1] + devs*fWerr[ki2-1]; 00716 ngrid = int(fWord7[3]); 00717 if (ngrid <= 0) { 00718 ngrid = 25; 00719 //*-* Computing MIN 00720 nx = TMath_Min(fNpagwd - 15,ngrid); 00721 //*-* Computing MIN 00722 ny = TMath_Min(fNpagln - 7,ngrid); 00723 } else { 00724 nx = ngrid; 00725 ny = ngrid; 00726 } 00727 if (nx < 11) nx = 11; 00728 if (ny < 11) ny = 11; 00729 if (nx >= 115) nx = 114; 00730 00731 //*-*- ask if parameter outside limits 00732 if (fNvarl[ke1-1] > 1) { 00733 if (xlo < fAlim[ke1-1]) xlo = fAlim[ke1-1]; 00734 if (xup > fBlim[ke1-1]) xup = fBlim[ke1-1]; 00735 } 00736 if (fNvarl[ke2-1] > 1) { 00737 if (ylo < fAlim[ke2-1]) ylo = fAlim[ke2-1]; 00738 if (yup > fBlim[ke2-1]) yup = fBlim[ke2-1]; 00739 } 00740 bwidx = (xup - xlo) / double(nx); 00741 bwidy = (yup - ylo) / double(ny); 00742 ixmid = int(((xsav - xlo)*double(nx) / (xup - xlo)) + 1); 00743 if (fAmin == fUndefi) mnamin(); 00744 00745 for (i = 1; i <= 20; ++i) { contur[i-1] = fAmin + fUp*(i-1)*(i-1); } 00746 contur[0] += fUp*.01; 00747 //*-*- fill FCNB to prepare first row, and find column zero/ 00748 fU[ke2-1] = yup; 00749 ixzero = 0; 00750 xb4 = 1; 00751 //TH 00752 chmid.resize(nx+1); 00753 chzero.resize(nx+1); 00754 chln.resize(nx+1); 00755 for (ix = 1; ix <= nx + 1; ++ix) { 00756 fU[ke1-1] = xlo + double(ix-1)*bwidx; 00757 //Printf(f_out,"debug : FCN : 002"); 00758 (*fFCN)(nparx, fGin, ff, fU, 4,fTag); 00759 fcnb[ix-1] = ff; 00760 if (xb4 < 0 && fU[ke1-1] > 0) ixzero = ix - 1; 00761 xb4 = fU[ke1-1]; 00762 chmid[ix-1] = '*'; 00763 chzero[ix-1] = '-'; 00764 } 00765 Printf(f_out," Y-AXIS: PARAMETER %3d: %s",ke2,fCpnam[ke2-1].c_str()); 00766 if (ixzero > 0) { 00767 chzero[ixzero-1] = '+'; 00768 chln = " "; 00769 Printf(f_out," X=0"); 00770 } 00771 //*-*- loop over rows 00772 for (iy = 1; iy <= ny; ++iy) { 00773 unext = fU[ke2-1] - bwidy; 00774 //*-*- prepare this line background pattern for contour 00775 chln = " "; 00776 // TH 00777 chln.resize(nx+1); 00778 chln[ixmid-1] = '*'; 00779 if (ixzero != 0) chln[ixzero-1] = ':'; 00780 if (fU[ke2-1] > ysav && unext < ysav) chln = chmid; 00781 if (fU[ke2-1] > 0 && unext < 0) chln = chzero; 00782 fU[ke2-1] = unext; 00783 ylabel = fU[ke2-1] + bwidy*.5; 00784 //*-*- move FCNB to FCNA and fill FCNB with next row 00785 for (ix = 1; ix <= nx + 1; ++ix) { 00786 fcna[ix-1] = fcnb[ix-1]; 00787 fU[ke1-1] = xlo + double(ix-1)*bwidx; 00788 //Printf(f_out,"debug : FCN : 003"); 00789 (*fFCN)(nparx, fGin, ff, fU, 4,fTag); 00790 fcnb[ix-1] = ff; 00791 } 00792 //*-*- look for contours crossing the FCNxy squares 00793 for (ix = 1; ix <= nx; ++ix) { 00794 d__1 = TMath_Max(fcna[ix-1],fcnb[ix-1]), 00795 d__2 = TMath_Max(fcna[ix],fcnb[ix]); 00796 fmx = TMath_Max(d__1,d__2); 00797 d__1 = TMath_Min(fcna[ix-1],fcnb[ix-1]), 00798 d__2 = TMath_Min(fcna[ix],fcnb[ix]); 00799 fmn = TMath_Min(d__1,d__2); 00800 for (ics = 1; ics <= 20; ++ics) { 00801 if (contur[ics-1] > fmn) goto L240; 00802 } 00803 continue; 00804 L240: 00805 if (contur[ics-1] < fmx) chln[ix-1] = clabel[ics-1]; 00806 } 00807 //*-*- print a row of the contour plot 00808 Printf(f_out," %12.4g %s",ylabel,chln.c_str()); 00809 } 00810 //*-*- contours printed, label x-axis 00811 chln = " "; 00812 chln[0] = 'I'; 00813 chln[ixmid-1] = 'I'; 00814 chln[nx-1] = 'I'; 00815 Printf(f_out," %s",chln.c_str()); 00816 00817 //*-*- the hardest of all: print x-axis scale! 00818 chln = " "; 00819 if (nx <= 26) { 00820 Printf(f_out," %12.4g%s%12.4g",xlo,chln.c_str(),xup); 00821 Printf(f_out," %s%12.4g",chln.c_str(),xsav); 00822 } else { 00823 Printf(f_out," %12.4g%s%12.4g%s%12.4g",xlo,chln.c_str(),xsav,chln.c_str(),xup); 00824 } 00825 Printf(f_out," X-AXIS: PARAMETER%3d: %s ONE COLUMN=%12.4g" 00826 ,ke1,fCpnam[ke1-1].c_str(),bwidx); 00827 Printf(f_out," FUNCTION VALUES: F(I)=%12.4g +%12.4g *I**2",fAmin,fUp); 00828 //*-*- finished. reset input values 00829 fU[ke1-1] = xsav; 00830 fU[ke2-1] = ysav; 00831 ierrf = 0; 00832 return; 00833 L1350: 00834 Printf(f_out," INVALID PARAMETER NUMBER(S) REQUESTED. IGNORED."); 00835 ierrf = 1; 00836 } /* mncntr_ */ 00837 00838 //______________________________________________________________________________ 00839 inline 00840 void fitter::mncomd(const std::string& crdbin, int &icondn) 00841 { 00842 //*-*-*-*-*-*-*-*-*-*-*Reads a command string and executes*-*-*-*-*-*-*-*-*-* 00843 //*-* =================================== 00844 //*-* Called by user. 'Reads' a command string and executes. 00845 //*-* Equivalent to MNEXCM except that the command is given as a 00846 //*-* character string. 00847 //*-* 00848 //*-* ICONDN = 0: command executed normally 00849 //*-* 1: command is blank, ignored 00850 //*-* 2: command line unreadable, ignored 00851 //*-* 3: unknown command, ignored 00852 //*-* 4: abnormal termination (e.g., MIGRAD not converged) 00853 //*-* 5: command is a request to read PARAMETER definitions 00854 //*-* 6: 'SET INPUT' command 00855 //*-* 7: 'SET TITLE' command 00856 //*-* 8: 'SET COVAR' command 00857 //*-* 9: reserved 00858 //*-* 10: END command 00859 //*-* 11: EXIT or STOP command 00860 //*-* 12: RETURN command 00861 //*-* 00862 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00863 00864 static const std::string clower = "abcdefghijklmnopqrstuvwxyz"; 00865 static const std::string cupper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 00866 00867 /* Local variables */ 00868 /*static*/ double plist[30]; 00869 /*static*/ int ierr, ipos, i, llist, ic, lenbuf, lnc; 00870 /*static*/ bool leader; 00871 /*static*/ std::string comand, crdbuf, ctemp; 00872 00873 lenbuf = crdbin.size(); 00874 crdbuf = crdbin; 00875 icondn = 0; 00876 //*-*- record not case-sensitive, get upper case, strip leading blanks 00877 leader = true; 00878 ipos = 1; 00879 for (i = 1; i <= TMath_Min(20,lenbuf); ++i) { 00880 if (crdbuf[i-1] == '\'') goto L111; 00881 if (crdbuf[i-1] == ' ') { 00882 if (leader) ++ipos; 00883 continue; 00884 } 00885 leader = false; 00886 for (ic = 1; ic <= 26; ++ic) { 00887 if (crdbuf[i-1] == clower[ic-1]) crdbuf[i-1] = cupper[ic-1]; 00888 } 00889 } 00890 L111: 00891 //*-*- blank or null command 00892 if (ipos > lenbuf) { 00893 Printf(f_out," BLANK COMMAND IGNORED."); 00894 icondn = 1; 00895 goto L900; 00896 } 00897 //*-*- . . preemptive commands 00898 //*-*- if command is 'PARAMETER' 00899 if (msubstr(crdbuf,ipos-1,3) == "PAR") { 00900 icondn = 5; 00901 fLphead = true; 00902 goto L900; 00903 } 00904 //*-*- if command is 'SET INPUT' 00905 if (msubstr(crdbuf,ipos-1,3) == "SET INP") { 00906 icondn = 6; 00907 fLphead = true; 00908 goto L900; 00909 } 00910 //*-*- if command is 'SET TITLE' 00911 if (msubstr(crdbuf,ipos-1,7) == "SET TIT") { 00912 icondn = 7; 00913 fLphead = true; 00914 goto L900; 00915 } 00916 //*-*- if command is 'SET COVARIANCE' 00917 if (msubstr(crdbuf,ipos-1,7) == "SET COV") { 00918 icondn = 8; 00919 fLphead = true; 00920 goto L900; 00921 } 00922 //*-*- crack the command . . . . . . . . . . . . . . . . 00923 ctemp = msubstr(crdbuf,ipos-1,7); 00924 mncrck(ctemp, 20, comand, lnc, 30, plist, llist, ierr, fIsyswr); 00925 if (ierr > 0) { 00926 Printf(f_out," COMMAND CANNOT BE INTERPRETED"); 00927 icondn = 2; 00928 goto L900; 00929 } 00930 00931 mnexcm(comand, plist, llist, ierr); 00932 icondn = ierr; 00933 L900: 00934 return; 00935 } /* mncomd_ */ 00936 00937 //______________________________________________________________________________ 00938 inline 00939 void fitter::mncont(int ke1, int ke2, int nptu, double *xptu, double *yptu, int &ierrf) 00940 { 00941 //*-*-*-*-*-*-*Find points along a contour where FCN is minimum*-*-*-*-*-*-* 00942 //*-* ================================================ 00943 //*-* Find NPTU points along a contour where the function 00944 //*-* FMIN (X(KE1),X(KE2)) = AMIN+UP 00945 //*-* where FMIN is the minimum of FCN with respect to all 00946 //*-* the other NPAR-2 variable parameters (if any). 00947 //*-* IERRF on return will be equal to the number of points found: 00948 //*-* NPTU if normal termination with NPTU points found 00949 //*-* -1 if errors in the calling sequence (KE1, KE2 not variable) 00950 //*-* 0 if less than four points can be found (using MNMNOT) 00951 //*-* n>3 if only n points can be found (n < NPTU) 00952 //*-* 00953 //*-* input arguments: parx, pary, devs, ngrid 00954 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 00955 /* System generated locals */ 00956 int i__1; 00957 00958 /* Local variables */ 00959 double d__1, d__2; 00960 /*static*/ double dist, xdir, ydir, aopt, u1min, u2min; 00961 /*static*/ double gcc[kMAXDIM], w[kMAXDIM], abest, scalx, scaly; 00962 /*static*/ double a1, a2, val2mi, val2pl, dc, sclfac, bigdis, sigsav; 00963 /*static*/ int nall, iold, line, mpar, ierr, inew, move, next, i, j, nfcol, iercr; 00964 /*static*/ int idist, npcol, kints, i2, i1, lr, nfcnco, ki1, ki2, ki3, ke3; 00965 /*static*/ int nowpts, istrav, nfmxin, isw2, isw4; 00966 /*static*/ bool ldebug; 00967 idist = 0; //GB : rm warning. 00968 nfcnco = 0; //GB : rm warning. 00969 00970 /* Function Body */ 00971 ldebug = fIdbg[6] >= 1; 00972 if (ke1 <= 0 || ke2 <= 0) goto L1350; 00973 if (ke1 > fNu || ke2 > fNu) goto L1350; 00974 ki1 = fNiofex[ke1-1]; 00975 ki2 = fNiofex[ke2-1]; 00976 if (ki1 <= 0 || ki2 <= 0) goto L1350; 00977 if (ki1 == ki2) goto L1350; 00978 if (nptu < 4) goto L1400; 00979 00980 nfcnco = fNfcn; 00981 fNfcnmx = (nptu + 5)*100*(fNpar + 1); 00982 //*-*- The minimum 00983 mncuve(); 00984 u1min = fU[ke1-1]; 00985 u2min = fU[ke2-1]; 00986 ierrf = 0; 00987 fCfrom = "MNContour "; 00988 fNfcnfr = nfcnco; 00989 if (fISW[4] >= 0) { 00990 Printf(f_out," START MNCONTOUR CALCULATION OF%4d POINTS ON CONTOUR.",nptu); 00991 if (fNpar > 2) { 00992 if (fNpar == 3) { 00993 ki3 = 6 - ki1 - ki2; 00994 ke3 = fNexofi[ki3-1]; 00995 Printf(f_out," EACH POINT IS A MINIMUM WITH RESPECT TO PARAMETER %3d %s",ke3,fCpnam[ke3-1].c_str()); 00996 } else { 00997 Printf(f_out," EACH POINT IS A MINIMUM WITH RESPECT TO THE OTHER%3d VARIABLE PARAMETERS.",fNpar - 2); 00998 } 00999 } 01000 } 01001 01002 //*-*- Find the first four points using MNMNOT 01003 //*-*- ........................ first two points 01004 mnmnot(ke1, ke2, val2pl, val2mi); 01005 if (fErn[ki1-1] == fUndefi) { 01006 xptu[0] = fAlim[ke1-1]; 01007 mnwarn("W", "MNContour ", "Contour squeezed by parameter limits."); 01008 } else { 01009 if (fErn[ki1-1] >= 0) goto L1500; 01010 xptu[0] = u1min + fErn[ki1-1]; 01011 } 01012 yptu[0] = val2mi; 01013 01014 if (fErp[ki1-1] == fUndefi) { 01015 xptu[2] = fBlim[ke1-1]; 01016 mnwarn("W", "MNContour ", "Contour squeezed by parameter limits."); 01017 } else { 01018 if (fErp[ki1-1] <= 0) goto L1500; 01019 xptu[2] = u1min + fErp[ki1-1]; 01020 } 01021 yptu[2] = val2pl; 01022 scalx = 1 / (xptu[2] - xptu[0]); 01023 //*-*- ........................... next two points 01024 mnmnot(ke2, ke1, val2pl, val2mi); 01025 if (fErn[ki2-1] == fUndefi) { 01026 yptu[1] = fAlim[ke2-1]; 01027 mnwarn("W", "MNContour ", "Contour squeezed by parameter limits."); 01028 } else { 01029 if (fErn[ki2-1] >= 0) goto L1500; 01030 yptu[1] = u2min + fErn[ki2-1]; 01031 } 01032 xptu[1] = val2mi; 01033 if (fErp[ki2-1] == fUndefi) { 01034 yptu[3] = fBlim[ke2-1]; 01035 mnwarn("W", "MNContour ", "Contour squeezed by parameter limits."); 01036 } else { 01037 if (fErp[ki2-1] <= 0) goto L1500; 01038 yptu[3] = u2min + fErp[ki2-1]; 01039 } 01040 xptu[3] = val2pl; 01041 scaly = 1 / (yptu[3] - yptu[1]); 01042 nowpts = 4; 01043 next = 5; 01044 if (ldebug) { 01045 Printf(f_out," Plot of four points found by MINOS"); 01046 fXpt[0] = u1min; 01047 fYpt[0] = u2min; 01048 fChpt[0] = " "; 01049 //*-* Computing MIN 01050 nall = TMath_Min(nowpts + 1,101); 01051 for (i = 2; i <= nall; ++i) { 01052 fXpt[i-1] = xptu[i-2]; 01053 fYpt[i-1] = yptu[i-2]; 01054 } 01055 fChpt[1] = "A"; 01056 fChpt[2] = "B"; 01057 fChpt[3] = "C"; 01058 fChpt[4] = "D"; 01059 mnplot(fXpt, fYpt, fChpt, nall, fNpagwd, fNpagln); 01060 } 01061 01062 //*-*- ..................... save some values before fixing 01063 isw2 = fISW[1]; 01064 isw4 = fISW[3]; 01065 sigsav = fEDM; 01066 istrav = fIstrat; 01067 dc = fDcovar; 01068 fApsi = fEpsi*.5; 01069 abest = fAmin; 01070 mpar = fNpar; 01071 nfmxin = fNfcnmx; 01072 for (i = 1; i <= mpar; ++i) { fXt[i-1] = fX[i-1]; } 01073 i__1 = mpar*(mpar + 1) / 2; 01074 for (j = 1; j <= i__1; ++j) { fVthmat[j-1] = fVhmat[j-1]; } 01075 for (i = 1; i <= mpar; ++i) { 01076 gcc[i-1] = fGlobcc[i-1]; 01077 w[i-1] = fWerr[i-1]; 01078 } 01079 //*-*- fix the two parameters in question 01080 kints = fNiofex[ke1-1]; 01081 mnfixp(kints-1, ierr); 01082 kints = fNiofex[ke2-1]; 01083 mnfixp(kints-1, ierr); 01084 //*-*- ......................Fill in the rest of the points 01085 for (inew = next; inew <= nptu; ++inew) { 01086 //*-* find the two neighbouring points with largest separation 01087 bigdis = 0; 01088 for (iold = 1; iold <= inew - 1; ++iold) { 01089 i2 = iold + 1; 01090 if (i2 == inew) i2 = 1; 01091 d__1 = scalx*(xptu[iold-1] - xptu[i2-1]); 01092 d__2 = scaly*(yptu[iold-1] - yptu[i2-1]); 01093 dist = d__1*d__1 + d__2*d__2; 01094 if (dist > bigdis) { 01095 bigdis = dist; 01096 idist = iold; 01097 } 01098 } 01099 i1 = idist; 01100 i2 = i1 + 1; 01101 if (i2 == inew) i2 = 1; 01102 //*-*- next point goes between I1 and I2 01103 a1 = .5; 01104 a2 = .5; 01105 L300: 01106 fXmidcr = a1*xptu[i1-1] + a2*xptu[i2-1]; 01107 fYmidcr = a1*yptu[i1-1] + a2*yptu[i2-1]; 01108 xdir = yptu[i2-1] - yptu[i1-1]; 01109 ydir = xptu[i1-1] - xptu[i2-1]; 01110 sclfac = TMath_Max(TMath_Abs(xdir*scalx),TMath_Abs(ydir*scaly)); 01111 fXdircr = xdir / sclfac; 01112 fYdircr = ydir / sclfac; 01113 fKe1cr = ke1; 01114 fKe2cr = ke2; 01115 //*-*- Find the contour crossing point along DIR 01116 fAmin = abest; 01117 mncros(aopt, iercr); 01118 if (iercr > 1) { 01119 //*-*- If cannot find mid-point, try closer to point 1 01120 if (a1 > .5) { 01121 if (fISW[4] >= 0) { 01122 Printf(f_out," MNCONT CANNOT FIND NEXT POINT ON CONTOUR. ONLY%3d POINTS FOUND.",nowpts); 01123 } 01124 goto L950; 01125 } 01126 mnwarn("W", "MNContour ", "Cannot find midpoint, try closer."); 01127 a1 = .75; 01128 a2 = .25; 01129 goto L300; 01130 } 01131 //*-*- Contour has been located, insert new point in list 01132 for (move = nowpts; move >= i1 + 1; --move) { 01133 xptu[move] = xptu[move-1]; 01134 yptu[move] = yptu[move-1]; 01135 } 01136 ++nowpts; 01137 xptu[i1] = fXmidcr + fXdircr*aopt; 01138 yptu[i1] = fYmidcr + fYdircr*aopt; 01139 } 01140 L950: 01141 01142 ierrf = nowpts; 01143 fCstatu = "SUCCESSFUL"; 01144 if (nowpts < nptu) fCstatu = "INCOMPLETE"; 01145 01146 //*-*- make a lineprinter plot of the contour 01147 if (fISW[4] >= 0) { 01148 fXpt[0] = u1min; 01149 fYpt[0] = u2min; 01150 fChpt[0] = " "; 01151 nall = TMath_Min(nowpts + 1,101); 01152 for (i = 2; i <= nall; ++i) { 01153 fXpt[i-1] = xptu[i-2]; 01154 fYpt[i-1] = yptu[i-2]; 01155 fChpt[i-1] = "X"; 01156 } 01157 Printf(f_out," Y-AXIS: PARAMETER %3d %s",ke2,fCpnam[ke2-1].c_str()); 01158 01159 mnplot(fXpt, fYpt, fChpt, nall, fNpagwd, fNpagln); 01160 01161 Printf(f_out," X-AXIS: PARAMETER %3d %s",ke1,fCpnam[ke1-1].c_str()); 01162 } 01163 //*-*- print out the coordinates around the contour 01164 if (fISW[4] >= 1) { 01165 npcol = (nowpts + 1) / 2; 01166 nfcol = nowpts / 2; 01167 Printf(f_out,"%5d POINTS ON CONTOUR. FMIN=%13.5e ERRDEF=%11.3g",nowpts,abest,fUp); 01168 Printf(f_out," %s%s%s%s",fCpnam[ke1-1].c_str(), 01169 fCpnam[ke2-1].c_str(), 01170 fCpnam[ke1-1].c_str(), 01171 fCpnam[ke2-1].c_str()); 01172 for (line = 1; line <= nfcol; ++line) { 01173 lr = line + npcol; 01174 Printf(f_out," %5d%13.5e%13.5e %5d%13.5e%13.5e",line,xptu[line-1],yptu[line-1],lr,xptu[lr-1],yptu[lr-1]); 01175 } 01176 if (nfcol < npcol) { 01177 Printf(f_out," %5d%13.5e%13.5e",npcol,xptu[npcol-1],yptu[npcol-1]); 01178 } 01179 } 01180 //*-*- . . contour finished. reset v 01181 fItaur = 1; 01182 mnfree(1); 01183 mnfree(1); 01184 i__1 = mpar*(mpar + 1) / 2; 01185 for (j = 1; j <= i__1; ++j) { fVhmat[j-1] = fVthmat[j-1]; } 01186 for (i = 1; i <= mpar; ++i) { 01187 fGlobcc[i-1] = gcc[i-1]; 01188 fWerr[i-1] = w[i-1]; 01189 fX[i-1] = fXt[i-1]; 01190 } 01191 mninex(fX); 01192 fEDM = sigsav; 01193 fAmin = abest; 01194 fISW[1] = isw2; 01195 fISW[3] = isw4; 01196 fDcovar = dc; 01197 fItaur = 0; 01198 fNfcnmx = nfmxin; 01199 fIstrat = istrav; 01200 fU[ke1-1] = u1min; 01201 fU[ke2-1] = u2min; 01202 goto L2000; 01203 //*-*- Error returns 01204 L1350: 01205 Printf(f_out," INVALID PARAMETER NUMBERS."); 01206 goto L1450; 01207 L1400: 01208 Printf(f_out," LESS THAN FOUR POINTS REQUESTED."); 01209 L1450: 01210 ierrf = -1; 01211 fCstatu = "USER ERROR"; 01212 goto L2000; 01213 L1500: 01214 Printf(f_out," MNCONT UNABLE TO FIND FOUR POINTS."); 01215 fU[ke1-1] = u1min; 01216 fU[ke2-1] = u2min; 01217 ierrf = 0; 01218 fCstatu = "FAILED"; 01219 L2000: 01220 fCfrom = "MNContour "; 01221 fNfcnfr = nfcnco; 01222 } /* mncont_ */ 01223 01224 //______________________________________________________________________________ 01225 inline 01226 void fitter::mncrck(const std::string &crdbuf, int maxcwd, std::string &comand, int &lnc, 01227 int mxp, double *plist, int &llist, int &ierr, int) 01228 { 01229 //*-*-*-*-*-*-*-*-*-*-*-*Cracks the free-format input*-*-*-*-*-*-*-*-*-*-*-*-* 01230 //*-* ============================ 01231 //*-* Called from MNREAD. 01232 //*-* Cracks the free-format input, expecting zero or more 01233 //*-* alphanumeric fields (which it joins into COMAND(1:LNC)) 01234 //*-* followed by one or more numeric fields separated by 01235 //*-* blanks and/or one comma. The numeric fields are put into 01236 //*-* the LLIST (but at most MXP) elements of PLIST. 01237 //*-* IERR = 0 if no errors, 01238 //*-* = 1 if error(s). 01239 //*-* Diagnostic messages are written to ISYSWR 01240 //*-* 01241 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 01242 /* Initialized data */ 01243 01244 static const std::string cnull = ")NULL STRING "; 01245 static const std::string cnumer = "123456789-.0+"; 01246 01247 /* Local variables */ 01248 /*static*/ int ifld, iend, lend, left, nreq, ipos, kcmnd, nextb, ic, ibegin, ltoadd; 01249 /*static*/ int ielmnt, lelmnt[25], nelmnt; 01250 /*static*/ std::string celmnt[25], ctemp; 01251 01252 /* Function Body */ 01253 ielmnt = 0; 01254 lend = crdbuf.size(); 01255 nextb = 1; 01256 ierr = 0; 01257 //*-*- . . . . loop over words CELMNT 01258 L10: 01259 for (ipos = nextb; ipos <= lend; ++ipos) { 01260 ibegin = ipos; 01261 if (crdbuf[ipos-1] == ' ') continue; 01262 if (crdbuf[ipos-1] == ',') goto L250; 01263 goto L150; 01264 } 01265 goto L300; 01266 L150: 01267 //*-*- found beginning of word, look for end 01268 for (ipos = ibegin + 1; ipos <= lend; ++ipos) { 01269 if (crdbuf[ipos-1] == ' ') goto L250; 01270 if (crdbuf[ipos-1] == ',') goto L250; 01271 } 01272 ipos = lend + 1; 01273 L250: 01274 iend = ipos - 1; 01275 ++ielmnt; 01276 if (iend >= ibegin) 01277 celmnt[ielmnt-1] = msubstr(crdbuf,ibegin-1, iend-ibegin+1); 01278 else 01279 celmnt[ielmnt-1] = cnull; 01280 lelmnt[ielmnt-1] = iend - ibegin + 1; 01281 if (lelmnt[ielmnt-1] > 19) { 01282 Printf(f_out," MINUIT WARNING: INPUT DATA WORD TOO LONG."); 01283 ctemp = msubstr(crdbuf,ibegin-1,iend-ibegin+1); 01284 Printf(f_out," ORIGINAL:%s",ctemp.c_str()); 01285 Printf(f_out," TRUNCATED TO:%s",celmnt[ielmnt-1].c_str()); 01286 lelmnt[ielmnt-1] = 19; 01287 } 01288 if (ipos >= lend) goto L300; 01289 if (ielmnt >= 25) goto L300; 01290 //*-*- look for comma or beginning of next word 01291 for (ipos = iend + 1; ipos <= lend; ++ipos) { 01292 if (crdbuf[ipos-1] == ' ') continue; 01293 nextb = ipos; 01294 if (crdbuf[ipos-1] == ',') nextb = ipos + 1; 01295 goto L10; 01296 } 01297 //*-*- All elements found, join the alphabetic ones to 01298 //*-*- form a command 01299 L300: 01300 nelmnt = ielmnt; 01301 comand = " "; 01302 lnc = 1; 01303 plist[0] = 0; 01304 llist = 0; 01305 if (ielmnt == 0) goto L900; 01306 kcmnd = 0; 01307 for (ielmnt = 1; ielmnt <= nelmnt; ++ielmnt) { 01308 if ( celmnt[ielmnt-1] == cnull) goto L450; 01309 for (ic = 1; ic <= 13; ++ic) { 01310 if (msubstr(celmnt[ielmnt-1],0,1) == 01311 msubstr(cnumer,ic-1,1)) goto L450; 01312 } 01313 if (kcmnd >= maxcwd) continue; 01314 left = maxcwd - kcmnd; 01315 ltoadd = lelmnt[ielmnt-1]; 01316 if (ltoadd > left) ltoadd = left; 01317 //comand(kcmnd,ltoadd) = msubstr(celmnt[ielmnt-1],0,ltoadd); 01318 //comand.replace(kcmnd,ltoadd,msubstr(celmnt[ielmnt-1],0,ltoadd)); 01319 mreplace(comand,kcmnd,ltoadd,msubstr(celmnt[ielmnt-1],0,ltoadd)); 01320 kcmnd += ltoadd; 01321 if (kcmnd == maxcwd) continue; 01322 comand[kcmnd] = ' '; 01323 ++kcmnd; 01324 } 01325 lnc = kcmnd; 01326 goto L900; 01327 L450: 01328 lnc = kcmnd; 01329 //*-*- . . . . we have come to a numeric field 01330 llist = 0; 01331 for (ifld = ielmnt; ifld <= nelmnt; ++ifld) { 01332 ++(llist); 01333 if (llist > mxp) { 01334 nreq = nelmnt - ielmnt + 1; 01335 Printf(f_out," MINUIT WARNING IN MNCRCK: "); 01336 Printf(f_out," COMMAND HAS INPUT%5d NUMERIC FIELDS, BUT MINUIT CAN ACCEPT ONLY%3d",nreq,mxp); 01337 goto L900; 01338 } 01339 if (celmnt[ifld-1] == cnull) plist[llist-1] = 0; 01340 else { 01341 Printf(f_out,"Fatal Error: mnerr code not yet implemented."); 01342 } 01343 } 01344 //*-*- end loop over numeric fields 01345 L900: 01346 if (lnc <= 0) lnc = 1; 01347 } /* mncrck_ */ 01348 01349 //______________________________________________________________________________ 01350 inline 01351 void fitter::mncros(double &aopt, int &iercr) 01352 { 01353 //*-*-*-*-*-*-*-*-*-*-*Find point where MNEVAL=AMIN+UP*-*-*-*-*-*-*-*-*-*-*-* 01354 //*-* =============================== 01355 //*-* Find point where MNEVAL=AMIN+UP, along the line through 01356 //*-* XMIDCR,YMIDCR with direction XDIRCR,YDIRCR, where X and Y 01357 //*-* are parameters KE1CR and KE2CR. If KE2CR=0 (from MINOS), 01358 //*-* only KE1CR is varied. From MNCONT, both are varied. 01359 //*-* Crossing point is at 01360 //*-* (U(KE1),U(KE2)) = (XMID,YMID) + AOPT*(XDIR,YDIR) 01361 //*-* 01362 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 01363 01364 static const std::string charal = " .ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 01365 01366 /* Local variables */ 01367 /*static*/ double alsb[3], flsb[3], bmin, bmax, zmid, sdev, zdir, zlim; 01368 /*static*/ double coeff[3], aleft, aulim, fdist, adist, aminsv; 01369 /*static*/ double anext, fnext, slope, s1, s2, x1, x2, ecarmn, ecarmx; 01370 /*static*/ double determ, rt, smalla, aright, aim, tla, tlf, dfda,ecart; 01371 /*static*/ int iout, i, ileft, ierev, maxlk, ibest, ik, it; 01372 /*static*/ int noless, iworst, iright, itoohi, kex, ipt; 01373 /*static*/ bool ldebug; 01374 /*static*/ std::string chsign; 01375 x2 = 0; 01376 iout = 0; //GB : rm warning. 01377 iworst = 0; //GB : rm warning. 01378 01379 ldebug = fIdbg[6] >= 1; 01380 aminsv = fAmin; 01381 //*-*- convergence when F is within TLF of AIM and next prediction 01382 //*-*- of AOPT is within TLA of previous value of AOPT 01383 aim = fAmin + fUp; 01384 tlf = fUp*.01; 01385 tla = .01; 01386 fXpt[0] = 0; 01387 fYpt[0] = aim; 01388 fChpt[0] = " "; 01389 ipt = 1; 01390 if (fKe2cr == 0) { 01391 fXpt[1] = -1; 01392 fYpt[1] = fAmin; 01393 fChpt[1] = "."; 01394 ipt = 2; 01395 } 01396 //*-*- find the largest allowed A 01397 aulim = 100; 01398 for (ik = 1; ik <= 2; ++ik) { 01399 if (ik == 1) { 01400 kex = fKe1cr; 01401 zmid = fXmidcr; 01402 zdir = fXdircr; 01403 } else { 01404 if (fKe2cr == 0) continue; 01405 kex = fKe2cr; 01406 zmid = fYmidcr; 01407 zdir = fYdircr; 01408 } 01409 if (fNvarl[kex-1] <= 1) continue; 01410 if (zdir == 0) continue; 01411 zlim = fAlim[kex-1]; 01412 if (zdir > 0) zlim = fBlim[kex-1]; 01413 aulim = TMath_Min(aulim,(zlim - zmid) / zdir); 01414 } 01415 //*-*- LSB = Line Search Buffer 01416 //*-*- first point 01417 anext = 0; 01418 aopt = anext; 01419 fLimset = false; 01420 if (aulim < aopt + tla) fLimset = true; 01421 mneval(anext, fnext, ierev); 01422 //*-* debug printout: 01423 if (ldebug) { 01424 Printf(f_out," MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt); 01425 } 01426 if (ierev > 0) goto L900; 01427 if (fLimset && fnext <= aim) goto L930; 01428 ++ipt; 01429 fXpt[ipt-1] = anext; 01430 fYpt[ipt-1] = fnext; 01431 fChpt[ipt-1] = msubstr(charal,ipt-1,1); 01432 alsb[0] = anext; 01433 flsb[0] = fnext; 01434 fnext = TMath_Max(fnext,aminsv + fUp*.1); 01435 aopt = TMath_Sqrt(fUp / (fnext - aminsv)) - 1; 01436 if (TMath_Abs(fnext - aim) < tlf) goto L800; 01437 01438 if (aopt < -.5)aopt = -.5; 01439 if (aopt > 1) aopt = 1; 01440 fLimset = false; 01441 if (aopt > aulim) { 01442 aopt = aulim; 01443 fLimset = true; 01444 } 01445 mneval(aopt, fnext, ierev); 01446 //*-* debug printout: 01447 if (ldebug) { 01448 Printf(f_out," MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt); 01449 } 01450 if (ierev > 0) goto L900; 01451 if (fLimset && fnext <= aim) goto L930; 01452 alsb[1] = aopt; 01453 ++ipt; 01454 fXpt[ipt-1] = alsb[1]; 01455 fYpt[ipt-1] = fnext; 01456 fChpt[ipt-1] = msubstr(charal,ipt-1,1); 01457 flsb[1] = fnext; 01458 dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]); 01459 //*-*- DFDA must be positive on the contour 01460 if (dfda > 0) goto L460; 01461 L300: 01462 mnwarn("D", "MNCROS ", "Looking for slope of the right sign"); 01463 maxlk = 15 - ipt; 01464 for (it = 1; it <= maxlk; ++it) { 01465 alsb[0] = alsb[1]; 01466 flsb[0] = flsb[1]; 01467 aopt = alsb[0] + double(it)*.2; 01468 fLimset = false; 01469 if (aopt > aulim) { 01470 aopt = aulim; 01471 fLimset = true; 01472 } 01473 mneval(aopt, fnext, ierev); 01474 //*-* debug printout: 01475 if (ldebug) { 01476 Printf(f_out," MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt); 01477 } 01478 if (ierev > 0) goto L900; 01479 if (fLimset && fnext <= aim) goto L930; 01480 alsb[1] = aopt; 01481 ++ipt; 01482 fXpt[ipt-1] = alsb[1]; 01483 fYpt[ipt-1] = fnext; 01484 fChpt[ipt-1] = msubstr(charal,ipt-1,1); 01485 flsb[1] = fnext; 01486 dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]); 01487 if (dfda > 0) goto L450; 01488 } 01489 mnwarn("W", "MNCROS ", "Cannot find slope of the right sign"); 01490 goto L950; 01491 L450: 01492 //*-*- we have two points with the right slope 01493 L460: 01494 aopt = alsb[1] + (aim - flsb[1]) / dfda; 01495 fdist = TMath_Min(TMath_Abs(aim - flsb[0]),TMath_Abs(aim - flsb[1])); 01496 adist = TMath_Min(TMath_Abs(aopt - alsb[0]),TMath_Abs(aopt - alsb[1])); 01497 tla = .01; 01498 if (TMath_Abs(aopt) > 1) tla = TMath_Abs(aopt)*.01; 01499 if (adist < tla && fdist < tlf) goto L800; 01500 if (ipt >= 15) goto L950; 01501 bmin = TMath_Min(alsb[0],alsb[1]) - 1; 01502 if (aopt < bmin) aopt = bmin; 01503 bmax = TMath_Max(alsb[0],alsb[1]) + 1; 01504 if (aopt > bmax) aopt = bmax; 01505 //*-*- Try a third point 01506 fLimset = false; 01507 if (aopt > aulim) { 01508 aopt = aulim; 01509 fLimset = true; 01510 } 01511 mneval(aopt, fnext, ierev); 01512 //*-* debug printout: 01513 if (ldebug) { 01514 Printf(f_out," MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt); 01515 } 01516 if (ierev > 0) goto L900; 01517 if (fLimset && fnext <= aim) goto L930; 01518 alsb[2] = aopt; 01519 ++ipt; 01520 fXpt[ipt-1] = alsb[2]; 01521 fYpt[ipt-1] = fnext; 01522 fChpt[ipt-1] = msubstr(charal,ipt-1,1); 01523 flsb[2] = fnext; 01524 //*-*- now we have three points, ask how many <AIM 01525 ecarmn = TMath_Abs(fnext-aim); 01526 ibest = 3; 01527 ecarmx = 0; 01528 noless = 0; 01529 for (i = 1; i <= 3; ++i) { 01530 ecart = TMath_Abs(flsb[i-1] - aim); 01531 if (ecart > ecarmx) { ecarmx = ecart; iworst = i; } 01532 if (ecart < ecarmn) { ecarmn = ecart; ibest = i; } 01533 if (flsb[i-1] < aim) ++noless; 01534 } 01535 //*-*- if at least one on each side of AIM, fit a parabola 01536 if (noless == 1 || noless == 2) goto L500; 01537 //*-*- if all three are above AIM, third must be closest to AIM 01538 if (noless == 0 && ibest != 3) goto L950; 01539 //*-*- if all three below, and third is not best, then slope 01540 //*-*- has again gone negative, look for positive slope. 01541 if (noless == 3 && ibest != 3) { 01542 alsb[1] = alsb[2]; 01543 flsb[1] = flsb[2]; 01544 goto L300; 01545 } 01546 //*-*- in other cases, new straight line thru last two points 01547 alsb[iworst-1] = alsb[2]; 01548 flsb[iworst-1] = flsb[2]; 01549 dfda = (flsb[1] - flsb[0]) / (alsb[1] - alsb[0]); 01550 goto L460; 01551 //*-*- parabola fit 01552 L500: 01553 mnpfit(alsb, flsb, 3, coeff, sdev); 01554 if (coeff[2] <= 0) { 01555 mnwarn("D", "MNCROS ", "Curvature is negative near contour line."); 01556 } 01557 determ = coeff[1]*coeff[1] - coeff[2]*4*(coeff[0] - aim); 01558 if (determ <= 0) { 01559 mnwarn("D", "MNCROS ", "Problem 2, impossible determinant"); 01560 goto L950; 01561 } 01562 //*-*- Find which root is the right one 01563 rt = TMath_Sqrt(determ); 01564 x1 = (-coeff[1] + rt) / (coeff[2]*2); 01565 x2 = (-coeff[1] - rt) / (coeff[2]*2); 01566 s1 = coeff[1] + x1*2*coeff[2]; 01567 s2 = coeff[1] + x2*2*coeff[2]; 01568 if (s1*s2 > 0) { 01569 Printf(f_out," MNCONTour problem 1"); 01570 } 01571 aopt = x1; 01572 slope = s1; 01573 if (s2 > 0) { 01574 aopt = x2; 01575 slope = s2; 01576 } 01577 //*-*- ask if converged 01578 tla = .01; 01579 if (TMath_Abs(aopt) > 1) tla = TMath_Abs(aopt)*.01; 01580 if (TMath_Abs(aopt - alsb[ibest-1]) < tla && TMath_Abs(flsb[ibest-1] - aim) < tlf) { 01581 goto L800; 01582 } 01583 if (ipt >= 15) goto L950; 01584 01585 //*-*- see if proposed point is in acceptable zone between L and R 01586 //*-*- first find ILEFT, IRIGHT, IOUT and IBEST 01587 ileft = 0; 01588 iright = 0; 01589 ibest = 1; 01590 ecarmx = 0; 01591 ecarmn = TMath_Abs(aim - flsb[0]); 01592 for (i = 1; i <= 3; ++i) { 01593 ecart = TMath_Abs(flsb[i-1] - aim); 01594 if (ecart < ecarmn) { ecarmn = ecart; ibest = i; } 01595 if (ecart > ecarmx) { ecarmx = ecart; } 01596 if (flsb[i-1] > aim) { 01597 if (iright == 0) iright = i; 01598 else if (flsb[i-1] > flsb[iright-1]) iout = i; 01599 else { iout = iright; iright = i; } 01600 } 01601 else if (ileft == 0) ileft = i; 01602 else if (flsb[i-1] < flsb[ileft-1]) iout = i; 01603 else { iout = ileft; ileft = i; } 01604 } 01605 //*-*- avoid keeping a very bad point next time around 01606 if (ecarmx > TMath_Abs(flsb[iout-1] - aim)*10) { 01607 aopt = aopt*.5 + (alsb[iright-1] + alsb[ileft-1])*.25; 01608 } 01609 //*-*- knowing ILEFT and IRIGHT, get acceptable window 01610 smalla = tla*.1; 01611 if (slope*smalla > tlf) smalla = tlf / slope; 01612 aleft = alsb[ileft-1] + smalla; 01613 aright = alsb[iright-1] - smalla; 01614 //*-*- move proposed point AOPT into window if necessary 01615 if (aopt < aleft) aopt = aleft; 01616 if (aopt > aright) aopt = aright; 01617 if (aleft > aright) aopt = (aleft + aright)*.5; 01618 01619 //*-*- see if proposed point outside limits (should be impossible!) 01620 fLimset = false; 01621 if (aopt > aulim) { 01622 aopt = aulim; 01623 fLimset = true; 01624 } 01625 //*-*- Evaluate function at new point AOPT 01626 mneval(aopt, fnext, ierev); 01627 //*-* debug printout: 01628 if (ldebug) { 01629 Printf(f_out," MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f",fNfcn,aim,fnext,aopt); 01630 } 01631 if (ierev > 0) goto L900; 01632 if (fLimset && fnext <= aim) goto L930; 01633 ++ipt; 01634 fXpt[ipt-1] = aopt; 01635 fYpt[ipt-1] = fnext; 01636 fChpt[ipt-1] = msubstr(charal,ipt-1,1); 01637 //*-*- Replace odd point by new one 01638 alsb[iout-1] = aopt; 01639 flsb[iout-1] = fnext; 01640 //*-*- the new point may not be the best, but it is the only one 01641 //*-*- which could be good enough to pass convergence criteria 01642 ibest = iout; 01643 goto L500; 01644 01645 //*-*- Contour has been located, return point to MNCONT OR MINOS 01646 L800: 01647 iercr = 0; 01648 goto L1000; 01649 //*-*- error in the minimization 01650 L900: 01651 if (ierev == 1) goto L940; 01652 goto L950; 01653 //*-*- parameter up against limit 01654 L930: 01655 iercr = 1; 01656 goto L1000; 01657 //*-*- too many calls to FCN 01658 L940: 01659 iercr = 2; 01660 goto L1000; 01661 //*-*- cannot find next point 01662 L950: 01663 iercr = 3; 01664 //*-*- in any case 01665 L1000: 01666 if (ldebug) { 01667 itoohi = 0; 01668 for (i = 1; i <= ipt; ++i) { 01669 if (fYpt[i-1] > aim + fUp) { 01670 fYpt[i-1] = aim + fUp; 01671 fChpt[i-1] = "+"; 01672 itoohi = 1; 01673 } 01674 } 01675 chsign = "POSI"; 01676 if (fXdircr < 0) chsign = "NEGA"; 01677 if (fKe2cr == 0) { 01678 Printf(f_out," %sTIVE MINOS ERROR, PARAMETER %3d", 01679 chsign.c_str(),fKe1cr); 01680 } 01681 if (itoohi == 1) { 01682 Printf(f_out,"POINTS LABELLED '+' WERE TOO HIGH TO PLOT."); 01683 } 01684 if (iercr == 1) { 01685 Printf(f_out,"RIGHTMOST POINT IS UP AGAINST LIMIT."); 01686 } 01687 mnplot(fXpt, fYpt, fChpt, ipt, fNpagwd, fNpagln); 01688 } 01689 } /* mncros_ */ 01690 01691 //______________________________________________________________________________ 01692 inline 01693 void fitter::mncuve() 01694 { 01695 //*-*-*-*-*-*-*-*Makes sure that the current point is a local minimum*-*-*-*-* 01696 //*-* ==================================================== 01697 //*-* Makes sure that the current point is a local 01698 //*-* minimum and that the error matrix exists, 01699 //*-* or at least something good enough for MINOS and MNCONT 01700 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 01701 01702 /* Local variables */ 01703 /*static*/ double dxdi, wint; 01704 /*static*/ int ndex, iext, i, j; 01705 01706 if (fISW[3] < 1) { 01707 Printf(f_out," FUNCTION MUST BE MINIMIZED BEFORE CALLING %s",fCfrom.c_str()); 01708 fApsi = fEpsi; 01709 mnmigr(); 01710 } 01711 if (fISW[1] < 3) { 01712 mnhess(); 01713 if (fISW[1] < 1) { 01714 mnwarn("W", fCfrom.c_str(), "NO ERROR MATRIX. WILL IMPROVISE."); 01715 for (i = 1; i <= fNpar; ++i) { 01716 ndex = i*(i-1) / 2; 01717 for (j = 1; j <= i-1; ++j) { 01718 ++ndex; 01719 fVhmat[ndex-1] = 0; 01720 } 01721 ++ndex; 01722 if (fG2[i-1] <= 0) { 01723 wint = fWerr[i-1]; 01724 iext = fNexofi[i-1]; 01725 if (fNvarl[iext-1] > 1) { 01726 mndxdi(fX[i-1], i-1, dxdi); 01727 if (TMath_Abs(dxdi) < .001) wint = .01; 01728 else wint /= TMath_Abs(dxdi); 01729 } 01730 fG2[i-1] = fUp / (wint*wint); 01731 } 01732 fVhmat[ndex-1] = 2 / fG2[i-1]; 01733 } 01734 fISW[1] = 1; 01735 fDcovar = 1; 01736 } else mnwerr(); 01737 } 01738 } /* mncuve_ */ 01739 01740 //______________________________________________________________________________ 01741 inline 01742 bool fitter::mnderi() //GB : return a bool. 01743 { 01744 //*-*-*-*-*-*-*-*Calculates the first derivatives of FCN (GRD)*-*-*-*-*-*-*-* 01745 //*-* ============================================= 01746 //*-* Calculates the first derivatives of FCN (GRD), 01747 //*-* either by finite differences or by transforming the user- 01748 //*-* supplied derivatives to internal coordinates, 01749 //*-* according to whether ISW(3) is zero or one. 01750 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 01751 01752 /* Local variables */ 01753 /*static*/ double step, dfmin, stepb4, dd, df, fs1; 01754 /*static*/ double tlrstp, tlrgrd, epspri, optstp, stpmax, stpmin, fs2, grbfor, d1d2, xtf; 01755 /*static*/ int icyc, ncyc, iint, iext, i, nparx; 01756 /*static*/ bool ldebug; 01757 grbfor = 0; //GB 01758 01759 nparx = fNpar; 01760 ldebug = fIdbg[2] >= 1; 01761 if (fAmin == fUndefi) mnamin(); 01762 if (fISW[2] == 1) goto L100; 01763 01764 if (ldebug) { 01765 //*-*- make sure starting at the right place 01766 mninex(fX); 01767 nparx = fNpar; 01768 if(!(*fFCN)(nparx, fGin, fs1, fU, 4,fTag)) return false; 01769 ++fNfcn; 01770 if (fs1 != fAmin) { 01771 df = fAmin - fs1; 01772 mnwarn("D", "MNDERI", Form("function value differs from AMIN by %12.3g",df)); 01773 fAmin = fs1; 01774 } 01775 Printf(f_out," FIRST DERIVATIVE DEBUG PRINTOUT. MNDERI"); 01776 Printf(f_out," PAR DERIV STEP MINSTEP OPTSTEP D1-D2 2ND DRV"); 01777 } 01778 dfmin = fEpsma2*8*(TMath_Abs(fAmin) + fUp); 01779 if (fIstrat <= 0) { 01780 ncyc = 2; 01781 tlrstp = .5; 01782 tlrgrd = .1; 01783 } else if (fIstrat == 1) { 01784 ncyc = 3; 01785 tlrstp = .3; 01786 tlrgrd = .05; 01787 } else { 01788 ncyc = 5; 01789 tlrstp = .1; 01790 tlrgrd = .02; 01791 } 01792 //*-*- loop over variable parameters 01793 for (i = 1; i <= fNpar; ++i) { 01794 epspri = fEpsma2 + TMath_Abs(fGrd[i-1]*fEpsma2); 01795 //*-*- two-point derivatives always assumed necessary 01796 //*-*- maximum number of cycles over step size depends on strategy 01797 xtf = fX[i-1]; 01798 stepb4 = 0; 01799 //*-*- loop as little as possible here!/ 01800 for (icyc = 1; icyc <= ncyc; ++icyc) { 01801 //*-*- ........ theoretically best step 01802 optstp = TMath_Sqrt(dfmin / (TMath_Abs(fG2[i-1]) + epspri)); 01803 //*-*- step cannot decrease by more than a factor of ten 01804 step = TMath_Max(optstp,TMath_Abs(fGstep[i-1]*.1)); 01805 //*-*- but if parameter has limits, max step size = 0.5 01806 if (fGstep[i-1] < 0 && step > .5) step = .5; 01807 //*-*- and not more than ten times the previous step 01808 stpmax = TMath_Abs(fGstep[i-1])*10; 01809 if (step > stpmax) step = stpmax; 01810 //*-*- minimum step size allowed by machine precision 01811 stpmin = TMath_Abs(fEpsma2*fX[i-1])*8; 01812 if (step < stpmin) step = stpmin; 01813 //*-*- end of iterations if step change less than factor 2 01814 if (TMath_Abs((step - stepb4) / step) < tlrstp) goto L50; 01815 //*-*- take step positive 01816 stepb4 = step; 01817 if (fGstep[i-1] > 0) fGstep[i-1] = TMath_Abs(step); 01818 else fGstep[i-1] = -TMath_Abs(step); 01819 stepb4 = step; 01820 fX[i-1] = xtf + step; 01821 mninex(fX); 01822 if(!(*fFCN)(nparx, fGin, fs1, fU, 4,fTag)) return false; //GB 01823 ++fNfcn; 01824 //*-*- take step negative 01825 fX[i-1] = xtf - step; 01826 mninex(fX); 01827 if(!(*fFCN)(nparx, fGin, fs2, fU, 4,fTag)) return false; //GB 01828 ++fNfcn; 01829 grbfor = fGrd[i-1]; 01830 fGrd[i-1] = (fs1 - fs2) / (step*2); 01831 fG2[i-1] = (fs1 + fs2 - fAmin*2) / (step*step); 01832 fX[i-1] = xtf; 01833 if (ldebug) { 01834 d1d2 = (fs1 + fs2 - fAmin*2) / step; 01835 Printf(f_out,"%4d%11.3g%11.3g%10.2g%10.2g%10.2g%10.2g%10.2g",i,fGrd[i-1],step,stpmin,optstp,d1d2,fG2[i-1]); 01836 } 01837 //*-*- see if another iteration is necessary 01838 if (TMath_Abs(grbfor - fGrd[i-1]) / (TMath_Abs(fGrd[i-1]) + dfmin/step) < tlrgrd) 01839 goto L50; 01840 } 01841 //*-*- end of ICYC loop. too many iterations 01842 if (ncyc == 1) goto L50; 01843 mnwarn("D", "MNDERI", Form("First derivative not converged. %g%g",fGrd[i-1],grbfor)); 01844 L50: 01845 ; 01846 } 01847 mninex(fX); 01848 return true; 01849 //*-*- . derivatives calc by fcn 01850 L100: 01851 for (iint = 1; iint <= fNpar; ++iint) { 01852 iext = fNexofi[iint-1]; 01853 if (fNvarl[iext-1] <= 1) { 01854 fGrd[iint-1] = fGin[iext-1]; 01855 } else { 01856 dd = (fBlim[iext-1] - fAlim[iext-1])*.5*TMath_Cos(fX[iint-1]); 01857 fGrd[iint-1] = fGin[iext-1]*dd; 01858 } 01859 } 01860 return true; 01861 } /* mnderi_ */ 01862 01863 //______________________________________________________________________________ 01864 inline 01865 void fitter::mndxdi(double pint, int ipar, double &dxdi) 01866 { 01867 //*-*-*-*Calculates the transformation factor between ext/internal values*-* 01868 //*-* ===================================================================== 01869 //*-* calculates the transformation factor between external and 01870 //*-* internal parameter values. this factor is one for 01871 //*-* parameters which are not limited. called from MNEMAT. 01872 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 01873 01874 int i = fNexofi[ipar]; 01875 dxdi = 1; 01876 if (fNvarl[i-1] > 1) { 01877 dxdi = TMath_Abs((fBlim[i-1] - fAlim[i-1])*TMath_Cos(pint))*.5; 01878 } 01879 } /* mndxdi_ */ 01880 01881 //______________________________________________________________________________ 01882 inline 01883 void fitter::mneig(double *a, int ndima, int n, int mits, double *work, double precis, int &ifault) 01884 { 01885 //*-*-*-*-*-*-*-*-*-*-*-*Compute matrix eigen values*-*-*-*-*-*-*-*-*-*-*-*-* 01886 //*-* =========================== 01887 /* System generated locals */ 01888 int a_offset; 01889 double d__1; 01890 01891 /* Local variables */ 01892 /*static*/ double b, c, f, h, r, s, hh, gl, pr, pt; 01893 /*static*/ int i, j, k, l, m, i0, i1, j1, m1, n1; 01894 m = 0; //GB : rm warning. 01895 01896 //*-*- PRECIS is the machine precision EPSMAC 01897 /* Parameter adjustments */ 01898 a_offset = ndima + 1; 01899 a -= a_offset; 01900 --work; 01901 01902 /* Function Body */ 01903 ifault = 1; 01904 01905 i = n; 01906 for (i1 = 2; i1 <= n; ++i1) { 01907 l = i-2; 01908 f = a[i + (i-1)*ndima]; 01909 gl = 0; 01910 01911 if (l < 1) goto L25; 01912 01913 for (k = 1; k <= l; ++k) { 01914 d__1 = a[i + k*ndima]; 01915 gl += d__1*d__1; 01916 } 01917 L25: 01918 h = gl + f*f; 01919 01920 if (gl > 1e-35) goto L30; 01921 01922 work[i] = 0; 01923 work[n + i] = f; 01924 goto L65; 01925 L30: 01926 ++l; 01927 gl = TMath_Sqrt(h); 01928 if (f >= 0) gl = -gl; 01929 work[n + i] = gl; 01930 h -= f*gl; 01931 a[i + (i-1)*ndima] = f - gl; 01932 f = 0; 01933 for (j = 1; j <= l; ++j) { 01934 a[j + i*ndima] = a[i + j*ndima] / h; 01935 gl = 0; 01936 for (k = 1; k <= j; ++k) { gl += a[j + k*ndima]*a[i + k*ndima]; } 01937 if (j >= l) goto L47; 01938 j1 = j + 1; 01939 for (k = j1; k <= l; ++k) { gl += a[k + j*ndima]*a[i + k*ndima]; } 01940 L47: 01941 work[n + j] = gl / h; 01942 f += gl*a[j + i*ndima]; 01943 } 01944 hh = f / (h + h); 01945 for (j = 1; j <= l; ++j) { 01946 f = a[i + j*ndima]; 01947 gl = work[n + j] - hh*f; 01948 work[n + j] = gl; 01949 for (k = 1; k <= j; ++k) { 01950 a[j + k*ndima] = a[j + k*ndima] - f*work[n + k] - gl*a[i + k*ndima]; 01951 } 01952 } 01953 work[i] = h; 01954 L65: 01955 --i; 01956 } 01957 work[1] = 0; 01958 work[n + 1] = 0; 01959 for (i = 1; i <= n; ++i) { 01960 l = i-1; 01961 if (work[i] == 0 || l == 0) goto L100; 01962 01963 for (j = 1; j <= l; ++j) { 01964 gl = 0; 01965 for (k = 1; k <= l; ++k) { gl += a[i + k*ndima]*a[k + j*ndima]; } 01966 for (k = 1; k <= l; ++k) { a[k + j*ndima] -= gl*a[k + i*ndima]; } 01967 } 01968 L100: 01969 work[i] = a[i + i*ndima]; 01970 a[i + i*ndima] = 1; 01971 if (l == 0) continue; 01972 01973 for (j = 1; j <= l; ++j) { 01974 a[i + j*ndima] = 0; 01975 a[j + i*ndima] = 0; 01976 } 01977 } 01978 01979 n1 = n - 1; 01980 for (i = 2; i <= n; ++i) { 01981 i0 = n + i-1; 01982 work[i0] = work[i0 + 1]; 01983 } 01984 work[n + n] = 0; 01985 b = 0; 01986 f = 0; 01987 for (l = 1; l <= n; ++l) { 01988 j = 0; 01989 h = precis*(TMath_Abs(work[l]) + TMath_Abs(work[n + l])); 01990 if (b < h) b = h; 01991 for (m1 = l; m1 <= n; ++m1) { 01992 m = m1; 01993 if (TMath_Abs(work[n + m]) <= b) goto L150; 01994 } 01995 01996 L150: 01997 if (m == l) goto L205; 01998 01999 L160: 02000 if (j == mits) return; 02001 ++j; 02002 pt = (work[l + 1] - work[l]) / (work[n + l]*2); 02003 r = TMath_Sqrt(pt*pt + 1); 02004 pr = pt + r; 02005 if (pt < 0) pr = pt - r; 02006 02007 h = work[l] - work[n + l] / pr; 02008 for (i = l; i <= n; ++i) { work[i] -= h; } 02009 f += h; 02010 pt = work[m]; 02011 c = 1; 02012 s = 0; 02013 m1 = m - 1; 02014 i = m; 02015 for (i1 = l; i1 <= m1; ++i1) { 02016 j = i; 02017 --i; 02018 gl = c*work[n + i]; 02019 h = c*pt; 02020 if (TMath_Abs(pt) >= TMath_Abs(work[n + i])) goto L180; 02021 02022 c = pt / work[n + i]; 02023 r = TMath_Sqrt(c*c + 1); 02024 work[n + j] = s*work[n + i]*r; 02025 s = 1 / r; 02026 c /= r; 02027 goto L190; 02028 L180: 02029 c = work[n + i] / pt; 02030 r = TMath_Sqrt(c*c + 1); 02031 work[n + j] = s*pt*r; 02032 s = c / r; 02033 c = 1 / r; 02034 L190: 02035 pt = c*work[i] - s*gl; 02036 work[j] = h + s*(c*gl + s*work[i]); 02037 for (k = 1; k <= n; ++k) { 02038 h = a[k + j*ndima]; 02039 a[k + j*ndima] = s*a[k + i*ndima] + c*h; 02040 a[k + i*ndima] = c*a[k + i*ndima] - s*h; 02041 } 02042 } 02043 work[n + l] = s*pt; 02044 work[l] = c*pt; 02045 02046 if (TMath_Abs(work[n + l]) > b) goto L160; 02047 02048 L205: 02049 work[l] += f; 02050 } 02051 for (i = 1; i <= n1; ++i) { 02052 k = i; 02053 pt = work[i]; 02054 i1 = i + 1; 02055 for (j = i1; j <= n; ++j) { 02056 if (work[j] >= pt) continue; 02057 k = j; 02058 pt = work[j]; 02059 } 02060 02061 if (k == i) continue; 02062 02063 work[k] = work[i]; 02064 work[i] = pt; 02065 for (j = 1; j <= n; ++j) { 02066 pt = a[j + i*ndima]; 02067 a[j + i*ndima] = a[j + k*ndima]; 02068 a[j + k*ndima] = pt; 02069 } 02070 } 02071 ifault = 0; 02072 } /* mneig_ */ 02073 02074 //______________________________________________________________________________ 02075 inline 02076 void fitter::mnemat(double *emat, int ndim) 02077 { 02078 //*-*-*-*-*-*Calculates the external error matrix from the internal matrix*-* 02079 //*-* ============================================================= 02080 //*-* Calculates the external error matrix from the internal 02081 //*-* to be called by user. 02082 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 02083 02084 /* System generated locals */ 02085 int emat_dim1, emat_offset; 02086 02087 /* Local variables */ 02088 /*static*/ double dxdi, dxdj; 02089 /*static*/ int i, j, k, npard, k2, kk, iz, nperln, kga, kgb; 02090 /*static*/ std::string ctemp; 02091 02092 /* Parameter adjustments */ 02093 emat_dim1 = ndim; 02094 emat_offset = emat_dim1 + 1; 02095 emat -= emat_offset; 02096 02097 /* Function Body */ 02098 if (fISW[1] < 1) return; 02099 if (fISW[4] >= 2) { 02100 Printf(f_out," EXTERNAL ERROR MATRIX. NDIM=%4d NPAR=%3d ERR DEF=%g",ndim,fNpar,fUp); 02101 } 02102 //*-*- size of matrix to be printed 02103 npard = fNpar; 02104 if (ndim < fNpar) { 02105 npard = ndim; 02106 if (fISW[4] >= 0) { 02107 Printf(f_out," USER-DIMENSIONED ARRAY EMAT NOT BIG ENOUGH. REDUCED MATRIX CALCULATED."); 02108 } 02109 } 02110 //*-*- NPERLN is the number of elements that fit on one line 02111 02112 nperln = (fNpagwd - 5) / 10; 02113 nperln = TMath_Min(nperln,13); 02114 if (fISW[4] >= 1 && npard > nperln) { 02115 Printf(f_out," ELEMENTS ABOVE DIAGONAL ARE NOT PRINTED."); 02116 } 02117 //*-*- I counts the rows of the matrix 02118 for (i = 1; i <= npard; ++i) { 02119 mndxdi(fX[i-1], i-1, dxdi); 02120 kga = i*(i-1) / 2; 02121 for (j = 1; j <= i; ++j) { 02122 mndxdi(fX[j-1], j-1, dxdj); 02123 kgb = kga + j; 02124 emat[i + j*emat_dim1] = dxdi*fVhmat[kgb-1]*dxdj*fUp; 02125 emat[j + i*emat_dim1] = emat[i + j*emat_dim1]; 02126 } 02127 } 02128 //*-*- IZ is number of columns to be printed in row I 02129 if (fISW[4] >= 2) { 02130 for (i = 1; i <= npard; ++i) { 02131 iz = npard; 02132 if (npard >= nperln) iz = i; 02133 ctemp = " "; 02134 for (k = 1; nperln < 0 ? k >= iz : k <= iz; k += nperln) { 02135 k2 = k + nperln - 1; 02136 if (k2 > iz) k2 = iz; 02137 for (kk = k; kk <= k2; ++kk) { 02138 ctemp += Form("%10.3e ",emat[i + kk*emat_dim1]); 02139 } 02140 Printf(f_out,"%s",ctemp.c_str()); 02141 } 02142 } 02143 } 02144 } /* mnemat_ */ 02145 02146 //______________________________________________________________________________ 02147 inline 02148 void fitter::mnerrs(int number, double &eplus, double &eminus, double &eparab, double &gcc) 02149 { 02150 //*-*-*-*-*-*-*-*-*-*Utility routine to get MINOS errors*-*-*-*-*-*-*-*-*-*-* 02151 //*-* =================================== 02152 //*-* Called by user. 02153 //*-* NUMBER is the parameter number 02154 //*-* values returned by MNERRS: 02155 //*-* EPLUS, EMINUS are MINOS errors of parameter NUMBER, 02156 //*-* EPARAB is 'parabolic' error (from error matrix). 02157 //*-* (Errors not calculated are set = 0) 02158 //*-* GCC is global correlation coefficient from error matrix 02159 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 02160 02161 /*static*/ double dxdi; 02162 /*static*/ int ndiag, iin, iex; 02163 02164 iex = number+1; 02165 02166 if (iex > fNu || iex <= 0) goto L900; 02167 iin = fNiofex[iex-1]; 02168 if (iin <= 0) goto L900; 02169 02170 //*-*- IEX is external number, IIN is internal number 02171 eplus = fErp[iin-1]; 02172 if (eplus == fUndefi) eplus = 0; 02173 eminus = fErn[iin-1]; 02174 if (eminus == fUndefi) eminus = 0; 02175 mndxdi(fX[iin-1], iin-1, dxdi); 02176 ndiag = iin*(iin + 1) / 2; 02177 eparab = TMath_Abs(dxdi*TMath_Sqrt(TMath_Abs(fUp*fVhmat[ndiag- 1]))); 02178 //*-*- global correlation coefficient 02179 gcc = 0; 02180 if (fISW[1] < 2) return; 02181 gcc = fGlobcc[iin-1]; 02182 return; 02183 //*-*- ERROR. parameter number not valid 02184 L900: 02185 eplus = 0; 02186 eminus = 0; 02187 eparab = 0; 02188 gcc = 0; 02189 } /* mnerrs_ */ 02190 02191 //______________________________________________________________________________ 02192 inline 02193 void fitter::mneval(double anext, double &fnext, int &ierev) 02194 { 02195 //*-*-*-*-*-*-*Evaluates the function being analyzed by MNCROS*-*-*-*-*-*-*-* 02196 //*-* =============================================== 02197 //*-* Evaluates the function being analyzed by MNCROS, which is 02198 //*-* generally the minimum of FCN with respect to all remaining 02199 //*-* variable parameters. The class data members contains the 02200 //*-* data necessary to know the values of U(KE1CR) and U(KE2CR) 02201 //*-* to be used, namely U(KE1CR) = XMIDCR + ANEXT*XDIRCR 02202 //*-* and (if KE2CR .NE. 0) U(KE2CR) = YMIDCR + ANEXT*YDIRCR 02203 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 02204 02205 /*static*/ int nparx; 02206 02207 fU[fKe1cr-1] = fXmidcr + anext*fXdircr; 02208 if (fKe2cr != 0) fU[fKe2cr-1] = fYmidcr + anext*fYdircr; 02209 mninex(fX); 02210 nparx = fNpar; 02211 //Printf(f_out,"debug : FCN : 007"); 02212 (*fFCN)(nparx, fGin, fnext, fU, 4,fTag); ++fNfcn; 02213 ierev = 0; 02214 if (fNpar > 0) { 02215 fItaur = 1; 02216 fAmin = fnext; 02217 fISW[0] = 0; 02218 mnmigr(); 02219 fItaur = 0; 02220 fnext = fAmin; 02221 if (fISW[0] >= 1) ierev = 1; 02222 if (fISW[3] < 1) ierev = 2; 02223 } 02224 } /* mneval_ */ 02225 02226 //______________________________________________________________________________ 02227 //GB : const for plist. 02228 inline 02229 void fitter::mnexcm(const std::string& comand, const double *plist, int llist, int &ierflg) 02230 { 02231 //*-*-*-*-*-*Interprets a command and takes appropriate action*-*-*-*-*-*-*-* 02232 //*-* ================================================= 02233 //*-* either directly by skipping to the corresponding code in 02234 //*-* MNEXCM, or by setting up a call to a function 02235 //*-* 02236 //*-* recognized MINUIT commands: 02237 //*-* obsolete commands: 02238 //*-* IERFLG is now (94.5) defined the same as ICONDN in MNCOMD 02239 //*-* = 0: command executed normally 02240 //*-* 1: command is blank, ignored 02241 //*-* 2: command line unreadable, ignored 02242 //*-* 3: unknown command, ignored 02243 //*-* 4: abnormal termination (e.g., MIGRAD not converged) 02244 //*-* 9: reserved 02245 //*-* 10: END command 02246 //*-* 11: EXIT or STOP command 02247 //*-* 12: RETURN command 02248 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 02249 02250 /* Initialized data */ 02251 02252 static const std::string clower = "abcdefghijklmnopqrstuvwxyz"; 02253 static const std::string cupper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 02254 static const std::string cname[40] = { 02255 "MINImize ", 02256 "SEEk ", 02257 "SIMplex ", 02258 "MIGrad ", 02259 "MINOs ", 02260 "SET xxx ", 02261 "SHOw xxx ", 02262 "TOP of pag", 02263 "FIX ", 02264 "REStore ", 02265 "RELease ", 02266 "SCAn ", 02267 "CONtour ", 02268 "HESse ", 02269 "SAVe ", 02270 "IMProve ", 02271 "CALl fcn ", 02272 "STAndard ", 02273 "END ", 02274 "EXIt ", 02275 "RETurn ", 02276 "CLEar ", 02277 "HELP ", 02278 "MNContour ", 02279 "STOp ", 02280 "JUMp ", 02281 " ", 02282 " ", 02283 " ", 02284 " ", 02285 " ", 02286 " ", 02287 " ", 02288 "COVARIANCE", 02289 "PRINTOUT ", 02290 "GRADIENT ", 02291 "MATOUT ", 02292 "ERROR DEF ", 02293 "LIMITS ", 02294 "PUNCH "}; 02295 02296 /*static*/ int nntot = 40; 02297 02298 /* Local variables */ 02299 /*static*/ double step, xptu[101], yptu[101], f, rno; 02300 /*static*/ int icol, kcol, ierr, iint, iext, lnow, nptu, i, iflag, ierrf; 02301 /*static*/ int ilist, nparx, izero, nf, lk, it, iw, inonde, nsuper; 02302 /*static*/ int it2, ke1, ke2, nowprt, kll, let, krl; 02303 /*static*/ std::string chwhy, c26, cvblnk, cneway, comd; 02304 /*static*/ std::string ctemp; 02305 /*static*/ bool lfreed, ltofix, lfixed; 02306 02307 //*-* alphabetical order of command names! 02308 02309 /* Function Body */ 02310 02311 lk = comand.size(); 02312 if (lk > 20) lk = 20; 02313 fCword = comand; 02314 //*-*- get upper case 02315 for (icol = 1; icol <= lk; ++icol) { 02316 for (let = 1; let <= 26; ++let) { 02317 if (fCword[icol-1] == clower[let-1]) { 02318 fCword[icol-1] = cupper[let-1]; 02319 } 02320 } 02321 } 02322 //*-*- Copy the first MAXP arguments into WORD7, making 02323 //*-*- sure that WORD7(1)=0 if LLIST=0 02324 for (iw = 1; iw <= 30; ++iw) { 02325 fWord7[iw-1] = 0; 02326 if (iw <= llist) fWord7[iw-1] = plist[iw-1]; 02327 } 02328 ++fIcomnd; 02329 fNfcnlc = fNfcn; 02330 if (msubstr(fCword,0,7) != "SET PRI" || fWord7[0] >= 0) { 02331 if (fISW[4] >= 0) { 02332 lnow = llist; 02333 if (lnow > 4) lnow = 4; 02334 Printf(f_out," **********"); 02335 ctemp = Form(" **%5d **%s",fIcomnd,fCword.c_str()); 02336 for (i = 1; i <= lnow; ++i) { 02337 ctemp += Form("%12.4g",plist[i-1]); 02338 } 02339 Printf(f_out,"%s",ctemp.c_str()); 02340 inonde = 0; 02341 if (llist > lnow) { 02342 kll = llist; 02343 if (llist > 30) { 02344 inonde = 1; 02345 kll = 30; 02346 } 02347 Printf(f_out," ***********"); 02348 for (i = lnow + 1; i <= kll; ++i) { 02349 Printf(f_out,"%12.4g",plist[i-1]); 02350 } 02351 } 02352 Printf(f_out," **********"); 02353 if (inonde > 0) { 02354 Printf(f_out," ERROR: ABOVE CALL TO MNEXCM TRIED TO PASS MORE THAN 30 PARAMETERS."); 02355 } 02356 } 02357 } 02358 fNfcnmx = int(fWord7[0]); 02359 if (fNfcnmx <= 0) { 02360 fNfcnmx = fNpar*100 + 200 + fNpar*fNpar*5; 02361 } 02362 fEpsi = fWord7[1]; 02363 if (fEpsi <= 0) { 02364 fEpsi = fUp*.1; 02365 } 02366 fLnewmn = false; 02367 fLphead = true; 02368 fISW[0] = 0; 02369 ierflg = 0; 02370 //*-*- look for command in list CNAME . . . . . . . . . . 02371 for (i = 1; i <= nntot; ++i) { 02372 if (msubstr(fCword,0,3) == msubstr(cname[i-1],0,3)) goto L90; 02373 } 02374 Printf(f_out,"UNKNOWN COMMAND IGNORED:%s", comand.c_str()); 02375 ierflg = 3; 02376 return; 02377 //*-*- normal case: recognized MINUIT command . . . . . . . 02378 L90: 02379 if (msubstr(fCword,0,4) == "MINO") i = 5; 02380 if (i != 6 && i != 7 && i != 8 && i != 23) { 02381 fCfrom = cname[i-1]; 02382 fNfcnfr = fNfcn; 02383 } 02384 //*-*- 1 2 3 4 5 6 7 8 9 10 02385 switch (i) { 02386 case 1: goto L400; 02387 case 2: goto L200; 02388 case 3: goto L300; 02389 case 4: goto L400; 02390 case 5: goto L500; 02391 case 6: goto L700; 02392 case 7: goto L700; 02393 case 8: goto L800; 02394 case 9: goto L900; 02395 case 10: goto L1000; 02396 case 11: goto L1100; 02397 case 12: goto L1200; 02398 case 13: goto L1300; 02399 case 14: goto L1400; 02400 case 15: goto L1500; 02401 case 16: goto L1600; 02402 case 17: goto L1700; 02403 case 18: goto L1800; 02404 case 19: goto L1900; 02405 case 20: goto L1900; 02406 case 21: goto L1900; 02407 case 22: goto L2200; 02408 case 23: goto L2300; 02409 case 24: goto L2400; 02410 case 25: goto L1900; 02411 case 26: goto L2600; 02412 case 27: goto L3300; 02413 case 28: goto L3300; 02414 case 29: goto L3300; 02415 case 30: goto L3300; 02416 case 31: goto L3300; 02417 case 32: goto L3300; 02418 case 33: goto L3300; 02419 case 34: goto L3400; 02420 case 35: goto L3500; 02421 case 36: goto L3600; 02422 case 37: goto L3700; 02423 case 38: goto L3800; 02424 case 39: goto L3900; 02425 case 40: goto L4000; 02426 } 02427 //*-*- . . . . . . . . . . seek 02428 L200: 02429 mnseek(); 02430 return; 02431 //*-*- . . . . . . . . . . simplex 02432 L300: 02433 mnsimp(); 02434 if (fISW[3] < 1) ierflg = 4; 02435 return; 02436 //*-*- . . . . . . migrad, minimize 02437 L400: 02438 nf = fNfcn; 02439 fApsi = fEpsi; 02440 if(!mnmigr()) { 02441 Printf(f_out,"fitter::mnexcm : mnmigr aborted."); 02442 ierflg = 4; 02443 return; 02444 } 02445 mnwerr(); 02446 if (fISW[3] >= 1) return; 02447 ierflg = 4; 02448 if (fISW[0] == 1) return; 02449 if (msubstr(fCword,0,3) == "MIG") return; 02450 02451 fNfcnmx = fNfcnmx + nf - fNfcn; 02452 nf = fNfcn; 02453 mnsimp(); 02454 if (fISW[0] == 1) return; 02455 fNfcnmx = fNfcnmx + nf - fNfcn; 02456 mnmigr(); 02457 if (fISW[3] >= 1) ierflg = 0; 02458 mnwerr(); 02459 return; 02460 //*-*- . . . . . . . . . . minos 02461 L500: 02462 //GB : NT/cl.exe gives a warning about << and precedence 02463 // in the below original code : 02464 //GB nsuper = fNfcn + (fNpar + 1 << 1)*fNfcnmx; 02465 //GB : I have change for the below. The precedence had been 02466 // on a Linux/gxx, MacOSX/gxx and OSF1/cxx. 02467 nsuper = fNfcn + ((fNpar + 1) << 1)*fNfcnmx; //GB 02468 //*-*- possible loop over new minima 02469 fEpsi = fUp*.1; 02470 L510: 02471 mncuve(); 02472 mnmnos(); 02473 if (! fLnewmn) return; 02474 mnrset(0); 02475 mnmigr(); 02476 mnwerr(); 02477 if (fNfcn < nsuper) goto L510; 02478 Printf(f_out," TOO MANY FUNCTION CALLS. MINOS GIVES UP"); 02479 ierflg = 4; 02480 return; 02481 //*-*- . . . . . . . . . .set, show 02482 L700: 02483 mnset(); 02484 return; 02485 //*-*- . . . . . . . . . . top of page 02486 02487 L800: 02488 Printf(f_out,"1"); 02489 return; 02490 //*-*- . . . . . . . . . . fix 02491 L900: 02492 ltofix = true; 02493 //*-*- . . (also release) .... 02494 L901: 02495 lfreed = false; 02496 lfixed = false; 02497 if (llist == 0) { 02498 Printf(f_out,"%s: NO PARAMETERS REQUESTED ",fCword.c_str()); 02499 return; 02500 } 02501 for (ilist = 1; ilist <= llist; ++ilist) { 02502 iext = int(plist[ilist-1]); 02503 chwhy = " IS UNDEFINED."; 02504 if (iext <= 0) goto L930; 02505 if (iext > fNu) goto L930; 02506 if (fNvarl[iext-1] < 0) goto L930; 02507 chwhy = " IS CONSTANT. "; 02508 if (fNvarl[iext-1] == 0) goto L930; 02509 iint = fNiofex[iext-1]; 02510 if (ltofix) { 02511 chwhy = " ALREADY FIXED."; 02512 if (iint == 0) goto L930; 02513 mnfixp(iint-1, ierr); 02514 if (ierr == 0) lfixed = true; 02515 else ierflg = 4; 02516 } else { 02517 chwhy = " ALREADY VARIABLE."; 02518 if (iint > 0) goto L930; 02519 krl = -TMath_int_abs(iext); 02520 mnfree(krl); 02521 lfreed = true; 02522 } 02523 continue; 02524 L930: 02525 Printf(f_out," PARAMETER%4d %s IGNORED.",iext,chwhy.c_str()); 02526 } 02527 if (lfreed || lfixed) mnrset(0); 02528 if (lfreed) { 02529 fISW[1] = 0; 02530 fDcovar = 1; 02531 fEDM = fBigedm; 02532 fISW[3] = 0; 02533 } 02534 mnwerr(); 02535 if (fISW[4] > 1) mnprin(5, fAmin); 02536 return; 02537 //*-*- . . . . . . . . . . restore 02538 L1000: 02539 it = int(fWord7[0]); 02540 if (it > 1 || it < 0) goto L1005; 02541 lfreed = fNpfix > 0; 02542 mnfree(it); 02543 if (lfreed) { 02544 mnrset(0); 02545 fISW[1] = 0; 02546 fDcovar = 1; 02547 fEDM = fBigedm; 02548 } 02549 return; 02550 L1005: 02551 Printf(f_out," IGNORED. UNKNOWN ARGUMENT:%4d",it); 02552 ierflg = 3; 02553 return; 02554 //*-*- . . . . . . . . . . release 02555 L1100: 02556 ltofix = false; 02557 goto L901; 02558 //*-*- . . . . . . . . . . scan . . . 02559 L1200: 02560 iext = int(fWord7[0]); 02561 if (iext <= 0) goto L1210; 02562 it2 = 0; 02563 if (iext <= fNu) it2 = fNiofex[iext-1]; 02564 if (it2 <= 0) goto L1250; 02565 02566 L1210: 02567 mnscan(); 02568 return; 02569 L1250: 02570 Printf(f_out," PARAMETER%4d NOT VARIABLE.",iext); 02571 ierflg = 3; 02572 return; 02573 //*-*- . . . . . . . . . . contour 02574 L1300: 02575 ke1 = int(fWord7[0]); 02576 ke2 = int(fWord7[1]); 02577 if (ke1 == 0) { 02578 if (fNpar == 2) { 02579 ke1 = fNexofi[0]; 02580 ke2 = fNexofi[1]; 02581 } else { 02582 Printf(f_out,"%s: NO PARAMETERS REQUESTED ",fCword.c_str()); 02583 ierflg = 3; 02584 return; 02585 } 02586 } 02587 fNfcnmx = 1000; 02588 mncntr(ke1, ke2, ierrf); 02589 if (ierrf > 0) ierflg = 3; 02590 return; 02591 //*-*- . . . . . . . . . . hesse 02592 L1400: 02593 mnhess(); 02594 mnwerr(); 02595 if (fISW[4] >= 0) mnprin(2, fAmin); 02596 if (fISW[4] >= 1) mnmatu(1); 02597 return; 02598 //*-*- . . . . . . . . . . save 02599 L1500: 02600 mnsave(); 02601 return; 02602 //*-*- . . . . . . . . . . improve 02603 L1600: 02604 mncuve(); 02605 mnimpr(); 02606 if (fLnewmn) goto L400; 02607 ierflg = 4; 02608 return; 02609 //*-*- . . . . . . . . . . call fcn 02610 L1700: 02611 iflag = int(fWord7[0]); 02612 nparx = fNpar; 02613 f = fUndefi; 02614 //Printf(f_out,"debug : FCN : 008"); 02615 (*fFCN)(nparx, fGin, f, fU, iflag,fTag); ++fNfcn; 02616 nowprt = 0; 02617 if (f != fUndefi) { 02618 if (fAmin == fUndefi) { 02619 fAmin = f; 02620 nowprt = 1; 02621 } else if (f < fAmin) { 02622 fAmin = f; 02623 nowprt = 1; 02624 } 02625 if (fISW[4] >= 0 && iflag <= 5 && nowprt == 1) { 02626 mnprin(5, fAmin); 02627 } 02628 if (iflag == 3) fFval3 = f; 02629 } 02630 if (iflag > 5) mnrset(1); 02631 return; 02632 //*-*- . . . . . . . . . . standard 02633 L1800: 02634 // stand(); 02635 return; 02636 //*-*- . . . return, stop, end, exit 02637 L1900: 02638 it = int(fWord7[0]); 02639 if (fFval3 != fAmin && it == 0) { 02640 iflag = 3; 02641 Printf(f_out," CALL TO USER FUNCTION WITH IFLAG = 3"); 02642 nparx = fNpar; 02643 //Printf(f_out,"debug : FCN : 009"); 02644 (*fFCN)(nparx, fGin, f, fU, iflag,fTag); ++fNfcn; 02645 } 02646 ierflg = 11; 02647 if (msubstr(fCword,0,3) == "END") ierflg = 10; 02648 if (msubstr(fCword,0,3) == "RET") ierflg = 12; 02649 return; 02650 //*-*- . . . . . . . . . . clear 02651 L2200: 02652 mncler(); 02653 if (fISW[4] >= 1) { 02654 Printf(f_out," MINUIT MEMORY CLEARED. NO PARAMETERS NOW DEFINED."); 02655 } 02656 return; 02657 //*-*- . . . . . . . . . . help 02658 L2300: 02659 kcol = 0; 02660 for (icol = 5; icol <= lk; ++icol) { 02661 if (fCword[icol-1] == ' ') continue; 02662 kcol = icol; 02663 goto L2320; 02664 } 02665 L2320: 02666 if (kcol == 0) comd = "* "; 02667 else comd.assign(1,fCword[kcol-1]); 02668 mnhelp(comd); 02669 return; 02670 //*-*- . . . . . . . . . . MNContour 02671 L2400: 02672 fEpsi = fUp*.05; 02673 ke1 = int(fWord7[0]); 02674 ke2 = int(fWord7[1]); 02675 if (ke1 == 0 && fNpar == 2) { 02676 ke1 = fNexofi[0]; 02677 ke2 = fNexofi[1]; 02678 } 02679 nptu = int(fWord7[2]); 02680 if (nptu <= 0) nptu = 20; 02681 if (nptu > 101) nptu = 101; 02682 fNfcnmx = (nptu + 5)*100*(fNpar + 1); 02683 mncont(ke1, ke2, nptu, xptu, yptu, ierrf); 02684 if (ierrf < nptu) ierflg = 4; 02685 if (ierrf == -1) ierflg = 3; 02686 return; 02687 //*-*- . . . . . . . . . . jump 02688 L2600: 02689 step = fWord7[0]; 02690 if (step <= 0) step = 2; 02691 rno = 0; 02692 izero = 0; 02693 for (i = 1; i <= fNpar; ++i) { 02694 mnrn15(rno, izero); 02695 rno = rno*2 - 1; 02696 fX[i-1] += rno*step*fWerr[i-1]; 02697 } 02698 mninex(fX); 02699 mnamin(); 02700 mnrset(0); 02701 return; 02702 //*-*- . . . . . . . . . . blank line 02703 L3300: 02704 Printf(f_out," BLANK COMMAND IGNORED."); 02705 ierflg = 1; 02706 return; 02707 //*-* . . . . . . . . obsolete commands . . . . . . . . . . . . . . 02708 //*-*- . . . . . . . . . . covariance 02709 L3400: 02710 Printf(f_out," THE *COVARIANCE* COMMAND IS OSBSOLETE. THE COVARIANCE MATRIX IS NOW SAVED IN A DIFFERENT FORMAT WITH THE *SAVE* COMMAND AND READ IN WITH:*SET COVARIANCE*"); 02711 ierflg = 3; 02712 return; 02713 //*-*- . . . . . . . . . . printout 02714 L3500: 02715 cneway = "SET PRInt "; 02716 goto L3100; 02717 //*-*- . . . . . . . . . . gradient 02718 L3600: 02719 cneway = "SET GRAd "; 02720 goto L3100; 02721 //*-*- . . . . . . . . . . matout 02722 L3700: 02723 cneway = "SHOW COVar"; 02724 goto L3100; 02725 //*-*- . . . . . . . . . error def 02726 L3800: 02727 cneway = "SET ERRdef"; 02728 goto L3100; 02729 //*-*- . . . . . . . . . . limits 02730 L3900: 02731 cneway = "SET LIMits"; 02732 goto L3100; 02733 //*-*- . . . . . . . . . . punch 02734 L4000: 02735 cneway = "SAVE "; 02736 //*-*- ....... come from obsolete commands 02737 L3100: 02738 Printf(f_out," OBSOLETE COMMAND:%s PLEASE USE: %s",fCword.c_str() 02739 ,cneway.c_str()); 02740 fCword = cneway; 02741 if (fCword == "SAVE ") goto L1500; 02742 goto L700; 02743 //*-* . . . . . . . . . . . . . . . . . . 02744 } /* mnexcm_ */ 02745 02746 //______________________________________________________________________________ 02747 inline 02748 void fitter::mnexin(double *pint) 02749 { 02750 //*-*-*-*-*Transforms the external parameter values U to internal values*-*-* 02751 //*-* ============================================================= 02752 //*-* Transforms the external parameter values U to internal 02753 //*-* values in the dense array PINT. 02754 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 02755 02756 /*static*/ double pinti; 02757 /*static*/ int iint, iext; 02758 02759 fLimset = false; 02760 for (iint = 1; iint <= fNpar; ++iint) { 02761 iext = fNexofi[iint-1]; 02762 mnpint(fU[iext-1], iext-1, pinti); 02763 pint[iint-1] = pinti; 02764 } 02765 } /* mnexin_ */ 02766 02767 //______________________________________________________________________________ 02768 inline 02769 void fitter::mnfixp(int iint1, int &ierr) 02770 { 02771 //*-*-*-*-*-*-*Removes parameter IINT from the internal parameter list*-*-* 02772 //*-* ======================================================= 02773 //*-* and arranges the rest of the list to fill the hole. 02774 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 02775 02776 /* Local variables */ 02777 /*static*/ double yy[kMAXDIM], yyover; 02778 /*static*/ int kold, nold, ndex, knew, iext, i, j, m, n, lc, ik; 02779 02780 //*-*- first see if it can be done 02781 ierr = 0; 02782 int iint = iint1+1; 02783 if (iint > fNpar || iint <= 0) { 02784 ierr = 1; 02785 Printf(f_out," MINUIT ERROR. ARGUMENT TO MNFIXP=%4d",iint); 02786 return; 02787 } 02788 iext = fNexofi[iint-1]; 02789 if (fNpfix >= fMaxpar) { 02790 ierr = 1; 02791 Printf(f_out," MINUIT CANNOT FIX PARAMETER%4d MAXIMUM NUMBER THAT CAN BE FIXED IS %d",iext,fMaxpar); 02792 return; 02793 } 02794 //*-*- reduce number of variable parameters by one 02795 02796 fNiofex[iext-1] = 0; 02797 nold = fNpar; 02798 --fNpar; 02799 //*-*- save values in case parameter is later restored 02800 02801 ++fNpfix; 02802 fIpfix[fNpfix-1] = iext; 02803 lc = iint; 02804 fXs[fNpfix-1] = fX[lc-1]; 02805 fXts[fNpfix-1] = fXt[lc-1]; 02806 fDirins[fNpfix-1] = fWerr[lc-1]; 02807 fGrds[fNpfix-1] = fGrd[lc-1]; 02808 fG2s[fNpfix-1] = fG2[lc-1]; 02809 fGsteps[fNpfix-1] = fGstep[lc-1]; 02810 //*-*- shift values for other parameters to fill hole 02811 for (ik = iext + 1; ik <= fNu; ++ik) { 02812 if (fNiofex[ik-1] > 0) { 02813 lc = fNiofex[ik-1] - 1; 02814 fNiofex[ik-1] = lc; 02815 fNexofi[lc-1] = ik; 02816 fX[lc-1] = fX[lc]; 02817 fXt[lc-1] = fXt[lc]; 02818 fDirin[lc-1] = fDirin[lc]; 02819 fWerr[lc-1] = fWerr[lc]; 02820 fGrd[lc-1] = fGrd[lc]; 02821 fG2[lc-1] = fG2[lc]; 02822 fGstep[lc-1] = fGstep[lc]; 02823 } 02824 } 02825 if (fISW[1] <= 0) return; 02826 //*-*- remove one row and one column from variance matrix 02827 if (fNpar <= 0) return; 02828 for (i = 1; i <= nold; ++i) { 02829 m = TMath_Max(i,iint); 02830 n = TMath_Min(i,iint); 02831 ndex = m*(m-1) / 2 + n; 02832 yy[i-1] = fVhmat[ndex-1]; 02833 } 02834 yyover = 1 / yy[iint-1]; 02835 knew = 0; 02836 kold = 0; 02837 for (i = 1; i <= nold; ++i) { 02838 for (j = 1; j <= i; ++j) { 02839 ++kold; 02840 if (j == iint || i == iint) continue; 02841 ++knew; 02842 fVhmat[knew-1] = fVhmat[kold-1] - yy[j-1]*yy[i-1]*yyover; 02843 } 02844 } 02845 } /* mnfixp_ */ 02846 02847 //______________________________________________________________________________ 02848 inline 02849 void fitter::mnfree(int k) 02850 { 02851 //*-*-*-*Restores one or more fixed parameter(s) to variable status*-*-*-*-*-* 02852 //*-* ========================================================== 02853 //*-* Restores one or more fixed parameter(s) to variable status 02854 //*-* by inserting it into the internal parameter list at the 02855 //*-* appropriate place. 02856 //*-* 02857 //*-* K = 0 means restore all parameters 02858 //*-* K = 1 means restore the last parameter fixed 02859 //*-* K = -I means restore external parameter I (if possible) 02860 //*-* IQ = fix-location where internal parameters were stored 02861 //*-* IR = external number of parameter being restored 02862 //*-* IS = internal number of parameter being restored 02863 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 02864 02865 /* Local variables */ 02866 /*static*/ double grdv, xv, dirinv, g2v, gstepv, xtv; 02867 /*static*/ int i, ipsav, ka, lc, ik, iq, ir, is; 02868 02869 if (k > 1) { 02870 Printf(f_out," CALL TO MNFREE IGNORED. ARGUMENT GREATER THAN ONE"); 02871 } 02872 if (fNpfix < 1) { 02873 Printf(f_out," CALL TO MNFREE IGNORED. THERE ARE NO FIXED PARAMETERS"); 02874 } 02875 if (k == 1 || k == 0) goto L40; 02876 02877 //*-*- release parameter with specified external number 02878 ka = TMath_int_abs(k); 02879 if (fNiofex[ka-1] == 0) goto L15; 02880 Printf(f_out," IGNORED. PARAMETER SPECIFIED IS ALREADY VARIABLE."); 02881 return; 02882 L15: 02883 if (fNpfix < 1) goto L21; 02884 for (ik = 1; ik <= fNpfix; ++ik) { if (fIpfix[ik-1] == ka) goto L24; } 02885 L21: 02886 Printf(f_out," PARAMETER%4d NOT FIXED. CANNOT BE RELEASED.",ka); 02887 return; 02888 L24: 02889 if (ik == fNpfix) goto L40; 02890 02891 //*-*- move specified parameter to end of list 02892 ipsav = ka; 02893 xv = fXs[ik-1]; 02894 xtv = fXts[ik-1]; 02895 dirinv = fDirins[ik-1]; 02896 grdv = fGrds[ik-1]; 02897 g2v = fG2s[ik-1]; 02898 gstepv = fGsteps[ik-1]; 02899 for (i = ik + 1; i <= fNpfix; ++i) { 02900 fIpfix[i-2] = fIpfix[i-1]; 02901 fXs[i-2] = fXs[i-1]; 02902 fXts[i-2] = fXts[i-1]; 02903 fDirins[i-2] = fDirins[i-1]; 02904 fGrds[i-2] = fGrds[i-1]; 02905 fG2s[i-2] = fG2s[i-1]; 02906 fGsteps[i-2] = fGsteps[i-1]; 02907 } 02908 fIpfix[fNpfix-1] = ipsav; 02909 fXs[fNpfix-1] = xv; 02910 fXts[fNpfix-1] = xtv; 02911 fDirins[fNpfix-1] = dirinv; 02912 fGrds[fNpfix-1] = grdv; 02913 fG2s[fNpfix-1] = g2v; 02914 fGsteps[fNpfix-1] = gstepv; 02915 //*-*- restore last parameter in fixed list -- IPFIX(NPFIX) 02916 L40: 02917 if (fNpfix < 1) goto L300; 02918 ir = fIpfix[fNpfix-1]; 02919 is = 0; 02920 for (ik = fNu; ik >= ir; --ik) { 02921 if (fNiofex[ik-1] > 0) { 02922 lc = fNiofex[ik-1] + 1; 02923 is = lc - 1; 02924 fNiofex[ik-1] = lc; 02925 fNexofi[lc-1] = ik; 02926 fX[lc-1] = fX[lc-2]; 02927 fXt[lc-1] = fXt[lc-2]; 02928 fDirin[lc-1] = fDirin[lc-2]; 02929 fWerr[lc-1] = fWerr[lc-2]; 02930 fGrd[lc-1] = fGrd[lc-2]; 02931 fG2[lc-1] = fG2[lc-2]; 02932 fGstep[lc-1] = fGstep[lc-2]; 02933 } 02934 } 02935 ++fNpar; 02936 if (is == 0) is = fNpar; 02937 fNiofex[ir-1] = is; 02938 fNexofi[is-1] = ir; 02939 iq = fNpfix; 02940 fX[is-1] = fXs[iq-1]; 02941 fXt[is-1] = fXts[iq-1]; 02942 fDirin[is-1] = fDirins[iq-1]; 02943 fWerr[is-1] = fDirins[iq-1]; 02944 fGrd[is-1] = fGrds[iq-1]; 02945 fG2[is-1] = fG2s[iq-1]; 02946 fGstep[is-1] = fGsteps[iq-1]; 02947 --fNpfix; 02948 fISW[1] = 0; 02949 fDcovar = 1; 02950 if (fISW[4] - fItaur >= 1) { 02951 Printf(f_out," PARAMETER%4d %s RESTORED TO VARIABLE.",ir,fCpnam[ir-1].c_str()); 02952 } 02953 if (k == 0) goto L40; 02954 L300: 02955 //*-*- if different from internal, external values are taken 02956 mnexin(fX); 02957 } /* mnfree_ */ 02958 02959 //______________________________________________________________________________ 02960 inline 02961 void fitter::mngrad() 02962 { 02963 //*-*-*-*-*-*-*-*-*-*Interprets the SET GRAD command*-*-*-*-*-*-*-*-*-*-*-*-* 02964 //*-* =============================== 02965 //*-* Called from MNSET 02966 //*-* Interprets the SET GRAD command, which informs MINUIT whether 02967 //*-* the first derivatives of FCN will be calculated by the user 02968 //*-* inside FCN. It can check the user derivative calculation 02969 //*-* by comparing it with a finite difference approximation. 02970 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 02971 02972 /* Local variables */ 02973 /*static*/ double gf[kMAXDIM], fzero, err; 02974 /*static*/ int i, nparx, lc, istsav; 02975 /*static*/ bool lnone; 02976 /*static*/ std::string cwd = " "; 02977 02978 fISW[2] = 1; 02979 nparx = fNpar; 02980 if (fWord7[0] > 0) goto L2000; 02981 02982 //*-*- get user-calculated first derivatives from FCN 02983 for (i = 1; i <= fNu; ++i) { fGin[i-1] = fUndefi; } 02984 mninex(fX); 02985 //Printf(f_out,"debug : FCN : 010"); 02986 (*fFCN)(nparx, fGin, fzero, fU, 2,fTag); ++fNfcn; 02987 mnderi(); 02988 for (i = 1; i <= fNpar; ++i) { gf[i-1] = fGrd[i-1]; } 02989 //*-*- get MINUIT-calculated first derivatives 02990 fISW[2] = 0; 02991 istsav = fIstrat; 02992 fIstrat = 2; 02993 mnhes1(); 02994 fIstrat = istsav; 02995 Printf(f_out," CHECK OF GRADIENT CALCULATION IN FCN"); 02996 Printf(f_out," PARAMETER G(IN FCN) G(MINUIT) DG(MINUIT) AGREEMENT"); 02997 fISW[2] = 1; 02998 lnone = false; 02999 for (lc = 1; lc <= fNpar; ++lc) { 03000 i = fNexofi[lc-1]; 03001 cwd = "GOOD"; 03002 err = fDgrd[lc-1]; 03003 if (TMath_Abs(gf[lc-1] - fGrd[lc-1]) > err) cwd = " BAD"; 03004 if (fGin[i-1] == fUndefi) { 03005 cwd = "NONE"; 03006 lnone = true; 03007 gf[lc-1] = 0; 03008 } 03009 if (cwd != "GOOD") fISW[2] = 0; 03010 Printf(f_out," %5d %10s%12.4e%12.4e%12.4e %s",i 03011 ,fCpnam[i-1].c_str() 03012 ,gf[lc-1],fGrd[lc-1],err,cwd.c_str()); 03013 } 03014 if (lnone) { 03015 Printf(f_out," AGREEMENT=NONE MEANS FCN DID NOT CALCULATE THE DERIVATIVE"); 03016 } 03017 if (fISW[2] == 0) { 03018 Printf(f_out," MINUIT DOES NOT ACCEPT DERIVATIVE CALCULATIONS BY FCN"); 03019 Printf(f_out," TO FORCE ACCEPTANCE, ENTER *SET GRAD 1*"); 03020 } 03021 03022 L2000: 03023 return; 03024 } /* mngrad_ */ 03025 03026 //______________________________________________________________________________ 03027 inline 03028 void fitter::mnhelp(const std::string& comd) 03029 { 03030 //*-*-*-*-*-*-*-*HELP routine for MINUIT interactive commands*-*-*-*-*-*-*-*-* 03031 //*-* ============================================ 03032 //*-* 03033 //*-* COMD ='* ' prints a global help for all commands 03034 //*-* COMD =Command_name: print detailed help for one command. 03035 //*-* Note that at least 3 characters must be given for the command 03036 //*-* name. 03037 //*-* 03038 //*-* Author: Rene Brun 03039 //*-* comments extracted from the MINUIT documentation file. 03040 //*-* 03041 //*-* 03042 //*-* command name ASSUMED to be in upper case 03043 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 03044 03045 /*static*/ std::string cmd3 = " "; 03046 03047 //*-*....................................................................... 03048 //*-* 03049 //*-* Global HELP: Summary of all commands 03050 //*-* ==================================== 03051 //*-* 03052 if (comd[0] == '*') { 03053 Printf(f_out," ==>List of MINUIT Interactive commands:"); 03054 Printf(f_out," CLEar Reset all parameter names and values undefined"); 03055 Printf(f_out," CONtour Make contour map of the user function"); 03056 Printf(f_out," EXIT Exit from Interactive Minuit"); 03057 Printf(f_out," FIX Cause parameter(s) to remain constant"); 03058 Printf(f_out," HESse Calculate the Hessian or error matrix."); 03059 Printf(f_out," IMPROVE Search for a new minimum around current minimum"); 03060 Printf(f_out," MIGrad Minimize by the method of Migrad"); 03061 Printf(f_out," MINImize MIGRAD + SIMPLEX method if Migrad fails"); 03062 Printf(f_out," MINOs Exact (non-linear) parameter error analysis"); 03063 Printf(f_out," MNContour Calculate one MINOS function contour"); 03064 Printf(f_out," PARameter Define or redefine new parameters and values"); 03065 Printf(f_out," RELease Make previously FIXed parameters variable again"); 03066 Printf(f_out," REStore Release last parameter fixed"); 03067 Printf(f_out," SAVe Save current parameter values on a file"); 03068 Printf(f_out," SCAn Scan the user function by varying parameters"); 03069 Printf(f_out," SEEk Minimize by the method of Monte Carlo"); 03070 Printf(f_out," SET Set various MINUIT constants or conditions"); 03071 Printf(f_out," SHOw Show values of current constants or conditions"); 03072 Printf(f_out," SIMplex Minimize by the method of Simplex"); 03073 goto L99; 03074 } 03075 03076 cmd3 = comd; 03077 //*-* __________________________________________________________________ 03078 //*-* 03079 //*-* -- Command CLEAR 03080 //*-* -- ============= 03081 //*-* 03082 if (cmd3 == "CLE") { 03083 Printf(f_out," ***>CLEAR"); 03084 Printf(f_out," Resets all parameter names and values to undefined."); 03085 Printf(f_out," Must normally be followed by a PARameters command or "); 03086 Printf(f_out," equivalent, in order to define parameter values."); 03087 goto L99; 03088 } 03089 //*-* __________________________________________________________________ 03090 //*-* -- 03091 //*-* -- Command CONTOUR 03092 //*-* -- =============== 03093 //*-* . 03094 if (cmd3 == "CON") { 03095 Printf(f_out," ***>CONTOUR <par1> <par2> [devs] [ngrid]"); 03096 Printf(f_out," Instructs Minuit to trace contour lines of the user function"); 03097 Printf(f_out," with respect to the two parameters whose external numbers"); 03098 Printf(f_out," are <par1> and <par2>."); 03099 Printf(f_out," Other variable parameters of the function, if any, will have"); 03100 Printf(f_out," their values fixed at the current values during the contour"); 03101 Printf(f_out," tracing. The optional parameter [devs] (default value 2.)"); 03102 Printf(f_out," gives the number of standard deviations in each parameter"); 03103 Printf(f_out," which should lie entirely within the plotting area."); 03104 Printf(f_out," Optional parameter [ngrid] (default value 25 unless page"); 03105 Printf(f_out," size is too small) determines the resolution of the plot,"); 03106 Printf(f_out," i.e. the number of rows and columns of the grid at which the"); 03107 Printf(f_out," function will be evaluated. [See also MNContour.]"); 03108 goto L99; 03109 } 03110 //*-* __________________________________________________________________ 03111 //*-* -- 03112 //*-* -- Command END 03113 //*-* -- =========== 03114 //*-* . 03115 if (cmd3 == "END") { 03116 Printf(f_out," ***>END"); 03117 Printf(f_out," Signals the end of a data block (i.e., the end of a fit),"); 03118 Printf(f_out," and implies that execution should continue, because another"); 03119 Printf(f_out," Data Block follows. A Data Block is a set of Minuit data"); 03120 Printf(f_out," consisting of"); 03121 Printf(f_out," (1) A Title,"); 03122 Printf(f_out," (2) One or more Parameter Definitions,"); 03123 Printf(f_out," (3) A blank line, and"); 03124 Printf(f_out," (4) A set of Minuit Commands."); 03125 Printf(f_out," The END command is used when more than one Data Block is to"); 03126 Printf(f_out," be used with the same FCN function. It first causes Minuit"); 03127 Printf(f_out," to issue a CALL FCN with IFLAG=3, in order to allow FCN to"); 03128 Printf(f_out," perform any calculations associated with the final fitted"); 03129 Printf(f_out," parameter values, unless a CALL FCN 3 command has already"); 03130 Printf(f_out," been executed at the current FCN value."); 03131 goto L99; 03132 } 03133 //*-* __________________________________________________________________ 03134 //*-* . 03135 //*-* -- 03136 //*-* -- Command EXIT 03137 //*-* -- ============ 03138 if (cmd3 == "EXI") { 03139 Printf(f_out," ***>EXIT"); 03140 Printf(f_out," Signals the end of execution."); 03141 Printf(f_out," The EXIT command first causes Minuit to issue a CALL FCN"); 03142 Printf(f_out," with IFLAG=3, to allow FCN to perform any calculations"); 03143 Printf(f_out," associated with the final fitted parameter values, unless a"); 03144 Printf(f_out," CALL FCN 3 command has already been executed."); 03145 goto L99; 03146 } 03147 //*-* __________________________________________________________________ 03148 //*-* -- 03149 //*-* -- Command FIX 03150 //*-* -- =========== 03151 //*-* . 03152 if (cmd3 == "FIX") { 03153 Printf(f_out," ***>FIX} <parno> [parno] ... [parno]"); 03154 Printf(f_out," Causes parameter(s) <parno> to be removed from the list of"); 03155 Printf(f_out," variable parameters, and their value(s) will remain constant"); 03156 Printf(f_out," during subsequent minimizations, etc., until another command"); 03157 Printf(f_out," changes their value(s) or status."); 03158 goto L99; 03159 } 03160 //*-* __________________________________________________________________ 03161 //*-* -- 03162 //*-* -- Command HESSE 03163 //*-* -- ============= 03164 //*-* . 03165 if (cmd3 == "HES") { 03166 Printf(f_out," ***>HESse [maxcalls]"); 03167 Printf(f_out," Calculate, by finite differences, the Hessian or error matrix."); 03168 Printf(f_out," That is, it calculates the full matrix of second derivatives"); 03169 Printf(f_out," of the function with respect to the currently variable"); 03170 Printf(f_out," parameters, and inverts it, printing out the resulting error"); 03171 Printf(f_out," matrix. The optional argument [maxcalls] specifies the"); 03172 Printf(f_out," (approximate) maximum number of function calls after which"); 03173 Printf(f_out," the calculation will be stopped."); 03174 goto L99; 03175 } 03176 //*-* __________________________________________________________________ 03177 //*-* -- 03178 //*-* -- Command IMPROVE 03179 //*-* -- =============== 03180 //*-* . 03181 if (cmd3 == "IMP") { 03182 Printf(f_out," ***>IMPROVE [maxcalls]"); 03183 Printf(f_out," If a previous minimization has converged, and the current"); 03184 Printf(f_out," values of the parameters therefore correspond to a local"); 03185 Printf(f_out," minimum of the function, this command requests a search for"); 03186 Printf(f_out," additional distinct local minima."); 03187 Printf(f_out," The optional argument [maxcalls] specifies the (approximate"); 03188 Printf(f_out," maximum number of function calls after which the calculation"); 03189 Printf(f_out," will be stopped."); 03190 goto L99; 03191 } 03192 //*-* __________________________________________________________________ 03193 //*-* -- 03194 //*-* -- Command MIGRAD 03195 //*-* -- ============== 03196 //*-* . 03197 if (cmd3 == "MIG") { 03198 Printf(f_out," ***>MIGrad [maxcalls] [tolerance]"); 03199 Printf(f_out," Causes minimization of the function by the method of Migrad,"); 03200 Printf(f_out," the most efficient and complete single method, recommended"); 03201 Printf(f_out," for general functions (see also MINImize)."); 03202 Printf(f_out," The minimization produces as a by-product the error matrix"); 03203 Printf(f_out," of the parameters, which is usually reliable unless warning"); 03204 Printf(f_out," messages are produced."); 03205 Printf(f_out," The optional argument [maxcalls] specifies the (approximate)"); 03206 Printf(f_out," maximum number of function calls after which the calculation"); 03207 Printf(f_out," will be stopped even if it has not yet converged."); 03208 Printf(f_out," The optional argument [tolerance] specifies required tolerance"); 03209 Printf(f_out," on the function value at the minimum."); 03210 Printf(f_out," The default tolerance is 0.1, and the minimization will stop"); 03211 Printf(f_out," when the estimated vertical distance to the minimum (EDM) is"); 03212 Printf(f_out," less than 0.001*[tolerance]*UP (see [SET ERRordef])."); 03213 goto L99; 03214 } 03215 //*-* __________________________________________________________________ 03216 //*-* -- 03217 //*-* -- Command MINIMIZE 03218 //*-* -- ================ 03219 //*-* . 03220 if (comd == "MINI") { 03221 Printf(f_out," ***>MINImize [maxcalls] [tolerance]"); 03222 Printf(f_out," Causes minimization of the function by the method of Migrad,"); 03223 Printf(f_out," as does the MIGrad command, but switches to the SIMplex method"); 03224 Printf(f_out," if Migrad fails to converge. Arguments are as for MIGrad."); 03225 Printf(f_out," Note that command requires four characters to be unambiguous."); 03226 goto L99; 03227 } 03228 //*-* __________________________________________________________________ 03229 //*-* -- 03230 //*-* -- Command MINOS 03231 //*-* -- ============= 03232 //*-* . 03233 if (comd == "MINO") { 03234 Printf(f_out," ***>MINOs [maxcalls] [parno] [parno] ..."); 03235 Printf(f_out," Causes a Minos error analysis to be performed on the parameters"); 03236 Printf(f_out," whose numbers [parno] are specified. If none are specified,"); 03237 Printf(f_out," Minos errors are calculated for all variable parameters."); 03238 Printf(f_out," Minos errors may be expensive to calculate, but are very"); 03239 Printf(f_out," reliable since they take account of non-linearities in the"); 03240 Printf(f_out," problem as well as parameter correlations, and are in general"); 03241 Printf(f_out," asymmetric."); 03242 Printf(f_out," The optional argument [maxcalls] specifies the (approximate)"); 03243 Printf(f_out," maximum number of function calls per parameter requested,"); 03244 Printf(f_out," after which the calculation will stop for that parameter."); 03245 goto L99; 03246 } 03247 //*-* __________________________________________________________________ 03248 //*-* -- 03249 //*-* -- Command MNCONTOUR 03250 //*-* -- ================= 03251 //*-* . 03252 if (cmd3 == "MNC") { 03253 Printf(f_out," ***>MNContour <par1> <par2> [npts]"); 03254 Printf(f_out," Calculates one function contour of FCN with respect to"); 03255 Printf(f_out," parameters par1 and par2, with FCN minimized always with"); 03256 Printf(f_out," respect to all other NPAR-2 variable parameters (if any)."); 03257 Printf(f_out," Minuit will try to find npts points on the contour (default 20)"); 03258 Printf(f_out," If only two parameters are variable at the time, it is not"); 03259 Printf(f_out," necessary to specify their numbers. To calculate more than"); 03260 Printf(f_out," one contour, it is necessary to SET ERRordef to the appropriate"); 03261 Printf(f_out," value and issue the MNContour command for each contour."); 03262 goto L99; 03263 } 03264 //*-* __________________________________________________________________ 03265 //*-* -- 03266 //*-* -- Command PARAMETER 03267 //*-* -- ================= 03268 //*-* . 03269 if (cmd3 == "PAR") { 03270 Printf(f_out," ***>PARameters"); 03271 Printf(f_out," followed by one or more parameter definitions."); 03272 Printf(f_out," Parameter definitions are of the form:"); 03273 Printf(f_out," <number> ''name'' <value> <step> [lolim] [uplim] "); 03274 Printf(f_out," for example:"); 03275 Printf(f_out," 3 ''K width'' 1.2 0.1"); 03276 Printf(f_out," the last definition is followed by a blank line or a zero."); 03277 goto L99; 03278 } 03279 //*-* __________________________________________________________________ 03280 //*-* -- 03281 //*-* -- Command RELEASE 03282 //*-* -- =============== 03283 //*-* . 03284 if (cmd3 == "REL") { 03285 Printf(f_out," ***>RELease <parno> [parno] ... [parno]"); 03286 Printf(f_out," If <parno> is the number of a previously variable parameter"); 03287 Printf(f_out," which has been fixed by a command: FIX <parno>, then that"); 03288 Printf(f_out," parameter will return to variable status. Otherwise a warning"); 03289 Printf(f_out," message is printed and the command is ignored."); 03290 Printf(f_out," Note that this command operates only on parameters which were"); 03291 Printf(f_out," at one time variable and have been FIXed. It cannot make"); 03292 Printf(f_out," constant parameters variable; that must be done by redefining"); 03293 Printf(f_out," the parameter with a PARameters command."); 03294 goto L99; 03295 } 03296 //*-* __________________________________________________________________ 03297 //*-* -- 03298 //*-* -- Command RESTORE 03299 //*-* -- =============== 03300 //*-* . 03301 if (cmd3 == "RES") { 03302 Printf(f_out," ***>REStore [code]"); 03303 Printf(f_out," If no [code] is specified, this command restores all previously"); 03304 Printf(f_out," FIXed parameters to variable status. If [code]=1, then only"); 03305 Printf(f_out," the last parameter FIXed is restored to variable status."); 03306 Printf(f_out," If code is neither zero nor one, the command is ignored."); 03307 goto L99; 03308 } 03309 //*-* __________________________________________________________________ 03310 //*-* -- 03311 //*-* -- Command RETURN 03312 //*-* -- ============== 03313 //*-* . 03314 if (cmd3 == "RET") { 03315 Printf(f_out," ***>RETURN"); 03316 Printf(f_out," Signals the end of a data block, and instructs Minuit to return"); 03317 Printf(f_out," to the program which called it. The RETurn command first"); 03318 Printf(f_out," causes Minuit to CALL FCN with IFLAG=3, in order to allow FCN"); 03319 Printf(f_out," to perform any calculations associated with the final fitted"); 03320 Printf(f_out," parameter values, unless a CALL FCN 3 command has already been"); 03321 Printf(f_out," executed at the current FCN value."); 03322 goto L99; 03323 } 03324 //*-* __________________________________________________________________ 03325 //*-* -- 03326 //*-* -- Command SAVE 03327 //*-* -- ============ 03328 //*-* . 03329 if (cmd3 == "SAV") { 03330 Printf(f_out," ***>SAVe"); 03331 Printf(f_out," Causes the current parameter values to be saved on a file in"); 03332 Printf(f_out," such a format that they can be read in again as Minuit"); 03333 Printf(f_out," parameter definitions. If the covariance matrix exists, it is"); 03334 Printf(f_out," also output in such a format. The unit number is by default 7,"); 03335 Printf(f_out," or that specified by the user in his call to MINTIO or"); 03336 Printf(f_out," MNINIT. The user is responsible for opening the file previous"); 03337 Printf(f_out," to issuing the [SAVe] command (except where this can be done"); 03338 Printf(f_out," interactively)."); 03339 goto L99; 03340 } 03341 //*-* __________________________________________________________________ 03342 //*-* -- 03343 //*-* -- Command SCAN 03344 //*-* -- ============ 03345 //*-* . 03346 if (cmd3 == "SCA") { 03347 Printf(f_out," ***>SCAn [parno] [numpts] [from] [to]"); 03348 Printf(f_out," Scans the value of the user function by varying parameter"); 03349 Printf(f_out," number [parno], leaving all other parameters fixed at the"); 03350 Printf(f_out," current value. If [parno] is not specified, all variable"); 03351 Printf(f_out," parameters are scanned in sequence."); 03352 Printf(f_out," The number of points [numpts] in the scan is 40 by default,"); 03353 Printf(f_out," and cannot exceed 100. The range of the scan is by default"); 03354 Printf(f_out," 2 standard deviations on each side of the current best value,"); 03355 Printf(f_out," but can be specified as from [from] to [to]."); 03356 Printf(f_out," After each scan, if a new minimum is found, the best parameter"); 03357 Printf(f_out," values are retained as start values for future scans or"); 03358 Printf(f_out," minimizations. The curve resulting from each scan is plotted"); 03359 Printf(f_out," on the output unit in order to show the approximate behaviour"); 03360 Printf(f_out," of the function."); 03361 Printf(f_out," This command is not intended for minimization, but is sometimes"); 03362 Printf(f_out," useful for debugging the user function or finding a"); 03363 Printf(f_out," reasonable starting point."); 03364 goto L99; 03365 } 03366 //*-* __________________________________________________________________ 03367 //*-* -- 03368 //*-* -- Command SEEK 03369 //*-* -- ============ 03370 //*-* . 03371 if (cmd3 == "SEE") { 03372 Printf(f_out," ***>SEEk [maxcalls] [devs]"); 03373 Printf(f_out," Causes a Monte Carlo minimization of the function, by choosing"); 03374 Printf(f_out," random values of the variable parameters, chosen uniformly"); 03375 Printf(f_out," over a hypercube centered at the current best value."); 03376 Printf(f_out," The region size is by default 3 standard deviations on each"); 03377 Printf(f_out," side, but can be changed by specifying the value of [devs]."); 03378 goto L99; 03379 } 03380 //*-* __________________________________________________________________ 03381 //*-* -- 03382 //*-* -- Command SET 03383 //*-* -- =========== 03384 //*-* . 03385 if (cmd3 == "SET") { 03386 Printf(f_out," ***>SET <option_name>"); 03387 Printf(f_out," SET BATch"); 03388 Printf(f_out," Informs Minuit that it is running in batch mode."); 03389 03390 Printf(f_out," "); 03391 Printf(f_out," SET EPSmachine <accuracy>"); 03392 Printf(f_out," Informs Minuit that the relative floating point arithmetic"); 03393 Printf(f_out," precision is <accuracy>. Minuit determines the nominal"); 03394 Printf(f_out," precision itself, but the SET EPSmachine command can be"); 03395 Printf(f_out," used to override Minuit own determination, when the user"); 03396 Printf(f_out," knows that the FCN function value is not calculated to"); 03397 Printf(f_out," the nominal machine accuracy. Typical values of <accuracy>"); 03398 Printf(f_out," are between 10**-5 and 10**-14."); 03399 03400 Printf(f_out," "); 03401 Printf(f_out," SET ERRordef <up>"); 03402 Printf(f_out," Sets the value of UP (default value= 1.), defining parameter"); 03403 Printf(f_out," errors. Minuit defines parameter errors as the change"); 03404 Printf(f_out," in parameter value required to change the function value"); 03405 Printf(f_out," by UP. Normally, for chisquared fits UP=1, and for negative"); 03406 Printf(f_out," log likelihood, UP=0.5."); 03407 03408 Printf(f_out," "); 03409 Printf(f_out," SET GRAdient [force]"); 03410 Printf(f_out," Informs Minuit that the user function is prepared to"); 03411 Printf(f_out," calculate its own first derivatives and return their values"); 03412 Printf(f_out," in the array GRAD when IFLAG=2 (see specs of FCN)."); 03413 Printf(f_out," If [force] is not specified, Minuit will calculate"); 03414 Printf(f_out," the FCN derivatives by finite differences at the current"); 03415 Printf(f_out," point and compare with the user calculation at that point,"); 03416 Printf(f_out," accepting the user values only if they agree."); 03417 Printf(f_out," If [force]=1, Minuit does not do its own derivative"); 03418 Printf(f_out," calculation, and uses the derivatives calculated in FCN."); 03419 03420 Printf(f_out," "); 03421 Printf(f_out," SET INPut [unitno] [filename]"); 03422 Printf(f_out," Causes Minuit, in data-driven mode only, to read subsequent"); 03423 Printf(f_out," commands (or parameter definitions) from a different input"); 03424 Printf(f_out," file. If no [unitno] is specified, reading reverts to the"); 03425 Printf(f_out," previous input file, assuming that there was one."); 03426 Printf(f_out," If [unitno] is specified, and that unit has not been opened,"); 03427 Printf(f_out," then Minuit attempts to open the file [filename]} if a"); 03428 Printf(f_out," name is specified. If running in interactive mode and"); 03429 Printf(f_out," [filename] is not specified and [unitno] is not opened,"); 03430 Printf(f_out," Minuit prompts the user to enter a file name."); 03431 Printf(f_out," If the word REWIND is added to the command (note:no blanks"); 03432 Printf(f_out," between INPUT and REWIND), the file is rewound before"); 03433 Printf(f_out," reading. Note that this command is implemented in standard"); 03434 Printf(f_out," Fortran 77 and the results may depend on the system;"); 03435 Printf(f_out," for example, if a filename is given under VM/CMS, it must"); 03436 Printf(f_out," be preceeded by a slash."); 03437 03438 Printf(f_out," "); 03439 Printf(f_out," SET INTeractive"); 03440 Printf(f_out," Informs Minuit that it is running interactively."); 03441 03442 Printf(f_out," "); 03443 Printf(f_out," SET LIMits [parno] [lolim] [uplim]"); 03444 Printf(f_out," Allows the user to change the limits on one or all"); 03445 Printf(f_out," parameters. If no arguments are specified, all limits are"); 03446 Printf(f_out," removed from all parameters. If [parno] alone is specified,"); 03447 Printf(f_out," limits are removed from parameter [parno]."); 03448 Printf(f_out," If all arguments are specified, then parameter [parno] will"); 03449 Printf(f_out," be bounded between [lolim] and [uplim]."); 03450 Printf(f_out," Limits can be specified in either order, Minuit will take"); 03451 Printf(f_out," the smaller as [lolim] and the larger as [uplim]."); 03452 Printf(f_out," However, if [lolim] is equal to [uplim], an error condition"); 03453 Printf(f_out," results."); 03454 03455 Printf(f_out," "); 03456 Printf(f_out," SET LINesperpage"); 03457 Printf(f_out," Sets the number of lines for one page of output."); 03458 Printf(f_out," Default value is 24 for interactive mode"); 03459 03460 Printf(f_out," "); 03461 Printf(f_out," SET NOGradient"); 03462 Printf(f_out," The inverse of SET GRAdient, instructs Minuit not to"); 03463 Printf(f_out," use the first derivatives calculated by the user in FCN."); 03464 03465 Printf(f_out," "); 03466 Printf(f_out," SET NOWarnings"); 03467 Printf(f_out," Supresses Minuit warning messages."); 03468 03469 Printf(f_out," "); 03470 Printf(f_out," SET OUTputfile <unitno>"); 03471 Printf(f_out," Instructs Minuit to write further output to unit <unitno>."); 03472 03473 Printf(f_out," "); 03474 Printf(f_out," SET PAGethrow <integer>"); 03475 Printf(f_out," Sets the carriage control character for ``new page'' to"); 03476 Printf(f_out," <integer>. Thus the value 1 produces a new page, and 0"); 03477 Printf(f_out," produces a blank line, on some devices (see TOPofpage)"); 03478 03479 03480 Printf(f_out," "); 03481 Printf(f_out," SET PARameter <parno> <value>"); 03482 Printf(f_out," Sets the value of parameter <parno> to <value>."); 03483 Printf(f_out," The parameter in question may be variable, fixed, or"); 03484 Printf(f_out," constant, but must be defined."); 03485 03486 Printf(f_out," "); 03487 Printf(f_out," SET PRIntout <level>"); 03488 Printf(f_out," Sets the print level, determining how much output will be"); 03489 Printf(f_out," produced. Allowed values and their meanings are displayed"); 03490 Printf(f_out," after a SHOw PRInt command, and are currently <level>=:"); 03491 Printf(f_out," [-1] no output except from SHOW commands"); 03492 Printf(f_out," [0] minimum output"); 03493 Printf(f_out," [1] default value, normal output"); 03494 Printf(f_out," [2] additional output giving intermediate results."); 03495 Printf(f_out," [3] maximum output, showing progress of minimizations."); 03496 Printf(f_out," Note: See also the SET WARnings command."); 03497 03498 Printf(f_out," "); 03499 Printf(f_out," SET RANdomgenerator <seed>"); 03500 Printf(f_out," Sets the seed of the random number generator used in SEEk."); 03501 Printf(f_out," This can be any integer between 10000 and 900000000, for"); 03502 Printf(f_out," example one which was output from a SHOw RANdom command of"); 03503 Printf(f_out," a previous run."); 03504 03505 Printf(f_out," "); 03506 Printf(f_out," SET STRategy <level>"); 03507 Printf(f_out," Sets the strategy to be used in calculating first and second"); 03508 Printf(f_out," derivatives and in certain minimization methods."); 03509 Printf(f_out," In general, low values of <level> mean fewer function calls"); 03510 Printf(f_out," and high values mean more reliable minimization."); 03511 Printf(f_out," Currently allowed values are 0, 1 (default), and 2."); 03512 03513 Printf(f_out," "); 03514 Printf(f_out," SET TITle"); 03515 Printf(f_out," Informs Minuit that the next input line is to be considered"); 03516 Printf(f_out," the (new) title for this task or sub-task. This is for"); 03517 Printf(f_out," the convenience of the user in reading his output."); 03518 03519 Printf(f_out," "); 03520 Printf(f_out," SET WARnings"); 03521 Printf(f_out," Instructs Minuit to output warning messages when suspicious"); 03522 Printf(f_out," conditions arise which may indicate unreliable results."); 03523 Printf(f_out," This is the default."); 03524 03525 Printf(f_out," "); 03526 Printf(f_out," SET WIDthpage"); 03527 Printf(f_out," Informs Minuit of the output page width."); 03528 Printf(f_out," Default values are 80 for interactive jobs"); 03529 goto L99; 03530 } 03531 //*-* __________________________________________________________________ 03532 //*-* -- 03533 //*-* -- Command SHOW 03534 //*-* -- ============ 03535 //*-* . 03536 if (cmd3 == "SHO") { 03537 Printf(f_out," ***>SHOw <option_name>"); 03538 Printf(f_out," All SET XXXX commands have a corresponding SHOw XXXX command."); 03539 Printf(f_out," In addition, the SHOw commands listed starting here have no"); 03540 Printf(f_out," corresponding SET command for obvious reasons."); 03541 03542 Printf(f_out," "); 03543 Printf(f_out," SHOw CORrelations"); 03544 Printf(f_out," Calculates and prints the parameter correlations from the"); 03545 Printf(f_out," error matrix."); 03546 03547 Printf(f_out," "); 03548 Printf(f_out," SHOw COVariance"); 03549 Printf(f_out," Prints the (external) covariance (error) matrix."); 03550 03551 Printf(f_out," "); 03552 Printf(f_out," SHOw EIGenvalues"); 03553 Printf(f_out," Calculates and prints the eigenvalues of the covariance"); 03554 Printf(f_out," matrix."); 03555 03556 Printf(f_out," "); 03557 Printf(f_out," SHOw FCNvalue"); 03558 Printf(f_out," Prints the current value of FCN."); 03559 goto L99; 03560 } 03561 //*-* __________________________________________________________________ 03562 //*-* -- 03563 //*-* -- Command SIMPLEX 03564 //*-* -- =============== 03565 //*-* . 03566 if (cmd3 == "SIM") { 03567 Printf(f_out," ***>SIMplex [maxcalls] [tolerance]"); 03568 Printf(f_out," Performs a function minimization using the simplex method of"); 03569 Printf(f_out," Nelder and Mead. Minimization terminates either when the"); 03570 Printf(f_out," function has been called (approximately) [maxcalls] times,"); 03571 Printf(f_out," or when the estimated vertical distance to minimum (EDM) is"); 03572 Printf(f_out," less than [tolerance]."); 03573 Printf(f_out," The default value of [tolerance] is 0.1*UP(see SET ERRordef)."); 03574 goto L99; 03575 } 03576 //*-* __________________________________________________________________ 03577 //*-* -- 03578 //*-* -- Command STANDARD 03579 //*-* -- ================ 03580 //*-* . 03581 if (cmd3 == "STA") { 03582 Printf(f_out," ***>STAndard"); 03583 goto L99; 03584 } 03585 //*-* __________________________________________________________________ 03586 //*-* -- 03587 //*-* -- Command STOP 03588 //*-* -- ============ 03589 //*-* . 03590 if (cmd3 == "STO") { 03591 Printf(f_out," ***>STOP"); 03592 Printf(f_out," Same as EXIT."); 03593 goto L99; 03594 } 03595 //*-* __________________________________________________________________ 03596 //*-* -- 03597 //*-* -- Command TOPOFPAGE 03598 //*-* -- ================= 03599 //*-* . 03600 if (cmd3 == "TOP") { 03601 Printf(f_out," ***>TOPofpage"); 03602 Printf(f_out," Causes Minuit to write the character specified in a"); 03603 Printf(f_out," SET PAGethrow command (default = 1) to column 1 of the output"); 03604 Printf(f_out," file, which may or may not position your output medium to"); 03605 Printf(f_out," the top of a page depending on the device and system."); 03606 goto L99; 03607 } 03608 //*-* __________________________________________________________________ 03609 Printf(f_out," Unknown MINUIT command. Type HELP for list of commands."); 03610 03611 L99: 03612 return; 03613 } /* mnhelp_ */ 03614 03615 //______________________________________________________________________________ 03616 inline 03617 void fitter::mnhess() 03618 { 03619 //*-*-*-*-*-*Calculates the full second-derivative matrix of FCN*-*-*-*-*-*-*-* 03620 //*-* =================================================== 03621 //*-* by taking finite differences. When calculating diagonal 03622 //*-* elements, it may iterate so that step size is nearly that 03623 //*-* which gives function change= UP/10. The first derivatives 03624 //*-* of course come as a free side effect, but with a smaller 03625 //*-* step size in order to obtain a known accuracy. 03626 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 03627 03628 /* Local variables */ 03629 /*static*/ double dmin_, dxdi, elem, wint, tlrg2, d, dlast, ztemp, g2bfor; 03630 /*static*/ double yy[kMAXDIM], df, aimsag, fs1, tlrstp, fs2, stpinm, g2i, sag, xtf, xti, xtj; 03631 /*static*/ int icyc, ncyc, ndex, idrv, iext, npar2, i, j, ifail, npard, nparx, idn, multpy; 03632 /*static*/ bool ldebug; 03633 sag = 0; //GB : to rm warning. 03634 03635 ldebug = fIdbg[3] >= 1; 03636 if (fAmin == fUndefi) { 03637 mnamin(); 03638 } 03639 if (fIstrat <= 0) { 03640 ncyc = 3; 03641 tlrstp = .5; 03642 tlrg2 = .1; 03643 } else if (fIstrat == 1) { 03644 ncyc = 5; 03645 tlrstp = .3; 03646 tlrg2 = .05; 03647 } else { 03648 ncyc = 7; 03649 tlrstp = .1; 03650 tlrg2 = .02; 03651 } 03652 if (fISW[4] >= 2 || ldebug) { 03653 Printf(f_out," START COVARIANCE MATRIX CALCULATION."); 03654 } 03655 fCfrom = "HESSE "; 03656 fNfcnfr = fNfcn; 03657 fCstatu = "OK "; 03658 npard = fNpar; 03659 //*-*- make sure starting at the right place 03660 mninex(fX); 03661 nparx = fNpar; 03662 //Printf(f_out,"debug : FCN : 011"); 03663 (*fFCN)(nparx, fGin, fs1, fU, 4,fTag); ++fNfcn; 03664 if (fs1 != fAmin) { 03665 df = fAmin - fs1; 03666 mnwarn("D", "MNHESS", Form("function value differs from AMIN by %g",df)); 03667 } 03668 fAmin = fs1; 03669 if (ldebug) { 03670 Printf(f_out," PAR D GSTEP D G2 GRD SAG "); 03671 } 03672 //*-*- . . . . . . diagonal elements . 03673 03674 //*-*- ISW(2) = 1 if approx, 2 if not posdef, 3 if ok 03675 //*-*- AIMSAG is the sagitta we are aiming for in second deriv calc. 03676 03677 aimsag = TMath_Sqrt(fEpsma2)*(TMath_Abs(fAmin) + fUp); 03678 //*-*- Zero the second derivative matrix 03679 npar2 = fNpar*(fNpar + 1) / 2; 03680 for (i = 1; i <= npar2; ++i) { fVhmat[i-1] = 0; } 03681 03682 //*-*- Loop over variable parameters for second derivatives 03683 idrv = 2; 03684 for (idn = 1; idn <= npard; ++idn) { 03685 i = idn + fNpar - npard; 03686 iext = fNexofi[i-1]; 03687 if (fG2[i-1] == 0) { 03688 mnwarn("W", "HESSE", Form("Second derivative enters zero, param %d",iext)); 03689 wint = fWerr[i-1]; 03690 if (fNvarl[iext-1] > 1) { 03691 mndxdi(fX[i-1], i-1, dxdi); 03692 if (TMath_Abs(dxdi) < .001) wint = .01; 03693 else wint /= TMath_Abs(dxdi); 03694 } 03695 fG2[i-1] = fUp / (wint*wint); 03696 } 03697 xtf = fX[i-1]; 03698 dmin_ = fEpsma2*8*TMath_Abs(xtf); 03699 03700 //*-*- find step which gives sagitta = AIMSAG 03701 d = TMath_Abs(fGstep[i-1]); 03702 int skip50 = 0; 03703 for (icyc = 1; icyc <= ncyc; ++icyc) { 03704 //*-*- loop here only if SAG=0 03705 for (multpy = 1; multpy <= 5; ++multpy) { 03706 //*-*- take two steps 03707 fX[i-1] = xtf + d; 03708 mninex(fX); 03709 nparx = fNpar; 03710 //Printf(f_out,"debug : FCN : 012"); 03711 (*fFCN)(nparx, fGin, fs1, fU, 4,fTag); ++fNfcn; 03712 fX[i-1] = xtf - d; 03713 mninex(fX); 03714 (*fFCN)(nparx, fGin, fs2, fU, 4,fTag); ++fNfcn; 03715 fX[i-1] = xtf; 03716 sag = (fs1 + fs2 - fAmin*2)*.5; 03717 if (sag != 0) goto L30; 03718 if (fGstep[i-1] < 0) { 03719 if (d >= .5) goto L26; 03720 d *= 10; 03721 if (d > .5) d = .51; 03722 continue; 03723 } 03724 d *= 10; 03725 } 03726 L26: 03727 mnwarn("W", "HESSE", Form("Second derivative zero for parameter%d",iext)); 03728 goto L390; 03729 //*-*- SAG is not zero 03730 L30: 03731 g2bfor = fG2[i-1]; 03732 fG2[i-1] = sag*2 / (d*d); 03733 fGrd[i-1] = (fs1 - fs2) / (d*2); 03734 if (ldebug) { 03735 Printf(f_out,"%4d%2d%12.5g%12.5g%12.5g%12.5g%12.5g%12.5g",i,idrv,fGstep[i-1],fG2[i-1],fGrd[i-1],sag); 03736 } 03737 if (fGstep[i-1] > 0) fGstep[i-1] = TMath_Abs(d); 03738 else fGstep[i-1] = -TMath_Abs(d); 03739 fDirin[i-1] = d; 03740 yy[i-1] = fs1; 03741 dlast = d; 03742 d = TMath_Sqrt(aimsag*2 / TMath_Abs(fG2[i-1])); 03743 //*-*- if parameter has limits, max int step size = 0.5 03744 stpinm = .5; 03745 if (fGstep[i-1] < 0) d = TMath_Min(d,stpinm); 03746 if (d < dmin_) d = dmin_; 03747 //*-*- see if converged 03748 if (TMath_Abs((d - dlast) / d) < tlrstp || 03749 TMath_Abs((fG2[i-1] - g2bfor) / fG2[i-1]) < tlrg2) { 03750 skip50 = 1; 03751 break; 03752 } 03753 d = TMath_Min(d,dlast*102); 03754 d = TMath_Max(d,dlast*.1); 03755 } 03756 //*-*- end of step size loop 03757 if (!skip50) 03758 mnwarn("D", "MNHESS", Form("Second Deriv. SAG,AIM= %d%g%g",iext,sag,aimsag)); 03759 03760 ndex = i*(i + 1) / 2; 03761 fVhmat[ndex-1] = fG2[i-1]; 03762 } 03763 //*-*- end of diagonal second derivative loop 03764 mninex(fX); 03765 //*-*- refine the first derivatives 03766 if (fIstrat > 0) mnhes1(); 03767 fISW[1] = 3; 03768 fDcovar = 0; 03769 //*-*- . . . . off-diagonal elements 03770 03771 if (fNpar == 1) goto L214; 03772 for (i = 1; i <= fNpar; ++i) { 03773 for (j = 1; j <= i-1; ++j) { 03774 xti = fX[i-1]; 03775 xtj = fX[j-1]; 03776 fX[i-1] = xti + fDirin[i-1]; 03777 fX[j-1] = xtj + fDirin[j-1]; 03778 mninex(fX); 03779 //Printf(f_out,"debug : FCN : 013"); 03780 (*fFCN)(nparx, fGin, fs1, fU, 4,fTag); ++fNfcn; 03781 fX[i-1] = xti; 03782 fX[j-1] = xtj; 03783 elem = (fs1 + fAmin - yy[i-1] - yy[j-1]) / ( 03784 fDirin[i-1]*fDirin[j-1]); 03785 ndex = i*(i-1) / 2 + j; 03786 fVhmat[ndex-1] = elem; 03787 } 03788 } 03789 L214: 03790 mninex(fX); 03791 //*-*- verify matrix positive-definite 03792 mnpsdf(); 03793 for (i = 1; i <= fNpar; ++i) { 03794 for (j = 1; j <= i; ++j) { 03795 ndex = i*(i-1) / 2 + j; 03796 fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[ndex-1]; 03797 fP[j + i*fMaxpar - fMaxpar-1] = fP[i + j*fMaxpar - fMaxpar-1]; 03798 } 03799 } 03800 mnvert(fP, fMaxint, fMaxint, fNpar, ifail); 03801 if (ifail > 0) { 03802 mnwarn("W", "HESSE", "Matrix inversion fails."); 03803 goto L390; 03804 } 03805 //*-*- . . . . . . . calculate e d m 03806 fEDM = 0; 03807 03808 for (i = 1; i <= fNpar; ++i) { 03809 //*-*- off-diagonal elements 03810 ndex = i*(i-1) / 2; 03811 for (j = 1; j <= i-1; ++j) { 03812 ++ndex; 03813 ztemp = fP[i + j*fMaxpar - fMaxpar-1]*2; 03814 fEDM += fGrd[i-1]*ztemp*fGrd[j-1]; 03815 fVhmat[ndex-1] = ztemp; 03816 } 03817 //*-*- diagonal elements 03818 ++ndex; 03819 fVhmat[ndex-1] = fP[i + i*fMaxpar - fMaxpar-1]*2; 03820 fEDM += fP[i + i*fMaxpar - fMaxpar-1]*(fGrd[i-1]*fGrd[i-1]); 03821 } 03822 if (fISW[4] >= 1 && fISW[1] == 3 && fItaur == 0) { 03823 Printf(f_out," COVARIANCE MATRIX CALCULATED SUCCESSFULLY"); 03824 } 03825 goto L900; 03826 //*-*- failure to invert 2nd deriv matrix 03827 L390: 03828 fISW[1] = 1; 03829 fDcovar = 1; 03830 fCstatu = "FAILED "; 03831 if (fISW[4] >= 0) { 03832 Printf(f_out," MNHESS FAILS AND WILL RETURN DIAGONAL MATRIX. "); 03833 } 03834 for (i = 1; i <= fNpar; ++i) { 03835 ndex = i*(i-1) / 2; 03836 for (j = 1; j <= i-1; ++j) { 03837 ++ndex; 03838 fVhmat[ndex-1] = 0; 03839 } 03840 ++ndex; 03841 g2i = fG2[i-1]; 03842 if (g2i <= 0) g2i = 1; 03843 fVhmat[ndex-1] = 2 / g2i; 03844 } 03845 L900: 03846 return; 03847 } /* mnhess_ */ 03848 03849 //______________________________________________________________________________ 03850 inline 03851 void fitter::mnhes1() 03852 { 03853 //*-*-*-*Calculate first derivatives (GRD) and uncertainties (DGRD)*-*-*-*-*-* 03854 //*-* ========================================================== 03855 //*-* and appropriate step sizes GSTEP 03856 //*-* Called from MNHESS and MNGRAD 03857 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 03858 03859 /* Local variables */ 03860 /*static*/ double dmin_, d, dfmin, dgmin, change, chgold, grdold, epspri; 03861 /*static*/ double fs1, optstp, fs2, grdnew, sag, xtf; 03862 /*static*/ int icyc, ncyc, idrv, i, nparx; 03863 /*static*/ bool ldebug; 03864 dgmin = 0; //GB : to rm warning. 03865 grdnew = 0; //GB 03866 grdold = 0; //GB 03867 03868 ldebug = fIdbg[5] >= 1; 03869 if (fIstrat <= 0) ncyc = 1; 03870 if (fIstrat == 1) ncyc = 2; 03871 if (fIstrat > 1) ncyc = 6; 03872 idrv = 1; 03873 nparx = fNpar; 03874 dfmin = fEpsma2*4*(TMath_Abs(fAmin) + fUp); 03875 //*-*- main loop over parameters 03876 for (i = 1; i <= fNpar; ++i) { 03877 xtf = fX[i-1]; 03878 dmin_ = fEpsma2*4*TMath_Abs(xtf); 03879 epspri = fEpsma2 + TMath_Abs(fGrd[i-1]*fEpsma2); 03880 optstp = TMath_Sqrt(dfmin / (TMath_Abs(fG2[i-1]) + epspri)); 03881 d = TMath_Abs(fGstep[i-1])*.2; 03882 if (d > optstp) d = optstp; 03883 if (d < dmin_) d = dmin_; 03884 chgold = 1e4; 03885 //*-*- iterate reducing step size 03886 for (icyc = 1; icyc <= ncyc; ++icyc) { 03887 fX[i-1] = xtf + d; 03888 mninex(fX); 03889 //Printf(f_out,"debug : FCN : 014"); 03890 (*fFCN)(nparx, fGin, fs1, fU, 4,fTag); ++fNfcn; 03891 fX[i-1] = xtf - d; 03892 mninex(fX); 03893 (*fFCN)(nparx, fGin, fs2, fU, 4,fTag); ++fNfcn; 03894 fX[i-1] = xtf; 03895 //*-*- check if step sizes appropriate 03896 sag = (fs1 + fs2 - fAmin*2)*.5; 03897 grdold = fGrd[i-1]; 03898 grdnew = (fs1 - fs2) / (d*2); 03899 dgmin = fEpsmac*(TMath_Abs(fs1) + TMath_Abs(fs2)) / d; 03900 if (ldebug) { 03901 Printf(f_out,"%4d%2d%12.5g%12.5g%12.5g%12.5g%12.5g%12.5g",i,idrv,fGstep[i-1],d,fG2[i-1],grdnew,sag); 03902 } 03903 if (grdnew == 0) goto L60; 03904 change = TMath_Abs((grdold - grdnew) / grdnew); 03905 if (change > chgold && icyc > 1) goto L60; 03906 chgold = change; 03907 fGrd[i-1] = grdnew; 03908 if (fGstep[i-1] > 0) fGstep[i-1] = TMath_Abs(d); 03909 else fGstep[i-1] = -TMath_Abs(d); 03910 //*-*- decrease step until first derivative changes by <5% 03911 if (change < .05) goto L60; 03912 if (TMath_Abs(grdold - grdnew) < dgmin) goto L60; 03913 if (d < dmin_) { 03914 mnwarn("D", "MNHES1", "Step size too small for 1st drv."); 03915 goto L60; 03916 } 03917 d *= .2; 03918 } 03919 //*-*- loop satisfied = too many iter 03920 mnwarn("D", "MNHES1", Form("Too many iterations on D1.%g%g",grdold,grdnew)); 03921 L60: 03922 fDgrd[i-1] = TMath_Max(dgmin,TMath_Abs(grdold - grdnew)); 03923 } 03924 //*-*- end of first deriv. loop 03925 mninex(fX); 03926 } /* mnhes1_ */ 03927 03928 //______________________________________________________________________________ 03929 inline 03930 void fitter::mnimpr() 03931 { 03932 //*-*-*-*-*-*-*Attempts to improve on a good local minimum*-*-*-*-*-*-*-*-*-* 03933 //*-* =========================================== 03934 //*-* Attempts to improve on a good local minimum by finding a 03935 //*-* better one. The quadratic part of FCN is removed by MNCALF 03936 //*-* and this transformed function is minimized using the simplex 03937 //*-* method from several random starting points. 03938 //*-* ref. -- Goldstein and Price, Math.Comp. 25, 569 (1971) 03939 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 03940 03941 /* Initialized data */ 03942 03943 /*static*/ double rnum = 0; 03944 03945 /* Local variables */ 03946 /*static*/ double amax, dsav[kMAXDIM], y[kMAXDIM+1], ycalf, ystar, ystst; 03947 /*static*/ double pb, ep, wg, xi, sigsav, reg, sig2; 03948 /*static*/ int npfn, ndex, loop, i, j, ifail, iseed; 03949 /*static*/ int jhold, nloop, nparx, nparp1, jh, jl; 03950 loop = 0; //GB : rm warning. 03951 03952 if (fNpar <= 0) return; 03953 if (fAmin == fUndefi) mnamin(); 03954 fCstatu = "UNCHANGED "; 03955 fItaur = 1; 03956 fEpsi = fUp*.1; 03957 npfn = fNfcn; 03958 nloop = int(fWord7[1]); 03959 if (nloop <= 0) nloop = fNpar + 4; 03960 nparx = fNpar; 03961 nparp1 = fNpar + 1; 03962 wg = 1 / double(fNpar); 03963 sigsav = fEDM; 03964 fApsi = fAmin; 03965 for (i = 1; i <= fNpar; ++i) { 03966 fXt[i-1] = fX[i-1]; 03967 dsav[i-1] = fWerr[i-1]; 03968 for (j = 1; j <= i; ++j) { 03969 ndex = i*(i-1) / 2 + j; 03970 fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[ndex-1]; 03971 fP[j + i*fMaxpar - fMaxpar-1] = fP[i + j*fMaxpar - fMaxpar-1]; 03972 } 03973 } 03974 mnvert(fP, fMaxint, fMaxint, fNpar, ifail); 03975 if (ifail >= 1) goto L280; 03976 //*-*- Save inverted matrix in VT 03977 for (i = 1; i <= fNpar; ++i) { 03978 ndex = i*(i-1) / 2; 03979 for (j = 1; j <= i; ++j) { 03980 ++ndex; 03981 fVthmat[ndex-1] = fP[i + j*fMaxpar - fMaxpar-1]; 03982 } 03983 } 03984 loop = 0; 03985 03986 L20: 03987 for (i = 1; i <= fNpar; ++i) { 03988 fDirin[i-1] = dsav[i-1]*2; 03989 mnrn15(rnum, iseed); 03990 fX[i-1] = fXt[i-1] + fDirin[i-1]*2*(rnum - .5); 03991 } 03992 ++loop; 03993 reg = 2; 03994 if (fISW[4] >= 0) { 03995 Printf(f_out,"START ATTEMPT NO.%2d TO FIND NEW MINIMUM",loop); 03996 } 03997 L30: 03998 mncalf(fX, ycalf); 03999 fAmin = ycalf; 04000 //*-*- . . . . set up random simplex 04001 jl = nparp1; 04002 jh = nparp1; 04003 y[nparp1-1] = fAmin; 04004 amax = fAmin; 04005 for (i = 1; i <= fNpar; ++i) { 04006 xi = fX[i-1]; 04007 mnrn15(rnum, iseed); 04008 fX[i-1] = xi - fDirin[i-1]*(rnum - .5); 04009 mncalf(fX, ycalf); 04010 y[i-1] = ycalf; 04011 if (y[i-1] < fAmin) { 04012 fAmin = y[i-1]; 04013 jl = i; 04014 } else if (y[i-1] > amax) { 04015 amax = y[i-1]; 04016 jh = i; 04017 } 04018 for (j = 1; j <= fNpar; ++j) { fP[j + i*fMaxpar - fMaxpar-1] = fX[j-1]; } 04019 fP[i + nparp1*fMaxpar - fMaxpar-1] = xi; 04020 fX[i-1] = xi; 04021 } 04022 04023 fEDM = fAmin; 04024 sig2 = fEDM; 04025 //*-*- . . . . . . . start main loop 04026 L50: 04027 if (fAmin < 0) goto L95; 04028 if (fISW[1] <= 2) goto L280; 04029 ep = fAmin*.1; 04030 if (sig2 < ep && fEDM < ep) goto L100; 04031 sig2 = fEDM; 04032 if (fNfcn - npfn > fNfcnmx) goto L300; 04033 //*-*- calculate new point * by reflection 04034 for (i = 1; i <= fNpar; ++i) { 04035 pb = 0; 04036 for (j = 1; j <= nparp1; ++j) { pb += wg*fP[i + j*fMaxpar - fMaxpar-1]; } 04037 fPbar[i-1] = pb - wg*fP[i + jh*fMaxpar - fMaxpar-1]; 04038 fPstar[i-1] = fPbar[i-1]*2 - fP[i + jh*fMaxpar - fMaxpar-1]*1; 04039 } 04040 mncalf(fPstar, ycalf); 04041 ystar = ycalf; 04042 if (ystar >= fAmin) goto L70; 04043 //*-*- point * better than jl, calculate new point ** 04044 for (i = 1; i <= fNpar; ++i) { 04045 fPstst[i-1] = fPstar[i-1]*2 + fPbar[i- 1]*-1; 04046 } 04047 mncalf(fPstst, ycalf); 04048 ystst = ycalf; 04049 if (ystst < y[jl-1]) goto L67; 04050 mnrazz(ystar, fPstar, y, jh, jl); 04051 goto L50; 04052 L67: 04053 mnrazz(ystst, fPstst, y, jh, jl); 04054 goto L50; 04055 //*-*- point * is not as good as jl 04056 L70: 04057 if (ystar >= y[jh-1]) goto L73; 04058 jhold = jh; 04059 mnrazz(ystar, fPstar, y, jh, jl); 04060 if (jhold != jh) goto L50; 04061 //*-*- calculate new point ** 04062 L73: 04063 for (i = 1; i <= fNpar; ++i) { 04064 fPstst[i-1] = fP[i + jh*fMaxpar - fMaxpar-1]*.5 + fPbar[i-1]*.5; 04065 } 04066 mncalf(fPstst, ycalf); 04067 ystst = ycalf; 04068 if (ystst > y[jh-1]) goto L30; 04069 //*-*- point ** is better than jh 04070 if (ystst < fAmin) goto L67; 04071 mnrazz(ystst, fPstst, y, jh, jl); 04072 goto L50; 04073 //*-*- . . . . . . end main loop 04074 L95: 04075 if (fISW[4] >= 0) { 04076 Printf(f_out," AN IMPROVEMENT ON THE PREVIOUS MINIMUM HAS BEEN FOUND"); 04077 } 04078 reg = .1; 04079 //*-*- . . . . . ask if point is new 04080 L100: 04081 mninex(fX); 04082 //Printf(f_out,"debug : FCN : 015"); 04083 (*fFCN)(nparx, fGin, fAmin, fU, 4,fTag); ++fNfcn; 04084 for (i = 1; i <= fNpar; ++i) { 04085 fDirin[i-1] = reg*dsav[i-1]; 04086 if (TMath_Abs(fX[i-1] - fXt[i-1]) > fDirin[i-1]) goto L150; 04087 } 04088 goto L230; 04089 L150: 04090 fNfcnmx = fNfcnmx + npfn - fNfcn; 04091 npfn = fNfcn; 04092 mnsimp(); 04093 if (fAmin >= fApsi) goto L325; 04094 for (i = 1; i <= fNpar; ++i) { 04095 fDirin[i-1] = dsav[i-1]*.1; 04096 if (TMath_Abs(fX[i-1] - fXt[i-1]) > fDirin[i-1]) goto L250; 04097 } 04098 L230: 04099 if (fAmin < fApsi) goto L350; 04100 goto L325; 04101 /* . . . . . . truly new minimum */ 04102 L250: 04103 fLnewmn = true; 04104 if (fISW[1] >= 1) { 04105 fISW[1] = 1; 04106 fDcovar = TMath_Max(fDcovar,.5); 04107 } else fDcovar = 1; 04108 fItaur = 0; 04109 fNfcnmx = fNfcnmx + npfn - fNfcn; 04110 fCstatu = "NEW MINIMU"; 04111 if (fISW[4] >= 0) { 04112 Printf(f_out," IMPROVE HAS FOUND A TRULY NEW MINIMUM"); 04113 Printf(f_out," *************************************"); 04114 } 04115 return; 04116 //*-*- . . . return to previous region 04117 L280: 04118 if (fISW[4] > 0) { 04119 Printf(f_out," COVARIANCE MATRIX WAS NOT POSITIVE-DEFINITE"); 04120 } 04121 goto L325; 04122 L300: 04123 fISW[0] = 1; 04124 L325: 04125 for (i = 1; i <= fNpar; ++i) { 04126 fDirin[i-1] = dsav[i-1]*.01; 04127 fX[i-1] = fXt[i-1]; 04128 } 04129 fAmin = fApsi; 04130 fEDM = sigsav; 04131 L350: 04132 mninex(fX); 04133 if (fISW[4] > 0) { 04134 Printf(f_out," IMPROVE HAS RETURNED TO REGION OF ORIGINAL MINIMUM"); 04135 } 04136 fCstatu = "UNCHANGED "; 04137 mnrset(0); 04138 if (fISW[1] < 2) goto L380; 04139 if (loop < nloop && fISW[0] < 1) goto L20; 04140 L380: 04141 mnprin(5, fAmin); 04142 fItaur = 0; 04143 } /* mnimpr_ */ 04144 04145 //______________________________________________________________________________ 04146 inline 04147 void fitter::mninex(double *pint) 04148 { 04149 //*-*-*-*-*Transforms from internal coordinates (PINT) to external (U)*-*-*-* 04150 //*-* =========================================================== 04151 //*-* The minimizing routines which work in 04152 //*-* internal coordinates call this routine before calling FCN. 04153 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 04154 04155 int i, j; 04156 04157 for (j = 1; j <= fNpar; ++j) { 04158 i = fNexofi[j-1]; 04159 if (fNvarl[i-1] == 1) { 04160 fU[i-1] = pint[j-1]; 04161 } else { 04162 fU[i-1] = fAlim[i-1] + (TMath_Sin(pint[j-1]) + 1)*.5*(fBlim[i-1] - fAlim[i-1]); 04163 } 04164 } 04165 } /* mninex_ */ 04166 04167 //______________________________________________________________________________ 04168 inline 04169 void fitter::mninit(int i1, int i2, int i3) 04170 { 04171 //*-*-*-*-*-*Main initialization member function for MINUIT*-*-*-*-*-*-*-*-* 04172 //*-* ============================================== 04173 //*-* It initializes some constants 04174 //*-* (including the logical I/O unit nos.), 04175 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 04176 04177 /* Local variables */ 04178 /*static*/ double piby2, epsp1, epsbak, epstry, distnn; 04179 /*static*/ int i, idb; 04180 04181 //*-*- I/O unit numbers 04182 fIsysrd = i1; 04183 fIsyswr = i2; 04184 fIstkwr[0] = fIsyswr; 04185 fNstkwr = 1; 04186 fIsyssa = i3; 04187 fNstkrd = 0; 04188 //*-*- version identifier 04189 fCvrsn = "95.03++ "; 04190 //*-*- some CONSTANT 04191 fMaxint = fMaxpar; 04192 fMaxext = 2*fMaxpar; 04193 fUndefi = -54321; 04194 fBigedm = 123456; 04195 fCundef = ")UNDEFINED"; 04196 fCovmes[0] = "NO ERROR MATRIX "; 04197 fCovmes[1] = "ERR MATRIX APPROXIMATE"; 04198 fCovmes[2] = "ERR MATRIX NOT POS-DEF"; 04199 fCovmes[3] = "ERROR MATRIX ACCURATE "; 04200 //*-*- some starting values 04201 fNblock = 0; 04202 fIcomnd = 0; 04203 fCtitl = fCundef; 04204 fCfrom = "INPUT "; 04205 fNfcn = 0; 04206 fNfcnfr = fNfcn; 04207 fCstatu = "INITIALIZE"; 04208 fISW[2] = 0; 04209 fISW[3] = 0; 04210 fISW[4] = 1; 04211 //*-*- ISW(6)=0 for batch jobs, =1 for interactive jobs 04212 //*-*- =-1 for originally interactive temporarily batch 04213 04214 fISW[5] = 0; 04215 // if (intrac(&dummy)) fISW[5] = 1; 04216 //*-*- DEBUG options set to default values 04217 for (idb = 0; idb <= 10; ++idb) { fIdbg[idb] = 0; } 04218 fLrepor = false; 04219 fLwarn = true; 04220 fLimset = false; 04221 fLnewmn = false; 04222 fIstrat = 1; 04223 fItaur = 0; 04224 //*-*- default page dimensions and 'new page' carriage control integer 04225 fNpagwd = 120; 04226 fNpagln = 56; 04227 fNewpag = 1; 04228 if (fISW[5] > 0) { 04229 fNpagwd = 80; 04230 fNpagln = 30; 04231 fNewpag = 0; 04232 } 04233 fUp = 1; 04234 fUpdflt = fUp; 04235 //*-*- determine machine accuracy epsmac 04236 epstry = .5; 04237 for (i = 1; i <= 100; ++i) { 04238 epstry *= .5; 04239 epsp1 = epstry + 1; 04240 mntiny(epsp1, epsbak); 04241 if (epsbak < epstry) goto L35; 04242 } 04243 epstry = 1e-7; 04244 fEpsmac = epstry*4; 04245 Printf(f_out," MNINIT UNABLE TO DETERMINE ARITHMETIC PRECISION. WILL ASSUME:%g",fEpsmac); 04246 L35: 04247 fEpsmac = epstry*8; 04248 fEpsma2 = TMath_Sqrt(fEpsmac)*2; 04249 //*-*- the vlims are a non-negligible distance from pi/2 04250 //*-*- used by MNPINT to set variables "near" the physical limits 04251 piby2 = TMath_ATan(1.)*2; 04252 distnn = TMath_Sqrt(fEpsma2)*8; 04253 fVlimhi = piby2 - distnn; 04254 fVlimlo = -piby2 + distnn; 04255 mncler(); 04256 // Printf(f_out," MINUIT RELEASE %s INITIALIZED. DIMENSIONS 100/50 EPSMAC=%g",fCvrsn.c_str(),fEpsmac); 04257 } /* mninit_ */ 04258 04259 //______________________________________________________________________________ 04260 inline 04261 void fitter::mnlims() 04262 { 04263 //*-*-*-*Interprets the SET LIM command, to reset the parameter limits*-*-*-* 04264 //*-* ============================================================= 04265 //*-* Called from MNSET 04266 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 04267 04268 /* Local variables */ 04269 /*static*/ double dxdi, snew; 04270 /*static*/ int kint, i2, newcod, ifx, inu; 04271 ifx = 1; //GB 04272 04273 fCfrom = "SET LIM "; 04274 fNfcnfr = fNfcn; 04275 fCstatu = "NO CHANGE "; 04276 i2 = int(fWord7[0]); 04277 if (i2 > fMaxext || i2 < 0) goto L900; 04278 if (i2 > 0) goto L30; 04279 //*-*- set limits on all parameters 04280 newcod = 4; 04281 if (fWord7[1] == fWord7[2]) newcod = 1; 04282 for (inu = 1; inu <= fNu; ++inu) { 04283 if (fNvarl[inu-1] <= 0) continue; 04284 if (fNvarl[inu-1] == 1 && newcod == 1) continue; 04285 kint = fNiofex[inu-1]; 04286 //*-*- see if parameter has been fixed 04287 if (kint <= 0) { 04288 if (fISW[4] >= 0) { 04289 Printf(f_out," LIMITS NOT CHANGED FOR FIXED PARAMETER:%4d",inu); 04290 } 04291 continue; 04292 } 04293 if (newcod == 1) { 04294 //*-*- remove limits from parameter 04295 if (fISW[4] > 0) { 04296 Printf(f_out," LIMITS REMOVED FROM PARAMETER :%3d",inu); 04297 } 04298 fCstatu = "NEW LIMITS"; 04299 mndxdi(fX[kint-1], kint-1, dxdi); 04300 snew = fGstep[kint-1]*dxdi; 04301 fGstep[kint-1] = TMath_Abs(snew); 04302 fNvarl[inu-1] = 1; 04303 } else { 04304 //*-*- put limits on parameter 04305 fAlim[inu-1] = TMath_Min(fWord7[1],fWord7[2]); 04306 fBlim[inu-1] = TMath_Max(fWord7[1],fWord7[2]); 04307 if (fISW[4] > 0) { 04308 Printf(f_out," PARAMETER %3d LIMITS SET TO %15.5g%15.5g",inu,fAlim[inu-1],fBlim[inu-1]); 04309 } 04310 fNvarl[inu-1] = 4; 04311 fCstatu = "NEW LIMITS"; 04312 fGstep[kint-1] = -.1; 04313 } 04314 } 04315 goto L900; 04316 //*-*- set limits on one parameter 04317 L30: 04318 if (fNvarl[i2-1] <= 0) { 04319 Printf(f_out," PARAMETER %3d IS NOT VARIABLE.", i2); 04320 goto L900; 04321 } 04322 kint = fNiofex[i2-1]; 04323 //*-*- see if parameter was fixed 04324 if (kint == 0) { 04325 Printf(f_out," REQUEST TO CHANGE LIMITS ON FIXED PARAMETER:%3d",i2); 04326 for (ifx = 1; ifx <= fNpfix; ++ifx) { 04327 if (i2 == fIpfix[ifx-1]) goto L92; 04328 } 04329 Printf(f_out," MINUIT BUG IN MNLIMS. SEE F. JAMES"); 04330 L92: 04331 ; 04332 } 04333 if (fWord7[1] != fWord7[2]) goto L235; 04334 //*-*- remove limits 04335 if (fNvarl[i2-1] != 1) { 04336 if (fISW[4] > 0) { 04337 Printf(f_out," LIMITS REMOVED FROM PARAMETER %2d",i2); 04338 } 04339 fCstatu = "NEW LIMITS"; 04340 if (kint <= 0) { 04341 fGsteps[ifx-1] = TMath_Abs(fGsteps[ifx-1]); 04342 } else { 04343 mndxdi(fX[kint-1], kint-1, dxdi); 04344 if (TMath_Abs(dxdi) < .01) dxdi = .01; 04345 fGstep[kint-1] = TMath_Abs(fGstep[kint-1]*dxdi); 04346 fGrd[kint-1] *= dxdi; 04347 } 04348 fNvarl[i2-1] = 1; 04349 } else { 04350 Printf(f_out," NO LIMITS SPECIFIED. PARAMETER %3d IS ALREADY UNLIMITED. NO CHANGE.",i2); 04351 } 04352 goto L900; 04353 //*-*- put on limits 04354 L235: 04355 fAlim[i2-1] = TMath_Min(fWord7[1],fWord7[2]); 04356 fBlim[i2-1] = TMath_Max(fWord7[1],fWord7[2]); 04357 fNvarl[i2-1] = 4; 04358 if (fISW[4] > 0) { 04359 Printf(f_out," PARAMETER %3d LIMITS SET TO %15.5g%15.5g",i2,fAlim[i2-1],fBlim[i2-1]); 04360 } 04361 fCstatu = "NEW LIMITS"; 04362 if (kint <= 0) fGsteps[ifx-1] = -.1; 04363 else fGstep[kint-1] = -.1; 04364 04365 L900: 04366 if (fCstatu != "NO CHANGE ") { 04367 mnexin(fX); 04368 mnrset(1); 04369 } 04370 } /* mnlims_ */ 04371 04372 //______________________________________________________________________________ 04373 inline 04374 void fitter::mnline(double *start, double fstart, double *step, double slope, double toler) 04375 { 04376 //*-*-*-*-*-*-*-*-*-*Perform a line search from position START*-*-*-*-*-*-*-* 04377 //*-* ========================================= 04378 //*-* along direction STEP, where the length of vector STEP 04379 //*-* gives the expected position of minimum. 04380 //*-* FSTART is value of function at START 04381 //*-* SLOPE (if non-zero) is df/dx along STEP at START 04382 //*-* TOLER is initial tolerance of minimum in direction STEP 04383 //*-* 04384 //*-* SLAMBG and ALPHA control the maximum individual steps allowed. 04385 //*-* The first step is always =1. The max length of second step is SLAMBG. 04386 //*-* The max size of subsequent steps is the maximum previous successful 04387 //*-* step multiplied by ALPHA + the size of most recent successful step, 04388 //*-* but cannot be smaller than SLAMBG. 04389 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 04390 04391 static const std::string charal = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 04392 04393 /* Local variables */ 04394 /*static*/ double xpq[12], ypq[12], slam, sdev, coeff[3], denom, flast; 04395 /*static*/ double fvals[3], xvals[3], f1, fvmin, xvmin, ratio, f2, f3, fvmax; 04396 /*static*/ double toler8, toler9, overal, undral, slamin, slamax, slopem; 04397 /*static*/ int i, nparx, nvmax, nxypt, kk, ipt; 04398 /*static*/ bool ldebug; 04399 std::string cmess, chpq[12]; 04400 int l65, l70, l80; 04401 04402 /* Function Body */ 04403 l65 = 0; l70 = 0; l80 = 0; 04404 ldebug = fIdbg[1] >= 1; 04405 //*-*- starting values for overall limits on total step SLAM 04406 overal = 1e3; 04407 undral = -100; 04408 //*-*- debug check if start is ok 04409 if (ldebug) { 04410 mninex(&start[0]); 04411 //Printf(f_out,"debug : FCN : 016"); 04412 (*fFCN)(nparx, fGin, f1, fU, 4,fTag); ++fNfcn; 04413 if (f1 != fstart) { 04414 Printf(f_out," MNLINE start point not consistent, F values, parameters="); 04415 for (kk = 1; kk <= fNpar; ++kk) { 04416 Printf(f_out," %14.5e",fX[kk-1]); 04417 } 04418 } 04419 } 04420 //*-*- . set up linear search along STEP 04421 fvmin = fstart; 04422 xvmin = 0; 04423 nxypt = 1; 04424 chpq[0].assign(1,charal[0]); 04425 xpq[0] = 0; 04426 ypq[0] = fstart; 04427 //*-*- SLAMIN = smallest possible value of ABS(SLAM) 04428 slamin = 0; 04429 for (i = 1; i <= fNpar; ++i) { 04430 if (step[i-1] != 0) { 04431 ratio = TMath_Abs(start[i-1] / step[i-1]); 04432 if (slamin == 0) slamin = ratio; 04433 if (ratio < slamin) slamin = ratio; 04434 } 04435 fX[i-1] = start[i-1] + step[i-1]; 04436 } 04437 if (slamin == 0) slamin = fEpsmac; 04438 slamin *= fEpsma2; 04439 nparx = fNpar; 04440 04441 mninex(fX); 04442 //Printf(f_out,"debug : FCN : 018"); 04443 (*fFCN)(nparx, fGin, f1, fU, 4,fTag); ++fNfcn; 04444 ++nxypt; 04445 chpq[nxypt-1].assign(1,charal[nxypt-1]); 04446 xpq[nxypt-1] = 1; 04447 ypq[nxypt-1] = f1; 04448 if (f1 < fstart) { 04449 fvmin = f1; 04450 xvmin = 1; 04451 } 04452 //*-*- . quadr interp using slope GDEL and two points 04453 slam = 1; 04454 toler8 = toler; 04455 slamax = 5; 04456 flast = f1; 04457 //*-*- can iterate on two-points (cut) if no imprvmnt 04458 04459 do { 04460 denom = (flast - fstart - slope*slam)*2 / (slam*slam); 04461 slam = 1; 04462 if (denom != 0) slam = -slope / denom; 04463 if (slam < 0) slam = slamax; 04464 if (slam > slamax) slam = slamax; 04465 if (slam < toler8) slam = toler8; 04466 if (slam < slamin) { 04467 l80 = 1; 04468 break; 04469 } 04470 if (TMath_Abs(slam - 1) < toler8 && f1 < fstart) { 04471 l70 = 1; 04472 break; 04473 } 04474 if (TMath_Abs(slam - 1) < toler8) slam = toler8 + 1; 04475 if (nxypt >= 12) { 04476 l65 = 1; 04477 break; 04478 } 04479 for (i = 1; i <= fNpar; ++i) { fX[i-1] = start[i-1] + slam*step[i-1]; } 04480 mninex(fX); 04481 //Printf(f_out,"debug : FCN : 019"); 04482 (*fFCN)(fNpar, fGin, f2, fU, 4,fTag); ++fNfcn; 04483 ++nxypt; 04484 chpq[nxypt-1].assign(1,charal[nxypt-1]); 04485 xpq[nxypt-1] = slam; 04486 ypq[nxypt-1] = f2; 04487 if (f2 < fvmin) { 04488 fvmin = f2; 04489 xvmin = slam; 04490 } 04491 if (fstart == fvmin) { 04492 flast = f2; 04493 toler8 = toler*slam; 04494 overal = slam - toler8; 04495 slamax = overal; 04496 } 04497 } while (fstart == fvmin); 04498 04499 if (!l65 && !l70 && !l80) { 04500 //*-*- . quadr interp using 3 points 04501 xvals[0] = xpq[0]; 04502 fvals[0] = ypq[0]; 04503 xvals[1] = xpq[nxypt-2]; 04504 fvals[1] = ypq[nxypt-2]; 04505 xvals[2] = xpq[nxypt-1]; 04506 fvals[2] = ypq[nxypt-1]; 04507 //*-*- begin iteration, calculate desired step 04508 do { 04509 slamax = TMath_Max(slamax,TMath_Abs(xvmin)*2); 04510 mnpfit(xvals, fvals, 3, coeff, sdev); 04511 if (coeff[2] <= 0) { 04512 slopem = coeff[2]*2*xvmin + coeff[1]; 04513 if (slopem <= 0) slam = xvmin + slamax; 04514 else slam = xvmin - slamax; 04515 } else { 04516 slam = -coeff[1] / (coeff[2]*2); 04517 if (slam > xvmin + slamax) slam = xvmin + slamax; 04518 if (slam < xvmin - slamax) slam = xvmin - slamax; 04519 } 04520 if (slam > 0) {if (slam > overal) slam = overal;} //GB : brace. 04521 else {if (slam < undral) slam = undral;} //GB : brace. 04522 04523 //*-*- come here if step was cut below 04524 do { 04525 toler9 = TMath_Max(toler8,TMath_Abs(toler8*slam)); 04526 for (ipt = 1; ipt <= 3; ++ipt) { 04527 if (TMath_Abs(slam - xvals[ipt-1]) < toler9) { 04528 l70 = 1; 04529 break; 04530 } 04531 } 04532 if (l70) break; 04533 //*-*- take the step 04534 if (nxypt >= 12) { 04535 l65 = 1; 04536 break; 04537 } 04538 for (i = 1; i <= fNpar; ++i) { fX[i-1] = start[i-1] + slam*step[i-1]; } 04539 mninex(fX); 04540 //Printf(f_out,"debug : FCN : 020"); 04541 (*fFCN)(nparx, fGin, f3, fU, 4,fTag); ++fNfcn; 04542 ++nxypt; 04543 chpq[nxypt-1].assign(1,charal[nxypt-1]); 04544 xpq[nxypt-1] = slam; 04545 ypq[nxypt-1] = f3; 04546 //*-*- find worst previous point out of three 04547 fvmax = fvals[0]; 04548 nvmax = 1; 04549 if (fvals[1] > fvmax) { 04550 fvmax = fvals[1]; 04551 nvmax = 2; 04552 } 04553 if (fvals[2] > fvmax) { 04554 fvmax = fvals[2]; 04555 nvmax = 3; 04556 } 04557 //*-*- if latest point worse than all three previous, cut step 04558 if (f3 >= fvmax) { 04559 if (nxypt >= 12) { 04560 l65 = 1; 04561 break; 04562 } 04563 if (slam > xvmin) overal = TMath_Min(overal,slam - toler8); 04564 if (slam < xvmin) undral = TMath_Max(undral,slam + toler8); 04565 slam = (slam + xvmin)*.5; 04566 } 04567 } while (f3 >= fvmax); 04568 04569 //*-*- prepare another iteration, replace worst previous point 04570 if (l65 || l70) break; 04571 04572 xvals[nvmax-1] = slam; 04573 fvals[nvmax-1] = f3; 04574 if (f3 < fvmin) { 04575 fvmin = f3; 04576 xvmin = slam; 04577 } else { 04578 if (slam > xvmin) overal = TMath_Min(overal,slam - toler8); 04579 if (slam < xvmin) undral = TMath_Max(undral,slam + toler8); 04580 } 04581 } while (nxypt < 12); 04582 } 04583 04584 //*-*- . . end of iteration . . . 04585 //*-*- stop because too many iterations 04586 if (!l70 && !l80) { 04587 cmess = " LINE SEARCH HAS EXHAUSTED THE LIMIT OF FUNCTION CALLS "; 04588 if (ldebug) { 04589 Printf(f_out," MNLINE DEBUG: steps="); 04590 for (kk = 1; kk <= fNpar; ++kk) { 04591 Printf(f_out," %12.4g",step[kk-1]); 04592 } 04593 } 04594 } 04595 //*-*- stop because within tolerance 04596 if (l70) cmess = " LINE SEARCH HAS ATTAINED TOLERANCE "; 04597 if (l80) cmess = " STEP SIZE AT ARITHMETICALLY ALLOWED MINIMUM"; 04598 04599 fAmin = fvmin; 04600 for (i = 1; i <= fNpar; ++i) { 04601 fDirin[i-1] = step[i-1]*xvmin; 04602 fX[i-1] = start[i-1] + fDirin[i-1]; 04603 } 04604 mninex(fX); 04605 if (xvmin < 0) { 04606 mnwarn("D", "MNLINE", " LINE MINIMUM IN BACKWARDS DIRECTION"); 04607 } 04608 if (fvmin == fstart) { 04609 mnwarn("D", "MNLINE", " LINE SEARCH FINDS NO IMPROVEMENT "); 04610 } 04611 if (ldebug) { 04612 Printf(f_out," AFTER%3d POINTS,%s",nxypt,cmess.c_str()); 04613 mnplot(xpq, ypq, chpq, nxypt, fNpagwd, fNpagln); 04614 } 04615 } /* mnline_ */ 04616 04617 //______________________________________________________________________________ 04618 inline 04619 void fitter::mnmatu(int kode) 04620 { 04621 //*-*-*-*-*-*-*-*Prints the covariance matrix v when KODE=1*-*-*-*-*-*-*-*-* 04622 //*-* ========================================== 04623 //*-* always prints the global correlations, and 04624 //*-* calculates and prints the individual correlation coefficients 04625 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 04626 04627 /* Local variables */ 04628 /*static*/ double vline[kMAXDIM]; 04629 /*static*/ int ndex, i, j, m, n, ncoef, nparm, idn, it, ix; 04630 /*static*/ int nsofar, ndi, ndj, iso, isw2, isw5; 04631 /*static*/ std::string ctemp; 04632 04633 isw2 = fISW[1]; 04634 if (isw2 < 1) { 04635 Printf(f_out,"%s",fCovmes[isw2].c_str()); 04636 return; 04637 } 04638 if (fNpar == 0) { 04639 Printf(f_out," MNMATU: NPAR=0"); 04640 return; 04641 } 04642 //*-*- . . . . .external error matrix 04643 if (kode == 1) { 04644 isw5 = fISW[4]; 04645 fISW[4] = 2; 04646 mnemat(fP, fMaxint); 04647 if (isw2 < 3) { 04648 Printf(f_out,"%s",fCovmes[isw2].c_str()); 04649 } 04650 fISW[4] = isw5; 04651 } 04652 //*-*- . . . . . correlation coeffs. . 04653 if (fNpar <= 1) return; 04654 mnwerr(); 04655 //*-*- NCOEF is number of coeff. that fit on one line, not to exceed 20 04656 ncoef = (fNpagwd - 19) / 6; 04657 ncoef = TMath_Min(ncoef,20); 04658 nparm = TMath_Min(fNpar,ncoef); 04659 Printf(f_out," PARAMETER CORRELATION COEFFICIENTS "); 04660 ctemp = " NO. GLOBAL"; 04661 for (idn = 1; idn <= nparm; ++idn) { 04662 ctemp += Form(" %6d",fNexofi[idn-1]); 04663 } 04664 Printf(f_out,"%s",ctemp.c_str()); 04665 for (i = 1; i <= fNpar; ++i) { 04666 ix = fNexofi[i-1]; 04667 ndi = i*(i + 1) / 2; 04668 for (j = 1; j <= fNpar; ++j) { 04669 m = TMath_Max(i,j); 04670 n = TMath_Min(i,j); 04671 ndex = m*(m-1) / 2 + n; 04672 ndj = j*(j + 1) / 2; 04673 vline[j-1] = fVhmat[ndex-1] / TMath_Sqrt(TMath_Abs(fVhmat[ndi-1]*fVhmat[ndj-1])); 04674 } 04675 nparm = TMath_Min(fNpar,ncoef); 04676 ctemp = Form(" %3d %7.5f ",ix); 04677 for (it = 1; it <= nparm; ++it) { 04678 ctemp += Form(" %6.3f",vline[it-1]); 04679 } 04680 Printf(f_out,"%s",ctemp.c_str()); 04681 if (i <= nparm) continue; 04682 ctemp = " "; 04683 for (iso = 1; iso <= 10; ++iso) { 04684 nsofar = nparm; 04685 nparm = TMath_Min(fNpar,nsofar + ncoef); 04686 for (it = nsofar + 1; it <= nparm; ++it) { 04687 ctemp += Form(" %6.3f",vline[it-1]); 04688 } 04689 Printf(f_out,"%s",ctemp.c_str()); 04690 if (i <= nparm) break; 04691 } 04692 } 04693 if (isw2 < 3) { 04694 Printf(f_out," %s",fCovmes[isw2].c_str()); 04695 } 04696 } /* mnmatu_ */ 04697 04698 //______________________________________________________________________________ 04699 inline 04700 bool fitter::mnmigr() //G.Barrand : return a bool 04701 { 04702 //*-*-*-*-*-*-*-*-*Performs a local function minimization*-*-*-*-*-*-*-*-*-* 04703 //*-* ====================================== 04704 //*-* Performs a local function minimization using basically the 04705 //*-* method of Davidon-Fletcher-Powell as modified by Fletcher 04706 //*-* ref. -- Fletcher, Comp.J. 13,317 (1970) "switching method" 04707 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 04708 04709 /* Local variables */ 04710 /*static*/ double gdel, gami, flnu[kMAXDIM], vlen, step[kMAXDIM], dsum, gssq, vsum, d; 04711 /*static*/ double fzero, gs[kMAXDIM], fs, ri, vg[kMAXDIM], delgam, rhotol; 04712 /*static*/ double gdgssq, gvg, vgi, xxs[kMAXDIM]; 04713 /*static*/ int npfn, ndex, iext, i, j, m, n, npsdf, nparx; 04714 /*static*/ int iswtr, lined2, kk, nfcnmg, nrstrt,iter; 04715 /*static*/ bool ldebug; 04716 /*static*/ double toler = 0.05; 04717 04718 if (fNpar <= 0) return false; //G.Barrand : return a bool. 04719 if (fAmin == fUndefi) mnamin(); 04720 ldebug = false; if ( fIdbg[4] >= 1) ldebug = true; 04721 fCfrom = "MIGRAD "; 04722 fNfcnfr = fNfcn; 04723 nfcnmg = fNfcn; 04724 fCstatu = "INITIATE "; 04725 iswtr = fISW[4] - 2*fItaur; 04726 npfn = fNfcn; 04727 nparx = fNpar; 04728 vlen = (double) (fNpar*(fNpar + 1) / 2); 04729 nrstrt = 0; 04730 npsdf = 0; 04731 lined2 = 0; 04732 fISW[3] = -1; 04733 rhotol = fApsi*.001; 04734 if (iswtr >= 1) { 04735 Printf(f_out," START MIGRAD MINIMIZATION. STRATEGY%2d. CONVERGENCE WHEN EDM .LT.%9.2e",fIstrat,rhotol); 04736 } 04737 //*-*- initialization strategy 04738 if (fIstrat < 2 || fISW[1] >= 3) goto L2; 04739 //*-*- come (back) here to restart completely 04740 L1: 04741 if (nrstrt > fIstrat) { 04742 fCstatu = "FAILED "; 04743 fISW[3] = -1; 04744 goto L230; 04745 } 04746 //*-*- . get full covariance and gradient 04747 mnhess(); 04748 mnwerr(); 04749 npsdf = 0; 04750 if (fISW[1] >= 1) goto L10; 04751 //*-*- . get gradient at start point 04752 L2: 04753 mninex(fX); 04754 if (fISW[2] == 1) { 04755 if(!(*fFCN)(nparx, fGin, fzero, fU, 2,fTag)) return false; //GB 04756 ++fNfcn; 04757 } 04758 if(!mnderi()) return false; 04759 if (fISW[1] >= 1) goto L10; 04760 //*-*- sometimes start with diagonal matrix 04761 for (i = 1; i <= fNpar; ++i) { 04762 xxs[i-1] = fX[i-1]; 04763 step[i-1] = 0; 04764 } 04765 //*-*- do line search if second derivative negative 04766 ++lined2; 04767 if (lined2 < (fIstrat + 1)*fNpar) { 04768 for (i = 1; i <= fNpar; ++i) { 04769 if (fG2[i-1] > 0) continue; 04770 if (fGrd[i-1] > 0) step[i-1] = -TMath_Abs(fGstep[i-1]); 04771 else step[i-1] = TMath_Abs(fGstep[i-1]); 04772 gdel = step[i-1]*fGrd[i-1]; 04773 fs = fAmin; 04774 mnline(xxs, fs, step, gdel, toler); 04775 mnwarn("D", "MNMIGR", "Negative G2 line search"); 04776 iext = fNexofi[i-1]; 04777 if (ldebug) { 04778 Printf(f_out," Negative G2 line search, param %3d %13.3g%13.3g",iext,fs,fAmin); 04779 } 04780 goto L2; 04781 } 04782 } 04783 //*-*- make diagonal error matrix 04784 for (i = 1; i <= fNpar; ++i) { 04785 ndex = i*(i-1) / 2; 04786 for (j = 1; j <= i-1; ++j) { 04787 ++ndex; 04788 fVhmat[ndex-1] = 0; 04789 } 04790 ++ndex; 04791 if (fG2[i-1] <= 0) fG2[i-1] = 1; 04792 fVhmat[ndex-1] = 2 / fG2[i-1]; 04793 } 04794 fDcovar = 1; 04795 if (ldebug) { 04796 Printf(f_out," DEBUG MNMIGR, STARTING MATRIX DIAGONAL, VHMAT="); 04797 for (kk = 1; kk <= int(vlen); ++kk) { 04798 Printf(f_out," %10.2g",fVhmat[kk-1]); 04799 } 04800 } 04801 //*-*- ready to start first iteration 04802 L10: 04803 ++nrstrt; 04804 if (nrstrt > fIstrat + 1) { 04805 fCstatu = "FAILED "; 04806 goto L230; 04807 } 04808 fs = fAmin; 04809 //*-*- . . . get EDM and set up loop 04810 fEDM = 0; 04811 for (i = 1; i <= fNpar; ++i) { 04812 gs[i-1] = fGrd[i-1]; 04813 xxs[i-1] = fX[i-1]; 04814 ndex = i*(i-1) / 2; 04815 for (j = 1; j <= i-1; ++j) { 04816 ++ndex; 04817 fEDM += gs[i-1]*fVhmat[ndex-1]*gs[j-1]; 04818 } 04819 ++ndex; 04820 fEDM += gs[i-1]*gs[i-1]*.5*fVhmat[ndex-1]; 04821 } 04822 fEDM = fEDM*.5*(fDcovar*3 + 1); 04823 if (fEDM < 0) { 04824 mnwarn("W", "MIGRAD", "STARTING MATRIX NOT POS-DEFINITE."); 04825 fISW[1] = 0; 04826 fDcovar = 1; 04827 goto L2; 04828 } 04829 if (fISW[1] == 0) fEDM = fBigedm; 04830 iter = 0; 04831 mninex(fX); 04832 mnwerr(); 04833 if (iswtr >= 1) mnprin(3, fAmin); 04834 if (iswtr >= 2) mnmatu(0); 04835 //*-*- . . . . . start main loop 04836 L24: 04837 if (fNfcn - npfn >= fNfcnmx) goto L190; 04838 gdel = 0; 04839 gssq = 0; 04840 for (i = 1; i <= fNpar; ++i) { 04841 ri = 0; 04842 gssq += gs[i-1]*gs[i-1]; 04843 for (j = 1; j <= fNpar; ++j) { 04844 m = TMath_Max(i,j); 04845 n = TMath_Min(i,j); 04846 ndex = m*(m-1) / 2 + n; 04847 ri += fVhmat[ndex-1]*gs[j-1]; 04848 } 04849 step[i-1] = ri*-.5; 04850 gdel += step[i-1]*gs[i-1]; 04851 } 04852 if (gssq == 0) { 04853 mnwarn("D", "MIGRAD", " FIRST DERIVATIVES OF FCN ARE ALL ZERO"); 04854 goto L300; 04855 } 04856 //*-*- if gdel positive, V not posdef 04857 if (gdel >= 0) { 04858 mnwarn("D", "MIGRAD", " NEWTON STEP NOT DESCENT."); 04859 if (npsdf == 1) goto L1; 04860 mnpsdf(); 04861 npsdf = 1; 04862 goto L24; 04863 } 04864 //*-*- . . . . do line search 04865 mnline(xxs, fs, step, gdel, toler); 04866 if (fAmin == fs) goto L200; 04867 fCfrom = "MIGRAD "; 04868 fNfcnfr = nfcnmg; 04869 fCstatu = "PROGRESS "; 04870 //*-*- . get gradient at new point 04871 mninex(fX); 04872 if (fISW[2] == 1) { 04873 if(!(*fFCN)(nparx, fGin, fzero, fU, 2,fTag)) return false; //GB 04874 ++fNfcn; 04875 } 04876 if(!mnderi()) return false; 04877 //*-*- . calculate new EDM 04878 npsdf = 0; 04879 L81: 04880 fEDM = 0; 04881 gvg = 0; 04882 delgam = 0; 04883 gdgssq = 0; 04884 for (i = 1; i <= fNpar; ++i) { 04885 ri = 0; 04886 vgi = 0; 04887 for (j = 1; j <= fNpar; ++j) { 04888 m = TMath_Max(i,j); 04889 n = TMath_Min(i,j); 04890 ndex = m*(m-1) / 2 + n; 04891 vgi += fVhmat[ndex-1]*(fGrd[j-1] - gs[j-1]); 04892 ri += fVhmat[ndex-1]*fGrd[j-1]; 04893 } 04894 vg[i-1] = vgi*.5; 04895 gami = fGrd[i-1] - gs[i-1]; 04896 gdgssq += gami*gami; 04897 gvg += gami*vg[i-1]; 04898 delgam += fDirin[i-1]*gami; 04899 fEDM += fGrd[i-1]*ri*.5; 04900 } 04901 fEDM = fEDM*.5*(fDcovar*3 + 1); 04902 //*-*- . if EDM negative, not positive-definite 04903 if (fEDM < 0 || gvg <= 0) { 04904 mnwarn("D", "MIGRAD", "NOT POS-DEF. EDM OR GVG NEGATIVE."); 04905 fCstatu = "NOT POSDEF"; 04906 if (npsdf == 1) goto L230; 04907 mnpsdf(); 04908 npsdf = 1; 04909 goto L81; 04910 } 04911 //*-*- print information about this iteration 04912 ++iter; 04913 //GB : if (iswtr >= 3 || iswtr == 2 && iter % 10 == 1) { 04914 if ( (iswtr >= 3) || ((iswtr == 2) && (iter % 10 == 1))) { //GB : have () 04915 mnwerr(); 04916 mnprin(3, fAmin); 04917 } 04918 if (gdgssq == 0) { 04919 mnwarn("D", "MIGRAD", "NO CHANGE IN FIRST DERIVATIVES OVER LAST STEP"); 04920 } 04921 if (delgam < 0) { 04922 mnwarn("D", "MIGRAD", "FIRST DERIVATIVES INCREASING ALONG SEARCH LINE"); 04923 } 04924 //*-*- . update covariance matrix 04925 fCstatu = "IMPROVEMNT"; 04926 if (ldebug) { 04927 Printf(f_out," VHMAT 1 ="); 04928 for (kk = 1; kk <= 10; ++kk) { 04929 Printf(f_out," %10.2g",fVhmat[kk-1]); 04930 } 04931 } 04932 dsum = 0; 04933 vsum = 0; 04934 for (i = 1; i <= fNpar; ++i) { 04935 for (j = 1; j <= i; ++j) { 04936 d = fDirin[i-1]*fDirin[j-1] / delgam - vg[i-1]*vg[j-1] / gvg; 04937 dsum += TMath_Abs(d); 04938 ndex = i*(i-1) / 2 + j; 04939 fVhmat[ndex-1] += d*2; 04940 vsum += TMath_Abs(fVhmat[ndex-1]); 04941 } 04942 } 04943 //*-*- smooth local fluctuations by averaging DCOVAR 04944 fDcovar = (fDcovar + dsum / vsum)*.5; 04945 if (iswtr >= 3 || ldebug) { 04946 Printf(f_out," RELATIVE CHANGE IN COV. MATRIX=%5.1f per cent",fDcovar*100); 04947 } 04948 if (ldebug) { 04949 Printf(f_out," VHMAT 2 ="); 04950 for (kk = 1; kk <= 10; ++kk) { 04951 Printf(f_out," %10.3g",fVhmat[kk-1]); 04952 } 04953 } 04954 if (delgam <= gvg) goto L135; 04955 for (i = 1; i <= fNpar; ++i) { 04956 flnu[i-1] = fDirin[i-1] / delgam - vg[i-1] / gvg; 04957 } 04958 for (i = 1; i <= fNpar; ++i) { 04959 for (j = 1; j <= i; ++j) { 04960 ndex = i*(i-1) / 2 + j; 04961 fVhmat[ndex-1] += gvg*2*flnu[i-1]*flnu[j-1]; 04962 } 04963 } 04964 L135: 04965 //*-*- and see if converged 04966 if (fEDM < rhotol*.1) goto L300; 04967 //*-*- if not, prepare next iteration 04968 for (i = 1; i <= fNpar; ++i) { 04969 xxs[i-1] = fX[i-1]; 04970 gs[i-1] = fGrd[i-1]; 04971 } 04972 fs = fAmin; 04973 if (fISW[1] == 0 && fDcovar < .5) fISW[1] = 1; 04974 if (fISW[1] == 3 && fDcovar > .1) fISW[1] = 1; 04975 if (fISW[1] == 1 && fDcovar < .05) fISW[1] = 3; 04976 goto L24; 04977 //*-*- . . . . . end main loop 04978 //*-*- . . call limit in MNMIGR 04979 L190: 04980 fISW[0] = 1; 04981 if (fISW[4] >= 0) { 04982 Printf(f_out," CALL LIMIT EXCEEDED IN MIGRAD."); 04983 } 04984 fCstatu = "CALL LIMIT"; 04985 goto L230; 04986 //*-*- . . fails to improve . . 04987 L200: 04988 if (iswtr >= 1) { 04989 Printf(f_out," MIGRAD FAILS TO FIND IMPROVEMENT"); 04990 } 04991 for (i = 1; i <= fNpar; ++i) { fX[i-1] = xxs[i-1]; } 04992 if (fEDM < rhotol) goto L300; 04993 if (fEDM < TMath_Abs(fEpsma2*fAmin)) { 04994 if (iswtr >= 0) { 04995 Printf(f_out," MACHINE ACCURACY LIMITS FURTHER IMPROVEMENT."); 04996 } 04997 goto L300; 04998 } 04999 if (fIstrat < 1) { 05000 if (fISW[4] >= 0) { 05001 Printf(f_out," MIGRAD FAILS WITH STRATEGY=0. WILL TRY WITH STRATEGY=1."); 05002 } 05003 fIstrat = 1; 05004 } 05005 goto L1; 05006 //*-*- . . fails to converge 05007 L230: 05008 if (iswtr >= 0) { 05009 Printf(f_out," MIGRAD TERMINATED WITHOUT CONVERGENCE."); 05010 } 05011 if (fISW[1] == 3) fISW[1] = 1; 05012 fISW[3] = -1; 05013 goto L400; 05014 //*-*- . . apparent convergence 05015 L300: 05016 if (iswtr >= 0) { 05017 Printf(f_out," MIGRAD MINIMIZATION HAS CONVERGED."); 05018 } 05019 if (fItaur == 0) { 05020 if (fIstrat >= 2 || (fIstrat == 1 && fISW[1] < 3)) { 05021 if (fISW[4] >= 0) { 05022 Printf(f_out," MIGRAD WILL VERIFY CONVERGENCE AND ERROR MATRIX."); 05023 } 05024 mnhess(); 05025 mnwerr(); 05026 npsdf = 0; 05027 if (fEDM > rhotol) goto L10; 05028 } 05029 } 05030 fCstatu = "CONVERGED "; 05031 fISW[3] = 1; 05032 //*-*- come here in any case 05033 L400: 05034 fCfrom = "MIGRAD "; 05035 fNfcnfr = nfcnmg; 05036 mninex(fX); 05037 mnwerr(); 05038 if (iswtr >= 0) mnprin(3, fAmin); 05039 if (iswtr >= 1) mnmatu(1); 05040 return true; //G.Barrand 05041 } /* mnmigr_ */ 05042 05043 //______________________________________________________________________________ 05044 inline 05045 void fitter::mnmnos() 05046 { 05047 //*-*-*-*-*-*-*-*-*-*-*Performs a MINOS error analysis*-*-*-*-*-*-*-*-*-*-*-* 05048 //*-* =============================== 05049 //*-* Performs a MINOS error analysis on those parameters for 05050 //*-* which it is requested on the MINOS command by calling 05051 //*-* MNMNOT for each parameter requested. 05052 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 05053 05054 /* Local variables */ 05055 /*static*/ double val2mi, val2pl; 05056 /*static*/ int nbad, ilax, ilax2, ngood, nfcnmi, iin, knt; 05057 05058 if (fNpar <= 0) goto L700; 05059 ngood = 0; 05060 nbad = 0; 05061 nfcnmi = fNfcn; 05062 //*-*- . loop over parameters requested 05063 for (knt = 1; knt <= fNpar; ++knt) { 05064 if (int(fWord7[1]) == 0) { 05065 ilax = fNexofi[knt-1]; 05066 } else { 05067 if (knt >= 7) break; 05068 ilax = int(fWord7[knt]); 05069 if (ilax == 0) break; 05070 if (ilax > 0 && ilax <= fNu) { 05071 if (fNiofex[ilax-1] > 0) goto L565; 05072 } 05073 Printf(f_out," PARAMETER NUMBER %3d NOT VARIABLE. IGNORED.",ilax); 05074 continue; 05075 } 05076 L565: 05077 //*-*- calculate one pair of M E s 05078 ilax2 = 0; 05079 mnmnot(ilax, ilax2, val2pl, val2mi); 05080 if (fLnewmn) goto L650; 05081 //*-*- update NGOOD and NBAD 05082 iin = fNiofex[ilax-1]; 05083 if (fErp[iin-1] > 0) ++ngood; 05084 else ++nbad; 05085 if (fErn[iin-1] < 0) ++ngood; 05086 else ++nbad; 05087 } 05088 //*-*- end of loop . . . . . . . 05089 //*-*- . . . . printout final values . 05090 fCfrom = "MINOS "; 05091 fNfcnfr = nfcnmi; 05092 fCstatu = "UNCHANGED "; 05093 if (ngood == 0 && nbad == 0) goto L700; 05094 if (ngood > 0 && nbad == 0) fCstatu = "SUCCESSFUL"; 05095 if (ngood == 0 && nbad > 0) fCstatu = "FAILURE "; 05096 if (ngood > 0 && nbad > 0) fCstatu = "PROBLEMS "; 05097 if (fISW[4] >= 0) mnprin(4, fAmin); 05098 if (fISW[4] >= 2) mnmatu(0); 05099 return; 05100 //*-*- . . . new minimum found . . . . 05101 L650: 05102 fCfrom = "MINOS "; 05103 fNfcnfr = nfcnmi; 05104 fCstatu = "NEW MINIMU"; 05105 if (fISW[4] >= 0) mnprin(4, fAmin); 05106 Printf(f_out," NEW MINIMUM FOUND. GO BACK TO MINIMIZATION STEP."); 05107 Printf(f_out," ================================================="); 05108 Printf(f_out," V"); 05109 Printf(f_out," V"); 05110 Printf(f_out," V"); 05111 Printf(f_out," VVVVVVV"); 05112 Printf(f_out," VVVVV"); 05113 Printf(f_out," VVV"); 05114 Printf(f_out," V"); 05115 Printf(f_out,""); 05116 return; 05117 L700: 05118 Printf(f_out," THERE ARE NO MINOS ERRORS TO CALCULATE."); 05119 } /* mnmnos_ */ 05120 05121 //______________________________________________________________________________ 05122 inline 05123 void fitter::mnmnot(int ilax, int ilax2, double &val2pl, double &val2mi) 05124 { 05125 //*-*-*-*-*-*Performs a MINOS error analysis on one parameter*-*-*-*-*-*-*-*-* 05126 //*-* ================================================ 05127 //*-* The parameter ILAX is varied, and the minimum of the 05128 //*-* function with respect to the other parameters is followed 05129 //*-* until it crosses the value FMIN+UP. 05130 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 05131 05132 /* System generated locals */ 05133 int i__1; 05134 05135 /* Local variables */ 05136 /*static*/ double xdev[kMAXDIM], delu, aopt, eros; 05137 /*static*/ double w[kMAXDIM], abest, xunit, dc, ut, sigsav, du1; 05138 /*static*/ double fac, gcc[kMAXDIM], sig, sav; 05139 /*static*/ int marc, isig, mpar, ndex, imax, indx, ierr, i, j; 05140 /*static*/ int iercr, it, istrav, nfmxin, nlimit, isw2, isw4; 05141 /*static*/ std::string csig; 05142 05143 //*-*- . . save and prepare start vals 05144 isw2 = fISW[1]; 05145 isw4 = fISW[3]; 05146 sigsav = fEDM; 05147 istrav = fIstrat; 05148 dc = fDcovar; 05149 fLnewmn = false; 05150 fApsi = fEpsi*.5; 05151 abest = fAmin; 05152 mpar = fNpar; 05153 nfmxin = fNfcnmx; 05154 for (i = 1; i <= mpar; ++i) { fXt[i-1] = fX[i-1]; } 05155 i__1 = mpar*(mpar + 1) / 2; 05156 for (j = 1; j <= i__1; ++j) { fVthmat[j-1] = fVhmat[j-1]; } 05157 for (i = 1; i <= mpar; ++i) { 05158 gcc[i-1] = fGlobcc[i-1]; 05159 w[i-1] = fWerr[i-1]; 05160 } 05161 it = fNiofex[ilax-1]; 05162 fErp[it-1] = 0; 05163 fErn[it-1] = 0; 05164 mninex(fXt); 05165 ut = fU[ilax-1]; 05166 if (fNvarl[ilax-1] == 1) { 05167 fAlim[ilax-1] = ut - w[it-1]*100; 05168 fBlim[ilax-1] = ut + w[it-1]*100; 05169 } 05170 ndex = it*(it + 1) / 2; 05171 xunit = TMath_Sqrt(fUp / fVthmat[ndex-1]); 05172 marc = 0; 05173 for (i = 1; i <= mpar; ++i) { 05174 if (i == it) continue; 05175 ++marc; 05176 imax = TMath_Max(it,i); 05177 indx = imax*(imax-1) / 2 + TMath_Min(it,i); 05178 xdev[marc-1] = xunit*fVthmat[indx-1]; 05179 } 05180 //*-*- fix the parameter in question 05181 mnfixp(it-1, ierr); 05182 if (ierr > 0) { 05183 Printf(f_out," MINUIT ERROR. CANNOT FIX PARAMETER%4d INTERNAL%3d",ilax,it); 05184 goto L700; 05185 } 05186 //*-*- . . . . . Nota Bene: from here on, NPAR=MPAR-1 05187 //*-*- Remember: MNFIXP squeezes IT out of X, XT, WERR, and VHMAT, 05188 //*-*- not W, VTHMAT 05189 for (isig = 1; isig <= 2; ++isig) { 05190 if (isig == 1) { 05191 sig = 1; 05192 csig = "POSI"; 05193 } else { 05194 sig = -1; 05195 csig = "NEGA"; 05196 } 05197 //*-*- . sig=sign of error being calcd 05198 if (fISW[4] > 1) { 05199 Printf(f_out," DETERMINATION OF %sTIVE MINOS ERROR FOR PARAMETER%d" 05200 ,csig.c_str(),ilax 05201 ,fCpnam[ilax-1].c_str()); 05202 } 05203 if (fISW[1] <= 0) { 05204 mnwarn("D", "MINOS", "NO COVARIANCE MATRIX."); 05205 } 05206 nlimit = fNfcn + nfmxin; 05207 fIstrat = TMath_Max(istrav-1,0); 05208 du1 = w[it-1]; 05209 fU[ilax-1] = ut + sig*du1; 05210 fU[ilax-1] = TMath_Min(fU[ilax-1],fBlim[ilax-1]); 05211 fU[ilax-1] = TMath_Max(fU[ilax-1],fAlim[ilax-1]); 05212 delu = fU[ilax-1] - ut; 05213 //*-*- stop if already at limit with negligible step size 05214 if (TMath_Abs(delu) / (TMath_Abs(ut) + TMath_Abs(fU[ilax-1])) < fEpsmac) goto L440; 05215 fac = delu / w[it-1]; 05216 for (i = 1; i <= fNpar; ++i) { 05217 fX[i-1] = fXt[i-1] + fac*xdev[i-1]; 05218 } 05219 if (fISW[4] > 1) { 05220 Printf(f_out," PARAMETER%4d SET TO%11.3e + %10.3e = %12.3e",ilax,ut,delu,fU[ilax-1]); 05221 } 05222 //*-*- loop to hit AMIN+UP 05223 fKe1cr = ilax; 05224 fKe2cr = 0; 05225 fXmidcr = fU[ilax-1]; 05226 fXdircr = delu; 05227 05228 fAmin = abest; 05229 fNfcnmx = nlimit - fNfcn; 05230 mncros(aopt, iercr); 05231 if (abest - fAmin > fUp*.01) goto L650; 05232 if (iercr == 1) goto L440; 05233 if (iercr == 2) goto L450; 05234 if (iercr == 3) goto L460; 05235 //*-*- . error successfully calculated 05236 eros = fXmidcr - ut + aopt*fXdircr; 05237 if (fISW[4] > 1) { 05238 Printf(f_out," THE %4sTIVE MINOS ERROR OF PARAMETER%3d %10s, IS %12.4e" 05239 ,csig.c_str(),ilax 05240 ,fCpnam[ilax-1].c_str(),eros); 05241 } 05242 goto L480; 05243 //*-*- . . . . . . . . failure returns 05244 L440: 05245 if (fISW[4] >= 1) { 05246 Printf(f_out," THE %4sTIVE MINOS ERROR OF PARAMETER%3d, %s EXCEEDS ITS LIMIT." 05247 ,csig.c_str(),ilax 05248 ,fCpnam[ilax-1].c_str()); 05249 } 05250 eros = fUndefi; 05251 goto L480; 05252 L450: 05253 if (fISW[4] >= 1) { 05254 Printf(f_out," THE %4sTIVE MINOS ERROR%4d REQUIRES MORE THAN%5d FUNCTION CALLS.",csig.c_str(),ilax,nfmxin); 05255 } 05256 eros = 0; 05257 goto L480; 05258 L460: 05259 if (fISW[4] >= 1) { 05260 Printf(f_out," %4sTIVE MINOS ERROR NOT CALCULATED FOR PARAMETER%d",csig.c_str(),ilax); 05261 } 05262 eros = 0; 05263 05264 L480: 05265 if (fISW[4] > 1) { 05266 Printf(f_out," **************************************************************************"); 05267 } 05268 if (sig < 0) { 05269 fErn[it-1] = eros; 05270 if (ilax2 > 0 && ilax2 <= fNu) val2mi = fU[ilax2-1]; 05271 } else { 05272 fErp[it-1] = eros; 05273 if (ilax2 > 0 && ilax2 <= fNu) val2pl = fU[ilax2-1]; 05274 } 05275 } 05276 //*-*- . . parameter finished. reset v 05277 //*-*- normal termination */ 05278 fItaur = 1; 05279 mnfree(1); 05280 i__1 = mpar*(mpar + 1) / 2; 05281 for (j = 1; j <= i__1; ++j) { fVhmat[j-1] = fVthmat[j-1]; } 05282 for (i = 1; i <= mpar; ++i) { 05283 fWerr[i-1] = w[i-1]; 05284 fGlobcc[i-1] = gcc[i-1]; 05285 fX[i-1] = fXt[i-1]; 05286 } 05287 mninex(fX); 05288 fEDM = sigsav; 05289 fAmin = abest; 05290 fISW[1] = isw2; 05291 fISW[3] = isw4; 05292 fDcovar = dc; 05293 goto L700; 05294 //*-*- new minimum 05295 L650: 05296 fLnewmn = true; 05297 fISW[1] = 0; 05298 fDcovar = 1; 05299 fISW[3] = 0; 05300 sav = fU[ilax-1]; 05301 fItaur = 1; 05302 mnfree(1); 05303 fU[ilax-1] = sav; 05304 mnexin(fX); 05305 fEDM = fBigedm; 05306 //*-*- in any case 05307 L700: 05308 fItaur = 0; 05309 fNfcnmx = nfmxin; 05310 fIstrat = istrav; 05311 } /* mnmnot_ */ 05312 05313 //______________________________________________________________________________ 05314 inline 05315 void fitter::mnparm(int k1, const std::string& cnamj, double uk, double wk, double a, double b, int &ierflg) 05316 { 05317 //*-*-*-*-*-*-*-*-*Implements one parameter definition*-*-*-*-*-*-*-*-*-*-*-* 05318 //*-* =================================== 05319 //*-* Called from MNPARS and user-callable 05320 //*-* Implements one parameter definition, that is: 05321 //*-* K (external) parameter number 05322 //*-* CNAMK parameter name 05323 //*-* UK starting value 05324 //*-* WK starting step size or uncertainty 05325 //*-* A, B lower and upper physical parameter limits 05326 //*-* and sets up (updates) the parameter lists. 05327 //*-* Output: IERFLG=0 if no problems 05328 //*-* >0 if MNPARM unable to implement definition 05329 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 05330 05331 /* Local variables */ 05332 /*static*/ double vplu, a_small, gsmin, pinti, vminu, danger, sav, sav2; 05333 /*static*/ int ierr, kint, in, ix, ktofix, lastin, kinfix, nvl; 05334 /*static*/ std::string cnamk, chbufi; 05335 ierr = 0; //GB 05336 05337 int k = k1+1; 05338 cnamk = cnamj; 05339 kint = fNpar; 05340 if (k < 1 || k > fMaxext) { 05341 //*-*- parameter number exceeds allowed maximum value 05342 Printf(f_out," MINUIT USER ERROR. PARAMETER NUMBER IS %3d ALLOWED RANGE IS ONE TO %4d",k,fMaxext); 05343 goto L800; 05344 } 05345 //*-*- normal parameter request 05346 ktofix = 0; 05347 if (fNvarl[k-1] < 0) goto L50; 05348 //*-*- previously defined parameter is being redefined 05349 //*-*- find if parameter was fixed 05350 for (ix = 1; ix <= fNpfix; ++ix) { 05351 if (fIpfix[ix-1] == k) ktofix = k; 05352 } 05353 if (ktofix > 0) { 05354 mnwarn("W", "PARAM DEF", "REDEFINING A FIXED PARAMETER."); 05355 if (kint >= fMaxint) { 05356 Printf(f_out," CANNOT RELEASE. MAX NPAR EXCEEDED."); 05357 goto L800; 05358 } 05359 mnfree(1); 05360 } 05361 //*-*- if redefining previously variable parameter 05362 if (fNiofex[k-1] > 0) kint = fNpar - 1; 05363 L50: 05364 05365 //*-*- . . .print heading 05366 if (fLphead && fISW[4] >= 0) { 05367 Printf(f_out," PARAMETER DEFINITIONS:"); 05368 Printf(f_out," NO. NAME VALUE STEP SIZE LIMITS"); 05369 fLphead = false; 05370 } 05371 if (wk > 0) goto L122; 05372 //*-*- . . .constant parameter . . . . 05373 if (fISW[4] >= 0) { 05374 Printf(f_out," %5d %-10s %13.5e constant", 05375 k,cnamk.c_str(),uk); 05376 } 05377 nvl = 0; 05378 goto L200; 05379 L122: 05380 if (a == 0 && b == 0) { 05381 //*-*- variable parameter without limits 05382 nvl = 1; 05383 if (fISW[4] >= 0) { 05384 Printf(f_out," %5d %-10s %13.5e%13.5e no limits", 05385 k,cnamk.c_str(),uk,wk); 05386 } 05387 } else { 05388 //*-*- variable parameter with limits 05389 nvl = 4; 05390 fLnolim = false; 05391 if (fISW[4] >= 0) { 05392 Printf(f_out," %5d '%-10s' %13.5e%13.5e %13.5e%13.5e", 05393 k,cnamk.c_str(),uk,wk,a,b); 05394 } 05395 } 05396 //*-*- . . request for another variable parameter 05397 ++kint; 05398 if (kint > fMaxint) { 05399 Printf(f_out," MINUIT USER ERROR. TOO MANY VARIABLE PARAMETERS."); 05400 goto L800; 05401 } 05402 if (nvl == 1) goto L200; 05403 if (a == b) { 05404 Printf(f_out," USER ERROR IN MINUIT PARAMETER"); 05405 Printf(f_out," DEFINITION"); 05406 Printf(f_out," UPPER AND LOWER LIMITS EQUAL."); 05407 goto L800; 05408 } 05409 if (b < a) { 05410 sav = b; 05411 b = a; 05412 a = sav; 05413 mnwarn("W", "PARAM DEF", "PARAMETER LIMITS WERE REVERSED."); 05414 if (fLwarn) fLphead = true; 05415 } 05416 if (b - a > 1e7) { 05417 mnwarn("W", "PARAM DEF", Form("LIMITS ON PARAM%d TOO FAR APART.",k)); 05418 if (fLwarn) fLphead = true; 05419 } 05420 danger = (b - uk)*(uk - a); 05421 if (danger < 0) { 05422 mnwarn("W", "PARAM DEF", "STARTING VALUE OUTSIDE LIMITS."); 05423 } 05424 if (danger == 0) { 05425 mnwarn("W", "PARAM DEF", "STARTING VALUE IS AT LIMIT."); 05426 } 05427 L200: 05428 //*-*- . . . input OK, set values, arrange lists, 05429 //*-*- calculate step sizes GSTEP, DIRIN 05430 fCfrom = "PARAMETR"; 05431 fNfcnfr = fNfcn; 05432 fCstatu = "NEW VALUES"; 05433 fNu = TMath_Max(fNu,k); 05434 fCpnam[k-1] = cnamk; 05435 fU[k-1] = uk; 05436 fAlim[k-1] = a; 05437 fBlim[k-1] = b; 05438 fNvarl[k-1] = nvl; 05439 mnrset(1); 05440 //*-*- K is external number of new parameter 05441 //*-*- LASTIN is the number of var. params with ext. param. no.< K 05442 lastin = 0; 05443 for (ix = 1; ix <= k-1; ++ix) { if (fNiofex[ix-1] > 0) ++lastin; } 05444 //*-*- KINT is new number of variable params, NPAR is old 05445 if (kint == fNpar) goto L280; 05446 if (kint > fNpar) { 05447 //*-*- insert new variable parameter in list 05448 for (in = fNpar; in >= lastin + 1; --in) { 05449 ix = fNexofi[in-1]; 05450 fNiofex[ix-1] = in + 1; 05451 fNexofi[in] = ix; 05452 fX[in] = fX[in-1]; 05453 fXt[in] = fXt[in-1]; 05454 fDirin[in] = fDirin[in-1]; 05455 fG2[in] = fG2[in-1]; 05456 fGstep[in] = fGstep[in-1]; 05457 } 05458 } else { 05459 //*-*- remove variable parameter from list 05460 for (in = lastin + 1; in <= kint; ++in) { 05461 ix = fNexofi[in]; 05462 fNiofex[ix-1] = in; 05463 fNexofi[in-1] = ix; 05464 fX[in-1] = fX[in]; 05465 fXt[in-1] = fXt[in]; 05466 fDirin[in-1] = fDirin[in]; 05467 fG2[in-1] = fG2[in]; 05468 fGstep[in-1] = fGstep[in]; 05469 } 05470 } 05471 L280: 05472 ix = k; 05473 fNiofex[ix-1] = 0; 05474 fNpar = kint; 05475 //*-*- lists are now arranged . . . . 05476 if (nvl > 0) { 05477 in = lastin + 1; 05478 fNexofi[in-1] = ix; 05479 fNiofex[ix-1] = in; 05480 sav = fU[ix-1]; 05481 mnpint(sav, ix-1, pinti); 05482 fX[in-1] = pinti; 05483 fXt[in-1] = fX[in-1]; 05484 fWerr[in-1] = wk; 05485 sav2 = sav + wk; 05486 mnpint(sav2, ix-1, pinti); 05487 vplu = pinti - fX[in-1]; 05488 sav2 = sav - wk; 05489 mnpint(sav2, ix-1, pinti); 05490 vminu = pinti - fX[in-1]; 05491 fDirin[in-1] = (TMath_Abs(vplu) + TMath_Abs(vminu))*.5; 05492 fG2[in-1] = fUp*2 / (fDirin[in-1]*fDirin[in-1]); 05493 gsmin = fEpsma2*8*TMath_Abs(fX[in-1]); 05494 fGstep[in-1] = TMath_Max(gsmin,fDirin[in-1]*.1); 05495 if (fAmin != fUndefi) { 05496 a_small = TMath_Sqrt(fEpsma2*(fAmin + fUp) / fUp); 05497 fGstep[in-1] = TMath_Max(gsmin,a_small*fDirin[in-1]); 05498 } 05499 fGrd[in-1] = fG2[in-1]*fDirin[in-1]; 05500 //*-*- if parameter has limits 05501 if (fNvarl[k-1] > 1) { 05502 if (fGstep[in-1] > .5) fGstep[in-1] = .5; 05503 fGstep[in-1] = -fGstep[in-1]; 05504 } 05505 } 05506 if (ktofix > 0) { 05507 kinfix = fNiofex[ktofix-1]; 05508 if (kinfix > 0) mnfixp(kinfix-1, ierr); 05509 if (ierr > 0) goto L800; 05510 } 05511 ierflg = 0; 05512 return; 05513 //*-*- error on input, unable to implement request . . . . 05514 L800: 05515 ierflg = 1; 05516 } /* mnparm_ */ 05517 05518 //______________________________________________________________________________ 05519 inline 05520 void fitter::mnpars(const std::string& crdbuf, int &icondn) 05521 { 05522 //*-*-*-*-*-*-*-*Implements one parameter definition*-*-*-*-*-*-*-*-*-*-*-*-* 05523 //*-* =========== ======================= 05524 //*-* Called from MNREAD and user-callable 05525 //*-* Implements one parameter definition, that is: 05526 //*-* parses the string CRDBUF and calls MNPARM 05527 //*-* 05528 //*-* output conditions: 05529 //*-* ICONDN = 0 all OK 05530 //*-* ICONDN = 1 error, attempt to define parameter is ignored 05531 //*-* ICONDN = 2 end of parameter definitions 05532 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 05533 05534 /* Local variables */ 05535 /*static*/ double a, b, plist[30], fk, uk, wk, xk; 05536 /*static*/ int ierr, kapo1, kapo2; 05537 /*static*/ int k, llist, ibegin, lenbuf, istart, lnc, icy; 05538 /*static*/ std::string cnamk, comand, celmnt, ctemp; 05539 char stmp[128]; 05540 05541 lenbuf = crdbuf.size(); 05542 //*-*- find out whether fixed or free-field format 05543 kapo1 = strspn(crdbuf.c_str(), "'"); 05544 if (kapo1 == 0) goto L150; 05545 kapo2 = strspn(crdbuf.c_str() + kapo1, "'"); 05546 if (kapo2 == 0) goto L150; 05547 //*-*- new (free-field) format 05548 kapo2 += kapo1; 05549 //*-*- skip leading blanks if any 05550 for (istart = 1; istart <= kapo1-1; ++istart) { 05551 if (crdbuf[istart-1] != ' ') goto L120; 05552 } 05553 goto L210; 05554 L120: 05555 //*-*- parameter number integer 05556 celmnt = msubstr(crdbuf,istart-1, kapo1-istart); 05557 //GB : have dummy if() to quiet g++-4.4.1 05558 if(scanf(celmnt.c_str(),fk)){} 05559 k = int(fk); 05560 if (k <= 0) goto L210; 05561 cnamk = "PARAM "; 05562 cnamk += celmnt; 05563 if (kapo2 - kapo1 > 1) { 05564 cnamk = msubstr(crdbuf,kapo1, kapo2-1-kapo1); 05565 } 05566 //*-* special handling if comma or blanks and a comma follow 'name' 05567 for (icy = kapo2 + 1; icy <= lenbuf; ++icy) { 05568 if (crdbuf[icy-1] == ',') goto L139; 05569 if (crdbuf[icy-1] != ' ') goto L140; 05570 } 05571 uk = 0; 05572 wk = 0; 05573 a = 0; 05574 b = 0; 05575 goto L170; 05576 L139: 05577 ++icy; 05578 L140: 05579 ibegin = icy; 05580 ctemp = msubstr(crdbuf,ibegin-1,lenbuf-ibegin); 05581 mncrck(ctemp, 20, comand, lnc, 30, plist, llist, ierr, fIsyswr); 05582 if (ierr > 0) goto L180; 05583 uk = plist[0]; 05584 wk = 0; 05585 if (llist >= 2) wk = plist[1]; 05586 a = 0; 05587 if (llist >= 3) a = plist[2]; 05588 b = 0; 05589 if (llist >= 4) b = plist[3]; 05590 goto L170; 05591 //*-*- old (fixed-field) format 05592 L150: 05593 //GB : have dummy if() to quiet g++-4.4.1 05594 if(scanf(crdbuf.c_str(),xk,stmp,uk,wk,a,b)){} 05595 cnamk = stmp; 05596 k = int(xk); 05597 if (k == 0) goto L210; 05598 //*-*- parameter format cracked, implement parameter definition 05599 L170: 05600 mnparm(k-1, cnamk, uk, wk, a, b, ierr); 05601 icondn = ierr; 05602 return; 05603 //*-*- format or other error 05604 L180: 05605 icondn = 1; 05606 return; 05607 //*-*- end of data 05608 L210: 05609 icondn = 2; 05610 } /* mnpars_ */ 05611 05612 //______________________________________________________________________________ 05613 inline 05614 void fitter::mnpfit(double *parx2p, double *pary2p, int npar2p, double *coef2p, double &sdev2p) 05615 { 05616 //*-*-*-*-*-*-*-*-*-*To fit a parabola to npar2p points*-*-*-*-*-*-*-*-*-*-* 05617 //*-* ================================== 05618 //*-* npar2p no. of points 05619 //*-* parx2p(i) x value of point i 05620 //*-* pary2p(i) y value of point i 05621 //*-* 05622 //*-* coef2p(1...3) coefficients of the fitted parabola 05623 //*-* y=coef2p(1) + coef2p(2)*x + coef2p(3)*x**2 05624 //*-* sdev2p= variance 05625 //*-* method : chi**2 = min equation solved explicitly 05626 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 05627 05628 /* Local variables */ 05629 /*static*/ double a, f, s, t, y, s2, x2, x3, x4, y2, cz[3], xm, xy, x2y; 05630 x2 = x3 = 0; 05631 int i; 05632 05633 /* Parameter adjustments */ 05634 --coef2p; 05635 --pary2p; 05636 --parx2p; 05637 05638 /* Function Body */ 05639 for (i = 1; i <= 3; ++i) { cz[i-1] = 0; } 05640 sdev2p = 0; 05641 if (npar2p < 3) goto L10; 05642 f = (double) (npar2p); 05643 //*-* --- center x values for reasons of machine precision 05644 xm = 0; 05645 for (i = 1; i <= npar2p; ++i) { xm += parx2p[i]; } 05646 xm /= f; 05647 x2 = 0; 05648 x3 = 0; 05649 x4 = 0; 05650 y = 0; 05651 y2 = 0; 05652 xy = 0; 05653 x2y = 0; 05654 for (i = 1; i <= npar2p; ++i) { 05655 s = parx2p[i] - xm; 05656 t = pary2p[i]; 05657 s2 = s*s; 05658 x2 += s2; 05659 x3 += s*s2; 05660 x4 += s2*s2; 05661 y += t; 05662 y2 += t*t; 05663 xy += s*t; 05664 x2y += s2*t; 05665 } 05666 a = (f*x4 - x2*x2)*x2 - f*(x3*x3); 05667 if (a == 0) goto L10; 05668 cz[2] = (x2*(f*x2y - x2*y) - f*x3*xy) / a; 05669 cz[1] = (xy - x3*cz[2]) / x2; 05670 cz[0] = (y - x2*cz[2]) / f; 05671 if (npar2p == 3) goto L6; 05672 sdev2p = y2 - (cz[0]*y + cz[1]*xy + cz[2]*x2y); 05673 if (sdev2p < 0) sdev2p = 0; 05674 sdev2p /= f - 3; 05675 L6: 05676 cz[0] += xm*(xm*cz[2] - cz[1]); 05677 cz[1] -= xm*2*cz[2]; 05678 L10: 05679 for (i = 1; i <= 3; ++i) { coef2p[i] = cz[i-1]; } 05680 } /* mnpfit_ */ 05681 05682 //______________________________________________________________________________ 05683 inline 05684 void fitter::mnpint(double &pexti, int i1, double &pinti) 05685 { 05686 //*-*-*-*-*-*-*Calculates the internal parameter value PINTI*-*-*-*-*-*-*-* 05687 //*-* ============================================= 05688 //*-* corresponding to the external value PEXTI for parameter I. 05689 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 05690 05691 /* Local variables */ 05692 /*static*/ double a, alimi, blimi, yy, yy2; 05693 /*static*/ int igo; 05694 /*static*/ std::string chbuf2, chbufi; 05695 05696 int i = i1+1; 05697 pinti = pexti; 05698 igo = fNvarl[i-1]; 05699 if (igo == 4) { 05700 //*-* -- there are two limits 05701 alimi = fAlim[i-1]; 05702 blimi = fBlim[i-1]; 05703 yy = (pexti - alimi)*2 / (blimi - alimi) - 1; 05704 yy2 = yy*yy; 05705 if (yy2 >= 1 - fEpsma2) { 05706 if (yy < 0) { 05707 a = fVlimlo; 05708 chbuf2 = " IS AT ITS LOWER ALLOWED LIMIT."; 05709 } else { 05710 a = fVlimhi; 05711 chbuf2 = " IS AT ITS UPPER ALLOWED LIMIT."; 05712 } 05713 pinti = a; 05714 pexti = alimi + (blimi - alimi)*.5*(TMath_Sin(a) + 1); 05715 fLimset = true; 05716 if (yy2 > 1) chbuf2 = " BROUGHT BACK INSIDE LIMITS."; 05717 mnwarn("W", fCfrom.c_str(), Form("VARIABLE%d%s",i,chbuf2.c_str())); 05718 } else { 05719 pinti = TMath_ASin(yy); 05720 } 05721 } 05722 } /* mnpint_ */ 05723 05724 //______________________________________________________________________________ 05725 inline 05726 void fitter::mnplot(double *xpt, double *ypt, std::string *chpt, int nxypt, int npagwd, int npagln) 05727 { 05728 //*-*-*-*Plots points in array xypt onto one page with labelled axes*-*-*-*-* 05729 //*-* =========================================================== 05730 //*-* NXYPT is the number of points to be plotted 05731 //*-* XPT(I) = x-coord. of ith point 05732 //*-* YPT(I) = y-coord. of ith point 05733 //*-* CHPT(I) = character to be plotted at this position 05734 //*-* the input point arrays XPT, YPT, CHPT are destroyed. 05735 //*-* 05736 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 05737 05738 /* Initialized data */ 05739 05740 static const std::string cdot = "."; 05741 static const std::string cslash = "/"; 05742 static const std::string cblank = " "; 05743 05744 /* Local variables */ 05745 /*static*/ double xmin, ymin, xmax, ymax, savx, savy, yprt; 05746 /*static*/ double bwidx, bwidy, xbest, ybest, ax, ay, bx, by; 05747 /*static*/ double xvalus[12], any, dxx, dyy; 05748 /*static*/ int iten, i, j, k, maxnx, maxny, iquit, ni, linodd; 05749 /*static*/ int nxbest, nybest, km1, ibk, isp1, nx, ny, ks, ix; 05750 /*static*/ std::string cline, chsav, chmess, chbest, ctemp; 05751 /*static*/ bool overpr; 05752 bwidx = 0; //GB : rm warning. 05753 bwidy = 0; //GB : rm warning. 05754 05755 /* Function Body */ 05756 //*-* Computing MIN 05757 maxnx = TMath_Min(npagwd-20,100); 05758 if (maxnx < 10) maxnx = 10; 05759 maxny = npagln; 05760 if (maxny < 10) maxny = 10; 05761 if (nxypt <= 1) return; 05762 xbest = xpt[0]; 05763 ybest = ypt[0]; 05764 chbest = chpt[0]; 05765 //*-*- order the points by decreasing y 05766 km1 = nxypt - 1; 05767 for (i = 1; i <= km1; ++i) { 05768 iquit = 0; 05769 ni = nxypt - i; 05770 for (j = 1; j <= ni; ++j) { 05771 if (ypt[j-1] > ypt[j]) continue; 05772 savx = xpt[j-1]; 05773 xpt[j-1] = xpt[j]; 05774 xpt[j] = savx; 05775 savy = ypt[j-1]; 05776 ypt[j-1] = ypt[j]; 05777 ypt[j] = savy; 05778 chsav = chpt[j-1]; 05779 chpt[j-1]= chpt[j]; 05780 chpt[j] = chsav; 05781 iquit = 1; 05782 } 05783 if (iquit == 0) break; 05784 } 05785 //*-*- find extreme values 05786 xmax = xpt[0]; 05787 xmin = xmax; 05788 for (i = 1; i <= nxypt; ++i) { 05789 if (xpt[i-1] > xmax) xmax = xpt[i-1]; 05790 if (xpt[i-1] < xmin) xmin = xpt[i-1]; 05791 } 05792 dxx = (xmax - xmin)*.001; 05793 xmax += dxx; 05794 xmin -= dxx; 05795 mnbins(xmin, xmax, maxnx, xmin, xmax, nx, bwidx); 05796 ymax = ypt[0]; 05797 ymin = ypt[nxypt-1]; 05798 if (ymax == ymin) ymax = ymin + 1; 05799 dyy = (ymax - ymin)*.001; 05800 ymax += dyy; 05801 ymin -= dyy; 05802 mnbins(ymin, ymax, maxny, ymin, ymax, ny, bwidy); 05803 any = (double) ny; 05804 //*-*- if first point is blank, it is an 'origin' 05805 if (chbest == cblank) goto L50; 05806 xbest = (xmax + xmin)*.5; 05807 ybest = (ymax + ymin)*.5; 05808 L50: 05809 //*-*- find scale constants 05810 ax = 1 / bwidx; 05811 ay = 1 / bwidy; 05812 bx = -ax*xmin + 2; 05813 by = -ay*ymin - 2; 05814 //*-*- convert points to grid positions 05815 for (i = 1; i <= nxypt; ++i) { 05816 xpt[i-1] = ax*xpt[i-1] + bx; 05817 ypt[i-1] = any - ay*ypt[i-1] - by; 05818 } 05819 nxbest = int((ax*xbest + bx)); 05820 nybest = int((any - ay*ybest - by)); 05821 //*-*- print the points 05822 ny += 2; 05823 nx += 2; 05824 isp1 = 1; 05825 linodd = 1; 05826 overpr = false; 05827 05828 for (i = 1; i <= ny; ++i) { 05829 cline.resize(nx+2); // added Z.Sz. 05830 for (ibk = 1; ibk <= nx; ++ibk) { cline[ibk-1] = ' '; } 05831 // cline[nx] = '\0'; // removed Z.Sz. 05832 cline[nx+1] = '\0'; 05833 cline[0] = '.'; 05834 cline[nx-1] = '.'; 05835 cline[nxbest-1] = '.'; 05836 if (i != 1 && i != nybest && i != ny) goto L320; 05837 for (j = 1; j <= nx; ++j) { cline[j-1] = '.'; } 05838 L320: 05839 yprt = ymax - double(i-1)*bwidy; 05840 if (isp1 > nxypt) goto L350; 05841 //*-*- find the points to be plotted on this line 05842 for (k = isp1; k <= nxypt; ++k) { 05843 ks = int(ypt[k-1]); 05844 if (ks > i) goto L345; 05845 ix = int(xpt[k-1]); 05846 if (cline[ix-1] == '.') goto L340; 05847 if (cline[ix-1] == ' ') goto L340; 05848 if (cline[ix-1] == chpt[k-1][0]) continue; 05849 overpr = true; 05850 //*-*- OVERPR is true if one or more positions contains more than 05851 //*-*- one point 05852 cline[ix-1] = '&'; 05853 continue; 05854 L340: 05855 cline[ix-1] = chpt[k-1][0]; 05856 } 05857 isp1 = nxypt + 1; 05858 goto L350; 05859 L345: 05860 isp1 = k; 05861 L350: 05862 if (linodd == 1 || i == ny) goto L380; 05863 linodd = 1; 05864 ctemp = msubstr(cline,0,nx); 05865 Printf(f_out," %s",ctemp.c_str()); 05866 goto L400; 05867 L380: 05868 ctemp = msubstr(cline,0,nx); 05869 Printf(f_out," %14.7g ..%s",yprt,ctemp.c_str()); 05870 linodd = 0; 05871 L400: 05872 ; 05873 } 05874 //*-*- print labels on x-axis every ten columns 05875 for (ibk = 1; ibk <= nx; ++ibk) { 05876 cline[ibk-1] = ' '; 05877 if (ibk % 10 == 1) cline[ibk-1] = '/'; 05878 } 05879 Printf(f_out," %s",cline.c_str()); 05880 05881 for (ibk = 1; ibk <= 12; ++ibk) { 05882 xvalus[ibk-1] = xmin + double(ibk-1)*10*bwidx; 05883 } 05884 Printf(f_out," "); 05885 iten = (nx + 9) / 10; 05886 05887 // wrong: numbers should be printed in one line !!!!!!!!!!!!!!!!!!!!!!!!! Z.Sz. 05888 for (ibk = 1; ibk <= iten; ++ibk) { 05889 Printf(f_out," %9.4g", xvalus[ibk-1]); 05890 } 05891 // until here !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 05892 05893 chmess = " "; 05894 if (overpr) chmess = " Overprint character is &"; 05895 Printf(f_out," ONE COLUMN=%13.7g%s", 05896 bwidx,chmess.c_str()); 05897 } /* mnplot_ */ 05898 05899 //______________________________________________________________________________ 05900 inline 05901 void fitter::mnpout(int iuext1, std::string& chnam, double &val, double &err, double &xlolim, double &xuplim, int &iuint) 05902 { 05903 //*-*-*-*Provides the user with information concerning the current status*-*-* 05904 //*-* ================================================================ 05905 //*-* of parameter number IUEXT. Namely, it returns: 05906 //*-* CHNAM: the name of the parameter 05907 //*-* VAL: the current (external) value of the parameter 05908 //*-* ERR: the current estimate of the parameter uncertainty 05909 //*-* XLOLIM: the lower bound (or zero if no limits) 05910 //*-* XUPLIM: the upper bound (or zero if no limits) 05911 //*-* IUINT: the internal parameter number (or zero if not variable, 05912 //*-* or negative if undefined). 05913 //*-* Note also: If IUEXT is negative, then it is -internal parameter 05914 //*-* number, and IUINT is returned as the EXTERNAL number. 05915 //*-* Except for IUINT, this is exactly the inverse of MNPARM 05916 //*-* User-called 05917 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 05918 05919 /* Local variables */ 05920 /*static*/ int iint, iext, nvl; 05921 05922 int iuext = iuext1 + 1; 05923 xlolim = 0; 05924 xuplim = 0; 05925 err = 0; 05926 if (iuext == 0) goto L100; 05927 if (iuext < 0) { 05928 //*-*- internal parameter number specified 05929 iint = -(iuext); 05930 if (iint > fNpar) goto L100; 05931 iext = fNexofi[iint-1]; 05932 iuint = iext; 05933 } else { 05934 //*-*- external parameter number specified 05935 iext = iuext; 05936 if (iext == 0) goto L100; 05937 if (iext > fNu) goto L100; 05938 iint = fNiofex[iext-1]; 05939 iuint = iint; 05940 } 05941 //*-*- in both cases 05942 nvl = fNvarl[iext-1]; 05943 if (nvl < 0) goto L100; 05944 chnam = fCpnam[iext-1]; 05945 val = fU[iext-1]; 05946 if (iint > 0) err = fWerr[iint-1]; 05947 if (nvl == 4) { 05948 xlolim = fAlim[iext-1]; 05949 xuplim = fBlim[iext-1]; 05950 } 05951 return; 05952 //*-*- parameter is undefined 05953 L100: 05954 iuint = -1; 05955 chnam = "undefined"; 05956 val = 0; 05957 } /* mnpout_ */ 05958 05959 //______________________________________________________________________________ 05960 inline 05961 void fitter::mnprin(int inkode, double fval) 05962 { 05963 //*-*-*-*Prints the values of the parameters at the time of the call*-*-*-*-* 05964 //*-* =========================================================== 05965 //*-* also prints other relevant information such as function value, 05966 //*-* estimated distance to minimum, parameter errors, step sizes. 05967 //*-* 05968 //*-* According to the value of IKODE, the printout is:/ 05969 //*-* IKODE=INKODE= 0 only info about function value 05970 //*-* 1 parameter values, errors, limits 05971 //*-* 2 values, errors, step sizes, internal values 05972 //*-* 3 values, errors, step sizes, first derivs. 05973 //*-* 4 values, parabolic errors, MINOS errors 05974 //*-* when INKODE=5, MNPRIN chooses IKODE=1,2, or 3, according to ISW(2) 05975 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 05976 05977 /* Initialized data */ 05978 05979 static const std::string cblank = " "; 05980 /*static*/ std::string cnambf = " "; 05981 05982 /* Local variables */ 05983 double dcmax, x1, x2, x3, dc; 05984 x2 = x3 = 0; 05985 /*static*/ int nadd, i, k, l, m, ikode, ic, nc, ntrail, lbl; 05986 /*static*/ std::string chedm; 05987 /*static*/ std::string colhdl[6], colhdu[6], cx2, cx3, cheval; 05988 05989 if (fNu == 0) { 05990 Printf(f_out," THERE ARE CURRENTLY NO PARAMETERS DEFINED"); 05991 return; 05992 } 05993 //*-*- get value of IKODE based in INKODE, ISW(2) 05994 ikode = inkode; 05995 if (inkode == 5) { 05996 ikode = fISW[1] + 1; 05997 if (ikode > 3) ikode = 3; 05998 } 05999 //*-*- set 'default' column headings 06000 for (k = 1; k <= 6; ++k) { 06001 colhdu[k-1] = "UNDEFINED"; 06002 colhdl[k-1] = "COLUMN HEAD"; 06003 } 06004 //*-*- print title if Minos errors, and title exists. 06005 if (ikode == 4 && fCtitl != fCundef) { 06006 Printf(f_out," MINUIT TASK: %s",fCtitl.c_str()); 06007 } 06008 //*-*- report function value and status 06009 if (fval == fUndefi) cheval = " unknown "; 06010 else cheval = Form("%g",fval); 06011 06012 if (fEDM == fBigedm) chedm = " unknown "; 06013 else chedm = Form("%g",fEDM); 06014 06015 nc = fNfcn - fNfcnfr; 06016 Printf(f_out," FCN=%s FROM %8s STATUS=%10s %6d CALLS %9d TOTAL" 06017 ,cheval.c_str() 06018 ,fCfrom.c_str() 06019 ,fCstatu.c_str(),nc,fNfcn); 06020 m = fISW[1]; 06021 if (m == 0 || m == 2 || fDcovar == 0) { 06022 Printf(f_out," EDM=%s STRATEGY=%2d %s" 06023 ,chedm.c_str(),fIstrat 06024 ,fCovmes[m].c_str()); 06025 } else { 06026 dcmax = 1; 06027 dc = TMath_Min(fDcovar,dcmax)*100; 06028 Printf(f_out," EDM=%s STRATEGY=%2d ERROR MATRIX UNCERTAINTY %5.1f per cent" 06029 ,chedm.c_str(),fIstrat,dc); 06030 } 06031 06032 if (ikode == 0) return; 06033 //*-*- find longest name (for Rene!) 06034 ntrail = 10; 06035 for (i = 1; i <= fNu; ++i) { 06036 if (fNvarl[i-1] < 0) continue; 06037 for (ic = 10; ic >= 1; --ic) { 06038 // FIXME : This substr starts outside string ! 06039 if (msubstr(fCpnam[i-1],ic-1,1) != " ") goto L16; 06040 } 06041 ic = 1; 06042 L16: 06043 lbl = 10 - ic; 06044 if (lbl < ntrail) ntrail = lbl; 06045 } 06046 nadd = ntrail / 2 + 1; 06047 if (ikode == 1) { 06048 colhdu[0] = " "; 06049 colhdl[0] = " ERROR "; 06050 colhdu[1] = " PHYSICAL"; 06051 colhdu[2] = " LIMITS "; 06052 colhdl[1] = " NEGATIVE "; 06053 colhdl[2] = " POSITIVE "; 06054 } 06055 if (ikode == 2) { 06056 colhdu[0] = " "; 06057 colhdl[0] = " ERROR "; 06058 colhdu[1] = " INTERNAL "; 06059 colhdl[1] = " STEP SIZE "; 06060 colhdu[2] = " INTERNAL "; 06061 colhdl[2] = " VALUE "; 06062 } 06063 if (ikode == 3) { 06064 colhdu[0] = " "; 06065 colhdl[0] = " ERROR "; 06066 colhdu[1] = " STEP "; 06067 colhdl[1] = " SIZE "; 06068 colhdu[2] = " FIRST "; 06069 colhdl[2] = " DERIVATIVE "; 06070 } 06071 if (ikode == 4) { 06072 colhdu[0] = " PARABOLIC "; 06073 colhdl[0] = " ERROR "; 06074 colhdu[1] = " MINOS "; 06075 colhdu[2] = "ERRORS "; 06076 colhdl[1] = " NEGATIVE "; 06077 colhdl[2] = " POSITIVE "; 06078 } 06079 06080 if (ikode != 4) { 06081 if (fISW[1] < 3) colhdu[0] = " APPROXIMATE "; 06082 if (fISW[1] < 1) colhdu[0] = " CURRENT GUESS"; 06083 } 06084 Printf(f_out," EXT PARAMETER %-14s%-14s%-14s", 06085 colhdu[0].c_str(),colhdu[1].c_str(),colhdu[2].c_str()); 06086 Printf(f_out," NO. NAME VALUE %-14s%-14s%-14s", 06087 colhdl[0].c_str(),colhdl[1].c_str(),colhdl[2].c_str()); 06088 //*-*- . . . loop over parameters . . 06089 for (i = 1; i <= fNu; ++i) { 06090 if (fNvarl[i-1] < 0) continue; 06091 l = fNiofex[i-1]; 06092 cnambf = msubstr(cblank,0,nadd); 06093 cnambf += fCpnam[i-1]; 06094 if (l == 0) goto L55; 06095 //*-*- variable parameter. 06096 x1 = fWerr[l-1]; 06097 cx2 = "PLEASE GET X.."; 06098 cx3 = "PLEASE GET X.."; 06099 if (ikode == 1) { 06100 if (fNvarl[i-1] <= 1) { 06101 Printf(f_out,"%4d %-11s%14.5e%14.5e",i,cnambf.c_str(),fU[i-1],x1); 06102 continue; 06103 } else { 06104 x2 = fAlim[i-1]; 06105 x3 = fBlim[i-1]; 06106 } 06107 } 06108 if (ikode == 2) { 06109 x2 = fDirin[l-1]; 06110 x3 = fX[l-1]; 06111 } 06112 if (ikode == 3) { 06113 x2 = fDirin[l-1]; 06114 x3 = fGrd[l-1]; 06115 if (fNvarl[i-1] > 1 && TMath_Abs(TMath_Cos(fX[l-1])) < .001) { 06116 cx3 = "** at limit **"; 06117 } 06118 } 06119 if (ikode == 4) { 06120 x2 = fErn[l-1]; 06121 if (x2 == 0) cx2 = " "; 06122 if (x2 == fUndefi) cx2 = " at limit "; 06123 x3 = fErp[l-1]; 06124 if (x3 == 0) cx3 = " "; 06125 if (x3 == fUndefi) cx3 = " at limit "; 06126 } 06127 if (cx2 == "PLEASE GET X..") cx2 = Form("%14.5e",x2); 06128 if (cx3 == "PLEASE GET X..") cx3 = Form("%14.5e",x3); 06129 Printf(f_out,"%4d %-11s%14.5e%14.5e%-14s%-14s",i 06130 ,cnambf.c_str(),fU[i-1],x1 06131 ,cx2.c_str(),cx3.c_str()); 06132 06133 //*-*- check if parameter is at limit 06134 if (fNvarl[i-1] <= 1 || ikode == 3) continue; 06135 if (TMath_Abs(TMath_Cos(fX[l-1])) < .001) { 06136 Printf(f_out," WARNING - - ABOVE PARAMETER IS AT LIMIT."); 06137 } 06138 continue; 06139 06140 //*-*- print constant or fixed parameter. 06141 L55: 06142 colhdu[0] = " constant "; 06143 if (fNvarl[i-1] > 0) colhdu[0] = " fixed "; 06144 if (fNvarl[i-1] == 4 && ikode == 1) { 06145 Printf(f_out,"%4d %-11s%14.5e%-14s%14.5e%14.5e",i 06146 ,cnambf.c_str(),fU[i-1] 06147 ,colhdu[0].c_str(),fAlim[i-1],fBlim[i-1]); 06148 } else { 06149 Printf(f_out,"%4d %-11s%14.5e%s",i 06150 ,cnambf.c_str(),fU[i-1],colhdu[0].c_str()); 06151 } 06152 } 06153 06154 if (fUp != fUpdflt) { 06155 Printf(f_out," ERR DEF= %g",fUp); 06156 } 06157 return; 06158 } /* mnprin_ */ 06159 06160 //______________________________________________________________________________ 06161 inline 06162 void fitter::mnpsdf() 06163 { 06164 //*-*-*-*-*-*Calculates the eigenvalues of v to see if positive-def*-*-*-*-* 06165 //*-* ====================================================== 06166 //*-* if not, adds constant along diagonal to make positive. 06167 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 06168 06169 /* Local variables */ 06170 /*static*/ double s[kMAXDIM], dgmin, padd, pmin, pmax, dg, epspdf, epsmin; 06171 /*static*/ int ndex, i, j, ndexd, ip, ifault; 06172 /*static*/ std::string chbuff, ctemp; 06173 06174 epsmin = 1e-6; 06175 epspdf = TMath_Max(epsmin,fEpsma2); 06176 dgmin = fVhmat[0]; 06177 //*-*- Check if negative or zero on diagonal 06178 for (i = 1; i <= fNpar; ++i) { 06179 ndex = i*(i + 1) / 2; 06180 if (fVhmat[ndex-1] <= 0) { 06181 mnwarn("W", fCfrom.c_str(), Form("Negative diagonal element %d in Error Matrix",i)); 06182 } 06183 if (fVhmat[ndex-1] < dgmin) dgmin = fVhmat[ndex-1]; 06184 } 06185 if (dgmin <= 0) { 06186 dg = epspdf + 1 - dgmin; 06187 mnwarn("W", fCfrom.c_str(), Form("%g added to diagonal of error matrix",dg)); 06188 } else { 06189 dg = 0; 06190 } 06191 //*-*- Store VHMAT in P, make sure diagonal pos. 06192 for (i = 1; i <= fNpar; ++i) { 06193 ndex = i*(i-1) / 2; 06194 ndexd = ndex + i; 06195 fVhmat[ndexd-1] += dg; 06196 s[i-1] = 1 / TMath_Sqrt(fVhmat[ndexd-1]); 06197 for (j = 1; j <= i; ++j) { 06198 ++ndex; 06199 fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[ndex-1]*s[i-1]*s[j-1]; 06200 } 06201 } 06202 //*-*- call eigen (p,p,maxint,npar,pstar,-npar) 06203 mneig(fP, fMaxint, fNpar, fMaxint, fPstar, epspdf, ifault); 06204 pmin = fPstar[0]; 06205 pmax = fPstar[0]; 06206 for (ip = 2; ip <= fNpar; ++ip) { 06207 if (fPstar[ip-1] < pmin) pmin = fPstar[ip-1]; 06208 if (fPstar[ip-1] > pmax) pmax = fPstar[ip-1]; 06209 } 06210 pmax = TMath_Max(TMath_Abs(pmax),double(1)); 06211 //GB : if (pmin <= 0 && fLwarn || fISW[4] >= 2) { 06212 if (((pmin <= 0) && fLwarn) || (fISW[4] >= 2)) { //GB : have () 06213 Printf(f_out," EIGENVALUES OF SECOND-DERIVATIVE MATRIX:"); 06214 ctemp = " "; 06215 for (ip = 1; ip <= fNpar; ++ip) { 06216 ctemp += Form(" %11.4e",fPstar[ip-1]); 06217 } 06218 Printf(f_out,ctemp.c_str()); 06219 } 06220 if (pmin > epspdf*pmax) return; 06221 if (fISW[1] == 3) fISW[1] = 2; 06222 padd = pmax*.001 - pmin; 06223 for (ip = 1; ip <= fNpar; ++ip) { 06224 ndex = ip*(ip + 1) / 2; 06225 fVhmat[ndex-1] *= padd + 1; 06226 } 06227 fCstatu = "NOT POSDEF"; 06228 mnwarn("W", fCfrom.c_str(), Form("MATRIX FORCED POS-DEF BY ADDING %f TO DIAGONAL.",padd)); 06229 06230 } /* mnpsdf_ */ 06231 06232 //______________________________________________________________________________ 06233 inline 06234 void fitter::mnrazz(double ynew, double *pnew, double *y, int &jh, int &jl) 06235 { 06236 //*-*-*-*-*Called only by MNSIMP (and MNIMPR) to add a new point*-*-*-*-*-*-* 06237 //*-* ===================================================== 06238 //*-* and remove an old one from the current simplex, and get the 06239 //*-* estimated distance to minimum. 06240 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 06241 06242 /* Local variables */ 06243 /*static*/ double pbig, plit; 06244 /*static*/ int i, j, nparp1; 06245 06246 /* Function Body */ 06247 for (i = 1; i <= fNpar; ++i) { fP[i + jh*fMaxpar - fMaxpar-1] = pnew[i-1]; } 06248 y[jh-1] = ynew; 06249 if (ynew < fAmin) { 06250 for (i = 1; i <= fNpar; ++i) { fX[i-1] = pnew[i-1]; } 06251 mninex(fX); 06252 fAmin = ynew; 06253 fCstatu = "PROGRESS "; 06254 jl = jh; 06255 } 06256 jh = 1; 06257 nparp1 = fNpar + 1; 06258 for (j = 2; j <= nparp1; ++j) { if (y[j-1] > y[jh-1]) jh = j; } 06259 fEDM = y[jh-1] - y[jl-1]; 06260 if (fEDM <= 0) goto L45; 06261 for (i = 1; i <= fNpar; ++i) { 06262 pbig = fP[i-1]; 06263 plit = pbig; 06264 for (j = 2; j <= nparp1; ++j) { 06265 if (fP[i + j*fMaxpar - fMaxpar-1] > pbig) pbig = fP[i + j*fMaxpar - fMaxpar-1]; 06266 if (fP[i + j*fMaxpar - fMaxpar-1] < plit) plit = fP[i + j*fMaxpar - fMaxpar-1]; 06267 } 06268 fDirin[i-1] = pbig - plit; 06269 } 06270 L40: 06271 return; 06272 L45: 06273 Printf(f_out," FUNCTION VALUE DOES NOT SEEM TO DEPEND ON ANY OF THE%d VARIABLE PARAMETERS.",fNpar); 06274 Printf(f_out," VERIFY THAT STEP SIZES ARE BIG ENOUGH AND CHECK FCN LOGIC."); 06275 Printf(f_out," *******************************************************************************"); 06276 Printf(f_out," *******************************************************************************"); 06277 goto L40; 06278 } /* mnrazz_ */ 06279 06280 //______________________________________________________________________________ 06281 inline 06282 void fitter::mnrn15(double &val, int &inseed) 06283 { 06284 //*-*-*-*-*-*-*This is a super-portable random number generator*-*-*-*-*-*-* 06285 //*-* ================================================ 06286 //*-* It should not overflow on any 32-bit machine. 06287 //*-* The cycle is only ~10**9, so use with care! 06288 //*-* Note especially that VAL must not be undefined on input. 06289 //*-* Set Default Starting Seed 06290 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 06291 06292 /* Initialized data */ 06293 06294 /*static*/ int iseed = 12345; 06295 06296 int k; 06297 06298 if (val == 3) goto L100; 06299 inseed = iseed; 06300 k = iseed / 53668; 06301 iseed = (iseed - k*53668)*40014 - k*12211; 06302 if (iseed < 0) iseed += 2147483563; 06303 val = double(iseed*4.656613e-10); 06304 return; 06305 //*-* "entry" to set seed, flag is VAL=3 06306 L100: 06307 iseed = inseed; 06308 } /* mnrn15_ */ 06309 06310 //______________________________________________________________________________ 06311 inline 06312 void fitter::mnrset(int iopt) 06313 { 06314 //*-*-*-*-*-*-*-*Resets function value and errors to UNDEFINED*-*-*-*-*-*-*-* 06315 //*-* ============================================= 06316 //*-* If IOPT=1, 06317 //*-* If IOPT=0, sets only MINOS errors to undefined 06318 //*-* Called from MNCLER and whenever problem changes, for example 06319 //*-* after SET LIMITS, SET PARAM, CALL FCN 6 06320 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 06321 06322 /*static*/ int iext, i; 06323 06324 fCstatu = "RESET "; 06325 if (iopt >= 1) { 06326 fAmin = fUndefi; 06327 fFval3 = TMath_Abs(fAmin)*2 + 1; 06328 fEDM = fBigedm; 06329 fISW[3] = 0; 06330 fISW[1] = 0; 06331 fDcovar = 1; 06332 fISW[0] = 0; 06333 } 06334 fLnolim = true; 06335 for (i = 1; i <= fNpar; ++i) { 06336 iext = fNexofi[i-1]; 06337 if (fNvarl[iext-1] >= 4) fLnolim = false; 06338 fErp[i-1] = 0; 06339 fErn[i-1] = 0; 06340 fGlobcc[i-1] = 0; 06341 } 06342 if (fISW[1] >= 1) { 06343 fISW[1] = 1; 06344 fDcovar = TMath_Max(fDcovar,.5); 06345 } 06346 } /* mnrset_ */ 06347 06348 //______________________________________________________________________________ 06349 inline 06350 void fitter::mnsave() 06351 { 06352 //*-*-*-*Writes current parameter values and step sizes onto file ISYSSA*-*-* 06353 //*-* =============================================================== 06354 //*-* in format which can be reread by Minuit for restarting. 06355 //*-* The covariance matrix is also output if it exists. 06356 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 06357 06358 Printf(f_out,"mnsave is dummy in the base class Minuit: Use MinuitOld"); 06359 06360 } /* mnsave_ */ 06361 06362 //______________________________________________________________________________ 06363 inline 06364 void fitter::mnscan() 06365 { 06366 //*-*-*-*-*Scans the values of FCN as a function of one parameter*-*-*-*-*-* 06367 //*-* ====================================================== 06368 //*-* and plots the resulting values as a curve using MNPLOT. 06369 //*-* It may be called to scan one parameter or all parameters. 06370 //*-* retains the best function and parameter values found. 06371 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 06372 06373 /* Local variables */ 06374 /*static*/ double step, uhigh, xhreq, xlreq, ubest, fnext, unext, xh, xl; 06375 /*static*/ int ipar, iint, icall, ncall, nbins, nparx; 06376 /*static*/ int nxypt, nccall, iparwd; 06377 step = 0; //GB 06378 06379 xlreq = TMath_Min(fWord7[2],fWord7[3]); 06380 xhreq = TMath_Max(fWord7[2],fWord7[3]); 06381 ncall = int((fWord7[1] + .01)); 06382 if (ncall <= 1) ncall = 41; 06383 if (ncall > 101) ncall = 101; 06384 nccall = ncall; 06385 if (fAmin == fUndefi) mnamin(); 06386 iparwd = int((fWord7[0] + .1)); 06387 ipar = TMath_Max(iparwd,0); 06388 iint = fNiofex[ipar-1]; 06389 fCstatu = "NO CHANGE"; 06390 if (iparwd > 0) goto L200; 06391 06392 //*-*- equivalent to a loop over parameters requested 06393 L100: 06394 ++ipar; 06395 if (ipar > fNu) goto L900; 06396 iint = fNiofex[ipar-1]; 06397 if (iint <= 0) goto L100; 06398 //*-*- set up range for parameter IPAR 06399 L200: 06400 ubest = fU[ipar-1]; 06401 fXpt[0] = ubest; 06402 fYpt[0] = fAmin; 06403 fChpt[0] = " "; 06404 fXpt[1] = ubest; 06405 fYpt[1] = fAmin; 06406 fChpt[1] = "X"; 06407 nxypt = 2; 06408 if (fNvarl[ipar-1] > 1) goto L300; 06409 06410 //*-*- no limits on parameter 06411 if (xlreq == xhreq) goto L250; 06412 unext = xlreq; 06413 step = (xhreq - xlreq) / double(ncall-1); 06414 goto L500; 06415 L250: 06416 xl = ubest - fWerr[iint-1]; 06417 xh = ubest + fWerr[iint-1]; 06418 mnbins(xl, xh, ncall, unext, uhigh, nbins, step); 06419 nccall = nbins + 1; 06420 goto L500; 06421 //*-*- limits on parameter 06422 L300: 06423 if (xlreq == xhreq) goto L350; 06424 //*-* Computing MAX 06425 xl = TMath_Max(xlreq,fAlim[ipar-1]); 06426 //*-* Computing MIN 06427 xh = TMath_Min(xhreq,fBlim[ipar-1]); 06428 if (xl >= xh) goto L700; 06429 unext = xl; 06430 step = (xh - xl) / double(ncall-1); 06431 goto L500; 06432 L350: 06433 unext = fAlim[ipar-1]; 06434 step = (fBlim[ipar-1] - fAlim[ipar-1]) / double(ncall-1); 06435 //*-*- main scanning loop over parameter IPAR 06436 L500: 06437 for (icall = 1; icall <= nccall; ++icall) { 06438 fU[ipar-1] = unext; 06439 nparx = fNpar; 06440 //Printf(f_out,"debug : FCN : 023"); 06441 (*fFCN)(nparx, fGin, fnext, fU, 4,fTag); ++fNfcn; 06442 ++nxypt; 06443 fXpt[nxypt-1] = unext; 06444 fYpt[nxypt-1] = fnext; 06445 fChpt[nxypt-1] = "*"; 06446 if (fnext < fAmin) { 06447 fAmin = fnext; 06448 ubest = unext; 06449 fCstatu = "IMPROVED "; 06450 } 06451 unext += step; 06452 } 06453 //*-*- finished with scan of parameter IPAR 06454 fU[ipar-1] = ubest; 06455 mnexin(fX); 06456 Printf(f_out,"%dSCAN OF PARAMETER NO. %d, %s" 06457 ,fNewpag,ipar,fCpnam[ipar-1].c_str()); 06458 mnplot(fXpt, fYpt, fChpt, nxypt, fNpagwd, fNpagln); 06459 goto L800; 06460 L700: 06461 Printf(f_out," REQUESTED RANGE OUTSIDE LIMITS FOR PARAMETER %d",ipar); 06462 L800: 06463 if (iparwd <= 0) goto L100; 06464 //*-*- finished with all parameters 06465 L900: 06466 mnprin(5, fAmin); 06467 } /* mnscan_ */ 06468 06469 //______________________________________________________________________________ 06470 inline 06471 void fitter::mnseek() 06472 { 06473 //*-*-*-*Performs a rough (but global) minimization by monte carlo search*-* 06474 //*-* ================================================================ 06475 //*-* Each time a new minimum is found, the search area is shifted 06476 //*-* to be centered at the best value. Random points are chosen 06477 //*-* uniformly over a hypercube determined by current step sizes. 06478 //*-* The Metropolis algorithm accepts a worse point with probability 06479 //*-* exp(-d/UP), where d is the degradation. Improved points 06480 //*-* are of course always accepted. Actual steps are random 06481 //*-* multiples of the nominal steps (DIRIN). 06482 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 06483 06484 /* Local variables */ 06485 /*static*/ double xmid[kMAXDIM], dxdi, rnum, ftry, rnum1, rnum2, alpha; 06486 /*static*/ double flast, xbest[kMAXDIM], bar; 06487 /*static*/ int ipar, iext, j, ifail, iseed, nparx, istep, ib, mxfail, mxstep; 06488 06489 mxfail = int(fWord7[0]); 06490 if (mxfail <= 0) mxfail = fNpar*20 + 100; 06491 mxstep = mxfail*10; 06492 if (fAmin == fUndefi) mnamin(); 06493 alpha = fWord7[1]; 06494 if (alpha <= 0) alpha = 3; 06495 if (fISW[4] >= 1) { 06496 Printf(f_out," MNSEEK: MONTE CARLO MINIMIZATION USING METROPOLIS ALGORITHM"); 06497 Printf(f_out," TO STOP AFTER %6d SUCCESSIVE FAILURES, OR %7d STEPS",mxfail,mxstep); 06498 Printf(f_out," MAXIMUM STEP SIZE IS %9.3f ERROR BARS.",alpha); 06499 } 06500 fCstatu = "INITIAL "; 06501 if (fISW[4] >= 2) mnprin(2, fAmin); 06502 fCstatu = "UNCHANGED "; 06503 ifail = 0; 06504 rnum = 0; 06505 rnum1 = 0; 06506 rnum2 = 0; 06507 nparx = fNpar; 06508 flast = fAmin; 06509 //*-*- set up step sizes, starting values 06510 for (ipar = 1; ipar <= fNpar; ++ipar) { 06511 iext = fNexofi[ipar-1]; 06512 fDirin[ipar-1] = alpha*2*fWerr[ipar-1]; 06513 if (fNvarl[iext-1] > 1) { 06514 //*-*- parameter with limits 06515 mndxdi(fX[ipar-1], ipar-1, dxdi); 06516 if (dxdi == 0) dxdi = 1; 06517 fDirin[ipar-1] = alpha*2*fWerr[ipar-1] / dxdi; 06518 if (TMath_Abs(fDirin[ipar-1]) > 6.2831859999999997) { 06519 fDirin[ipar-1] = 6.2831859999999997; 06520 } 06521 } 06522 xmid[ipar-1] = fX[ipar-1]; 06523 xbest[ipar-1] = fX[ipar-1]; 06524 } 06525 //*-*- search loop 06526 for (istep = 1; istep <= mxstep; ++istep) { 06527 if (ifail >= mxfail) break; 06528 for (ipar = 1; ipar <= fNpar; ++ipar) { 06529 mnrn15(rnum1, iseed); 06530 mnrn15(rnum2, iseed); 06531 fX[ipar-1] = xmid[ipar-1] + (rnum1 + rnum2 - 1)*.5*fDirin[ipar-1]; 06532 } 06533 mninex(fX); 06534 //Printf(f_out,"debug : FCN : 024"); 06535 (*fFCN)(nparx, fGin, ftry, fU, 4,fTag); ++fNfcn; 06536 if (ftry < flast) { 06537 if (ftry < fAmin) { 06538 fCstatu = "IMPROVEMNT"; 06539 fAmin = ftry; 06540 for (ib = 1; ib <= fNpar; ++ib) { xbest[ib-1] = fX[ib-1]; } 06541 ifail = 0; 06542 if (fISW[4] >= 2) mnprin(2, fAmin); 06543 } 06544 goto L300; 06545 } else { 06546 ++ifail; 06547 //*-*- Metropolis algorithm 06548 bar = (fAmin - ftry) / fUp; 06549 mnrn15(rnum, iseed); 06550 if (bar < TMath_Log(rnum)) continue; 06551 } 06552 //*-*- Accept new point, move there 06553 L300: 06554 for (j = 1; j <= fNpar; ++j) { xmid[j-1] = fX[j-1]; } 06555 flast = ftry; 06556 } 06557 //*-*- end search loop 06558 if (fISW[4] > 1) { 06559 Printf(f_out," MNSEEK: %5d SUCCESSIVE UNSUCCESSFUL TRIALS.",ifail); 06560 } 06561 for (ib = 1; ib <= fNpar; ++ib) { fX[ib-1] = xbest[ib-1]; } 06562 mninex(fX); 06563 if (fISW[4] >= 1) mnprin(2, fAmin); 06564 if (fISW[4] == 0) mnprin(0, fAmin); 06565 } /* mnseek_ */ 06566 06567 //______________________________________________________________________________ 06568 inline 06569 void fitter::mnset() 06570 { 06571 //*-*-*-*-*Interprets the commands that start with SET and SHOW*-*-*-*-*-*-* 06572 //*-* ==================================================== 06573 //*-* Called from MNEXCM 06574 //*-* file characteristics for SET INPUT 06575 //*-* 'SET ' or 'SHOW', 'ON ' or 'OFF', 'SUPPRESSED' or 'REPORTED ' 06576 //*-* explanation of print level numbers -1:3 and strategies 0:2 06577 //*-* identification of debug options 06578 //*-* things that can be set or shown 06579 //*-* options not intended for normal users 06580 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 06581 06582 /* Initialized data */ 06583 06584 static const std::string cname[30] = { 06585 "FCN value ", 06586 "PARameters", 06587 "LIMits ", 06588 "COVariance", 06589 "CORrelatio", 06590 "PRInt levl", 06591 "NOGradient", 06592 "GRAdient ", 06593 "ERRor def ", 06594 "INPut file", 06595 "WIDth page", 06596 "LINes page", 06597 "NOWarnings", 06598 "WARnings ", 06599 "RANdom gen", 06600 "TITle ", 06601 "STRategy ", 06602 "EIGenvalue", 06603 "PAGe throw", 06604 "MINos errs", 06605 "EPSmachine", 06606 "OUTputfile", 06607 "BATch ", 06608 "INTeractiv", 06609 "VERsion ", 06610 "reserve ", 06611 "NODebug ", 06612 "DEBug ", 06613 "SHOw ", 06614 "SET "}; 06615 06616 /*static*/ int nname = 25; 06617 /*static*/ int nntot = 30; 06618 static const std::string cprlev[5] = { 06619 "-1: NO OUTPUT EXCEPT FROM SHOW ", 06620 " 0: REDUCED OUTPUT ", 06621 " 1: NORMAL OUTPUT ", 06622 " 2: EXTRA OUTPUT FOR PROBLEM CASES", 06623 " 3: MAXIMUM OUTPUT "}; 06624 06625 static const std::string cstrat[3] = { 06626 " 0: MINIMIZE THE NUMBER OF CALLS TO FUNCTION", 06627 " 1: TRY TO BALANCE SPEED AGAINST RELIABILITY", 06628 " 2: MAKE SURE MINIMUM TRUE, ERRORS CORRECT "}; 06629 06630 static const std::string cdbopt[7] = { 06631 "REPORT ALL EXCEPTIONAL CONDITIONS ", 06632 "MNLINE: LINE SEARCH MINIMIZATION ", 06633 "MNDERI: FIRST DERIVATIVE CALCULATIONS ", 06634 "MNHESS: SECOND DERIVATIVE CALCULATIONS ", 06635 "MNMIGR: COVARIANCE MATRIX UPDATES ", 06636 "MNHES1: FIRST DERIVATIVE UNCERTAINTIES ", 06637 "MNCONT: MNCONTOUR PLOT (MNCROS SEARCH) "}; 06638 06639 /* System generated locals */ 06640 int f_inqu(); 06641 06642 /* Local variables */ 06643 /*static*/ double val; 06644 /*static*/ int iset, iprm, i, jseed, kname, iseed, iunit, idx, ii, kk; 06645 /*static*/ int ikseed, idbopt, igrain, iswsav, isw2; 06646 /*static*/ std::string cfname, cmode, ckind, cwarn, copt, ctemp, ctemp2; 06647 //G.Barrand /*static*/ bool lname; 06648 igrain = 0; //GB : rm warning. 06649 06650 for (i = 1; i <= nntot; ++i) { 06651 ctemp = msubstr(cname[i-1],0,3); 06652 ctemp2 = msubstr(fCword,3,7); 06653 if (strstr(ctemp2.c_str(), ctemp.c_str())) goto L5; 06654 } 06655 i = 0; 06656 L5: 06657 kname = i; 06658 06659 //*-*- Command could be SET xxx, SHOW xxx, HELP SET or HELP SHOW 06660 if (msubstr(fCword,0,3) == "HEL") goto L2000; 06661 if (msubstr(fCword,0,3) == "SHO") goto L1000; 06662 if (msubstr(fCword,0,3) != "SET") goto L1900; 06663 //*-*- --- 06664 ckind = "SET "; 06665 //*-*- . . . . . . . . . . set unknown 06666 if (kname <= 0) goto L1900; 06667 //*-*- . . . . . . . . . . set known 06668 switch ((int)kname) { 06669 case 1: goto L3000; 06670 case 2: goto L20; 06671 case 3: goto L30; 06672 case 4: goto L40; 06673 case 5: goto L3000; 06674 case 6: goto L60; 06675 case 7: goto L70; 06676 case 8: goto L80; 06677 case 9: goto L90; 06678 case 10: goto L100; 06679 case 11: goto L110; 06680 case 12: goto L120; 06681 case 13: goto L130; 06682 case 14: goto L140; 06683 case 15: goto L150; 06684 case 16: goto L160; 06685 case 17: goto L170; 06686 case 18: goto L3000; 06687 case 19: goto L190; 06688 case 20: goto L3000; 06689 case 21: goto L210; 06690 case 22: goto L220; 06691 case 23: goto L230; 06692 case 24: goto L240; 06693 case 25: goto L3000; 06694 case 26: goto L1900; 06695 case 27: goto L270; 06696 case 28: goto L280; 06697 case 29: goto L290; 06698 case 30: goto L300; 06699 } 06700 06701 //*-*- . . . . . . . . . . set param 06702 L20: 06703 iprm = int(fWord7[0]); 06704 if (iprm > fNu) goto L25; 06705 if (iprm <= 0) goto L25; 06706 if (fNvarl[iprm-1] < 0) goto L25; 06707 fU[iprm-1] = fWord7[1]; 06708 mnexin(fX); 06709 isw2 = fISW[1]; 06710 mnrset(1); 06711 //*-*- Keep approximate covariance matrix, even if new param value 06712 fISW[1] = TMath_Min(isw2,1); 06713 fCfrom = "SET PARM"; 06714 fNfcnfr = fNfcn; 06715 fCstatu = "NEW VALUES"; 06716 return; 06717 L25: 06718 Printf(f_out," UNDEFINED PARAMETER NUMBER. IGNORED."); 06719 return; 06720 //*-*- . . . . . . . . . . set limits 06721 L30: 06722 mnlims(); 06723 return; 06724 //*-*- . . . . . . . . . . set covar 06725 L40: 06726 //*-* this command must be handled by MNREAD, and is not Fortran-callable 06727 goto L3000; 06728 //*-*- . . . . . . . . . . set print 06729 L60: 06730 fISW[4] = int(fWord7[0]); 06731 return; 06732 //*-*- . . . . . . . . . . set nograd 06733 L70: 06734 fISW[2] = 0; 06735 return; 06736 //*-*- . . . . . . . . . . set grad 06737 L80: 06738 mngrad(); 06739 return; 06740 //*-*- . . . . . . . . . . set errdef 06741 L90: 06742 if (fWord7[0] == fUp) return; 06743 if (fWord7[0] <= 0) { 06744 if (fUp == fUpdflt) return; 06745 fUp = fUpdflt; 06746 } else { 06747 fUp = fWord7[0]; 06748 } 06749 for (i = 1; i <= fNpar; ++i) { 06750 fErn[i-1] = 0; 06751 fErp[i-1] = 0; 06752 } 06753 mnwerr(); 06754 return; 06755 //*-*- . . . . . . . . . . set input 06756 //*-* This command must be handled by MNREAD. If it gets this far, 06757 //*-*- it is illegal. 06758 L100: 06759 goto L3000; 06760 //*-*- . . . . . . . . . . set width 06761 L110: 06762 fNpagwd = int(fWord7[0]); 06763 fNpagwd = TMath_Max(fNpagwd,50); 06764 return; 06765 06766 L120: 06767 fNpagln = int(fWord7[0]); 06768 return; 06769 //*-*- . . . . . . . . . . set nowarn 06770 06771 L130: 06772 fLwarn = false; 06773 return; 06774 //*-*- . . . . . . . . . . set warn 06775 L140: 06776 fLwarn = true; 06777 mnwarn("W", "SHO", "SHO"); 06778 return; 06779 //*-*- . . . . . . . . . . set random 06780 L150: 06781 jseed = int(fWord7[0]); 06782 val = 3; 06783 mnrn15(val, jseed); 06784 if (fISW[4] > 0) { 06785 Printf(f_out," MINUIT RANDOM NUMBER SEED SET TO %d",jseed); 06786 } 06787 return; 06788 //*-*- . . . . . . . . . . set title 06789 L160: 06790 //*-* this command must be handled by MNREAD, and is not Fortran-callable 06791 goto L3000; 06792 //*-*- . . . . . . . . . set strategy 06793 L170: 06794 fIstrat = int(fWord7[0]); 06795 fIstrat = TMath_Max(fIstrat,0); 06796 fIstrat = TMath_Min(fIstrat,2); 06797 if (fISW[4] > 0) goto L1172; 06798 return; 06799 //*-*- . . . . . . . . . set page throw 06800 L190: 06801 fNewpag = int(fWord7[0]); 06802 goto L1190; 06803 //*-*- . . . . . . . . . . set epsmac 06804 L210: 06805 if (fWord7[0] > 0 && fWord7[0] < .1) { 06806 fEpsmac = fWord7[0]; 06807 } 06808 fEpsma2 = TMath_Sqrt(fEpsmac); 06809 goto L1210; 06810 //*-*- . . . . . . . . . . set outputfile 06811 L220: 06812 iunit = int(fWord7[0]); 06813 fIsyswr = iunit; 06814 fIstkwr[0] = iunit; 06815 if (fISW[4] >= 0) goto L1220; 06816 return; 06817 //*-*- . . . . . . . . . . set batch 06818 L230: 06819 fISW[5] = 0; 06820 if (fISW[4] >= 0) goto L1100; 06821 return; 06822 //*-*- . . . . . . . . . . set interactive 06823 L240: 06824 fISW[5] = 1; 06825 if (fISW[4] >= 0) goto L1100; 06826 return; 06827 //*-*- . . . . . . . . . . set nodebug 06828 L270: 06829 iset = 0; 06830 goto L281; 06831 //*-*- . . . . . . . . . . set debug 06832 L280: 06833 iset = 1; 06834 L281: 06835 idbopt = int(fWord7[0]); 06836 if (idbopt > 6) goto L288; 06837 if (idbopt >= 0) { 06838 fIdbg[idbopt] = iset; 06839 if (iset == 1) fIdbg[0] = 1; 06840 } else { 06841 //*-*- SET DEBUG -1 sets all debug options 06842 /*G.Barrand : have idx*/ 06843 for (idx = 0; idx <= 6; ++idx) { fIdbg[idx] = iset; } 06844 } 06845 fLrepor = fIdbg[0] >= 1; 06846 mnwarn("D", "SHO", "SHO"); 06847 return; 06848 L288: 06849 Printf(f_out," UNKNOWN DEBUG OPTION %d REQUESTED. IGNORED",idbopt); 06850 return; 06851 //*-*- . . . . . . . . . . set show 06852 L290: 06853 //*-*- . . . . . . . . . . set set 06854 L300: 06855 goto L3000; 06856 //*-*- ----------------------------------------------------- 06857 L1000: 06858 //*-*- at this point, CWORD must be 'SHOW' 06859 ckind = "SHOW"; 06860 if (kname <= 0) goto L1900; 06861 06862 switch ((int)kname) { 06863 case 1: goto L1010; 06864 case 2: goto L1020; 06865 case 3: goto L1030; 06866 case 4: goto L1040; 06867 case 5: goto L1050; 06868 case 6: goto L1060; 06869 case 7: goto L1070; 06870 case 8: goto L1070; 06871 case 9: goto L1090; 06872 case 10: goto L1100; 06873 case 11: goto L1110; 06874 case 12: goto L1120; 06875 case 13: goto L1130; 06876 case 14: goto L1130; 06877 case 15: goto L1150; 06878 case 16: goto L1160; 06879 case 17: goto L1170; 06880 case 18: goto L1180; 06881 case 19: goto L1190; 06882 case 20: goto L1200; 06883 case 21: goto L1210; 06884 case 22: goto L1220; 06885 case 23: goto L1100; 06886 case 24: goto L1100; 06887 case 25: goto L1250; 06888 case 26: goto L1900; 06889 case 27: goto L1270; 06890 case 28: goto L1270; 06891 case 29: goto L1290; 06892 case 30: goto L1300; 06893 } 06894 06895 //*-*- . . . . . . . . . . show fcn 06896 L1010: 06897 if (fAmin == fUndefi) mnamin(); 06898 mnprin(0, fAmin); 06899 return; 06900 //*-*- . . . . . . . . . . show param 06901 L1020: 06902 if (fAmin == fUndefi) mnamin(); 06903 mnprin(5, fAmin); 06904 return; 06905 //*-*- . . . . . . . . . . show limits 06906 L1030: 06907 if (fAmin == fUndefi) mnamin(); 06908 mnprin(1, fAmin); 06909 return; 06910 //*-*- . . . . . . . . . . show covar 06911 L1040: 06912 mnmatu(1); 06913 return; 06914 //*-*- . . . . . . . . . . show corre 06915 L1050: 06916 mnmatu(0); 06917 return; 06918 //*-*- . . . . . . . . . . show print 06919 L1060: 06920 if (fISW[4] < -1) fISW[4] = -1; 06921 if (fISW[4] > 3) fISW[4] = 3; 06922 Printf(f_out," ALLOWED PRINT LEVELS ARE:"); 06923 Printf(f_out," %s",cprlev[0].c_str()); 06924 Printf(f_out," %s",cprlev[1].c_str()); 06925 Printf(f_out," %s",cprlev[2].c_str()); 06926 Printf(f_out," %s",cprlev[3].c_str()); 06927 Printf(f_out," %s",cprlev[4].c_str()); 06928 Printf(f_out," CURRENT PRINTOUT LEVEL IS %s",cprlev[fISW[4]].c_str()); 06929 return; 06930 //*-*- . . . . . . . show nograd, grad 06931 L1070: 06932 if (fISW[2] <= 0) { 06933 Printf(f_out," NOGRAD IS SET. DERIVATIVES NOT COMPUTED IN FCN."); 06934 } else { 06935 Printf(f_out," GRAD IS SET. USER COMPUTES DERIVATIVES IN FCN."); 06936 } 06937 return; 06938 //*-*- . . . . . . . . . . show errdef 06939 L1090: 06940 Printf(f_out," ERRORS CORRESPOND TO FUNCTION CHANGE OF %g",fUp); 06941 return; 06942 //*-*- . . . . . . . . . . show input, 06943 //*-*- batch, or interactive 06944 L1100: 06945 // ioin__1.inerr = 0; 06946 // ioin__1.inunit = fIsysrd; 06947 // ioin__1.infile = 0; 06948 // ioin__1.inex = 0; 06949 // ioin__1.inopen = 0; 06950 // ioin__1.innum = 0; 06951 // ioin__1.innamed = &lname; 06952 // ioin__1.innamlen = 64; 06953 // ioin__1.inname = cfname; 06954 // ioin__1.inacc = 0; 06955 // ioin__1.inseq = 0; 06956 // ioin__1.indir = 0; 06957 // ioin__1.infmt = 0; 06958 // ioin__1.inform = 0; 06959 // ioin__1.inunf = 0; 06960 // ioin__1.inrecl = 0; 06961 // ioin__1.innrec = 0; 06962 // ioin__1.inblank = 0; 06963 // f_inqu(&ioin__1); 06964 cmode = "BATCH MODE "; 06965 if (fISW[5] == 1) cmode = "INTERACTIVE MODE"; 06966 /*G.Barrand if (! lname)*/ cfname = "unknown"; 06967 Printf(f_out," INPUT NOW BEING READ IN %s FROM UNIT NO. %d FILENAME: %s" 06968 ,cmode.c_str(),fIsysrd,cfname.c_str()); 06969 return; 06970 //*-*- . . . . . . . . . . show width 06971 L1110: 06972 Printf(f_out," PAGE WIDTH IS SET TO %d COLUMNS",fNpagwd); 06973 return; 06974 //*-*- . . . . . . . . . . show lines 06975 L1120: 06976 Printf(f_out," PAGE LENGTH IS SET TO %d LINES",fNpagln); 06977 return; 06978 //*-*- . . . . . . .show nowarn, warn 06979 L1130: 06980 cwarn = "SUPPRESSED"; 06981 if (fLwarn) cwarn = "REPORTED "; 06982 Printf(f_out,"%s",cwarn.c_str()); 06983 if (! fLwarn) mnwarn("W", "SHO", "SHO"); 06984 return; 06985 //*-*- . . . . . . . . . . show random 06986 L1150: 06987 val = 0; 06988 mnrn15(val, igrain); 06989 ikseed = igrain; 06990 Printf(f_out," MINUIT RNDM SEED IS CURRENTLY=",ikseed); 06991 val = 3; 06992 iseed = ikseed; 06993 mnrn15(val, iseed); 06994 return; 06995 //*-*- . . . . . . . . . show title 06996 L1160: 06997 Printf(f_out," TITLE OF CURRENT TASK IS:%s",fCtitl.c_str()); 06998 return; 06999 //*-*- . . . . . . . show strategy 07000 L1170: 07001 Printf(f_out," ALLOWED STRATEGIES ARE:"); 07002 Printf(f_out," %s",cstrat[0].c_str()); 07003 Printf(f_out," %s",cstrat[1].c_str()); 07004 Printf(f_out," %s",cstrat[2].c_str()); 07005 L1172: 07006 Printf(f_out," NOW USING STRATEGY %s",cstrat[fIstrat].c_str()); 07007 return; 07008 //*-*- . . . . . show eigenvalues 07009 L1180: 07010 iswsav = fISW[4]; 07011 fISW[4] = 3; 07012 if (fISW[1] < 1) { 07013 Printf(f_out,"%s",fCovmes[0].c_str()); 07014 } else { 07015 mnpsdf(); 07016 } 07017 fISW[4] = iswsav; 07018 return; 07019 //*-*- . . . . . show page throw 07020 L1190: 07021 Printf(f_out," PAGE THROW CARRIAGE CONTROL = %d",fNewpag); 07022 if (fNewpag == 0) { 07023 Printf(f_out," NO PAGE THROWS IN MINUIT OUTPUT"); 07024 } 07025 return; 07026 //*-*- . . . . . . show minos errors 07027 L1200: 07028 for (ii = 1; ii <= fNpar; ++ii) { 07029 if (fErp[ii-1] > 0 || fErn[ii-1] < 0) goto L1204; 07030 } 07031 Printf(f_out," THERE ARE NO MINOS ERRORS CURRENTLY VALID."); 07032 return; 07033 L1204: 07034 mnprin(4, fAmin); 07035 return; 07036 //*-*- . . . . . . . . . show epsmac 07037 L1210: 07038 Printf(f_out," FLOATING-POINT NUMBERS ASSUMED ACCURATE TO %g",fEpsmac); 07039 return; 07040 //*-*- . . . . . . show outputfiles 07041 L1220: 07042 Printf(f_out," MINUIT PRIMARY OUTPUT TO UNIT %d",fIsyswr); 07043 return; 07044 //*-*- . . . . . . show version 07045 L1250: 07046 Printf(f_out," THIS IS MINUIT VERSION:%s",fCvrsn.c_str()); 07047 return; 07048 //*-*- . . . . . . show nodebug, debug 07049 L1270: 07050 /*G.Barrand : have idx.*/ 07051 for (idx = 0; idx <= 6; ++idx) { 07052 copt = "OFF"; 07053 if (fIdbg[idx] >= 1) copt = "ON "; 07054 Printf(f_out," DEBUG OPTION %3d IS %3s :%s" 07055 ,idx,copt.c_str(),cdbopt[idx].c_str()); 07056 } 07057 if (! fLrepor) mnwarn("D", "SHO", "SHO"); 07058 return; 07059 //*-*- . . . . . . . . . . show show 07060 L1290: 07061 ckind = "SHOW"; 07062 goto L2100; 07063 //*-*- . . . . . . . . . . show set 07064 L1300: 07065 ckind = "SET "; 07066 goto L2100; 07067 //*-*- ----------------------------------------------------- 07068 //*-*- UNKNOWN COMMAND 07069 L1900: 07070 Printf(f_out," THE COMMAND:%10s IS UNKNOWN.",fCword.c_str()); 07071 goto L2100; 07072 //*-*- ----------------------------------------------------- 07073 //*-*- HELP SHOW, HELP SET, SHOW SET, or SHOW SHOW 07074 L2000: 07075 ckind = "SET "; 07076 ctemp = msubstr(fCword,3,7); 07077 if (ctemp=="SHO") ckind = "SHOW"; 07078 L2100: 07079 Printf(f_out," THE FORMAT OF THE %4s COMMAND IS:",ckind.c_str()); 07080 Printf(f_out," %s xxx [numerical arguments if any]",ckind.c_str()); 07081 Printf(f_out," WHERE xxx MAY BE ONE OF THE FOLLOWING:"); 07082 for (kk = 1; kk <= nname; ++kk) { 07083 Printf(f_out," %s",cname[kk-1].c_str()); 07084 } 07085 return; 07086 //*-*- ----------------------------------------------------- 07087 //*-*- ILLEGAL COMMAND 07088 L3000: 07089 Printf(f_out," ABOVE COMMAND IS ILLEGAL. IGNORED"); 07090 07091 } /* mnset_ */ 07092 07093 //______________________________________________________________________________ 07094 inline 07095 void fitter::mnsimp() 07096 { 07097 //*-*-*-*-*Minimization using the simplex method of Nelder and Mead*-*-*-*-* 07098 //*-* ======================================================== 07099 //*-* Performs a minimization using the simplex method of Nelder 07100 //*-* and Mead (ref. -- Comp. J. 7,308 (1965)). 07101 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 07102 07103 /* Initialized data */ 07104 07105 /*static*/ double alpha = 1; 07106 /*static*/ double beta = .5; 07107 /*static*/ double gamma = 2; 07108 /*static*/ double rhomin = 4; 07109 /*static*/ double rhomax = 8; 07110 07111 /* Local variables */ 07112 /*static*/ double dmin_, dxdi, yrho, f, ynpp1, y[kMAXDIM+1], aming, ypbar; 07113 /*static*/ double bestx, ystar, y1, y2, ystst, pb, wg; 07114 /*static*/ double absmin, rho, sig2, rho1, rho2; 07115 /*static*/ int npfn, i, j, k, jhold, ncycl, nparx; 07116 /*static*/ int nparp1, kg, jh, nf, jl, ns; 07117 07118 if (fNpar <= 0) return; 07119 if (fAmin == fUndefi) mnamin(); 07120 fCfrom = "SIMPLEX "; 07121 fNfcnfr = fNfcn; 07122 fCstatu = "UNCHANGED "; 07123 npfn = fNfcn; 07124 nparp1 = fNpar + 1; 07125 nparx = fNpar; 07126 rho1 = alpha + 1; 07127 rho2 = rho1 + alpha*gamma; 07128 wg = 1 / double(fNpar); 07129 if (fISW[4] >= 0) { 07130 Printf(f_out," START SIMPLEX MINIMIZATION. CONVERGENCE WHEN EDM .LT. %g",fEpsi); 07131 } 07132 for (i = 1; i <= fNpar; ++i) { 07133 fDirin[i-1] = fWerr[i-1]; 07134 mndxdi(fX[i-1], i-1, dxdi); 07135 if (dxdi != 0) fDirin[i-1] = fWerr[i-1] / dxdi; 07136 dmin_ = fEpsma2*TMath_Abs(fX[i-1]); 07137 if (fDirin[i-1] < dmin_) fDirin[i-1] = dmin_; 07138 } 07139 //*-* ** choose the initial simplex using single-parameter searches 07140 L1: 07141 ynpp1 = fAmin; 07142 jl = nparp1; 07143 y[nparp1-1] = fAmin; 07144 absmin = fAmin; 07145 for (i = 1; i <= fNpar; ++i) { 07146 aming = fAmin; 07147 fPbar[i-1] = fX[i-1]; 07148 bestx = fX[i-1]; 07149 kg = 0; 07150 ns = 0; 07151 nf = 0; 07152 L4: 07153 fX[i-1] = bestx + fDirin[i-1]; 07154 mninex(fX); 07155 //Printf(f_out,"debug : FCN : 025"); 07156 (*fFCN)(nparx, fGin, f, fU, 4,fTag); ++fNfcn; 07157 if (f <= aming) goto L6; 07158 //*-*- failure 07159 if (kg == 1) goto L8; 07160 kg = -1; 07161 ++nf; 07162 fDirin[i-1] *= -.4; 07163 if (nf < 3) goto L4; 07164 ns = 6; 07165 //*-*- success 07166 L6: 07167 bestx = fX[i-1]; 07168 fDirin[i-1] *= 3; 07169 aming = f; 07170 fCstatu = "PROGRESS "; 07171 kg = 1; 07172 ++ns; 07173 if (ns < 6) goto L4; 07174 //*-*- local minimum found in ith direction 07175 L8: 07176 y[i-1] = aming; 07177 if (aming < absmin) jl = i; 07178 if (aming < absmin) absmin = aming; 07179 fX[i-1] = bestx; 07180 for (k = 1; k <= fNpar; ++k) { fP[k + i*fMaxpar - fMaxpar-1] = fX[k-1]; } 07181 } 07182 jh = nparp1; 07183 fAmin = y[jl-1]; 07184 mnrazz(ynpp1, fPbar, y, jh, jl); 07185 for (i = 1; i <= fNpar; ++i) { fX[i-1] = fP[i + jl*fMaxpar - fMaxpar-1]; } 07186 mninex(fX); 07187 fCstatu = "PROGRESS "; 07188 if (fISW[4] >= 1) mnprin(5, fAmin); 07189 fEDM = fBigedm; 07190 sig2 = fEDM; 07191 ncycl = 0; 07192 //*-*- . . . . . start main loop 07193 L50: 07194 if (sig2 < fEpsi && fEDM < fEpsi) goto L76; 07195 sig2 = fEDM; 07196 if (fNfcn - npfn > fNfcnmx) goto L78; 07197 //*-*- calculate new point * by reflection 07198 for (i = 1; i <= fNpar; ++i) { 07199 pb = 0; 07200 for (j = 1; j <= nparp1; ++j) { pb += wg*fP[i + j*fMaxpar - fMaxpar-1]; } 07201 fPbar[i-1] = pb - wg*fP[i + jh*fMaxpar - fMaxpar-1]; 07202 fPstar[i-1] = (alpha + 1)*fPbar[i-1] - alpha*fP[i + jh*fMaxpar - fMaxpar-1]; 07203 } 07204 mninex(fPstar); 07205 //Printf(f_out,"debug : FCN : 026"); 07206 (*fFCN)(nparx, fGin, ystar, fU, 4,fTag); ++fNfcn; 07207 if (ystar >= fAmin) goto L70; 07208 //*-*- point * better than jl, calculate new point ** 07209 for (i = 1; i <= fNpar; ++i) { 07210 fPstst[i-1] = gamma*fPstar[i-1] + (1 - gamma)*fPbar[i-1]; 07211 } 07212 mninex(fPstst); 07213 //Printf(f_out,"debug : FCN : 027"); 07214 (*fFCN)(nparx, fGin, ystst, fU, 4,fTag); ++fNfcn; 07215 //*-*- try a parabola through ph, pstar, pstst. min = prho 07216 y1 = (ystar - y[jh-1])*rho2; 07217 y2 = (ystst - y[jh-1])*rho1; 07218 rho = (rho2*y1 - rho1*y2)*.5 / (y1 - y2); 07219 if (rho < rhomin) goto L66; 07220 if (rho > rhomax) rho = rhomax; 07221 for (i = 1; i <= fNpar; ++i) { 07222 fPrho[i-1] = rho*fPbar[i-1] + (1 - rho)*fP[i + jh*fMaxpar - fMaxpar-1]; 07223 } 07224 mninex(fPrho); 07225 //Printf(f_out,"debug : FCN : 028"); 07226 (*fFCN)(nparx, fGin, yrho, fU, 4,fTag); ++fNfcn; 07227 if (yrho < y[jl-1] && yrho < ystst) goto L65; 07228 if (ystst < y[jl-1]) goto L67; 07229 if (yrho > y[jl-1]) goto L66; 07230 //*-*- accept minimum point of parabola, PRHO 07231 L65: 07232 mnrazz(yrho, fPrho, y, jh, jl); 07233 goto L68; 07234 L66: 07235 if (ystst < y[jl-1]) goto L67; 07236 mnrazz(ystar, fPstar, y, jh, jl); 07237 goto L68; 07238 L67: 07239 mnrazz(ystst, fPstst, y, jh, jl); 07240 L68: 07241 ++ncycl; 07242 if (fISW[4] < 2) goto L50; 07243 if (fISW[4] >= 3 || ncycl % 10 == 0) { 07244 mnprin(5, fAmin); 07245 } 07246 goto L50; 07247 //*-*- point * is not as good as jl 07248 L70: 07249 if (ystar >= y[jh-1]) goto L73; 07250 jhold = jh; 07251 mnrazz(ystar, fPstar, y, jh, jl); 07252 if (jhold != jh) goto L50; 07253 //*-*- calculate new point ** 07254 L73: 07255 for (i = 1; i <= fNpar; ++i) { 07256 fPstst[i-1] = beta*fP[i + jh*fMaxpar - fMaxpar-1] + (1 - beta)*fPbar[i-1]; 07257 } 07258 mninex(fPstst); 07259 //Printf(f_out,"debug : FCN : 029"); 07260 (*fFCN)(nparx, fGin, ystst, fU, 4,fTag); ++fNfcn; 07261 if (ystst > y[jh-1]) goto L1; 07262 //*-*- point ** is better than jh 07263 if (ystst < fAmin) goto L67; 07264 mnrazz(ystst, fPstst, y, jh, jl); 07265 goto L50; 07266 //*-*- . . . . . . end main loop 07267 L76: 07268 if (fISW[4] >= 0) { 07269 Printf(f_out," SIMPLEX MINIMIZATION HAS CONVERGED."); 07270 } 07271 fISW[3] = 1; 07272 goto L80; 07273 L78: 07274 if (fISW[4] >= 0) { 07275 Printf(f_out," SIMPLEX TERMINATES WITHOUT CONVERGENCE."); 07276 } 07277 fCstatu = "CALL LIMIT"; 07278 fISW[3] = -1; 07279 fISW[0] = 1; 07280 L80: 07281 for (i = 1; i <= fNpar; ++i) { 07282 pb = 0; 07283 for (j = 1; j <= nparp1; ++j) { pb += wg*fP[i + j*fMaxpar - fMaxpar-1]; } 07284 fPbar[i-1] = pb - wg*fP[i + jh*fMaxpar - fMaxpar-1]; 07285 } 07286 mninex(fPbar); 07287 //Printf(f_out,"debug : FCN : 030"); 07288 (*fFCN)(nparx, fGin, ypbar, fU, 4,fTag); ++fNfcn; 07289 if (ypbar < fAmin) mnrazz(ypbar, fPbar, y, jh, jl); 07290 mninex(fX); 07291 if (fNfcnmx + npfn - fNfcn < fNpar*3) goto L90; 07292 if (fEDM > fEpsi*2) goto L1; 07293 L90: 07294 if (fISW[4] >= 0) mnprin(5, fAmin); 07295 } /* mnsimp_ */ 07296 07297 //______________________________________________________________________________ 07298 inline 07299 void fitter::mnstat(double &fmin, double &fedm, double &errdef, int &npari, int &nparx, int &istat) 07300 { 07301 07302 //*-*-*-*-*Returns concerning the current status of the minimization*-*-*-*-* 07303 //*-* ========================================================= 07304 //*-* User-called 07305 //*-* Namely, it returns: 07306 //*-* FMIN: the best function value found so far 07307 //*-* FEDM: the estimated vertical distance remaining to minimum 07308 //*-* ERRDEF: the value of UP defining parameter uncertainties 07309 //*-* NPARI: the number of currently variable parameters 07310 //*-* NPARX: the highest (external) parameter number defined by user 07311 //*-* ISTAT: a status integer indicating how good is the covariance 07312 //*-* matrix: 0= not calculated at all 07313 //*-* 1= approximation only, not accurate 07314 //*-* 2= full matrix, but forced positive-definite 07315 //*-* 3= full accurate covariance matrix 07316 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 07317 07318 fmin = fAmin; 07319 fedm = fEDM; 07320 errdef = fUp; 07321 npari = fNpar; 07322 nparx = fNu; 07323 istat = fISW[1]; 07324 if (fEDM == fBigedm) fedm = fUp; 07325 if (fAmin == fUndefi) { 07326 fmin = 0; 07327 fedm = fUp; 07328 istat = 0; 07329 } 07330 } /* mnstat_ */ 07331 07332 //______________________________________________________________________________ 07333 inline 07334 void fitter::mntiny(double epsp1, double &epsbak) 07335 { 07336 //*-*-*-*-*-*-*-*To find the machine precision*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 07337 //*-* ============================= 07338 //*-* Compares its argument with the value 1.0, and returns 07339 //*-* the value .TRUE. if they are equal. To find EPSMAC 07340 //*-* safely by foiling the Fortran optimizer 07341 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 07342 07343 epsbak = epsp1 - 1; 07344 } /* mntiny_ */ 07345 07346 //______________________________________________________________________________ 07347 inline 07348 bool fitter::mnunpt(const std::string &cfname) 07349 { 07350 //*-*-*-*-*-*Returns .TRUE. if CFNAME contains unprintable characters*-*-*-* 07351 //*-* ======================================================== 07352 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 07353 07354 /*static*/ int i, l, ic; 07355 bool ret_val; 07356 static const std::string cpt = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./;:[]$%*_!@#&+()"; 07357 07358 ret_val = false; 07359 l = cfname.size(); 07360 for (i = 1; i <= l; ++i) { 07361 for (ic = 1; ic <= 80; ++ic) { 07362 if (cfname[i-1] == cpt[ic-1]) goto L100; 07363 } 07364 return true; 07365 L100: 07366 ; 07367 } 07368 return ret_val; 07369 } /* mnunpt_ */ 07370 07371 //______________________________________________________________________________ 07372 inline 07373 void fitter::mnvert(double *a, int l, int, int n, int &ifail) 07374 { 07375 //*-*-*-*-*-*-*-*-*-*-*-*Inverts a symmetric matrix*-*-*-*-*-*-*-*-*-*-*-*-* 07376 //*-* ========================== 07377 //*-* inverts a symmetric matrix. matrix is first scaled to 07378 //*-* have all ones on the diagonal (equivalent to change of units) 07379 //*-* but no pivoting is done since matrix is positive-definite. 07380 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 07381 07382 /* System generated locals */ 07383 int a_offset; 07384 07385 /* Local variables */ 07386 /*static*/ double q[kMAXDIM], s[kMAXDIM], si, pp[kMAXDIM]; 07387 /*static*/ int i, j, k, kp1, km1; 07388 07389 /* Parameter adjustments */ 07390 a_offset = l + 1; 07391 a -= a_offset; 07392 07393 /* Function Body */ 07394 ifail = 0; 07395 if (n < 1) goto L100; 07396 if (n > fMaxint) goto L100; 07397 //*-*- scale matrix by sqrt of diag elements 07398 for (i = 1; i <= n; ++i) { 07399 si = a[i + i*l]; 07400 if (si <= 0) goto L100; 07401 s[i-1] = 1 / TMath_Sqrt(si); 07402 } 07403 for (i = 1; i <= n; ++i) { 07404 for (j = 1; j <= n; ++j) { 07405 a[i + j*l] = a[i + j*l]*s[i-1]*s[j-1]; 07406 } 07407 } 07408 //*-*- . . . start main loop . . . . 07409 for (i = 1; i <= n; ++i) { 07410 k = i; 07411 //*-*- preparation for elimination step1 07412 if (a[k + k*l] != 0) q[k-1] = 1 / a[k + k*l]; 07413 else goto L100; 07414 pp[k-1] = 1; 07415 a[k + k*l] = 0; 07416 kp1 = k + 1; 07417 km1 = k - 1; 07418 if (km1 < 0) goto L100; 07419 else if (km1 == 0) goto L50; 07420 else goto L40; 07421 L40: 07422 for (j = 1; j <= km1; ++j) { 07423 pp[j-1] = a[j + k*l]; 07424 q[j-1] = a[j + k*l]*q[k-1]; 07425 a[j + k*l] = 0; 07426 } 07427 L50: 07428 if (k - n < 0) goto L51; 07429 else if (k - n == 0) goto L60; 07430 else goto L100; 07431 L51: 07432 for (j = kp1; j <= n; ++j) { 07433 pp[j-1] = a[k + j*l]; 07434 q[j-1] = -a[k + j*l]*q[k-1]; 07435 a[k + j*l] = 0; 07436 } 07437 //*-*- elimination proper 07438 L60: 07439 for (j = 1; j <= n; ++j) { 07440 for (k = j; k <= n; ++k) { a[j + k*l] += pp[j-1]*q[k-1]; } 07441 } 07442 } 07443 //*-*- elements of left diagonal and unscaling 07444 for (j = 1; j <= n; ++j) { 07445 for (k = 1; k <= j; ++k) { 07446 a[k + j*l] = a[k + j*l]*s[k-1]*s[j-1]; 07447 a[j + k*l] = a[k + j*l]; 07448 } 07449 } 07450 return; 07451 //*-*- failure return 07452 L100: 07453 ifail = 1; 07454 } /* mnvert_ */ 07455 07456 //______________________________________________________________________________ 07457 inline 07458 void fitter::mnwarn(const std::string& copt1, const std::string& corg1, const std::string& cmes1) 07459 { 07460 //*-*-*-*-*-*-*-*-*-*-*-*Prints Warning messages*-*-*-*-*-*-*-*-*-*-*-*-*-* 07461 //*-* ======================= 07462 //*-* If COPT='W', CMES is a WARning message from CORG. 07463 //*-* If COPT='D', CMES is a DEBug message from CORG. 07464 //*-* If SET WARnings is in effect (the default), this routine 07465 //*-* prints the warning message CMES coming from CORG. 07466 //*-* If SET NOWarnings is in effect, the warning message is 07467 //*-* stored in a circular buffer of length MAXMES. 07468 //*-* If called with CORG=CMES='SHO', it prints the messages in 07469 //*-* the circular buffer, FIFO, and empties the buffer. 07470 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 07471 07472 std::string copt = copt1; 07473 std::string corg = corg1; 07474 std::string cmes = cmes1; 07475 07476 const int MAXMES = 10; 07477 /*static*/ int ityp, i, ic, nm; 07478 /*static*/ std::string englsh, ctyp; 07479 07480 if (msubstr(corg,0,3) != "SHO" || msubstr(cmes,0,3) != "SHO") { 07481 07482 //*-*- Either print warning or put in buffer 07483 if (copt == "W") { 07484 ityp = 1; 07485 if (fLwarn) { 07486 Printf(f_out," MINUIT WARNING IN %s",corg.c_str()); 07487 Printf(f_out," ============== ",cmes.c_str()); 07488 return; 07489 } 07490 } else { 07491 ityp = 2; 07492 if (fLrepor) { 07493 Printf(f_out," MINUIT DEBUG FOR %s",corg.c_str()); 07494 Printf(f_out," =============== %s ",cmes.c_str()); 07495 return; 07496 } 07497 } 07498 //*-*- if appropriate flag is off, fill circular buffer 07499 if (fNwrmes[ityp-1] == 0) fIcirc[ityp-1] = 0; 07500 ++fNwrmes[ityp-1]; 07501 ++fIcirc[ityp-1]; 07502 if (fIcirc[ityp-1] > 10) fIcirc[ityp-1] = 1; 07503 ic = fIcirc[ityp-1]; 07504 fOrigin[ic + ityp*10 - 11] = corg; 07505 fWarmes[ic + ityp*10 - 11] = cmes; 07506 fNfcwar[ic + ityp*10 - 11] = fNfcn; 07507 return; 07508 } 07509 07510 //*-*- 'SHO WARnings', ask if any suppressed mess in buffer 07511 if (copt == "W") { 07512 ityp = 1; 07513 ctyp = "WARNING"; 07514 } else { 07515 ityp = 2; 07516 ctyp = "*DEBUG*"; 07517 } 07518 if (fNwrmes[ityp-1] > 0) { 07519 englsh = " WAS SUPPRESSED. "; 07520 if (fNwrmes[ityp-1] > 1) englsh = "S WERE SUPPRESSED."; 07521 Printf(f_out," %5d MINUIT %s MESSAGE%s",fNwrmes[ityp-1] 07522 ,ctyp.c_str(),englsh.c_str()); 07523 nm = fNwrmes[ityp-1]; 07524 ic = 0; 07525 if (nm > MAXMES) { 07526 Printf(f_out," ONLY THE MOST RECENT 10 WILL BE LISTED BELOW."); 07527 nm = MAXMES; 07528 ic = fIcirc[ityp-1]; 07529 } 07530 Printf(f_out," CALLS ORIGIN MESSAGE"); 07531 for (i = 1; i <= nm; ++i) { 07532 ++ic; 07533 if (ic > MAXMES) ic = 1; 07534 Printf(f_out," %6d %s %s", fNfcwar[ic + ityp*10 - 11], 07535 fOrigin[(ic + ityp*10 - 11)*10].c_str(), 07536 fWarmes[(ic + ityp*10 - 11)*60].c_str()); 07537 } 07538 fNwrmes[ityp-1] = 0; 07539 Printf(f_out," "); 07540 } 07541 } /* mnwarn_ */ 07542 07543 //______________________________________________________________________________ 07544 inline 07545 void fitter::mnwerr() 07546 { 07547 //*-*-*-*-*-*-*-*Calculates the WERR, external parameter errors*-*-*-*-*-*-* 07548 //*-* ============================================== 07549 //*-* and the global correlation coefficients, to be called 07550 //*-* whenever a new covariance matrix is available. 07551 //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 07552 07553 /*static*/ double denom, ba, al, dx, du1, du2; 07554 /*static*/ int ndex, ierr, i, j, k, l, ndiag, k1, iin; 07555 07556 //*-*- calculate external error if v exists 07557 if (fISW[1] >= 1) { 07558 for (l = 1; l <= fNpar; ++l) { 07559 ndex = l*(l + 1) / 2; 07560 dx = TMath_Sqrt(TMath_Abs(fVhmat[ndex-1]*fUp)); 07561 i = fNexofi[l-1]; 07562 if (fNvarl[i-1] > 1) { 07563 al = fAlim[i-1]; 07564 ba = fBlim[i-1] - al; 07565 du1 = al + 0.5*(TMath_Sin(fX[l-1] + dx) + 1)*ba - fU[i-1]; 07566 du2 = al + 0.5*(TMath_Sin(fX[l-1] - dx) + 1)*ba - fU[i-1]; 07567 if (dx > 1) du1 = ba; 07568 dx = 0.5*(TMath_Abs(du1) + TMath_Abs(du2)); 07569 } 07570 fWerr[l-1] = dx; 07571 } 07572 } 07573 //*-*- global correlation coefficients 07574 if (fISW[1] >= 1) { 07575 for (i = 1; i <= fNpar; ++i) { 07576 fGlobcc[i-1] = 0; 07577 k1 = i*(i-1) / 2; 07578 for (j = 1; j <= i; ++j) { 07579 k = k1 + j; 07580 fP[i + j*fMaxpar - fMaxpar-1] = fVhmat[k-1]; 07581 fP[j + i*fMaxpar - fMaxpar-1] = fP[i + j*fMaxpar - fMaxpar-1]; 07582 } 07583 } 07584 mnvert(fP, fMaxint, fMaxint, fNpar, ierr); 07585 if (ierr == 0) { 07586 for (iin = 1; iin <= fNpar; ++iin) { 07587 ndiag = iin*(iin + 1) / 2; 07588 denom = fP[iin + iin*fMaxpar - fMaxpar-1]*fVhmat[ndiag-1]; 07589 if (denom <= 1 && denom >= 0) fGlobcc[iin-1] = 0; 07590 else fGlobcc[iin-1] = TMath_Sqrt(1 - 1 / denom); 07591 } 07592 } 07593 } 07594 } /* mnwerr_ */ 07595 07596 }} //namespace 07597 07598 #include "fit_func" 07599 07600 namespace inlib { 07601 namespace f2cmn { 07602 07603 class point { 07604 public: 07605 point():m_value(0),m_error(0){} 07606 virtual ~point(){} 07607 public: 07608 point(const point& a_from) 07609 :m_coords(a_from.m_coords) 07610 ,m_value(a_from.m_value) 07611 ,m_error(a_from.m_error) 07612 {} 07613 point& operator=(const point& a_from){ 07614 m_coords = a_from.m_coords; 07615 m_value = a_from.m_value; 07616 m_error = a_from.m_error; 07617 return *this; 07618 } 07619 public: 07620 std::vector<double> m_coords; 07621 double m_value; 07622 double m_error; 07623 }; 07624 07625 class parameter { 07626 public: 07627 parameter():m_start(0),m_step(0),m_min(0),m_max(0) {} 07628 virtual ~parameter(){} 07629 public: 07630 parameter(const parameter& a_from) 07631 :m_name(a_from.m_name) 07632 ,m_start(a_from.m_start) 07633 ,m_step(a_from.m_step) 07634 ,m_min(a_from.m_min) 07635 ,m_max(a_from.m_max) 07636 {} 07637 parameter& operator=(const parameter& a_from){ 07638 m_name = a_from.m_name; 07639 m_start = a_from.m_start; 07640 m_step = a_from.m_step; 07641 m_min = a_from.m_min; 07642 m_max = a_from.m_max; 07643 return *this; 07644 } 07645 public: 07646 std::string m_name; 07647 double m_start; 07648 double m_step; 07649 double m_min; 07650 double m_max; 07651 }; 07652 07653 class command { 07654 public: 07655 #ifdef ANDROID_NDK 07656 command() //FIXME : for inlib/stl/vector. 07657 :m_argn(0) 07658 {} 07659 #endif 07660 command(const std::string& a_name, 07661 unsigned int a_argn = 0, 07662 double a_0 = 0,double a_1 = 0,double a_2 = 0, 07663 double a_3 = 0,double a_4 = 0,double a_5 = 0, 07664 double a_6 = 0,double a_7 = 0,double a_8 = 0, 07665 double a_9 = 0,double a_10 = 0,double a_11 = 0, 07666 double a_12 = 0,double a_13 = 0,double a_14 = 0, 07667 double a_15 = 0,double a_16 = 0,double a_17 = 0, 07668 double a_18 = 0,double a_19 = 0,double a_20 = 0, 07669 double a_21 = 0,double a_22 = 0,double a_23 = 0, 07670 double a_24 = 0,double a_25 = 0,double a_26 = 0, 07671 double a_27 = 0,double a_28 = 0,double a_29 = 0) 07672 :m_name(a_name) 07673 ,m_argn(a_argn) 07674 { 07675 if(m_argn>30) m_argn = 30; 07676 m_args[ 0] = a_0; m_args[ 1] = a_1; m_args[ 2] = a_2; 07677 m_args[ 3] = a_3; m_args[ 4] = a_4; m_args[ 5] = a_5; 07678 m_args[ 6] = a_6; m_args[ 7] = a_7; m_args[ 8] = a_8; 07679 m_args[ 9] = a_9; m_args[10] = a_10;m_args[11] = a_11; 07680 m_args[12] = a_12;m_args[13] = a_13;m_args[14] = a_14; 07681 m_args[15] = a_15;m_args[16] = a_16;m_args[17] = a_17; 07682 m_args[18] = a_18;m_args[19] = a_19;m_args[20] = a_20; 07683 m_args[21] = a_21;m_args[22] = a_22;m_args[23] = a_23; 07684 m_args[24] = a_24;m_args[25] = a_25;m_args[26] = a_26; 07685 m_args[27] = a_27;m_args[28] = a_28;m_args[29] = a_29; 07686 } 07687 command(const std::string& a_name,const std::vector<double>& a_args) 07688 :m_name(a_name) 07689 ,m_argn(a_args.size()) 07690 { 07691 if(m_argn>30) m_argn = 30; 07692 for(unsigned int index=0;index<m_argn;index++) m_args[index] = a_args[index]; 07693 } 07694 virtual ~command(){} 07695 public: 07696 command(const command& a_from) 07697 :m_name(a_from.m_name) 07698 ,m_argn(a_from.m_argn) 07699 { 07700 ::memcpy(m_args,a_from.m_args,30*sizeof(double)); 07701 } 07702 command& operator=(const command& a_from){ 07703 m_name = a_from.m_name; 07704 m_argn = a_from.m_argn; 07705 ::memcpy(m_args,a_from.m_args,30*sizeof(double)); 07706 return *this; 07707 } 07708 const std::string& name() const {return m_name;} 07709 std::string name() {return m_name;} 07710 07711 unsigned int argn() const {return m_argn;} 07712 const double* args() const {return m_args;} 07713 private: 07714 std::string m_name; 07715 unsigned int m_argn; 07716 double m_args[30]; 07717 }; 07718 07719 class func_fitter { 07720 public: 07721 bool value(int /*a_paramn*/,double* a_params,double& a_value) { 07722 //{printf("debug : param number : %d\n",a_paramn); 07723 // for(unsigned int i=0;i<a_paramn;i++) { 07724 // printf("debug : %d %g\n",i,a_params[i]); 07725 //}} 07726 m_chi2 = 0; 07727 if(!m_func.set(a_params)) {a_value = 0;return false;} 07728 unsigned int npt = m_data.size(); 07729 for(unsigned int ipt=0;ipt<npt;ipt++) { 07730 double value = m_func.value(m_data[ipt].m_coords); 07731 double chinew = (m_data[ipt].m_value - value)/m_data[ipt].m_error; 07732 m_chi2 += (chinew * chinew); 07733 } 07734 a_value = m_chi2; 07735 return true; 07736 } 07737 virtual double chi2() const { return m_chi2;} 07738 07739 protected: 07740 func_fitter(const std::vector<point>& a_data,fit_func& a_func) 07741 :m_data(a_data),m_func(a_func),m_chi2(0) 07742 {} 07743 virtual ~func_fitter() {} 07744 protected: 07745 static bool function(int& aParamn,double* /*aGrad*/,double& aValue, 07746 double* aParams,int /*aStatus*/,void* aTag){ 07747 func_fitter& fcn = *((func_fitter*)aTag); 07748 return fcn.value(aParamn,aParams,aValue); 07749 } 07750 public: 07751 static bool fit(std::ostream& a_out, 07752 const std::vector<point>& a_data, 07753 const std::vector<parameter> a_params, 07754 fit_func& a_func, 07755 std::vector<double>& a_output, 07756 const std::vector<command>& a_cmds = 07757 std::vector<command>(1,command("MIGRAD")) ){ 07758 07759 //NOTE : the size of a_output is : 07760 // 2 + a_params.size() * 4 07761 // with : 07762 // a_output[0] = chi2 07763 // a_output[1] = number of degree of freedom 07764 07765 //exa cmd : MINIMIZE, MINOS 07766 07767 a_output.clear(); 07768 07769 func_fitter fcn(a_data,a_func); 07770 fitter minuit(0); 07771 minuit.SetFCN(function,&fcn); 07772 minuit.SetOut(&a_out); 07773 07774 07775 {double args[10]; 07776 args[0] = -1; //shut up by default. 07777 int status; 07778 minuit.mnexcm("SET PRI",args,1,status);} 07779 07780 unsigned int paramn = a_params.size(); 07781 for(unsigned int index=0;index<paramn;index++) { 07782 int status; 07783 minuit.mnparm(index, 07784 a_params[index].m_name.c_str(), 07785 a_params[index].m_start, 07786 a_params[index].m_step, 07787 a_params[index].m_min, 07788 a_params[index].m_max, 07789 status); 07790 } 07791 07792 std::vector<command>::const_iterator it; 07793 for(it=a_cmds.begin();it!=a_cmds.end();++it) { 07794 int status; 07795 minuit.mnexcm((*it).name(),(*it).args(),(*it).argn(),status); 07796 if(status>0) return false; 07797 } 07798 07799 //in principle a_func should have the ending (fitted) parameters. 07800 07801 // output : 07802 a_output.push_back(fcn.chi2()); 07803 a_output.push_back(a_data.size()-a_params.size()); //ndf (num deg of freedom) 07804 for(unsigned int index=0;index<paramn;index++) { 07805 std::string s; 07806 double value,err; 07807 double bmin,bmax; 07808 int ierr; 07809 minuit.mnpout(index,s,value,err,bmin,bmax,ierr); 07810 a_output.push_back(value); 07811 a_output.push_back(err); 07812 a_output.push_back(bmin); 07813 a_output.push_back(bmax); 07814 } 07815 07816 return true; 07817 } 07818 private: 07819 const std::vector<point>& m_data; 07820 fit_func& m_func; 07821 double m_chi2; 07822 }; 07823 07824 inline bool fit_data(std::ostream& a_out, 07825 const std::vector< inlib::f2cmn::point >& a_data, 07826 const std::vector< inlib::f2cmn::parameter >& a_params, 07827 inlib::fit_func& a_func, 07828 std::vector<double>& a_output, 07829 const std::vector<command>& a_cmds = 07830 std::vector<command>(1,command("MIGRAD"))){ 07831 07832 //NOTE : the size of a_output is : 07833 // 2 + a_params.size() * 4 07834 // with : 07835 // a_output[0] = chi2 07836 // a_output[1] = number of degree of freedom 07837 07838 if(a_data.empty()) { 07839 a_out << "inlib::f2cmn::fit_data :" 07840 << " no starting points." 07841 << std::endl; 07842 return false; 07843 } 07844 07845 if(!func_fitter::fit(a_out,a_data,a_params,a_func,a_output,a_cmds)) { 07846 a_out << "inlib::f2cmn::fit_data :" 07847 << " fit failed." 07848 << std::endl; 07849 return false; 07850 } 07851 07852 return true; 07853 } 07854 07855 //T can be h1d or p1D 07856 template <class T> 07857 inline bool fit_1D(std::ostream& a_out, 07858 T& a_histo, 07859 const std::vector< inlib::f2cmn::parameter >& a_params, 07860 inlib::fit_func& a_func, 07861 std::vector<double>& a_output, 07862 const std::vector<command>& a_cmds = 07863 std::vector<command>(1,command("MIGRAD")) ){ 07864 07865 //NOTE : the size of a_output is : 07866 // 2 + a_params.size() * 4 07867 // with : 07868 // a_output[0] = chi2 07869 // a_output[1] = number of degree of freedom 07870 07871 if(a_histo.entries()==0) { 07872 a_out << "inlib::f2cmn::fit_1D :" 07873 << " histogram has no entries." 07874 << std::endl; 07875 return false; 07876 } 07877 07878 int nbin = a_histo.axis().bins(); 07879 if(nbin<=0) { 07880 a_out << "inlib::f2cmn::fit_1D :" 07881 << " has no bins." 07882 << std::endl; 07883 return false; 07884 } 07885 07886 std::vector<double> pt; 07887 pt.resize(1,0); 07888 07889 std::vector< inlib::f2cmn::point > data; 07890 07891 for(int index=0;index<nbin;index++) { 07892 int nent = a_histo.bin_entries(index); 07893 if(nent==0) continue; // Do not take bin without entry. 07894 // Take middle of bin. 07895 double xx = 07896 (a_histo.axis().bin_lower_edge(index)+ 07897 a_histo.axis().bin_upper_edge(index))/2.; 07898 double val = a_histo.bin_height(index); 07899 double err = ::sqrt(::fabs(val)); // Take statistical error. 07900 if(err==0.) { 07901 a_out << "inlib::f2cmn::fit_1D :" 07902 << " null error for bin " << index 07903 << " x " << xx << " value " << val 07904 << ". Set error to 0.01." 07905 << std::endl; 07906 //return 0; 07907 err = 0.01; //FIXME 07908 } 07909 inlib::f2cmn::point fpt; 07910 pt[0] = xx; 07911 fpt.m_coords = pt; 07912 fpt.m_value = val; 07913 fpt.m_error = err; 07914 data.push_back(fpt); 07915 } 07916 if(data.empty()) { 07917 a_out << "inlib::f2cmn::fit_1D :" 07918 << " no starting points." 07919 << std::endl; 07920 return false; 07921 } 07922 07923 if(!func_fitter::fit(a_out,data,a_params,a_func,a_output,a_cmds)) { 07924 a_out << "inlib::f2cmn::fit_1D :" 07925 << " fit failed." 07926 << std::endl; 07927 return false; 07928 } 07929 07930 return true; 07931 } 07932 07933 template <class T> 07934 inline bool fit_xve(std::ostream& a_out, 07935 const std::vector<T>& a_xs, //one dim coordinates 07936 const std::vector<T>& a_vs, //values 07937 const std::vector<T>& a_es, //errors 07938 const std::vector< inlib::f2cmn::parameter >& a_params, 07939 inlib::fit_func& a_func, 07940 std::vector<double>& a_output, 07941 const std::vector<command>& a_cmds = 07942 std::vector<command>(1,command("MIGRAD"))){ 07943 07944 //NOTE : the size of a_output is : 07945 // 2 + a_params.size() * 4 07946 // with : 07947 // a_output[0] = chi2 07948 // a_output[1] = number of degree of freedom 07949 07950 if(a_vs.size() != a_xs.size() ) { 07951 a_out << "inlib::f2cmn::fit_xve :" 07952 << " coordinate and value vectors have different sizes." 07953 << std::endl; 07954 return false; 07955 } 07956 07957 if(a_es.size() != a_xs.size() ) { 07958 a_out << "inlib::f2cmn::fit_xve :" 07959 << " coordinate and error vectors have different sizes." 07960 << std::endl; 07961 return false; 07962 } 07963 07964 int nbin = a_xs.size(); 07965 07966 std::vector<double> pt; 07967 pt.resize(1,0); 07968 07969 std::vector< inlib::f2cmn::point > data; 07970 07971 for(int index=0;index<nbin;index++) { 07972 inlib::f2cmn::point fpt; 07973 pt[0] = a_xs[index]; 07974 fpt.m_coords = pt; 07975 fpt.m_value = a_vs[index]; 07976 fpt.m_error = a_es[index]; 07977 data.push_back(fpt); 07978 } 07979 if(data.empty()) { 07980 a_out << "inlib::f2cmn::fit_xve :" 07981 << " no starting points." 07982 << std::endl; 07983 return false; 07984 } 07985 07986 if(!func_fitter::fit(a_out,data,a_params,a_func,a_output,a_cmds)) { 07987 a_out << "inlib::f2cmn::fit_xve :" 07988 << " fit failed." 07989 << std::endl; 07990 return false; 07991 } 07992 07993 return true; 07994 } 07995 07996 }} //namespace 07997 07998 #endif