CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
List of all members | Public Member Functions | Private Attributes
hitfit::Chisq_Constrainer Class Reference

Minimize a $\chi^{2}$ subject to a set of constraints. Based on the SQUAW algorithm. More...

#include <Chisq_Constrainer.h>

Inheritance diagram for hitfit::Chisq_Constrainer:
hitfit::Base_Constrainer

Public Member Functions

 Chisq_Constrainer (const Chisq_Constrainer_Args &args)
 
virtual double fit (Constraint_Calculator &constraint_calculator, const Column_Vector &xm, Column_Vector &x, const Column_Vector &ym, Column_Vector &y, const Matrix &G_i, const Diagonal_Matrix &Y, Column_Vector &pullx, Column_Vector &pully, Matrix &Q, Matrix &R, Matrix &S)
 
virtual std::ostream & print (std::ostream &s) const
 Print the state of this instance of Chisq_Constrainer. More...
 
virtual ~Chisq_Constrainer ()
 
- Public Member Functions inherited from hitfit::Base_Constrainer
 Base_Constrainer (const Base_Constrainer_Args &args)
 
virtual ~Base_Constrainer ()
 

Private Attributes

const Chisq_Constrainer_Args _args
 

Additional Inherited Members

- Protected Member Functions inherited from hitfit::Base_Constrainer
bool call_constraint_fcn (Constraint_Calculator &constraint_calculator, const Column_Vector &x, const Column_Vector &y, Row_Vector &F, Matrix &Bx, Matrix &By) const
 Helper function to evaluate constraints. This takes care of checking what the user function returns againts numerical derivatives, it that was requested. More...
 

Detailed Description

Minimize a $\chi^{2}$ subject to a set of constraints. Based on the SQUAW algorithm.

Definition at line 253 of file Chisq_Constrainer.h.

Constructor & Destructor Documentation

hitfit::Chisq_Constrainer::Chisq_Constrainer ( const Chisq_Constrainer_Args args)

Constructor. Create an instance of Chisq_Constrainer from a Chisq_Constrainer_Args object.

Parameters
argsThe parameter settings for this instance.

Definition at line 308 of file Chisq_Constrainer.cc.

316  _args (args)
317 {
318 }
const Base_Constrainer_Args & base_constrainer_args() const
Base_Constrainer(const Base_Constrainer_Args &args)
const Chisq_Constrainer_Args _args
virtual hitfit::Chisq_Constrainer::~Chisq_Constrainer ( )
inlinevirtual

Destructor.

Definition at line 275 of file Chisq_Constrainer.h.

275 {}

Member Function Documentation

double hitfit::Chisq_Constrainer::fit ( Constraint_Calculator constraint_calculator,
const Column_Vector xm,
Column_Vector x,
const Column_Vector ym,
Column_Vector y,
const Matrix G_i,
const Diagonal_Matrix Y,
Column_Vector pullx,
Column_Vector pully,
Matrix Q,
Matrix R,
Matrix S 
)
virtual

@ brief Do a constrained fit. Call the number of well-measured variables Nw, the number of poorly-measured variables Np, and the number of constraints Nc.

Parameters
constraint_calculatorThe object that will be used to evaluate the constraints.
xmMeasured values of the well-measured variables, has dimension Nw.
xBefore the fit: starting value of the well-measured variables for the fit, has dimension Nw. After the fit: final values of the well-measured variables.
ymMeasured values of the poorly-measured variables, has dimension Np.
yBefore the fit: starting value of the poorly-measured variables for the fit, has dimension Np. After the fit: final values of the poorly-measured variables.
G_iError matrix for the well-measured variables, has dimension Nw,Nw.
YInverse error matrix for the poorly-measured variables, has dimension Np,Np.
pullxPull quantities for the well-measured variables, has dimension Nw.
pullyPull quantities for the poorly-measured variables, has dimension Np.
QError matrix for the well-measured variables, has dimension Nw,Nw.
RError matrix for the poorly-measured variables, has dimension Np,Np.
SError matrix for the correlation between well-measured variables and poorly-measured variables, has dimension Nw,Np.
Input:
constraint_calculator, xm, x, ym, y, G_i, y..
Output:
x, y, pullx, pully, Q, R, S.
Return:
$\chi^{2}$ of the fit. Should returns a negative value if the fit does not converge.

cout << "singular matrix!";

Implements hitfit::Base_Constrainer.

Definition at line 321 of file Chisq_Constrainer.cc.

