CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_6/src/TopQuarkAnalysis/TopHitFit/src/Base_Constrainer.cc

Go to the documentation of this file.
00001 //
00002 // $Id: Base_Constrainer.cc,v 1.1 2011/05/26 09:46:59 mseidel Exp $
00003 //
00004 // File: src/Base_Constrainer.cc
00005 // Purpose: Abstract base for the chisq fitter classes.
00006 //          This allows for different algorithms to be used.
00007 // Created: Jul, 2000, sss, based on run 1 mass analysis code.
00008 //
00009 // CMSSW File      : src/Base_Constrainer.cc
00010 // Original Author : Scott Stuart Snyder <snyder@bnl.gov> for D0
00011 // Imported to CMSSW by Haryo Sumowidagdo <Suharyo.Sumowidagdo@cern.ch>
00012 //
00013 
00040 #include "TopQuarkAnalysis/TopHitFit/interface/Base_Constrainer.h"
00041 #include "TopQuarkAnalysis/TopHitFit/interface/matutil.h"
00042 #include "TopQuarkAnalysis/TopHitFit/interface/Defaults.h"
00043 #include <iostream>
00044 #include <cmath>
00045 #include <cstdlib>
00046 
00047 using std::abort;
00048 using std::abs;
00049 using std::cout;
00050 using std::ostream;
00051 
00052 
00053 //*************************************************************************
00054 // Helper function for doing gradient testing.
00055 //
00056 
00057 
00058 namespace {
00059 
00073 bool test_different (double a, double b, double c, double eps)
00074 //
00075 // Purpose: Test if A is significantly different than B.
00076 //          C sets the scale for the comparison; EPS gives
00077 //          by how much they may differ.
00078 //
00079 {
00080   double scale = eps * (abs (a) + abs (b) + abs (c));
00081   if (abs (a) != 0 && abs (b) / abs (a) < 0.1 && abs (a) > scale)
00082     scale = abs (a) * .5;
00083   if (scale == 0) return false;
00084   if (scale < eps) scale = eps;
00085   return abs (a - b) > scale;
00086 }
00087 
00088 
00089 } // unnamed namespace
00090 
00091 
00092 //*************************************************************************
00093 
00094 
00095 namespace hitfit {
00096 
00097 
00098 //*************************************************************************
00099 
00100 
00101 Base_Constrainer_Args::Base_Constrainer_Args (const Defaults& defs)
00102 //
00103 // Purpose: Constructor.
00104 //
00105 // Inputs:
00106 //   defs -        The Defaults instance from which to initialize.
00107 //
00108   : _test_gradient (defs.get_bool ("test_gradient")),
00109     _test_step (defs.get_float ("test_step")),
00110     _test_eps (defs.get_float ("test_eps"))
00111 {
00112 }
00113 
00114 
00115 bool Base_Constrainer_Args::test_gradient () const
00116 //
00117 // Purpose: Return the test_gradient parameter.
00118 //          See the header for documentation.
00119 //
00120 {
00121   return _test_gradient;
00122 }
00123 
00124 
00125 double Base_Constrainer_Args::test_step () const
00126 //
00127 // Purpose: Return the test_step parameter.
00128 //          See the header for documentation.
00129 //
00130 {
00131   return _test_step;
00132 }
00133 
00134 
00135 double Base_Constrainer_Args::test_eps () const
00136 //
00137 // Purpose: Return the test_eps parameter.
00138 //          See the header for documentation.
00139 //
00140 {
00141   return _test_eps;
00142 }
00143 
00144 
00145 //*************************************************************************
00146 
00147 
00148 Constraint_Calculator::Constraint_Calculator (int nconstraints)
00149 //
00150 // Purpose: Constructor.
00151 //
00152 // Inputs:
00153 //   nconstraints- The number of constraint functions.
00154 //
00155   : _nconstraints (nconstraints)
00156 {
00157 }
00158 
00159 
00160 int Constraint_Calculator::nconstraints () const
00161 //
00162 // Purpose: Return the number of constraint functions.
00163 //
00164 // Returns:
00165 //   The number of constraint functions.
00166 //
00167 {
00168   return _nconstraints;
00169 }
00170 
00171 
00172 //*************************************************************************
00173 
00174 
00175 Base_Constrainer::Base_Constrainer (const Base_Constrainer_Args& args)
00176 //
00177 // Purpose: Constructor.
00178 //
00179 // Inputs:
00180 //   args -        The parameter settings for this instance.
00181 //
00182   : _args (args)
00183 {
00184 }
00185 
00186 
00187 std::ostream& Base_Constrainer::print (std::ostream& s) const
00188 //
00189 // Purpose: Print our state.
00190 //
00191 // Inputs:
00192 //   s -           The stream to which to write.
00193 //
00194 // Returns:
00195 //   The stream S.
00196 //
00197 {
00198   s << "Base_Constrainer parameters:\n";
00199   s << " test_gradient: " << _args.test_gradient()
00200     << " test_step: " << _args.test_step()
00201     << " test_eps: " << _args.test_eps() << "\n";
00202   return s;
00203 }
00204 
00205 
00215 std::ostream& operator<< (std::ostream& s, const Base_Constrainer& f)
00216 //
00217 // Purpose: Print our state.
00218 //
00219 // Inputs:
00220 //   s -           The stream to which to write.
00221 //   f -           The instance to dump.
00222 //
00223 // Returns:
00224 //   The stream S.
00225 //
00226 {
00227   return f.print (s);
00228 }
00229 
00230 
00231 bool Base_Constrainer::call_constraint_fcn (Constraint_Calculator&
00232                                             constraint_calculator,
00233                                             const Column_Vector& x,
00234                                             const Column_Vector& y,
00235                                             Row_Vector& F,
00236                                             Matrix& Bx,
00237                                             Matrix& By) const
00238 //
00239 // Purpose: Call the constraint function for the point x, y.
00240 //          Return F, Bx, By, and a flag saying if the
00241 //          point is acceptable.
00242 //
00243 //          If test_gradient is on, we verify the gradients returned
00244 //          by also computing them numerically.
00245 //
00246 // Inputs:
00247 //   constraints - The user-supplied object to evaluate the constraints.
00248 //   x(Nw) -       Vector of well-measured quantities where we evaluate
00249 //                 the constraints.
00250 //   y(Np) -       Vector of poorly-measured quantities where we evaluate
00251 //                 the constraints.
00252 //
00253 // Outputs:
00254 //   F(Nc) -       The results of the constraint functions.
00255 //   Bx(Nw,Nc) -   Gradients of F with respect to x.
00256 //   By(Np,Nc) -   Gradients of F with respect to y.
00257 //
00258 // Returns:
00259 //   True if the point is accepted, false if it was rejected.
00260 {
00261   // Call the user's function.
00262   bool val = constraint_calculator.eval (x, y, F, Bx, By);
00263 
00264   // If we're not doing gradients numerically, we're done.
00265   if (!_args.test_gradient())
00266     return val;
00267 
00268   // Bail if the point was rejected.
00269   if (!val)
00270     return false;
00271 
00272   int Nw = x.num_row();
00273   int Np = y.num_row();
00274   int Nc = F.num_col();
00275 
00276   // Numerically check Bx.
00277   for (int i=1; i<=Nc; i++) {
00278     // Step a little along variable I.
00279     Column_Vector step_x (Nw, 0);
00280     step_x(i) = _args.test_step();
00281     Column_Vector new_x = x + step_x;
00282 
00283     // Evaluate the constraints at the new point.
00284     Matrix new_Bx (Nw, Nc);
00285     Matrix new_By (Np, Nc);
00286     Row_Vector new_F (Nc);
00287     if (! constraint_calculator.eval (new_x, y, new_F, new_Bx, new_By))
00288       return false;
00289 
00290     // Calculate what we expect the constraints to be at this point,
00291     // given the user's gradients.
00292     Row_Vector test_F = F + step_x.T() * Bx;
00293 
00294     // Check the results.
00295     for (int j=1; j<=Nc; j++) {
00296       if (test_different (test_F(j), new_F(j), F(j), _args.test_eps())) {
00297         cout << "bad gradient x " << i << " " << j << "\n";
00298         cout << x;
00299         cout << y;
00300         cout << new_x;
00301         cout << F;
00302         cout << new_F;
00303         cout << Bx;
00304         cout << (test_F - new_F);
00305         abort ();
00306       }
00307     }
00308   }
00309 
00310   // Numerically check By.
00311   for (int i=1; i<=Np; i++) {
00312     // Step a little along variable I.
00313     Column_Vector step_y (Np, 0);
00314     step_y(i) = _args.test_step();
00315     Column_Vector new_y = y + step_y;
00316 
00317     // Evaluate the constraints at the new point.
00318     Matrix new_Bx (Nw, Nc);
00319     Matrix new_By (Np, Nc);
00320     Row_Vector new_F (Nc);
00321     if (! constraint_calculator.eval (x, new_y, new_F, new_Bx, new_By))
00322       return false;
00323 
00324     // Calculate what we expect the constraints to be at this point,
00325     // given the user's gradients.
00326     Row_Vector test_F = F + step_y.T() * By;
00327 
00328     // Check the results.
00329     for (int j=1; j<=Nc; j++) {
00330       if (test_different (test_F(j), new_F(j), F(j), _args.test_eps())) {
00331         cout << "bad gradient y " << i << " " << j << "\n";
00332         cout << x;
00333         cout << y;
00334         cout << new_y;
00335         cout << F;
00336         cout << new_F;
00337         cout << Bx;
00338         cout << (test_F - new_F);
00339         abort ();
00340       }
00341     }
00342   }
00343 
00344   // Done!
00345   return true;
00346 }
00347 
00348 
00349 } // namespace hitfit