CMS 3D CMS Logo

LeastSquares.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <iomanip>
3 #include <cstring>
4 #include <vector>
5 #include <cmath>
6 
7 #include <TMatrixD.h>
8 #include <TVectorD.h>
9 #include <TDecompSVD.h>
10 
12 
17 
19 
20 namespace PhysicsTools {
21 
23  coeffs(n + 2), covar(n + 1), corr(n + 1), rotation(n, n),
24  weights(n + 1), variance(n + 1), trace(n), n(n)
25 {
26 }
27 
29 {
30 }
31 
32 void LeastSquares::add(const std::vector<double> &values,
33  double dest, double weight)
34 {
35  if (values.size() != n)
36  throw cms::Exception("LeastSquares")
37  << "add(): invalid array size!" << std::endl;
38 
39  for(unsigned int i = 0; i < n; i++) {
40  for(unsigned int j = 0; j < n; j++)
41  coeffs(i, j) += values[i] * values[j] * weight;
42 
43  coeffs(n, i) += values[i] * dest * weight;
44  coeffs(i, n) += values[i] * dest * weight;
45  coeffs(n + 1, i) += values[i] * weight;
46  coeffs(i, n + 1) += values[i] * weight;
47  }
48 
49  coeffs(n, n) += dest * dest * weight;
50  coeffs(n + 1, n) += dest * weight;
51  coeffs(n, n + 1) += dest * weight;
52  coeffs(n + 1, n + 1) += weight;
53 }
54 
56 {
57  if (other.getSize() != n)
58  throw cms::Exception("LeastSquares")
59  << "add(): invalid array size!" << std::endl;
60 
61  coeffs += weight * other.coeffs;
62 }
63 
64 TVectorD LeastSquares::solveFisher(const TMatrixDSym &coeffs)
65 {
66  unsigned int n = coeffs.GetNrows() - 2;
67 
68  TMatrixDSym tmp;
69  coeffs.GetSub(0, n, tmp);
70  tmp[n] = TVectorD(n + 1, coeffs[n + 1].GetPtr());
71  tmp(n, n) = coeffs(n + 1, n + 1);
72 
73  TDecompSVD decCoeffs(tmp);
74  bool ok;
75  return decCoeffs.Solve(TVectorD(n + 1, coeffs[n].GetPtr()), ok);
76 }
77 
78 TMatrixD LeastSquares::solveRotation(const TMatrixDSym &covar, TVectorD &trace)
79 {
80  TMatrixDSym tmp;
81  covar.GetSub(0, covar.GetNrows() - 2, tmp);
82  TDecompSVD decCovar(tmp);
83  trace = decCovar.GetSig();
84  return decCovar.GetU();
85 }
86 
88 {
89  double N = coeffs(n + 1, n + 1);
90 
91  for(unsigned int i = 0; i <= n; i++) {
92  double M = coeffs(n + 1, i);
93  for(unsigned int j = 0; j <= n; j++)
94  covar(i, j) = coeffs(i, j) * N - M * coeffs(n + 1, j);
95  }
96 
97  for(unsigned int i = 0; i <= n; i++) {
98  double c = covar(i, i);
99  variance[i] = c > 0.0 ? std::sqrt(c) : 0.0;
100  }
101 
102  for(unsigned int i = 0; i <= n; i++) {
103  double M = variance[i];
104  for(unsigned int j = 0; j <= n; j++) {
105  double v = M * variance[j];
106  double w = covar(i, j);
107 
108  corr(i, j) = (v >= 1.0e-9) ? (w / v) : (i == j);
109  }
110  }
111 
114 }
115 
116 std::vector<double> LeastSquares::getWeights() const
117 {
118  std::vector<double> results;
119  results.reserve(n);
120 
121  for(unsigned int i = 0; i < n; i++)
122  results.push_back(weights[i]);
123 
124  return results;
125 }
126 
127 std::vector<double> LeastSquares::getMeans() const
128 {
129  std::vector<double> results;
130  results.reserve(n);
131 
132  double N = coeffs(n + 1, n + 1);
133  for(unsigned int i = 0; i < n; i++)
134  results.push_back(coeffs(n + 1, i) / N);
135 
136  return results;
137 }
138 
140 {
141  return weights[n];
142 }
143 
144 static void loadMatrix(DOMElement *elem, unsigned int n, TMatrixDBase &matrix)
145 {
146  if (std::strcmp(XMLSimpleStr(elem->getNodeName()),
147  "matrix") != 0)
148  throw cms::Exception("LeastSquares")
149  << "Expected matrix in data file."
150  << std::endl;
151 
152  unsigned int row = 0;
153  for(DOMNode *node = elem->getFirstChild();
154  node; node = node->getNextSibling()) {
155  if (node->getNodeType() != DOMNode::ELEMENT_NODE)
156  continue;
157 
158  if (std::strcmp(XMLSimpleStr(node->getNodeName()),
159  "row") != 0)
160  throw cms::Exception("LeastSquares")
161  << "Expected row tag in data file."
162  << std::endl;
163 
164  if (row >= n)
165  throw cms::Exception("LeastSquares")
166  << "Too many rows in data file." << std::endl;
167 
168  elem = static_cast<DOMElement*>(node);
169 
170  unsigned int col = 0;
171  for(DOMNode *subNode = elem->getFirstChild();
172  subNode; subNode = subNode->getNextSibling()) {
173  if (subNode->getNodeType() != DOMNode::ELEMENT_NODE)
174  continue;
175 
176  if (std::strcmp(XMLSimpleStr(subNode->getNodeName()),
177  "value") != 0)
178  throw cms::Exception("LeastSquares")
179  << "Expected value tag in data file."
180  << std::endl;
181 
182  if (col >= n)
183  throw cms::Exception("LeastSquares")
184  << "Too many columns in data file."
185  << std::endl;
186 
187  matrix(row, col) =
188  XMLDocument::readContent<double>(subNode);
189  col++;
190  }
191 
192  if (col != n)
193  throw cms::Exception("LeastSquares")
194  << "Missing columns in data file."
195  << std::endl;
196  row++;
197  }
198 
199  if (row != n)
200  throw cms::Exception("LeastSquares")
201  << "Missing rows in data file."
202  << std::endl;
203 }
204 
205 static void loadVector(DOMElement *elem, unsigned int n, TVectorD &vector)
206 {
207  if (std::strcmp(XMLSimpleStr(elem->getNodeName()),
208  "vector") != 0)
209  throw cms::Exception("LeastSquares")
210  << "Expected matrix in data file."
211  << std::endl;
212 
213  unsigned int col = 0;
214  for(DOMNode *node = elem->getFirstChild();
215  node; node = node->getNextSibling()) {
216  if (node->getNodeType() != DOMNode::ELEMENT_NODE)
217  continue;
218 
219  if (std::strcmp(XMLSimpleStr(node->getNodeName()),
220  "value") != 0)
221  throw cms::Exception("LeastSquares")
222  << "Expected value tag in data file."
223  << std::endl;
224 
225  if (col >= n)
226  throw cms::Exception("LeastSquares")
227  << "Too many columns in data file."
228  << std::endl;
229 
230  vector(col) = XMLDocument::readContent<double>(node);
231  col++;
232  }
233 
234  if (col != n)
235  throw cms::Exception("LeastSquares")
236  << "Missing columns in data file."
237  << std::endl;
238 }
239 
240 static DOMElement *saveMatrix(DOMDocument *doc, unsigned int n,
241  const TMatrixDBase &matrix)
242 {
243  DOMElement *root = doc->createElement(XMLUniStr("matrix"));
244  XMLDocument::writeAttribute<unsigned int>(root, "size", n);
245 
246  for(unsigned int i = 0; i < n; i++) {
247  DOMElement *row = doc->createElement(XMLUniStr("row"));
248  root->appendChild(row);
249 
250  for(unsigned int j = 0; j < n; j++) {
251  DOMElement *value =
252  doc->createElement(XMLUniStr("value"));
253  row->appendChild(value);
254 
255  XMLDocument::writeContent<double>(value, doc,
256  matrix(i, j));
257  }
258  }
259 
260  return root;
261 }
262 
263 static DOMElement *saveVector(DOMDocument *doc, unsigned int n,
264  const TVectorD &vector)
265 {
266  DOMElement *root = doc->createElement(XMLUniStr("vector"));
267  XMLDocument::writeAttribute<unsigned int>(root, "size", n);
268 
269  for(unsigned int i = 0; i < n; i++) {
270  DOMElement *value =
271  doc->createElement(XMLUniStr("value"));
272  root->appendChild(value);
273 
274  XMLDocument::writeContent<double>(value, doc, vector(i));
275  }
276 
277  return root;
278 }
279 
280 void LeastSquares::load(DOMElement *elem)
281 {
282  if (std::strcmp(XMLSimpleStr(elem->getNodeName()),
283  "LinearAnalysis") != 0)
284  throw cms::Exception("LeastSquares")
285  << "Expected LinearAnalysis in data file."
286  << std::endl;
287 
288  unsigned int version = XMLDocument::readAttribute<unsigned int>(
289  elem, "version", 1);
290 
291  enum Position {
292  POS_COEFFS, POS_COVAR, POS_CORR, POS_ROTATION,
293  POS_SUMS, POS_WEIGHTS, POS_VARIANCE, POS_TRACE, POS_DONE
294  } pos = POS_COEFFS;
295 
296  for(DOMNode *node = elem->getFirstChild();
297  node; node = node->getNextSibling()) {
298  if (node->getNodeType() != DOMNode::ELEMENT_NODE)
299  continue;
300 
301  DOMElement *elem = static_cast<DOMElement*>(node);
302 
303  switch(pos) {
304  case POS_COEFFS:
305  if (version < 2) {
306  loadMatrix(elem, n + 1, coeffs);
307  coeffs.ResizeTo(n + 2, n + 2);
308  for(unsigned int i = 0; i <= n; i++) {
309  coeffs(n + 1, i) = coeffs(n, i);
310  coeffs(i, n + 1) = coeffs(i, n);
311  }
312  coeffs(n + 1, n + 1) = coeffs(n + 1, n);
313  } else
314  loadMatrix(elem, n + 2, coeffs);
315  break;
316  case POS_COVAR:
317  if (version < 2)
318  loadMatrix(elem, n, covar);
319  else
320  loadMatrix(elem, n + 1, covar);
321  break;
322  case POS_CORR:
323  if (version < 2)
324  loadMatrix(elem, n, corr);
325  else
326  loadMatrix(elem, n + 1, corr);
327  break;
328  case POS_ROTATION:
329  loadMatrix(elem, n, rotation);
330  break;
331  case POS_SUMS:
332  if (version < 2) {
333  TVectorD tmp(n + 1);
334  loadVector(elem, n + 1, tmp);
335 
336  double M = coeffs(n + 1, n);
337  double N = coeffs(n + 1, n + 1);
338 
339  for(unsigned int i = 0; i <= n; i++) {
340  double v = coeffs(n, i) * N -
341  M * coeffs(n + 1, i);
342  double w = coeffs(n, i) * N - v;
343 
344  covar(n, i) = w;
345  covar(i, n) = w;
346  }
347 
348  break;
349  } else
350  pos = (Position)(pos + 1);
351  case POS_WEIGHTS:
352  loadVector(elem, n + 1, weights);
353  break;
354  case POS_VARIANCE:
355  if (version < 2) {
356  loadVector(elem, n, variance);
357 
358  double M = covar(n, n);
359  M = M > 0.0 ? std::sqrt(M) : 0.0;
360  variance[n] = M;
361 
362  for(unsigned int i = 0; i <= n; i++) {
363  double v = M * variance[i];
364  double w = covar(n, i);
365  double c = (v >= 1.0e-9)
366  ? (w / v) : (i == n);
367 
368  corr(n, i) = c;
369  corr(i, n) = c;
370  }
371  } else
372  loadVector(elem, n + 1, variance);
373  break;
374  case POS_TRACE:
375  loadVector(elem, n, trace);
376  break;
377  default:
378  throw cms::Exception("LeastSquares")
379  << "Superfluous content in data file."
380  << std::endl;
381  }
382 
383  pos = (Position)(pos + 1);
384  }
385 
386  if (pos != POS_DONE)
387  throw cms::Exception("LeastSquares")
388  << "Missing objects in data file."
389  << std::endl;
390 }
391 
392 DOMElement *LeastSquares::save(DOMDocument *doc) const
393 {
394  DOMElement *root = doc->createElement(XMLUniStr("LinearAnalysis"));
395  XMLDocument::writeAttribute<unsigned int>(root, "version", 2);
396  XMLDocument::writeAttribute<unsigned int>(root, "size", n);
397 
398  root->appendChild(saveMatrix(doc, n + 2, coeffs));
399  root->appendChild(saveMatrix(doc, n + 1, covar));
400  root->appendChild(saveMatrix(doc, n + 1, corr));
401  root->appendChild(saveMatrix(doc, n, rotation));
402  root->appendChild(saveVector(doc, n + 1, weights));
403  root->appendChild(saveVector(doc, n + 1, variance));
404  root->appendChild(saveVector(doc, n, trace));
405 
406  return root;
407 }
408 
409 } // namespace PhysicsTools
std::vector< double > getWeights() const
static void loadMatrix(DOMElement *elem, unsigned int n, TMatrixDBase &matrix)
const double w
Definition: UKUtility.cc:23
static TVectorD solveFisher(const TMatrixDSym &coeffs)
Definition: LeastSquares.cc:64
double getConstant() const
unsigned int getSize() const
Definition: LeastSquares.h:29
Definition: weight.py:1
T trace(ROOT::Math::SMatrix< T, N, N > const &matrix)
static void loadVector(DOMElement *elem, unsigned int n, TVectorD &vector)
const unsigned int n
Definition: LeastSquares.h:51
T sqrt(T t)
Definition: SSEVec.h:18
XERCES_CPP_NAMESPACE_QUALIFIER DOMElement * save(XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc) const
Definition: value.py:1
static DOMElement * saveVector(DOMDocument *doc, unsigned int n, const TVectorD &vector)
JetCorrectorParameters corr
Definition: classes.h:5
def elem(elemtype, innerHTML='', html_class='', kwargs)
Definition: HTMLExport.py:18
static TMatrixD solveRotation(const TMatrixDSym &covar, TVectorD &trace)
Definition: LeastSquares.cc:78
#define N
Definition: blowfish.cc:9
LeastSquares(unsigned int n)
Definition: LeastSquares.cc:22
void load(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *elem)
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
col
Definition: cuy.py:1008
static DOMElement * saveMatrix(DOMDocument *doc, unsigned int n, const TMatrixDBase &matrix)
void add(const std::vector< double > &values, double dest, double weight=1.0)
Definition: LeastSquares.cc:32
std::vector< double > getMeans() const