References _args, a, abs, alpha, beta, trackerHits::c, alignmentValidation::c1, hitfit::Base_Constrainer::call_constraint_fcn(), hitfit::Chisq_Constrainer_Args::chisq_diff_eps(), hitfit::Chisq_Constrainer_Args::chisq_test_eps(), hitfit::Chisq_Constrainer_Args::constraint_sum_eps(), gather_cfg::cout, hitfit::Chisq_Constrainer_Args::cutsize(), delta, F(), i, hitfit::Chisq_Constrainer_Args::max_cut(), hitfit::Chisq_Constrainer_Args::maxit(), hitfit::Chisq_Constrainer_Args::min_tot_cutsize(), hitfit::Constraint_Calculator::nconstraints(), hitfit::Chisq_Constrainer_Args::printfit(), dttmaxenums::R, hitfit::scalar(), mathSSE::sqrt(), and hitfit::Chisq_Constrainer_Args::use_G().

362 {
363  // Check that the various matrices we've been passed have consistent
364  // dimensionalities.
365  int nvars = x.num_row();
366  assert (nvars == G_i.num_col());
367  assert (nvars == xm.num_row());
368 
369  int nbadvars = y.num_row();
370  assert (nbadvars == Y.num_col());
371  assert (nbadvars == ym.num_row());
372 
373  // If we're going to check the chisq calculation by explicitly using G,
374  // calculate it now from its inverse G_i.
375  Matrix G (nvars, nvars);
376  if (_args.use_G()) {
377  int ierr = 0;
378  G = G_i.inverse (ierr);
379  assert (!ierr);
380  }
381 
382  int nconstraints = constraint_calculator.nconstraints ();
383 
384  // Results of the constraint evaluation function.
385  Row_Vector F (nconstraints); // Constraint vector.
386  Matrix Bx (nvars, nconstraints); // Gradients wrt x
387  Matrix By (nbadvars, nconstraints); // Gradients wrt y
388 
389  // (2) Evaluate the constraints at the starting point.
390  // If the starting point is rejected as invalid,
391  // give up and return an error.
392  if (! call_constraint_fcn (constraint_calculator, x, y, F, Bx, By)) {
393  // cout << "Bad initial values!";
394  // return -1000;
395  return -999.0;
396  }
397 
398  // (3) Initialize variables for the fitting loop.
399  double constraint_sum_last = -1000;
400  double chisq_last = -1000;
401  bool near_convergence = false;
402  double last_step_cutsize = 1;
403 
404  unsigned nit = 0;
405 
406  // Initialize the displacement vectors c and d.
407  Column_Vector c = x - xm;
408  Column_Vector d = y - ym;
409 
410  Matrix E (nvars, nconstraints);
411  Matrix W (nconstraints, nconstraints);
412  Matrix U (nbadvars, nbadvars);
413  Matrix V (nbadvars, nconstraints);
414 
415  // (4) Fitting loop:
416  do {
417  // (5) Calculate E, H, and r.
418  E = G_i * Bx;
419  Matrix H = E.T() * Bx;
420  Row_Vector r = c.T() * Bx + d.T() * By - F;
421 
422  // (6) Solve the linearized system for the new values
423  // of the Lagrange multipliers
424  // $\alpha$ and the new value for the displacements d.
425  Column_Vector alpha (nvars);
426  Column_Vector d1 (nbadvars);
427  if (!solve_linear_system (H, Y, By, r,
428  alpha, d1, W, U, V)) {
430  // return -1000;
431  return -998.0;
432  }
433 
434  // (7) Compute the new values for the displacements c and the chisq.
435  Column_Vector c1 = -E * alpha;
436  double chisq = - scalar (r * alpha);
437 
438  double psi_cut = 0;
439 
440  // (8) Find where this step is going to be taking us.
441  x = c1 + xm;
442  y = d1 + ym;
443 
444  // (9) Set up for cutting this step, should we have to.
445  Matrix save_By = By;
446  Row_Vector save_negF = - F;
447  double this_step_cutsize = 1;
448  double constraint_sum = -1;
449  unsigned ncut = 0;
450 
451  // (10) Evaluate the constraints at the new point.
452  // If the point is rejected, we have to try to cut the step.
453  // We accept the step if:
454  // The constraint sum is below the convergence threshold
455  // constraint_sum_eps, or
456  // This is the first iteration, or
457  // The constraint sum has decreased since the last iteration.
458  // Otherwise, the constraints have gotten worse, and we
459  // try to cut the step.
460  while (! call_constraint_fcn (constraint_calculator, x, y, F, Bx, By) ||
461  ((constraint_sum = norm_infinity (F))
463  nit > 0 &&
464  constraint_sum > constraint_sum_last))
465  {
466 
467  // Doing step cutting...
468  if (nit > 0 && _args.printfit() && ncut == 0) {
469  cout << "(" << chisq << " " << chisq_last << ") ";
470  }
471 
472  // (10a) If this is the first time we've tried to cut this step,
473  // test to see if the chisq is stationary. If it hasn't changed
474  // since the last iteration, try a directed step.
475  if (ncut == 0 &&
476  abs (chisq - chisq_last) < _args.chisq_diff_eps()) {
477 
478  // Trying a directed step now.
479  // Try to make the smallest step which satisfies the
480  // (linearized) constraints.
481  if (_args.printfit())
482  cout << " directed step ";
483 
484  // (10a.i) Solve the linearized system for $\beta$ and
485  // the y-displacement vector $\delta$.
486  Column_Vector beta (nconstraints);
487  Column_Vector delta (nbadvars);
488  solve_linear_system (H, Y, save_By, save_negF,
489  beta, delta, W, U, V);
490 
491  // (10a.ii) Get the x-displacement vector $\gamma$.
492  Column_Vector gamma = -E * beta;
493 
494  // (10a.iii) Find the destination of the directed step.
495  x = c + xm + gamma;
496  y = d + ym + delta;
497 
498  // (10a.iv) Accept this point if it's not rejected by the constraint
499  // function, and the constraints improve.
500  if (call_constraint_fcn (constraint_calculator, x, y, F, Bx, By) &&
501  (constraint_sum = norm_infinity (F)) > 0 &&
502  (constraint_sum < constraint_sum_last)) {
503 
504  // Accept this step. Calculate the chisq and new displacement
505  // vectors.
506  chisq = chisq_last - scalar ((-save_negF + r*2) * beta);
507  c1 = x - xm;
508  d1 = y - ym;
509 
510  // Exit from step cutting loop.
511  break;
512  }
513  }
514 
515  // If this is the first time we're cutting the step,
516  // initialize $\psi$.
517  if (ncut == 0)
518  psi_cut = scalar ((save_negF - r) * alpha);
519 
520  // (10b) Give up if we've tried to cut this step too many times.
521  if (++ncut > _args.max_cut()) {
522  // cout << " Too many cut steps ";
523  // return -1000;
524  return -997.0;
525  }
526 
527  // (10c) Set up the size by which we're going to cut this step.
528  // Normally, this is cutsize. But if this is the first time we're
529  // cutting this step and the last step was also cut, set the cut
530  // size to twice the final cut size from the last step (provided
531  // that it is less than cutsize).
532  double this_cutsize = _args.cutsize();
533  if (ncut == 1 && last_step_cutsize < 1) {
534  this_cutsize = 2 * last_step_cutsize;
535  if (this_cutsize > _args.cutsize())
536  this_cutsize = _args.cutsize();
537  }
538 
539  // (10d) Keep track of the total amount by which we've cut this step.
540  this_step_cutsize *= this_cutsize;
541 
542  // If it falls below min_tot_cutsize, give up.
543  if (this_step_cutsize < _args.min_tot_cutsize()) {
544  // cout << "Cut size underflow ";
545  // return -1000;
546  return -996.0;
547  }
548 
549  // (10e) Cut the step: calculate the new displacement vectors.
550  double cutleft = 1 - this_cutsize;
551  c1 = c1 * this_cutsize + c * cutleft;
552  d1 = d1 * this_cutsize + d * cutleft;
553 
554  // (10f) Calculate the new chisq.
555  if (chisq_last >= 0) {
556  chisq = this_cutsize*this_cutsize * chisq +
557  cutleft*cutleft * chisq_last +
558  2*this_cutsize*cutleft * psi_cut;
559  psi_cut = this_cutsize * psi_cut + cutleft * chisq_last;
560  }
561  else
562  chisq = chisq_last;
563 
564  // Log what we've done.
565  if (_args.printfit()) {
566  cout << constraint_sum << " cut " << ncut << " size "
567  << setiosflags (ios_base::scientific)
568  << this_cutsize << " tot size " << this_step_cutsize
569  << resetiosflags (ios_base::scientific)
570  << " " << chisq << "\n";
571  }
572 
573  // Find the new step destination.
574  x = c1 + xm;
575  y = d1 + ym;
576 
577  // Now, go and test the step again for acceptability.
578  }
579 
580  // (11) At this point, we have an acceptable step.
581  // Shuffle things around to prepare for the next step.
582  last_step_cutsize = this_step_cutsize;
583 
584  // If requested, calculate the chisq using G to test for
585  // possible loss of precision.
586  double chisq_b = 0;
587  if (_args.use_G()) {
588  chisq_b = scalar (c1.T() * G * c1) + scalar (d1.T() * Y * d1);
589  if (chisq >= 0 &&
590  abs ((chisq - chisq_b) / chisq) > _args.chisq_test_eps()) {
591  cout << chisq << " " << chisq_b
592  << "lost precision?\n";
593  abort ();
594  }
595  }
596 
597  // Log what we're doing.
598  if (_args.printfit()) {
599  cout << chisq << " ";
600  if (_args.use_G())
601  cout << chisq_b << " ";
602  }
603 
604  double z2 = abs (chisq - chisq_last);
605 
606  if (_args.printfit()) {
607  cout << constraint_sum << " " << z2 << "\n";
608  }
609 
610  c = c1;
611  d = d1;
612  chisq_last = chisq;
613  constraint_sum_last = constraint_sum;
614 
615  // (12) Test for convergence. The conditions must be satisfied
616  // for two iterations in a row.
617  if (chisq >= 0 && constraint_sum < _args.constraint_sum_eps() &&
618  z2 < _args.chisq_diff_eps())
619  {
620  if (near_convergence) break; // Converged! Exit loop.
621  near_convergence = true;
622  }
623  else
624  near_convergence = false;
625 
626  // (13) Give up if we've done this too many times.
627  if (++nit > _args.maxit()) {
628  // cout << "too many iterations";
629  // return -1000;
630  return -995.0;
631  }
632 
633  } while (1);
634 
635  // (15) Ok, we have a successful fit!
636 
637 
638  // Calculate the error matrices.
639  Q = E * W * E.T();
640  S = - E * V.T();
641  R = U;
642 
643  // And the vectors of pull functions.
644  pullx = Column_Vector (nvars);
645  for (int i=1; i<=nvars; i++) {
646  double a = Q(i,i);
647  if (a < 0)
648  pullx(i) = c(i) / sqrt (-a);
649  else {
650  pullx(i) = 0;
651  // cout << " bad pull fcn for var " << i << " (" << a << ") ";
652  }
653  }
654 
655  pully = Column_Vector (nbadvars);
656  for (int i=1; i<=nbadvars; i++) {
657  double a = 1 - Y(i,i)*R(i,i);
658  if (a > 0)
659  pully(i) = d(i) * sqrt (Y(i,i) / a);
660  else {
661  pully(i) = 0;
662  // cout << " bad pull fcn for badvar " << i << " ";
663  }
664  }
665 
666  // Finish calculation of Q.
667  Q = Q + G_i;
668 
669  // Return the final chisq.
670  return chisq_last;
671 }
const double beta
dbl * delta
Definition: mlp_gen.cc:36
int i
Definition: DBlmapReader.cc:9
float alpha
Definition: AMPTWrapper.h:95
CLHEP::HepVector Column_Vector
Definition: matutil.h:67
#define abs(x)
Definition: mlp_lapack.h:159
CLHEP::HepMatrix Matrix
Definition: matutil.h:66
T sqrt(T t)
Definition: SSEVec.h:46
bool call_constraint_fcn(Constraint_Calculator &constraint_calculator, const Column_Vector &x, const Column_Vector &y, Row_Vector &F, Matrix &Bx, Matrix &By) const
Helper function to evaluate constraints. This takes care of checking what the user function returns a...
double a
Definition: hdecay.h:121
const Chisq_Constrainer_Args _args
tuple cout
Definition: gather_cfg.py:121
static uInt32 F(BLOWFISH_CTX *ctx, uInt32 x)
Definition: blowfish.cc:281
x
Definition: VDTMath.h:216
Row-vector class. CLHEP doesn&#39;t have a row-vector class, so HitFit uses its own. This is only a simpl...
Definition: matutil.h:84
double scalar(const CLHEP::HepGenMatrix &m)
Return the matrix as a scalar. Raise an assertion if the matris is not .
Definition: matutil.cc:184
std::ostream & hitfit::Chisq_Constrainer::print ( std::ostream &  s) const
virtual

