CMS 3D CMS Logo

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