00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00029
00030 #include<iostream>
00031 #include<cmath>
00032
00033 #include "jbltools/kinfit/WWFitterFast.h"
00034
00035 #include "jbltools/kinfit/BaseFitObject.h"
00036 #include "jbltools/kinfit/BaseConstraint.h"
00037 #include "jbltools/kinfit/ftypes.h"
00038 #include "jbltools/kinfit/cernlib.h"
00039
00040 using std::cout;
00041 using std::endl;
00042
00043
00044 WWFitterFast::WWFitterFast() : npar(0), nmea(0), nunm(0), ncon(0), ierr (0) {};
00045
00046
00047 WWFitterFast::~WWFitterFast() {};
00048
00049
00050 double WWFitterFast::fit() {
00051
00052
00053 bool debug = false;
00054
00055
00056 initialize();
00057
00058
00059 FDouble eta[NPARMAX];
00060 FDouble etasv[NPARMAX];
00061 FDouble y[NPARMAX];
00062
00063 for (unsigned int i = 0; i < fitobjects.size(); ++i) {
00064 for (int ilocal = 0; ilocal < fitobjects[i]->getNPar(); ++ilocal) {
00065 int iglobal = fitobjects[i]->getGlobalParNum (ilocal);
00066 if (iglobal >= 0) y[iglobal] = eta[iglobal] = fitobjects[i]->getParam(ilocal);
00067
00068
00069 }
00070 }
00071
00072
00073 FDouble dfeta[NCONMAX][NPARMAX];
00074 for (int k=0; k < ncon; k++) {
00075 for (int j=0; j < npar; j++) dfeta[k][j]=0;
00076 constraints[k]->getDerivatives(NPARMAX, dfeta[k]);
00077
00078
00079
00080 }
00081
00082
00083
00084 FDouble R[NCONMAX];
00085 FDouble S[NCONMAX][NCONMAX];
00086 FDouble W1[NUNMMAX][NUNMMAX];
00087 FDouble V[NPARMAX][NPARMAX];
00088 FDouble dxi[NUNMMAX];
00089 FDouble alam[NCONMAX];
00090
00091
00092 double chinew=0, chit=0, chik=0;
00093 double alph = 1.;
00094 nit = 0;
00095
00096
00097 int nitmax = 200;
00098 double chik0 = 100.;
00099 double chit0 = 100.;
00100 double dchikc = 1.0E-3;
00101 double dchitc = 1.0E-4;
00102 double dchikt = 1.0E-2;
00103 double dchik = 1.05;
00104 double chimxw = 1000.;
00105 double almin = 0.05;
00106
00107
00108
00109 bool repeat = true;
00110 bool scut = false;
00111 bool calcerr = true;
00112
00113
00114 while (repeat) {
00115 bool updatesuccess = true;
00116
00117
00118 if (scut) {
00119 for (int j=0; j < npar; j++) eta[j] = etasv[j];
00120 updatesuccess = updateFitObjects (eta);
00121 if (!updatesuccess) {
00122 std::cerr << "WWFitterFast::fit: old parameters are garbage!" << std::endl;
00123 return -1;
00124 }
00125 for (int k = 0; k < ncon; ++k) {
00126 for (int j=0; j < npar; j++) dfeta[k][j]=0;
00127 constraints[k]->getDerivatives(NPARMAX, dfeta[k]);
00128 }
00129 }
00130 else {
00131 for (int j=0; j < npar; j++) etasv[j] = eta[j];
00132 chik0 = chik;
00133 chit0 = chit;
00134 }
00135
00136
00137 for (int i = 0; i < npar; ++i)
00138 for (int j = 0; j < npar; ++j) V[i][j] = 0;
00139 for (unsigned int ifitobj = 0; ifitobj<fitobjects.size(); ++ifitobj) {
00140 fitobjects[ifitobj]->addToGlobCov (&V[0][0], NPARMAX);
00141 }
00142
00143
00144
00145 for (int k = 0; k < ncon; ++k) R[k] = constraints[k]->getValue();
00146 for (int j = 0; j < nmea; ++j) {
00147 double dy = y[j]-eta[j];
00148 for (int k = 0; k < ncon; ++k) {
00149 R[k] += dfeta[k][j]*dy;
00150 }
00151 }
00152
00153 for (int l = 0; l < ncon; ++l) {
00154 for (int k = 0; k < ncon; ++k) S[k][l] = 0;
00155 }
00156 for (int i = 0; i < nmea; ++i) {
00157 for (int j = 0; j < nmea; ++j) {
00158 double v=V[i][j];
00159 for (int k = 0; k < ncon; ++k){
00160 double dfetav = dfeta[k][i]*v;
00161 for (int l = 0; l < ncon; ++l) {
00162 S[k][l] += dfetav * dfeta[l][j];
00163 }
00164 }
00165 }
00166 }
00167
00168
00169
00170
00171
00172
00173
00174 if (nunm > 0) {
00175 FDouble xhelp[NCONMAX][NPARMAX];
00176 for (int k=0; k < ncon; k++) {
00177 for (int j=0; j < npar; j++) xhelp[k][j] = dfeta[k][nmea+j];
00178 }
00179 dseqn (ncon, &S[0][0], NCONMAX, nunm, &xhelp[0][0]);
00180
00181 for (int i = 0; i < nunm; ++i) {
00182 for (int j = 0; j < nunm; ++j) W1[i][j] = 0;
00183 }
00184 for (int k = 0; k < ncon; ++k) {
00185 for (int j = 0; j < nunm; ++j) {
00186 for (int i = 0; i < nunm; ++i) {
00187 W1[i][j] += dfeta[k][nmea+i] * xhelp[j][k];
00188 }
00189 }
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 std::cerr << "WWFitterFast::fit(): Untested!!!" << endl;
00204
00205 for (int i = 0; i < nunm; ++i) dxi[i] = 0;
00206
00207 FDouble Sr[NCONMAX];
00208
00209 for (int l = 0; l < ncon; ++l) Sr[l] = R[l];
00210 dsfeqn (ncon, &S[0][0], NCONMAX, 1, Sr);
00211
00212 for (int k = 0; k < ncon; ++k) {
00213 for (int i = 0; i < nunm; ++i) {
00214 dxi[i] -= dfeta[k][nmea+i]* Sr[k];
00215 }
00216 }
00217
00218 dseqn (nunm, &W1[0][0], NUNMMAX, ierr, 1, dxi);
00219 }
00220
00221
00222
00223 for (int i = 0; i < nunm; ++i) {
00224 eta[nmea+i] += dxi[i];
00225 }
00226
00227
00228
00229
00230 for (int k = 0; k < ncon; ++k) {
00231 alam[k] = R[k];
00232 }
00233 for (int j = 0; j < nunm; ++j) {
00234 double d = dxi[j];
00235 int nmeaj = nmea+j;
00236 for (int k = 0; k < ncon; ++k) {
00237 alam[k] += dfeta[k][nmeaj] * d;
00238 }
00239 }
00240 if (nunm > 0) {
00241 dsfeqn (ncon, &S[0][0], NCONMAX, 1, alam);
00242 }
00243 else {
00244 dseqn (ncon, &S[0][0], NCONMAX, 1, alam);
00245 }
00246
00247 for (int i = 0; i < nmea; ++i) eta[i] = y[i];
00248 for (int k = 0; k < ncon; ++k) {
00249 double a = alam[k];
00250 for (int j = 0; j < nmea; ++j) {
00251 double dfetaa = dfeta[k][j] * a;
00252 for (int i = 0; i < nmea; ++i) {
00253 eta[i] -= V[i][j] * dfetaa;
00254 }
00255 }
00256 }
00257
00258
00259
00260
00261
00262 updatesuccess = updateFitObjects (eta);
00263
00264 if (debug) {
00265 cout << "After adjustment of all parameters:\n";
00266 for (int k = 0; k < ncon; ++k) {
00267 cout << "Value of constraint " << k << " = " << constraints[k]->getValue()
00268 << endl;
00269 }
00270 }
00271 for (int k=0; k < ncon; k++) {
00272 for (int j=0; j < npar; j++) dfeta[k][j]=0;
00273 constraints[k]->getDerivatives(NPARMAX, dfeta[k]);
00274 }
00275
00276
00277
00278
00279
00280
00281 FDouble deta[NPARMAX];
00282 FDouble Vinvdeta[NPARMAX];
00283
00284 chit = 0;
00285 for (int i = 0; i < nmea; ++i) {
00286 Vinvdeta[i] = deta[i] = (y[i]-eta[i]);
00287 }
00288
00289 dseqn (nmea, &V[0][0], NPARMAX, 1, Vinvdeta);
00290
00291 chit = 0;
00292 for (int i = 0; i < nmea; ++i) {
00293 chit += deta[i] * Vinvdeta[i];
00294 }
00295 chik = 0;
00296 for (int k = 0; k < ncon; ++k) chik += std::abs(2*alam[k]*constraints[k]->getValue());
00297
00298 chinew = chit + chik;
00299
00300
00301 nit++;
00302
00303 bool sconv = (std::abs(chik-chik0) < dchikc)
00304 && (std::abs(chit-chit0) < dchitc*chit)
00305 && (chik < dchikt*chit);
00306
00307
00308
00309
00310
00311
00312
00313 double eps = 1E-8;
00314 bool sconv2 = true;
00315 for (int k = 0; sconv2 && (k < ncon); ++k)
00316 sconv2 &= (std::abs(constraints[k]->getValue()) < eps);
00317 if (sconv2 && debug)
00318 cout << "All constraints fulfilled to better than " << eps << endl;
00319
00320 for (int j = 0; sconv2 && (j < npar); ++j)
00321 sconv2 &= (std::abs(eta[j] - etasv[j]) < eps);
00322 if (sconv2 && debug)
00323 cout << "All parameters stable to better than " << eps << endl;
00324 sconv |= sconv2;
00325
00326 bool sbad = (chik > dchik*chik0)
00327 && (chik > dchikt*chit)
00328 && (chik > chik0 + 1.E-10);
00329
00330 if (nit > nitmax) {
00331
00332 repeat = false;
00333 ierr = 1;
00334 }
00335 else if (sconv && updatesuccess) {
00336
00337 repeat = false;
00338 ierr = 0;
00339 }
00340 else if ( nit > 2 && chinew > chimxw && updatesuccess) {
00341
00342 repeat = false;
00343 calcerr = false;
00344 ierr = 2;
00345 }
00346 else if (sbad && nit > 1 || !updatesuccess) {
00347
00348 if ( alph == almin ) {
00349 repeat = false;
00350 calcerr = false;
00351 ierr = 3;
00352 }
00353 else {
00354 alph = std::max (almin, 0.5 * alph);
00355 scut = true;
00356 repeat = true;
00357 ierr = 4;
00358 }
00359 }
00360 else {
00361
00362 alph = std::min (alph+0.1, 1. );
00363 repeat = true;
00364 ierr = 5;
00365 }
00366
00367 if (debug) cout << "======== NIT = " << nit << ", CHI2 = " << chinew
00368 << ", ierr = " << ierr << endl;
00369
00370 if (debug)
00371 for (unsigned int i = 0; i < fitobjects.size(); ++i)
00372 cout << "fitobject " << i << ": " << *fitobjects[i] << endl;
00373
00374 }
00375
00376
00377 FDouble VETA[NPARMAX][NPARMAX];
00378 for (int i = 0; i < npar; ++i)
00379 for (int j = 0; j < npar; ++j) VETA[i][j] = 0;
00380
00381 FDouble Sinv[NCONMAX][NCONMAX];
00382
00383 if (calcerr) {
00384
00385
00386 for (int k = 0; k < ncon; ++k) {
00387 for (int l = 0; l < ncon; ++l) {
00388 S[k][l] = 0;
00389 }
00390 }
00391 for (int i = 0; i < npar; ++i) {
00392 for (int j = 0; j < npar; ++j) {
00393 double v = V[i][j];
00394 for (int k = 0; k < ncon; ++k) {
00395 double dfetav = dfeta[k][i] * v;
00396 for (int l = 0; l < ncon; ++l) {
00397 S[k][l] += dfetav * dfeta[l][j];
00398 }
00399 }
00400 }
00401 }
00402 for (int k = 0; k < ncon; ++k) {
00403 for (int l = 0; l < ncon; ++l) {
00404 Sinv[k][l] = S[k][l];
00405 }
00406 }
00407
00408
00409
00410
00411 dsinv(ncon, &Sinv[0][0], NCONMAX, ierr);
00412
00413
00414
00415 FDouble G[NPARMAX][NPARMAX];
00416 for (int i = 0; i < nmea; ++i) {
00417 for (int j = 0; j < nmea; ++j) G[i][j] = 0;
00418 }
00419 for (int k = 0; k < ncon; ++k) {
00420 for (int l = 0; l < ncon; ++l) {
00421 double s = Sinv[k][l];
00422 for (int i = 0; i < nmea; ++i) {
00423 double dfetas = s*dfeta[k][i];
00424 for (int j = 0; j < nmea; ++j) {
00425 G[i][j] += dfetas * dfeta[l][j];
00426 }
00427 }
00428 }
00429 }
00430
00431 if (nunm > 0) {
00432
00433
00434 FDouble H[NPARMAX][NUNMMAX];
00435 for (int i = 0; i < nmea; ++i) {
00436 for (int j = 0; j < nunm; ++j) {
00437 H[i][j] = 0;
00438 for (int k = 0; k < ncon; ++k) {
00439 for (int l = 0; l < ncon; ++l) {
00440 H[i][j] += dfeta[k][i] * Sinv[k][l] * dfeta[l][nmea+j];
00441 }
00442 }
00443 }
00444 }
00445
00446
00447
00448 FDouble U[NUNMMAX][NUNMMAX];
00449 for (int i = 0; i < nunm; ++i) {
00450 for (int j = 0; j < nunm; ++j) {
00451 U[i][j] = 0;
00452 for (int k = 0; k < ncon; ++k) {
00453 for (int l = 0; l < ncon; ++l) {
00454 U[i][j] += dfeta[k][nmea+i] * Sinv[k][l] * dfeta[l][nmea+j];
00455 }
00456 }
00457 }
00458 }
00459 dsinv(nunm, &U[0][0], NUNMMAX, ierr);
00460
00461
00462 for (int i = 0; i < nunm; ++i) {
00463 for (int j = 0; j < nunm; ++j) {
00464 VETA[nmea+i][nmea+j] = U[i][j];
00465 }
00466 }
00467
00468
00469 for (int i = 0; i < nmea; ++i) {
00470 for (int j = 0; j < nunm; ++j) {
00471 VETA[i][nmea+j] = 0.;
00472 for (int ii = 0; ii < nmea; ++ii) {
00473 for (int jj = 0; jj < nunm; ++jj) {
00474 VETA[i][nmea+j] -= V[i][ii] * H[ii][jj] * U[jj][j];
00475 }
00476 }
00477 }
00478 }
00479
00480
00481 for (int i = 0; i < nmea; ++i) {
00482 for (int j = 0; j < nunm; ++j) {
00483 VETA[nmea+j][i] = VETA[i][nmea+j];
00484 }
00485 }
00486
00487
00488 for (int i = 0; i < nmea; ++i) {
00489 for (int j = 0; j < nmea; ++j) {
00490 for (int ii = 0; ii < nunm; ++ii) {
00491 for (int jj = 0; jj < nunm; ++jj) {
00492 G[i][j] -= H[i][ii] * U[ii][jj] * H[j][jj];
00493 }
00494 }
00495 }
00496 }
00497
00498 }
00499
00500
00501 FDouble GV[NPARMAX][NPARMAX];
00502 for (int i = 0; i < nmea; ++i) {
00503 for (int j = 0; j < nmea; ++j) {
00504 if (i == j) GV[i][j] = 1.;
00505 else GV[i][j] = 0.;
00506 for (int ii = 0; ii < nmea; ++ii) {
00507 GV[i][j] -= G[i][ii] * V[ii][j];
00508 }
00509 }
00510 }
00511
00512
00513 for (int i = 0; i < nmea; ++i) {
00514 for (int j = 0; j < nmea; ++j) {
00515 VETA[i][j] = 0.;
00516 for (int ii = 0; ii < nmea; ++ii) {
00517 VETA[i][j] += V[i][ii] * GV[ii][j];
00518 }
00519 }
00520 }
00521
00522
00523
00524 for (unsigned int ifitobj = 0; ifitobj < fitobjects.size(); ++ifitobj) {
00525 for (int ilocal = 0; ilocal < fitobjects[ifitobj]->getNPar(); ++ilocal) {
00526 int iglobal = fitobjects[ifitobj]->getGlobalParNum (ilocal);
00527 if (iglobal >= 0) fitobjects[ifitobj]->setError(ilocal,
00528 std::sqrt(std::fabs(VETA[iglobal][iglobal])));
00529 }
00530 }
00531
00532 }
00533
00534
00535 FReal chi = FReal(chinew);
00536 fitprob = (ncon-nunm > 0) ? prob(chi,ncon-nunm) : 0.5;
00537 chi2 = chinew;
00538
00539 return fitprob;
00540
00541 };
00542
00543 bool WWFitterFast::initialize() {
00544
00545 int iglobal = 0;
00546
00547 for (unsigned int ifitobj = 0; ifitobj < fitobjects.size(); ++ifitobj) {
00548 for (int ilocal = 0; ilocal < fitobjects[ifitobj]->getNPar(); ++ilocal) {
00549 if (fitobjects[ifitobj]->isParamMeasured(ilocal) &&
00550 !fitobjects[ifitobj]->isParamFixed(ilocal)) {
00551 fitobjects[ifitobj]->setGlobalParNum (ilocal, iglobal);
00552 ++iglobal;
00553 }
00554 }
00555 }
00556 nmea = iglobal;
00557
00558 for (unsigned int ifitobj = 0; ifitobj < fitobjects.size(); ++ifitobj) {
00559 for (int ilocal = 0; ilocal < fitobjects[ifitobj]->getNPar(); ++ilocal) {
00560 if (!fitobjects[ifitobj]->isParamMeasured(ilocal) &&
00561 !fitobjects[ifitobj]->isParamFixed(ilocal)) {
00562 fitobjects[ifitobj]->setGlobalParNum (ilocal, iglobal);
00563 ++iglobal;
00564 }
00565 }
00566 }
00567 npar = iglobal;
00568 nunm = npar - nmea;
00569
00570
00571 ncon = constraints.size();
00572
00573 return true;
00574
00575 };
00576
00577 bool WWFitterFast::updateFitObjects (double eta[]) {
00578 bool debug = false;
00579 bool result = true;
00580 for (unsigned int ifitobj = 0; ifitobj < fitobjects.size(); ++ifitobj) {
00581 for (int ilocal = 0; ilocal < fitobjects[ifitobj]->getNPar(); ++ilocal) {
00582 int iglobal = fitobjects[ifitobj]->getGlobalParNum (ilocal);
00583 if (!fitobjects[ifitobj]->isParamFixed (ilocal) && iglobal >= 0) {
00584 if (debug) cout << "Parameter " << iglobal
00585 << " (" << fitobjects[ifitobj]->getName()
00586 << ": " << fitobjects[ifitobj]->getParamName(ilocal)
00587 << ") set to " << eta[iglobal];
00588 result &= fitobjects[ifitobj]->setParam(ilocal, eta[iglobal]);
00589 eta[iglobal] = fitobjects[ifitobj]->getParam(ilocal);
00590 if (debug) cout << " => " << eta[iglobal] << endl;
00591 }
00592 }
00593 }
00594 return result;
00595 };
00596
00597 int WWFitterFast::getError() const {return ierr;}
00598 double WWFitterFast::getProbability() const {return fitprob;}
00599 double WWFitterFast::getChi2() const {return chi2;}
00600 int WWFitterFast::getIterations() const {return nit;}