Print the state of this instance of Chisq_Constrainer.

Parameters
sThe output stream to which the output is sent.

Reimplemented from hitfit::Base_Constrainer.

Definition at line 674 of file Chisq_Constrainer.cc.

References hitfit::Base_Constrainer::print(), and alignCSCRings::s.

684 {
686  s << " printfit: " << _args.printfit()
687  << " use_G: " << _args.use_G() << "\n";
688  s << " constraint_sum_eps: " << _args.constraint_sum_eps()
689  << " chisq_diff_eps: " << _args.chisq_diff_eps()
690  << " chisq_test_eps: " << _args.chisq_test_eps() << "\n";
691  s << " maxit: " << _args.maxit()
692  << " max_cut: " << _args.max_cut()
693  << " min_tot_cutsize: " << _args.min_tot_cutsize()
694  << " cutsize: " << _args.cutsize() << "\n";
695  return s;
696 }
const Chisq_Constrainer_Args _args
virtual std::ostream & print(std::ostream &s) const
Print out internal state to output stream.

Member Data Documentation

const Chisq_Constrainer_Args hitfit::Chisq_Constrainer::_args
private

Parameter settings for this instance of Chisq_Constrainer.

Definition at line 377 of file Chisq_Constrainer.h.

Referenced by Vispa.Main.Application.Application::_readCommandLineAttributes(), and fit().