CMS 3D CMS Logo

BorderedBandMatrix.cc
Go to the documentation of this file.
1 /*
2  * BorderedBandMatrix.cpp
3  *
4  * Created on: Aug 14, 2011
5  * Author: kleinwrt
6  */
7 
31 using namespace Eigen;
32 
34 namespace gbl {
35 
37  BorderedBandMatrix::BorderedBandMatrix() :
38  numSize(0), numBorder(0), numBand(0), numCol(0) {
39  }
40 
42  }
43 
45 
50  void BorderedBandMatrix::resize(unsigned int nSize, unsigned int nBorder,
51  unsigned int nBand) {
52  numSize = nSize;
53  numBorder = nBorder;
54  numCol = nSize - nBorder;
55  numBand = 0;
58  theBand.resize((nBand + 1), numCol);
59  }
60 
62 
71  const std::vector<unsigned int>* anIndex,
72  const std::vector<double>* aVector) {
73  int nBorder = numBorder;
74  for (unsigned int i = 0; i < anIndex->size(); ++i) {
75  int iIndex = (*anIndex)[i] - 1; // anIndex has to be sorted
76  for (unsigned int j = 0; j <= i; ++j) {
77  int jIndex = (*anIndex)[j] - 1;
78  if (iIndex < nBorder) {
79  theBorder(iIndex, jIndex) += (*aVector)[i] * aWeight
80  * (*aVector)[j];
81  } else if (jIndex < nBorder) {
82  theMixed(jIndex, iIndex - nBorder) += (*aVector)[i] * aWeight
83  * (*aVector)[j];
84  } else {
85  unsigned int nBand = iIndex - jIndex;
86  theBand(nBand, jIndex - nBorder) += (*aVector)[i] * aWeight
87  * (*aVector)[j];
88  numBand = std::max(numBand, nBand); // update band width
89  }
90  }
91  }
92  }
93 
95 
104  void BorderedBandMatrix::addBlockMatrix(double aWeight, unsigned int aSize,
105  unsigned int* anIndex, double* aVector) {
106  int nBorder = numBorder;
107  for (unsigned int i = 0; i < aSize; ++i) {
108  int iIndex = anIndex[i] - 1; // anIndex has to be sorted
109  for (unsigned int j = 0; j <= i; ++j) {
110  int jIndex = anIndex[j] - 1;
111  if (iIndex < nBorder) {
112  theBorder(iIndex, jIndex) += aVector[i] * aWeight * aVector[j];
113  } else if (jIndex < nBorder) {
114  theMixed(jIndex, iIndex - nBorder) += aVector[i] * aWeight
115  * aVector[j];
116  } else {
117  unsigned int nBand = iIndex - jIndex;
118  theBand(nBand, jIndex - nBorder) += aVector[i] * aWeight
119  * aVector[j];
120  numBand = std::max(numBand, nBand); // update band width
121  }
122  }
123  }
124  }
125 
127 
132  const std::vector<unsigned int> anIndex) const {
133 
134  MatrixXd aMatrix(anIndex.size(), anIndex.size());
135  int nBorder = numBorder;
136  for (unsigned int i = 0; i < anIndex.size(); ++i) {
137  int iIndex = anIndex[i] - 1; // anIndex has to be sorted
138  for (unsigned int j = 0; j <= i; ++j) {
139  int jIndex = anIndex[j] - 1;
140  if (iIndex < nBorder) {
141  aMatrix(i, j) = theBorder(iIndex, jIndex); // border part of inverse
142  } else if (jIndex < nBorder) {
143  aMatrix(i, j) = -theMixed(jIndex, iIndex - nBorder); // mixed part of inverse
144  } else {
145  unsigned int nBand = iIndex - jIndex;
146  aMatrix(i, j) = theBand(nBand, jIndex - nBorder); // band part of inverse
147  }
148  aMatrix(j, i) = aMatrix(i, j);
149  }
150  }
151  return aMatrix;
152  }
153 
155 
160  MatrixXd BorderedBandMatrix::getBlockMatrix(unsigned int aSize,
161  unsigned int* anIndex) const {
162 
163  MatrixXd aMatrix(aSize, aSize);
164  int nBorder = numBorder;
165  for (unsigned int i = 0; i < aSize; ++i) {
166  int iIndex = anIndex[i] - 1; // anIndex has to be sorted
167  for (unsigned int j = 0; j <= i; ++j) {
168  int jIndex = anIndex[j] - 1;
169  if (iIndex < nBorder) {
170  aMatrix(i, j) = theBorder(iIndex, jIndex); // border part of inverse
171  } else if (jIndex < nBorder) {
172  aMatrix(i, j) = -theMixed(jIndex, iIndex - nBorder); // mixed part of inverse
173  } else {
174  unsigned int nBand = iIndex - jIndex;
175  aMatrix(i, j) = theBand(nBand, jIndex - nBorder); // band part of inverse
176  }
177  aMatrix(j, i) = aMatrix(i, j);
178  }
179  }
180  return aMatrix;
181  }
182 
184 
211  const VVector &aRightHandSide, VVector &aSolution) {
212 
213  // decompose band
214  decomposeBand();
215  // invert band
216  VMatrix inverseBand = invertBand();
217  if (numBorder > 0) { // need to use block matrix decomposition to solve
218  // solve for mixed part
219  const VMatrix auxMat = solveBand(theMixed);// = Xt
220  const VMatrix auxMatT = auxMat.transpose();// = X
221  // solve for border part
222  const VVector auxVec = aRightHandSide.getVec(numBorder)
223  - auxMat * aRightHandSide.getVec(numCol, numBorder);// = b1 - Xt*b2
224  VSymMatrix inverseBorder = theBorder - theMixed * auxMatT;
225  inverseBorder.invert();// = E
226  const VVector borderSolution = inverseBorder * auxVec;// = x1
227  // solve for band part
228  const VVector bandSolution = solveBand(
229  aRightHandSide.getVec(numCol, numBorder));// = x
230  aSolution.putVec(borderSolution);
231  aSolution.putVec(bandSolution - auxMatT * borderSolution, numBorder);// = x2
232  // parts of inverse
233  theBorder = inverseBorder;// E
234  theMixed = inverseBorder * auxMat;// E*Xt (-mixed part of inverse) !!!
235  theBand = inverseBand + bandOfAVAT(auxMatT, inverseBorder);// band(D^-1 + X*E*Xt)
236  } else {
237  aSolution.putVec(solveBand(aRightHandSide));
238  theBand = inverseBand;
239  }
240  }
241 
244  std::cout << "Border part " << std::endl;
245  theBorder.print();
246  std::cout << "Mixed part " << std::endl;
247  theMixed.print();
248  std::cout << "Band part " << std::endl;
249  theBand.print();
250  }
251 
252  /*============================================================================
253  from Dbandmatrix.F (MillePede-II by V. Blobel, Univ. Hamburg)
254  ============================================================================*/
256 
263 
264  int nRow = numBand + 1;
265  int nCol = numCol;
266  VVector auxVec(nCol);
267  for (int i = 0; i < nCol; ++i) {
268  auxVec(i) = theBand(0, i) * 16.0; // save diagonal elements
269  }
270  for (int i = 0; i < nCol; ++i) {
271  if ((theBand(0, i) + auxVec(i)) != theBand(0, i)) {
272  theBand(0, i) = 1.0 / theBand(0, i);
273  if (theBand(0, i) < 0.) {
274  throw 3; // not positive definite
275  }
276  } else {
277  theBand(0, i) = 0.0;
278  throw 2; // singular
279  }
280  for (int j = 1; j < std::min(nRow, nCol - i); ++j) {
281  double rxw = theBand(j, i) * theBand(0, i);
282  for (int k = 0; k < std::min(nRow, nCol - i) - j; ++k) {
283  theBand(k, i + j) -= theBand(k + j, i) * rxw;
284  }
285  theBand(j, i) = rxw;
286  }
287  }
288  }
289 
291 
297  VVector BorderedBandMatrix::solveBand(const VVector &aRightHandSide) const {
298 
299  int nRow = theBand.getNumRows();
300  int nCol = theBand.getNumCols();
301  VVector aSolution(aRightHandSide);
302  for (int i = 0; i < nCol; ++i) // forward substitution
303  {
304  for (int j = 1; j < std::min(nRow, nCol - i); ++j) {
305  aSolution(j + i) -= theBand(j, i) * aSolution(i);
306  }
307  }
308  for (int i = nCol - 1; i >= 0; i--) // backward substitution
309  {
310  double rxw = theBand(0, i) * aSolution(i);
311  for (int j = 1; j < std::min(nRow, nCol - i); ++j) {
312  rxw -= theBand(j, i) * aSolution(j + i);
313  }
314  aSolution(i) = rxw;
315  }
316  return aSolution;
317  }
318 
320 
326  VMatrix BorderedBandMatrix::solveBand(const VMatrix &aRightHandSide) const {
327 
328  int nRow = theBand.getNumRows();
329  int nCol = theBand.getNumCols();
330  VMatrix aSolution(aRightHandSide);
331  for (unsigned int iBorder = 0; iBorder < numBorder; iBorder++) {
332  for (int i = 0; i < nCol; ++i) // forward substitution
333  {
334  for (int j = 1; j < std::min(nRow, nCol - i); ++j) {
335  aSolution(iBorder, j + i) -= theBand(j, i)
336  * aSolution(iBorder, i);
337  }
338  }
339  for (int i = nCol - 1; i >= 0; i--) // backward substitution
340  {
341  double rxw = theBand(0, i) * aSolution(iBorder, i);
342  for (int j = 1; j < std::min(nRow, nCol - i); ++j) {
343  rxw -= theBand(j, i) * aSolution(iBorder, j + i);
344  }
345  aSolution(iBorder, i) = rxw;
346  }
347  }
348  return aSolution;
349  }
350 
352 
356 
357  int nRow = numBand + 1;
358  int nCol = numCol;
359  VMatrix inverseBand(nRow, nCol);
360 
361  for (int i = nCol - 1; i >= 0; i--) {
362  double rxw = theBand(0, i);
363  for (int j = i; j >= std::max(0, i - nRow + 1); j--) {
364  for (int k = j + 1; k < std::min(nCol, j + nRow); ++k) {
365  rxw -= inverseBand(abs(i - k), std::min(i, k))
366  * theBand(k - j, j);
367  }
368  inverseBand(i - j, j) = rxw;
369  rxw = 0.;
370  }
371  }
372  return inverseBand;
373  }
374 
376 
380  const VSymMatrix &aSymArray) const {
381  int nBand = numBand;
382  int nCol = numCol;
383  int nBorder = numBorder;
384  double sum;
385  VMatrix aBand((nBand + 1), nCol);
386  for (int i = 0; i < nCol; ++i) {
387  for (int j = std::max(0, i - nBand); j <= i; ++j) {
388  sum = 0.;
389  for (int l = 0; l < nBorder; ++l) { // diagonal
390  sum += anArray(i, l) * aSymArray(l, l) * anArray(j, l);
391  for (int k = 0; k < l; ++k) { // off diagonal
392  sum += anArray(i, l) * aSymArray(l, k) * anArray(j, k)
393  + anArray(i, k) * aSymArray(l, k) * anArray(j, l);
394  }
395  }
396  aBand(i - j, j) = sum;
397  }
398  }
399  return aBand;
400  }
401 
402 }
void printMatrix() const
Print bordered band matrix.
VVector getVec(unsigned int len, unsigned int start=0) const
Get part of vector.
Definition: VMatrix.cc:273
void addBlockMatrix(double aWeight, const std::vector< unsigned int > *anIndex, const std::vector< double > *aVector)
Add symmetric block matrix.
void print() const
Print matrix.
Definition: VMatrix.cc:189
unsigned int getNumRows() const
Get number of rows.
Definition: VMatrix.cc:79
Simple Matrix based on std::vector<double>
Definition: VMatrix.h:63
Eigen::MatrixXd getBlockMatrix(const std::vector< unsigned int > anIndex) const
Retrieve symmetric block matrix.
unsigned int invert()
Matrix inversion.
Definition: VMatrix.cc:348
void putVec(const VVector &aVector, unsigned int start=0)
Put part of vector.
Definition: VMatrix.cc:284
void resize(const unsigned int nRows, const unsigned int nCols)
Resize Matrix.
Definition: VMatrix.cc:55
unsigned int numCol
Band matrix size.
void resize(const unsigned int nRows)
Resize symmetric matrix.
Definition: VMatrix.cc:175
VMatrix transpose() const
Get transposed matrix.
Definition: VMatrix.cc:65
VMatrix invertBand()
Invert band part.
VMatrix theMixed
Mixed part.
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void decomposeBand()
(root free) Cholesky decomposition of band part: C=LDL^T
Namespace for the general broken lines package.
unsigned int numBorder
Border size.
T min(T a, T b)
Definition: MathUtil.h:58
Simple symmetric Matrix based on std::vector<double>
Definition: VMatrix.h:86
VSymMatrix theBorder
Border part.
int k[5][pyjets_maxn]
void print() const
Print matrix.
Definition: VMatrix.cc:92
unsigned int getNumCols() const
Get number of columns.
Definition: VMatrix.cc:87
void resize(unsigned int nSize, unsigned int nBorder=1, unsigned int nBand=5)
Resize bordered band matrix.
VMatrix theBand
Band part.
VMatrix bandOfAVAT(const VMatrix &anArray, const VSymMatrix &aSymArray) const
Calculate band part of: &#39;anArray * aSymArray * anArray.T&#39;.
Simple Vector based on std::vector<double>
Definition: VMatrix.h:43
unsigned int numSize
Matrix size.
VVector solveBand(const VVector &aRightHandSide) const
Solve for band part.
void solveAndInvertBorderedBand(const VVector &aRightHandSide, VVector &aSolution)
Solve linear equation system, partially calculate inverse.
unsigned int numBand
Band width.