00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00039 #include "TopQuarkAnalysis/TopHitFit/interface/Chisq_Constrainer.h"
00040 #include "TopQuarkAnalysis/TopHitFit/interface/Defaults.h"
00041 #include <cmath>
00042 #include <cassert>
00043 #include <iostream>
00044 #include <iomanip>
00045
00046 using std::abs;
00047 using std::cout;
00048 using std::fixed;
00049 using std::ios_base;
00050 using std::ostream;
00051 using std::resetiosflags;
00052 using std::setiosflags;
00053 using std::sqrt;
00054
00055
00056
00057
00058
00059 namespace hitfit {
00060
00061
00062 Chisq_Constrainer_Args::Chisq_Constrainer_Args (const Defaults& defs)
00063
00064
00065
00066
00067
00068
00069 : _base_constrainer_args (defs)
00070 {
00071 _use_G = defs.get_bool ("use_G");
00072 _printfit = defs.get_bool ("printfit");
00073 _constraint_sum_eps = defs.get_float ("constraint_sum_eps");
00074 _chisq_diff_eps = defs.get_float ("chisq_diff_eps");
00075 _maxit = defs.get_int ("maxit");
00076 _max_cut = defs.get_int ("maxcut");
00077 _cutsize = defs.get_float ("cutsize");
00078 _min_tot_cutsize = defs.get_float ("min_tot_cutsize");
00079 _chisq_test_eps = defs.get_float ("chisq_test_eps");
00080 }
00081
00082
00083 bool Chisq_Constrainer_Args::printfit () const
00084
00085
00086
00087
00088 {
00089 return _printfit;
00090 }
00091
00092
00093 bool Chisq_Constrainer_Args::use_G () const
00094
00095
00096
00097
00098 {
00099 return _use_G;
00100 }
00101
00102
00103 double Chisq_Constrainer_Args::constraint_sum_eps () const
00104
00105
00106
00107
00108 {
00109 return _constraint_sum_eps;
00110 }
00111
00112
00113 double Chisq_Constrainer_Args::chisq_diff_eps () const
00114
00115
00116
00117
00118 {
00119 return _chisq_diff_eps;
00120 }
00121
00122
00123 unsigned Chisq_Constrainer_Args::maxit () const
00124
00125
00126
00127
00128 {
00129 return _maxit;
00130 }
00131
00132
00133 unsigned Chisq_Constrainer_Args::max_cut () const
00134
00135
00136
00137
00138 {
00139 return _max_cut;
00140 }
00141
00142
00143 double Chisq_Constrainer_Args::cutsize () const
00144
00145
00146
00147
00148 {
00149 return _cutsize;
00150 }
00151
00152
00153 double Chisq_Constrainer_Args::min_tot_cutsize () const
00154
00155
00156
00157
00158 {
00159 return _min_tot_cutsize;
00160 }
00161
00162
00163 double Chisq_Constrainer_Args::chisq_test_eps () const
00164
00165
00166
00167
00168 {
00169 return _chisq_test_eps;
00170 }
00171
00172
00173 const Base_Constrainer_Args&
00174 Chisq_Constrainer_Args::base_constrainer_args () const
00175
00176
00177
00178
00179 {
00180 return _base_constrainer_args;
00181 }
00182
00183
00184 }
00185
00186
00187
00188
00189
00190 namespace {
00191
00192
00193 using namespace hitfit;
00194
00195
00212 bool solve_linear_system (const Matrix& H,
00213 const Diagonal_Matrix& Y,
00214 const Matrix& By,
00215 const Row_Vector& r,
00216 Column_Vector& alpha,
00217 Column_Vector& d,
00218 Matrix& W,
00219 Matrix& U,
00220 Matrix& V)
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 {
00239 int nconstraints = H.num_row();
00240 int nbadvars = Y.num_row();
00241
00242
00243 Matrix A (nconstraints+nbadvars, nconstraints+nbadvars);
00244 A.sub (1, 1, -H);
00245 if (nbadvars > 0) {
00246 A.sub (nconstraints+1, nconstraints+1, Y);
00247 A.sub (1, nconstraints+1, By.T());
00248 A.sub (nconstraints+1, 1, By);
00249 }
00250
00251
00252 Column_Vector yy(nconstraints + nbadvars, 0);
00253 yy.sub (1, r.T());
00254
00255
00256
00257 Matrix Ai;
00258 int ierr = 0;
00259 do {
00260 Ai = A.inverse (ierr);
00261 if (ierr) {
00262 int allzero = 0;
00263 for (int i=1; i<=nconstraints; i++) {
00264 allzero = 1;
00265 for (int j=1; j<=nconstraints; j++) {
00266 if (A(i,j) != 0) {
00267 allzero = 0;
00268 break;
00269 }
00270 }
00271 if (allzero) {
00272 A(i,i) = 1;
00273 break;
00274 }
00275 }
00276 if (!allzero) return false;
00277 }
00278 } while (ierr != 0);
00279
00280
00281 Column_Vector xx = Ai * yy;
00282
00283
00284
00285 W = Ai.sub (1, nconstraints, 1, nconstraints);
00286 if (nbadvars > 0) {
00287 U = Ai.sub (nconstraints+1, nconstraints+nbadvars,
00288 nconstraints+1, nconstraints+nbadvars);
00289 V = Ai.sub (nconstraints+1, nconstraints+nbadvars, 1, nconstraints);
00290 d = xx.sub (nconstraints+1, nconstraints+nbadvars);
00291 }
00292
00293 alpha = xx.sub (1, nconstraints);
00294
00295 return true;
00296 }
00297
00298
00299 }
00300
00301
00302 namespace hitfit {
00303
00304
00305
00306
00307
00308 Chisq_Constrainer::Chisq_Constrainer (const Chisq_Constrainer_Args& args)
00309
00310
00311
00312
00313
00314
00315 : Base_Constrainer (args.base_constrainer_args()),
00316 _args (args)
00317 {
00318 }
00319
00320
00321 double Chisq_Constrainer::fit (Constraint_Calculator& constraint_calculator,
00322 const Column_Vector& xm,
00323 Column_Vector& x,
00324 const Column_Vector& ym,
00325 Column_Vector& y,
00326 const Matrix& G_i,
00327 const Diagonal_Matrix& Y,
00328 Column_Vector& pullx,
00329 Column_Vector& pully,
00330 Matrix& Q,
00331 Matrix& R,
00332 Matrix& S)
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 {
00363
00364
00365 int nvars = x.num_row();
00366 assert (nvars == G_i.num_col());
00367 assert (nvars == xm.num_row());
00368
00369 int nbadvars = y.num_row();
00370 assert (nbadvars == Y.num_col());
00371 assert (nbadvars == ym.num_row());
00372
00373
00374
00375 Matrix G (nvars, nvars);
00376 if (_args.use_G()) {
00377 int ierr = 0;
00378 G = G_i.inverse (ierr);
00379 assert (!ierr);
00380 }
00381
00382 int nconstraints = constraint_calculator.nconstraints ();
00383
00384
00385 Row_Vector F (nconstraints);
00386 Matrix Bx (nvars, nconstraints);
00387 Matrix By (nbadvars, nconstraints);
00388
00389
00390
00391
00392 if (! call_constraint_fcn (constraint_calculator, x, y, F, Bx, By)) {
00393
00394
00395 return -999.0;
00396 }
00397
00398
00399 double constraint_sum_last = -1000;
00400 double chisq_last = -1000;
00401 bool near_convergence = false;
00402 double last_step_cutsize = 1;
00403
00404 unsigned nit = 0;
00405
00406
00407 Column_Vector c = x - xm;
00408 Column_Vector d = y - ym;
00409
00410 Matrix E (nvars, nconstraints);
00411 Matrix W (nconstraints, nconstraints);
00412 Matrix U (nbadvars, nbadvars);
00413 Matrix V (nbadvars, nconstraints);
00414
00415
00416 do {
00417
00418 E = G_i * Bx;
00419 Matrix H = E.T() * Bx;
00420 Row_Vector r = c.T() * Bx + d.T() * By - F;
00421
00422
00423
00424
00425 Column_Vector alpha (nvars);
00426 Column_Vector d1 (nbadvars);
00427 if (!solve_linear_system (H, Y, By, r,
00428 alpha, d1, W, U, V)) {
00430
00431 return -998.0;
00432 }
00433
00434
00435 Column_Vector c1 = -E * alpha;
00436 double chisq = - scalar (r * alpha);
00437
00438 double psi_cut = 0;
00439
00440
00441 x = c1 + xm;
00442 y = d1 + ym;
00443
00444
00445 Matrix save_By = By;
00446 Row_Vector save_negF = - F;
00447 double this_step_cutsize = 1;
00448 double constraint_sum = -1;
00449 unsigned ncut = 0;
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 while (! call_constraint_fcn (constraint_calculator, x, y, F, Bx, By) ||
00461 ((constraint_sum = norm_infinity (F))
00462 > _args.constraint_sum_eps() &&
00463 nit > 0 &&
00464 constraint_sum > constraint_sum_last))
00465 {
00466
00467
00468 if (nit > 0 && _args.printfit() && ncut == 0) {
00469 cout << "(" << chisq << " " << chisq_last << ") ";
00470 }
00471
00472
00473
00474
00475 if (ncut == 0 &&
00476 abs (chisq - chisq_last) < _args.chisq_diff_eps()) {
00477
00478
00479
00480
00481 if (_args.printfit())
00482 cout << " directed step ";
00483
00484
00485
00486 Column_Vector beta (nconstraints);
00487 Column_Vector delta (nbadvars);
00488 solve_linear_system (H, Y, save_By, save_negF,
00489 beta, delta, W, U, V);
00490
00491
00492 Column_Vector gamma = -E * beta;
00493
00494
00495 x = c + xm + gamma;
00496 y = d + ym + delta;
00497
00498
00499
00500 if (call_constraint_fcn (constraint_calculator, x, y, F, Bx, By) &&
00501 (constraint_sum = norm_infinity (F)) > 0 &&
00502 (constraint_sum < constraint_sum_last)) {
00503
00504
00505
00506 chisq = chisq_last - scalar ((-save_negF + r*2) * beta);
00507 c1 = x - xm;
00508 d1 = y - ym;
00509
00510
00511 break;
00512 }
00513 }
00514
00515
00516
00517 if (ncut == 0)
00518 psi_cut = scalar ((save_negF - r) * alpha);
00519
00520
00521 if (++ncut > _args.max_cut()) {
00522
00523
00524 return -997.0;
00525 }
00526
00527
00528
00529
00530
00531
00532 double this_cutsize = _args.cutsize();
00533 if (ncut == 1 && last_step_cutsize < 1) {
00534 this_cutsize = 2 * last_step_cutsize;
00535 if (this_cutsize > _args.cutsize())
00536 this_cutsize = _args.cutsize();
00537 }
00538
00539
00540 this_step_cutsize *= this_cutsize;
00541
00542
00543 if (this_step_cutsize < _args.min_tot_cutsize()) {
00544
00545
00546 return -996.0;
00547 }
00548
00549
00550 double cutleft = 1 - this_cutsize;
00551 c1 = c1 * this_cutsize + c * cutleft;
00552 d1 = d1 * this_cutsize + d * cutleft;
00553
00554
00555 if (chisq_last >= 0) {
00556 chisq = this_cutsize*this_cutsize * chisq +
00557 cutleft*cutleft * chisq_last +
00558 2*this_cutsize*cutleft * psi_cut;
00559 psi_cut = this_cutsize * psi_cut + cutleft * chisq_last;
00560 }
00561 else
00562 chisq = chisq_last;
00563
00564
00565 if (_args.printfit()) {
00566 cout << constraint_sum << " cut " << ncut << " size "
00567 << setiosflags (ios_base::scientific)
00568 << this_cutsize << " tot size " << this_step_cutsize
00569 << resetiosflags (ios_base::scientific)
00570 << " " << chisq << "\n";
00571 }
00572
00573
00574 x = c1 + xm;
00575 y = d1 + ym;
00576
00577
00578 }
00579
00580
00581
00582 last_step_cutsize = this_step_cutsize;
00583
00584
00585
00586 double chisq_b = 0;
00587 if (_args.use_G()) {
00588 chisq_b = scalar (c1.T() * G * c1) + scalar (d1.T() * Y * d1);
00589 if (chisq >= 0 &&
00590 abs ((chisq - chisq_b) / chisq) > _args.chisq_test_eps()) {
00591 cout << chisq << " " << chisq_b
00592 << "lost precision?\n";
00593 abort ();
00594 }
00595 }
00596
00597
00598 if (_args.printfit()) {
00599 cout << chisq << " ";
00600 if (_args.use_G())
00601 cout << chisq_b << " ";
00602 }
00603
00604 double z2 = abs (chisq - chisq_last);
00605
00606 if (_args.printfit()) {
00607 cout << constraint_sum << " " << z2 << "\n";
00608 }
00609
00610 c = c1;
00611 d = d1;
00612 chisq_last = chisq;
00613 constraint_sum_last = constraint_sum;
00614
00615
00616
00617 if (chisq >= 0 && constraint_sum < _args.constraint_sum_eps() &&
00618 z2 < _args.chisq_diff_eps())
00619 {
00620 if (near_convergence) break;
00621 near_convergence = true;
00622 }
00623 else
00624 near_convergence = false;
00625
00626
00627 if (++nit > _args.maxit()) {
00628
00629
00630 return -995.0;
00631 }
00632
00633 } while (1);
00634
00635
00636
00637
00638
00639 Q = E * W * E.T();
00640 S = - E * V.T();
00641 R = U;
00642
00643
00644 pullx = Column_Vector (nvars);
00645 for (int i=1; i<=nvars; i++) {
00646 double a = Q(i,i);
00647 if (a < 0)
00648 pullx(i) = c(i) / sqrt (-a);
00649 else {
00650 pullx(i) = 0;
00651
00652 }
00653 }
00654
00655 pully = Column_Vector (nbadvars);
00656 for (int i=1; i<=nbadvars; i++) {
00657 double a = 1 - Y(i,i)*R(i,i);
00658 if (a > 0)
00659 pully(i) = d(i) * sqrt (Y(i,i) / a);
00660 else {
00661 pully(i) = 0;
00662
00663 }
00664 }
00665
00666
00667 Q = Q + G_i;
00668
00669
00670 return chisq_last;
00671 }
00672
00673
00674 std::ostream& Chisq_Constrainer::print (std:: ostream& s) const
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684 {
00685 Base_Constrainer::print (s);
00686 s << " printfit: " << _args.printfit()
00687 << " use_G: " << _args.use_G() << "\n";
00688 s << " constraint_sum_eps: " << _args.constraint_sum_eps()
00689 << " chisq_diff_eps: " << _args.chisq_diff_eps()
00690 << " chisq_test_eps: " << _args.chisq_test_eps() << "\n";
00691 s << " maxit: " << _args.maxit()
00692 << " max_cut: " << _args.max_cut()
00693 << " min_tot_cutsize: " << _args.min_tot_cutsize()
00694 << " cutsize: " << _args.cutsize() << "\n";
00695 return s;
00696 }
00697
00698
00699 }