CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
GenericHouseholder.cc
Go to the documentation of this file.
1 
10 #include <cfloat>
11 #include <cmath>
12 
13 
15  :normaliseFlag(normalise)
16 {
17 }
18 
19 
21 {
22 }
23 
24 
25 std::vector<float> GenericHouseholder::iterate(const std::vector<std::vector<float> >& eventMatrix, const std::vector<float>& energyVector, const int nIter)
26 {
27  std::vector<float> solution;
28  std::vector<float> theCalibVector(energyVector.size(),1.);
29  std::vector<std::vector<float> > myEventMatrix(eventMatrix);
30  int Nevents = eventMatrix.size(); // Number of events to calibrate with
31  int Nchannels = eventMatrix[0].size(); // Number of channel coefficients
32 
33  // Iterate the correction
34  for (int iter=1;iter<=nIter;iter++)
35  {
36  // make one iteration
37  solution = iterate(myEventMatrix, energyVector);
38 
39  if (solution.empty()) return solution;
40  // R.O.: or throw an exception, what's the standard CMS way ?
41 
42  // re-calibrate eventMatrix with solution
43  for (int i=0; i<Nchannels; i++)
44  {
45  for (int ievent = 0; ievent<Nevents; ievent++)
46  {
47  myEventMatrix[ievent][i] *= solution[i];
48  }
49  // save solution into theCalibVector
50  theCalibVector[i] *= solution[i];
51  }
52 
53  } // end iterate the correction
54 
55  return theCalibVector;
56 }
57 
58 
59 std::vector<float> GenericHouseholder::iterate(const std::vector<std::vector<float> >& eventMatrix, const std::vector<float>& energyVector)
60 {
61  // An implementation of the Householder in-situ calibration algorithm
62  // (Least squares minimisation of residual R=b-Ax, with QR decomposition of A)
63  // A: matrix of channel response for all calib events
64  // x: vector of channel calibration coefficients
65  // b: vector of energies
66  // adapted from the original code by Matt Probert 9/08/01.
67 
68  std::vector<float> solution;
69 
70  unsigned int m=eventMatrix.size(); // Number of events to calibrate with
71  unsigned int n=eventMatrix[0].size(); // Number of channel coefficients to optimize
72 
73  std::cout << "Householder::runIter(): starting calibration optimization:" << std::endl;
74  std::cout << " Events:" << m << ", channels: " << n << std::endl;
75 
76  // Sanity check
77  if (m != energyVector.size())
78  {
79  std::cout << "Householder::runIter(): matrix dimensions non-conformant. " << std::endl;
80  std::cout << " energyVector.size()=" << energyVector.size() << std::endl;
81  std::cout << " eventMatrix[0].size()=" << eventMatrix[0].size() << std::endl;
82  std::cout << " ****************** ERROR *********************" << std::endl;
83  return solution; // empty vector
84  }
85 
86  // Reserve workspace
87  float e25p;
88  unsigned int i,j;
89  std::vector<std::vector<float> > A(eventMatrix);
90  std::vector<float> energies(energyVector);
91 
92  float normalisation = 0.;
93 
94  // Normalise if normaliseFlag is set
95  if (normaliseFlag)
96  {
97  std::cout << "Householder::iterate(): Normalising event data" << std::endl;
98  std::cout << " WARNING: assuming 5x5 filtering has already been done" << std::endl;
99 
100  for (i=0; i<m; i++)
101  {
102  e25p = 0.;
103  for (j=0;j<n;j++){
104  e25p += eventMatrix[i][j]; // lorenzo -> trying to use ESetup which already performs calibs on rechits
105  }
106  e25p /= energyVector[i];
107  normalisation += e25p; // SUM e25p for all events
108  }
109  normalisation/=m;
110  std::cout << " Normalisation = " << normalisation << std::endl;
111 
112  for (i=0;i<energies.size();++i)
113  energies[i]*=normalisation;
114  }
115 
116 
117  // This is where the work goes on...
118  // matrix decomposition
119  std::vector<std::vector<float> > Acopy(A);
120  std::vector<float> alpha(n);
121  std::vector<int> pivot(n);
122  if( !decompose(m, n, A, alpha, pivot)) {
123  std::cout << "Householder::runIter(): Failed: Singular condition in decomposition."
124  << std::endl;
125  std::cout << "***************** PROBLEM in DECOMPOSITION *************************"<<std::endl;
126  return solution; // empty vector
127  }
128 
129  /* DBL_EPSILON: Difference between 1.0 and the minimum float greater than 1.0 */
130  float etasqr = DBL_EPSILON*DBL_EPSILON;
131  std::cout<<"LOOK at DBL_EPSILON :"<<DBL_EPSILON<<std::endl;
132 
133  std::vector<float> r(energies); // copy energies vector
134  std::vector<float> e(n);
135 
136  // apply transformations to rhs - find solution vector
137  solution.assign(n,0.);
138  solve(m,n,A,alpha,pivot,r,solution);
139 
140  // compute residual vector r
141  for (i=0;i<m;i++) {
142  r[i]=energies[i];
143  for (j=0;j<n;j++)
144  r[i]-=Acopy[i][j]*solution[j];
145  }
146  // compute first correction vector e
147  solve(m,n,A,alpha,pivot,r,e);
148 
149  float normy0=0.;
150  float norme1=0.;
151  float norme0;
152 
153  for (i=0;i<n;i++) {
154  normy0+=solution[i]*solution[i];
155  norme1+=e[i]*e[i];
156  }
157 
158  std::cout << "Householder::runIter(): applying first correction" << std::endl;
159  std::cout << " normy0 = " << normy0 << std::endl;
160  std::cout << " norme1 = " << norme1 << std::endl;
161 
162  // not attempt at obtaining the solution is made unless the norm of the first
163  // correction is significantly smaller than the norm of the initial solution
164  if (norme1>(0.0625*normy0)) {
165  std::cout << "Householder::runIter(): first correction is too large. Failed."
166  << std::endl;
167  }
168 
169  // improve the solution
170  for (i=0;i<n;i++)
171  solution[i]+=e[i];
172 
173  std::cout << "Householder::runIter(): improving solution...." << std::endl;
174 
175  // only continue iteration if the correction was significant
176  while (norme1>(etasqr*normy0)) {
177  std::cout << "Householder::runIter(): norme1 = " << norme1 << std::endl;
178 
179  for (i=0;i<m;i++) {
180  r[i] = energies[i];
181  for (j=0;j<n;j++)
182  r[i]-=Acopy[i][j]*solution[j];
183  }
184 
185  // compute next correction vector
186  solve(m,n,A,alpha,pivot,r,e);
187 
188  norme0=norme1;
189  norme1=0.;
190  for (i=0;i<n;i++)
191  norme1+=e[i]*e[i];
192 
193  // terminate iteration if the norm of the new correction failed to decrease
194  // significantly compared to the norm of the previous correction
195  if (norme1>(0.0625*norme0))
196  break;
197 
198  // apply correction vector
199  for (i=0;i<n;i++)
200  solution[i]+=e[i];
201  }
202 
203 return solution;
204 }
205 
206 
207 bool GenericHouseholder::decompose(const int m, const int n, std::vector<std::vector<float> >& qr, std::vector<float>& alpha, std::vector<int>& pivot)
208 {
209  int i,j,jbar,k;
210  float beta,sigma,alphak,qrkk;
211  std::vector<float> y(n);
212  std::vector<float> sum(n);
213 
214  std::cout << "Householder::decompose() started" << std::endl;
215 
216  for (j=0;j<n;j++) {
217  // jth column sum
218 
219  sum[j]=0.;
220  for (i=0;i<m;i++)
221 // std::cout << "0: qr[i][j]" << qr[i][j] << " i = " << i << " j = " << j << std::endl;
222  sum[j]+=qr[i][j]*qr[i][j];
223 
224  pivot[j] = j;
225  }
226 
227  for (k=0;k<n;k++) {
228  // kth Householder transformation
229 
230  sigma = sum[k];
231  jbar = k;
232 
233  for (j=k+1;j<n;j++) {
234  if (sigma < sum[j]) {
235  sigma = sum[j];
236  jbar=j;
237  }
238  }
239 
240  if (jbar != k) {
241  // column interchange
242  i = pivot[k];
243  pivot[k]=pivot[jbar];
244  pivot[jbar]=i;
245  sum[jbar]=sum[k];
246  sum[k]=sigma;
247 
248  for (i=0;i<m;i++) {
249  sigma=qr[i][k];
250  qr[i][k]=qr[i][jbar];
251 // std::cout << "A: qr[i][k]" << qr[i][k] << " i = " << i << " k = " << k << std::endl;
252  qr[i][jbar]=sigma;
253 // std::cout << "B: qr[i][jbar]" << qr[i][k] << " i = " << i << " jbar = " << jbar << std::endl;
254  }
255  } // end column interchange
256 
257  sigma=0.;
258  for (i=k;i<m;i++){
259  sigma+=qr[i][k]*qr[i][k];
260 // std::cout << "C: qr[i][k]" << qr[i][k] << " i = " << i << " k = " << k << std::endl;
261 }
262 
263  if (sigma == 0.) {
264  std::cout << "Householder::decompose() failed" << std::endl;
265  return false;
266  }
267 
268  qrkk = qr[k][k];
269 
270  if (qrkk < 0.)
271  alpha[k] = sqrt(sigma);
272  else
273  alpha[k] = sqrt(sigma) * (-1.);
274  alphak = alpha[k];
275 
276  beta = 1/(sigma-qrkk*alphak);
277  qr[k][k]=qrkk-alphak;
278 
279  for (j=k+1;j<n;j++) {
280  y[j]=0.;
281  for (i=k;i<m;i++)
282  y[j]+=qr[i][k]*qr[i][j];
283  y[j]*=beta;
284  }
285 
286  for (j=k+1;j<n;j++) {
287 
288  for (i=k;i<m;i++) {
289  qr[i][j]-=qr[i][k]*y[j];
290  sum[j]-=qr[k][j]*qr[k][j];
291  }
292  }
293  } // end of kth householder transformation
294 
295  std::cout << "Householder::decompose() finished" << std::endl;
296 
297  return true;
298 }
299 
300 
301 void GenericHouseholder::solve(int m, int n, const std::vector<std::vector<float> > &qr, const std::vector<float> &alpha, const std::vector<int> &pivot,
302  std::vector<float> &r, std::vector<float> &y)
303 {
304  std::vector<float> z(n,0.);
305 
306  float gamma;
307  int i,j;
308 
309  std::cout << "Householder::solve() begin" << std::endl;
310 
311  for (j=0;j<n;j++) {
312  // apply jth transformation to the right hand side
313  gamma=0.;
314  for (i=j;i<m;i++)
315  gamma+=qr[i][j]*r[i];
316  gamma/=(alpha[j]*qr[j][j]);
317 
318  for (i=j;i<m;i++)
319  r[i]+=gamma*qr[i][j];
320  }
321 
322  // std::cout<<"OK1:"<<std::endl;
323  z[n-1]=r[n-1]/alpha[n-1];
324  // std::cout<<"OK2:"<<std::endl;
325 
326  for (i=n-2;i>=0;i--) {
327  z[i]= r[i];
328  for (j=i+1;j<n;j++)
329  z[i]-=qr[i][j]*z[j];
330  z[i]/=alpha[i];
331  }
332  // std::cout<<"OK3:"<<std::endl;
333 
334  for (i=0;i<n;i++)
335  y[pivot[i]]=z[i];
336 
337  std::cout << "Householder::solve() finished." << std::endl;
338 
339 }
const double beta
int i
Definition: DBlmapReader.cc:9
float alpha
Definition: AMPTWrapper.h:95
bool decompose(const int m, const int n, std::vector< std::vector< float > > &qr, std::vector< float > &alpha, std::vector< int > &pivot)
double double double z
void solve(int m, int n, const std::vector< std::vector< float > > &qr, const std::vector< float > &alpha, const std::vector< int > &pivot, std::vector< float > &r, std::vector< float > &y)
T sqrt(T t)
Definition: SSEVec.h:46
int j
Definition: DBlmapReader.cc:9
int k[5][pyjets_maxn]
GenericHouseholder(bool normalise=false)
std::vector< float > iterate(const std::vector< std::vector< float > > &eventMatrix, const std::vector< float > &energyVector, const int nIter)
run the Householder Algorithm several times (nIter). Returns the final vector of calibration coeffici...
tuple cout
Definition: gather_cfg.py:121
~GenericHouseholder()
Destructor.