Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
SparseMatrix.cpp
1 /* This file is part of the BIAS library (Basic ImageAlgorithmS).
2 
3  Copyright (C) 2003-2009 (see file CONTACT for details)
4  Multimediale Systeme der Informationsverarbeitung
5  Institut fuer Informatik
6  Christian-Albrechts-Universitaet Kiel
7 
8 
9  BIAS is free software; you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation; either version 2.1 of the License, or
12  (at your option) any later version.
13 
14  BIAS is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with BIAS; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
22 
23 
24 
25 #include <Base/Common/W32Compat.hh>
26 
27 #include "SparseMatrix.hh"
28 #include <MathAlgo/SVD.hh>
29 
30 using namespace BIAS;
31 using namespace std;
32 
33 #define ABS(x) (((x) < 0) ? -(x) : (x))
34 #define MAX(x,y) ((x) > (y)) ? (x) : (y)
35 
36 //#define GAUSS_JORDAN_DEBUG
37 
38 
40  numRow_ = A.GetRows();
41  numCol_ = A.GetCols();
42 
43  maxRow_ = 0;
44  maxCol_ = 0;
45 
46  double val;
47  for (unsigned int i = 0; i < numRow_; i++) {
48  std::list<std::pair<unsigned int, double> > row;
49  for (unsigned int j = 0; j < numCol_; j++) {
50  val = A[i][j];
51  if (ABS(val) > SPARSE_MATRIX_EPSILON) {
52  row.push_back(std::pair<unsigned int, double>(j, val));
53  maxRow_ = MAX(maxRow_, i);
54  maxCol_ = MAX(maxCol_, j);
55  }
56  }
57  if (!row.empty()) rows_[i] = row;
58  }
59 }
60 
61 
62 //////////////////////////////////////////////////////////////////////////////
63 //
64 // Assignment Operator
65 //
66 //////////////////////////////////////////////////////////////////////////////
68 {
69  // copy sizes
70  numRow_ = S.GetRowsNum();
71  numCol_ = S.GetColsNum();
72 
73  maxRow_ = S.GetRows()-1;
74  maxCol_ = S.GetCols()-1;
75 
76 
77 // rows_.clear();
78 //
79 // // copy map
80 // double val;
81 // for (unsigned int i = 0; i <= maxRow_; i++) {
82 // std::list<std::pair<unsigned int, double> > row;
83 // for (unsigned int j = 0; j <= maxCol_; j++) {
84 // val = GetElement(i, j);
85 // if (ABS(val) > SPARSE_MATRIX_EPSILON) {
86 // row.push_back(std::pair<unsigned int, double>(j, val));
87 // }
88 // }
89 // if (!row.empty()) rows_[i] = row;
90 // }
91 
92  // copy map the simple way
93  rows_ = S.rows_;
94 
95  return (*this);
96 }
97 
98 double SparseMatrix::
99 GetElement(unsigned int row, unsigned int col) const
100 {
101  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
102  const_iterator rowsIter = rows_.find(row);
103  if (rowsIter != rows_.end()) {
104  std::list<std::pair<unsigned int, double> >::const_iterator colsIter;
105  std::list<std::pair<unsigned int, double> >::const_iterator colsEnd
106  = rowsIter->second.end();
107  for (colsIter = rowsIter->second.begin();
108  colsIter != colsEnd && colsIter->first < col; colsIter++);
109  if (colsIter != colsEnd && colsIter->first == col) {
110  return colsIter->second;
111  }
112  }
113  return 0.0;
114 }
115 
116 void SparseMatrix::
117 SetElement(unsigned int row, unsigned int col, double val)
118 {
119  maxRow_ = MAX(maxRow_, row);
120  maxCol_ = MAX(maxCol_, col);
121  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
122  iterator rowsIter = rows_.find(row);
123  if (rowsIter == rows_.end() && ABS(val) <= SPARSE_MATRIX_EPSILON) {
124  return; // Row not found, no element to set
125  }
126  std::list<std::pair<unsigned int, double> >::iterator it;
127  std::list<std::pair<unsigned int, double> >::iterator end = rows_[row].end();
128  for (it = rows_[row].begin(); it != end && it->first < col; it++);
129  if (it != end && it->first == col) {
130  if (ABS(val) > SPARSE_MATRIX_EPSILON) {
131  it->second = val;
132  } else {
133  rows_[row].erase(it);
134  if (rows_[row].empty()) rows_.erase(row);
135  }
136  } else if (ABS(val) > SPARSE_MATRIX_EPSILON) {
137  rows_[row].insert(it, std::pair<unsigned int,double>(col, val));
138  }
139 
140  if (numRow_ < (row + 1) || numCol_ < (col + 1)){
141  BIASWARNONCE("Element was set out of current matrix dimensions. "
142  << "Dimensions have been increased!")
143  numRow_ = MAX(numRow_, (row + 1));
144  numCol_ = MAX(numCol_, (col + 1));
145  }
146 
147 }
148 
149 void SparseMatrix::
150 SetSubMatrix(unsigned int row, unsigned int col,
151  BIAS::Matrix<double> const &A,
152  unsigned int startRowInA, unsigned int startColInA,
153  unsigned int row_count, unsigned int col_count)
154 {
155  BIASASSERT(startRowInA+row_count <= (unsigned int)(A.GetRows()));
156  BIASASSERT(startColInA+col_count <= (unsigned int)(A.GetCols()));
157 
158 // cout << "sparse matrix : set subMatrix " << A << endl;
159 // cout << "to be taken " << startRowInA << " " << startColInA << " num "
160 // << row_count << " " << col_count << endl;
161 
162  maxRow_ = MAX(maxRow_, row+row_count-1);
163  maxCol_ = MAX(maxCol_, col+col_count-1);
164  for (unsigned int i = 0; i < row_count; i++) {
165  std::list<std::pair<unsigned int, double> >::iterator it;
166  std::list<std::pair<unsigned int, double> >::iterator end
167  = rows_[row+i].end();
168  for (it = rows_[row+i].begin(); it != end && it->first < col; it++);
169 
170  // Make sure that there is no element set within the submatrix range
171  BIASASSERT(it == end || it->first >= col+col_count);
172 
173  for (unsigned int j = 0; j < col_count; j++) {
174  if (ABS(A[startRowInA+i][startColInA+j]) > SPARSE_MATRIX_EPSILON) {
175  rows_[row+i].insert(it, std::pair<unsigned int, double>
176  (col+j, A[startRowInA+i][startColInA+j]));
177  }
178  }
179  }
180 
181  if (numRow_ < (row+row_count) || numCol_ < (col+col_count)){
182  BIASWARNONCE("Sub matrix exceeds current matrix dimensions. "
183  << "Dimensions have been increased!");
184  numRow_ = MAX(numRow_, (row+row_count));
185  numCol_ = MAX(numCol_, (col+col_count));
186  }
187 
188 }
189 
191 {
192  result.maxRow_ = maxCol_;
193  result.maxCol_ = maxRow_;
194  result.numRow_ = numCol_;
195  result.numCol_ = numRow_;
196  result.rows_.clear();
197  std::map< unsigned int, std::list<std::pair<unsigned int, double> > >::
198  iterator rowsIter;
199  std::map< unsigned int, std::list<std::pair<unsigned int, double> > >::
200  iterator rowsEnd = rows_.end();
201  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
202  std::list<std::pair<unsigned int, double> >::iterator colsIter;
203  std::list<std::pair<unsigned int, double> >::iterator colsEnd
204  = rowsIter->second.end();
205  for (colsIter = rowsIter->second.begin();
206  colsIter != colsEnd; colsIter++) {
207  // @note More efficient than InsertElement_, since we go ordered
208  // through rows/columns and fill them up!
209  result.rows_[colsIter->first].push_back(
210  std::pair<unsigned int, double>(rowsIter->first, colsIter->second));
211  }
212  }
213 
214 
215 }
216 
217 
218 
219 
220 void SparseMatrix::
221 InsertElement_(unsigned int row, unsigned int col, double value)
222 {
223  std::list<std::pair<unsigned int, double> >::iterator it;
224  std::list<std::pair<unsigned int, double> >::iterator end = rows_[row].end();
225  for (it = rows_[row].begin(); it != end && it->first < col; it++);
226 
227  // Make sure that element is not already set
228  BIASASSERT(it == end || it->first > col);
229 
230  rows_[row].insert(it, std::pair<unsigned int, double>(col, value));
231 }
232 
233 
234 void SparseMatrix::MultiplyIP(const double multiplier)
235 {
236  std::map< unsigned int,
237  std::list<std::pair<unsigned int, double> > >::iterator row;
238  std::list< std::pair<unsigned int, double> >::iterator elem;
239  for (row = rows_.begin(); row != rows_.end(); row++) {
240  for (elem = row->second.begin(); elem != row->second.end(); elem++) {
241  elem->second *= multiplier;
242  }
243  }
244 }
245 
246 
248 {
249 
250 
251  SparseMatrix AT(A.numCol_, A.numRow_);
252  A.Transpose(AT);
253  MultiplyWithTransposeOf(AT, result);
254 
255 }
256 
257 void SparseMatrix::
259 {
260  if(numCol_ != A.numCol_){
261  BIASERR("does not work for some reason, returing with doing anything...");
262  BIASABORT;
263  return;
264  }
265 
266  result.maxRow_ = maxRow_;
267  result.maxCol_ = A.maxRow_;
268  result.rows_.clear();
269  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
270  iterator rowsIter1;
271  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
272  iterator rowsEnd1 = rows_.end();
273  for (rowsIter1 = rows_.begin(); rowsIter1 != rowsEnd1; rowsIter1++) {
274  std::list<std::pair<unsigned int, double> > row;
275  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
276  iterator rowsIter2;
277  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
278  iterator rowsEnd2 = A.rows_.end();
279  for (rowsIter2 = A.rows_.begin(); rowsIter2 != rowsEnd2; rowsIter2++) {
280  double sum = 0;
281  std::list<std::pair<unsigned int, double> >::iterator colsIter1 =
282  rowsIter1->second.begin();
283  std::list<std::pair<unsigned int, double> >::iterator colsIter2 =
284  rowsIter2->second.begin();
285  std::list<std::pair<unsigned int, double> >::iterator colsEnd1 =
286  rowsIter1->second.end();
287  std::list<std::pair<unsigned int, double> >::iterator colsEnd2 =
288  rowsIter2->second.end();
289  while (colsIter1 != colsEnd1 && colsIter2 != colsEnd2) {
290  if (colsIter1->first < colsIter2->first) {
291  colsIter1++;
292  } else if (colsIter1->first > colsIter2->first) {
293  colsIter2++;
294  } else {
295  sum += colsIter1->second * colsIter2->second;
296  colsIter1++;
297  colsIter2++;
298  }
299  }
300  if (ABS(sum) > SPARSE_MATRIX_EPSILON) {
301  // @note More efficient than InsertElement_, since we go ordered
302  // through rows/columns and fill them up!
303  row.push_back(std::pair<unsigned int, double>(rowsIter2->first, sum));
304  }
305  }
306  if (!row.empty()) result.rows_[rowsIter1->first] = row;
307  }
308 
309  result.numRow_ = numRow_;
310  result.numCol_ = A.numRow_;
311 
312 }
313 
315 {
316  M.newsize(numRow_, numCol_);
317  M.SetZero();
318  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
319  const_iterator rowsIter;
320  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
321  const_iterator rowsEnd = rows_.end();
322  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
323  BIASASSERT(rowsIter->first < M.GetRows());
324  std::list<std::pair<unsigned int, double> >::const_iterator colsIter;
325  std::list<std::pair<unsigned int, double> >::const_iterator colsEnd
326  = rowsIter->second.end();
327  for (colsIter = rowsIter->second.begin();
328  colsIter != colsEnd; colsIter++) {
329  BIASASSERT(colsIter->first < M.GetCols());
330  M[rowsIter->first][colsIter->first] = colsIter->second;
331  }
332  }
333 }
334 
335 double SparseMatrix::
336 GetMaxDiagonalElement(unsigned int &index) const
337 {
338  index = 0;
339  double maxValue = 0.0;
340  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
341  const_iterator rowsIter;
342  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
343  const_iterator rowsEnd = rows_.end();
344  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
345  std::list<std::pair<unsigned int, double> >::const_iterator colsIter;
346  std::list<std::pair<unsigned int, double> >::const_iterator colsEnd
347  = rowsIter->second.end();
348  for (colsIter = rowsIter->second.begin();
349  colsIter != colsEnd; colsIter++) {
350  // Check if we run past diagonal
351  if (colsIter->first > rowsIter->first) break;
352  if (colsIter->first == rowsIter->first) {
353  if (colsIter->second > maxValue) {
354  maxValue = colsIter->second;
355  index = colsIter->first;
356  }
357  }
358  }
359  }
360  return maxValue;
361 }
362 
363 double SparseMatrix::
364 GetMaxRowElement(unsigned int row, unsigned int &col) const
365 {
366  col = 0;
367  double maxValue = 0.0;
368  map<unsigned int, std::list<std::pair<unsigned int, double> > >::
369  const_iterator rowsIter = rows_.find(row);
370  if (rowsIter != rows_.end()) {
371  std::list<std::pair<unsigned int, double> >::const_iterator colsIter;
372  std::list<std::pair<unsigned int, double> >::const_iterator colsEnd
373  = rowsIter->second.end();
374  for (colsIter = rowsIter->second.begin();
375  colsIter != colsEnd; colsIter++) {
376  if (colsIter->second > maxValue) {
377  maxValue = colsIter->second;
378  col = colsIter->first;
379  }
380  }
381  }
382  return maxValue;
383 }
384 
385 /// TODO Not efficient because of row->column mapping...
386 double SparseMatrix::
387 GetMaxColumnElement(unsigned int col, unsigned int &row) const
388 {
389  row = 0;
390  double maxValue = 0.0;
391  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
392  const_iterator rowsIter;
393  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
394  const_iterator rowsEnd = rows_.end();
395  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
396  std::list<std::pair<unsigned int, double> >::const_iterator colsIter;
397  std::list<std::pair<unsigned int, double> >::const_iterator colsEnd
398  = rowsIter->second.end();
399  for (colsIter = rowsIter->second.begin();
400  colsIter != colsEnd; colsIter++) {
401  // Check if we run past column
402  if (colsIter->first > col) break;
403  if (colsIter->first == col) {
404  if (colsIter->second > maxValue) {
405  maxValue = colsIter->second;
406  row = rowsIter->first;
407  }
408  }
409  }
410  }
411  return maxValue;
412 }
413 
414 void SparseMatrix::MultiplyDiagonalBy(const double &value)
415 {
416  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
417  iterator rowsIter;
418  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
419  iterator rowsEnd = rows_.end();
420  // Run over all existing rows
421  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
422  std::list<std::pair<unsigned int, double> >::iterator colsIter;
423  std::list<std::pair<unsigned int, double> >::iterator colsEnd
424  = rowsIter->second.end();
425  // In each row, look for column (row;row)
426  for (colsIter = rowsIter->second.begin();
427  colsIter != colsEnd; colsIter++) {
428  // Check if we are further than the diagonal
429  if (colsIter->first > rowsIter->first) break;
430  // Check if we are at the diagonal
431  if (colsIter->first == rowsIter->first) {
432  colsIter->second *= value;
433  break;
434  }
435  }
436  }
437 
438 }
439 
440 void SparseMatrix::AddToDiagonal(const double &value)
441 {
442  // Works only for square matrices so far:
443  // For rectangular, we need to check maxRow_ and maxCol_ always!
444  BIASASSERT(maxRow_ == maxCol_);
445  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
446  iterator rowsIter = rows_.begin();
447 
448  // Run over all rows and find diagonal element
449  for (unsigned int rowId = 0; rowId <= maxRow_; rowId++) {
450  // Insert rowId-th row if it does not exist yet
451  if (rowsIter == rows_.end() || rowsIter->first != rowId) {
452  std::list<pair<unsigned int, double> > newRow;
453  newRow.push_back(std::pair<unsigned int, double>(rowId, value));
454  rowsIter = rows_.insert(rowsIter,
455  std::pair<unsigned int,
456  list<pair<unsigned int, double> > >(rowId, newRow));
457  } else {
458  // Here we can be sure that rowsIter is valid and points to
459  // the rowId-th row! Now find the diagonal element.
460  std::list<std::pair<unsigned int, double> >::iterator colsIter;
461  std::list<std::pair<unsigned int, double> >::iterator colsEnd
462  = rowsIter->second.end();
463  bool missingCol = true;
464  for (colsIter = rowsIter->second.begin();
465  colsIter != colsEnd && missingCol; colsIter++) {
466  // Check if we are further than the diagonal
467  if (colsIter->first > rowId) break;
468  // Check if we are at the diagonal
469  if (colsIter->first == rowId) {
470  colsIter->second += value;
471  missingCol = false;
472  break;
473  }
474  }
475  // The diagonal element is missing (value == 0) in this row, add it!
476  if (missingCol) {
477  rowsIter->second.insert(colsIter,
478  std::pair<unsigned int, double>(rowId, value));
479  }
480  }
481  rowsIter++;
482  }
483 
484 
485  if (numRow_ < (maxRow_+1) || numCol_ < (maxCol_+1)){
486  BIASWARNONCE("Sub matrix exceeds current matrix dimensions. "
487  << "Dimensions have been increased!");
488  numRow_ = MAX(numRow_, (maxRow_+1));
489  numCol_ = MAX(numCol_, (maxCol_+1));
490  }
491 
492 }
493 
494 void SparseMatrix::GetAsDense(unsigned int row, unsigned int col,
495  unsigned int numRows, unsigned int numCols,
496  BIAS::Matrix<double> &M) const
497 {
498  M.newsize(numRows, numCols);
499  M.SetZero();
500  map<unsigned int, std::list<std::pair<unsigned int, double> > >::
501  const_iterator rowsIter = rows_.find(row);
502  map<unsigned int, std::list<std::pair<unsigned int, double> > >::
503  const_iterator rowsEnd = rows_.end();
504  // If the first row could not be found, try to find the next one.
505  // Don't give up before we couldn't find the last interesting one!
506  unsigned int rowOffset = 0;
507  while (rowsIter == rowsEnd && rowOffset < numRows) {
508  rowsIter = rows_.find(row + (++rowOffset));
509  }
510 
511  // Now that we've found the first interesting row, start with iterating.
512 
513  // TODO Will the map-iterator deliver sorted numbers?! Then why are there no
514  // maps through columns, it would save all the nasty iterator-insertions!!
515 
516  for (; rowsIter != rowsEnd; rowsIter++) {
517  // Check if at 2nd or n-th iteration we are outside the submatrix.
518  if (rowsIter->first >= numRows+row) break;
519  std::list<std::pair<unsigned int, double> >::const_iterator colsIter;
520  std::list<std::pair<unsigned int, double> >::const_iterator colsEnd
521  = rowsIter->second.end();
522  // Now run along current row and find first interesting column.
523  for (colsIter = rowsIter->second.begin();
524  colsIter != colsEnd; colsIter++) {
525 #ifdef BIAS_DEBUG
526  if (colsIter == colsEnd) {
527  BIASERR("Sparse matrix is not consistent (contains empty rows)!");
528  break;
529  }
530 #else
531  if (colsIter == colsEnd) break;
532 #endif
533  // Check whether we have to go further in the row
534  if (colsIter->first >= col) break;
535  }
536  for (; colsIter != colsEnd; colsIter++) {
537  if (colsIter->first >= numCols+col) break;
538  BIASASSERT(rowsIter->first >= row && rowsIter->first < M.GetRows()+row);
539  BIASASSERT(colsIter->first >= col && colsIter->first < M.GetCols()+col);
540  M[rowsIter->first-row][colsIter->first-col] = colsIter->second;
541  }
542  }
543 }
544 
545 void SparseMatrix::
546 Print(std::string const &name, std::ostream &stream) const
547 {
548  stream << name << " m " << GetRowsNum() << "n " << GetColsNum() << endl;
549  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
550  const_iterator rowsIter;
551  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
552  const_iterator rowsEnd = rows_.end();
553  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
554  std::list<std::pair<unsigned int, double> >::const_iterator colsIter;
555  std::list<std::pair<unsigned int, double> >::const_iterator colsEnd
556  = rowsIter->second.end();
557  for (colsIter = rowsIter->second.begin();
558  colsIter != colsEnd; colsIter++) {
559  stream << name << "[" << rowsIter->first << "][" << colsIter->first
560  << "] = " << colsIter->second << endl;
561  }
562  }
563 }
564 
565 
566 void SparseMatrix::
568 {
569  // BIASASSERT(x.Size() == numCol_)
570  result.newsize(numRow_);
571  result.SetZero();
572  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
573  iterator rowsIter;
574  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
575  iterator rowsEnd = rows_.end();
576  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
577  double sum = 0;
578  std::list<std::pair<unsigned int, double> >::iterator colsIter;
579  std::list<std::pair<unsigned int, double> >::iterator colsEnd
580  = rowsIter->second.end();
581  for (colsIter = rowsIter->second.begin();
582  colsIter != colsEnd; colsIter++) {
583  sum += colsIter->second * x[colsIter->first];
584  }
585  result[rowsIter->first] = sum;
586 
587  }
588 }
589 
591 {
592  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
593  iterator rowsIter;
594  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
595  iterator rowsEnd = H.rows_.end();
596 
597 
598  for (rowsIter = H.rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
599  rows_[numRow_+rowsIter->first] = rowsIter->second;
600  }
601 
602 
603  if (H.numRow_ > 0){
604  maxRow_ = numRow_ + H.maxRow_;
605  numRow_ += H.numRow_;
606  }
607 
608 
609  if (H.numCol_ > 0){
610  maxCol_ = MAX(maxCol_, H.maxCol_);
611  }
612 
613 
614 // if (numRow_ < (maxRow_ + 1)){
615 // BIASWARNONCE("Append matrix exceeds current matrix dimensions. "
616 // << "Dimensions have been increased!")
617 // numRow_ = maxRow_ + 1;
618 // }
619 
620 // if (numCol_ < (maxCol_ + 1)){
621 // BIASWARNONCE("Append matrix exceeds current matrix dimensions. "
622 // << "Dimensions have been increased!")
623 // numCol_ = maxCol_ + 1;
624 // }
625 
626 
627 }
628 
630 {
631  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
632  iterator rowsIter;
633  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
634  iterator rowsEnd = H.rows_.end();
635  for (rowsIter = H.rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
636  std::list<std::pair<unsigned int, double> > row = rows_[rowsIter->first];
637  std::list<std::pair<unsigned int, double> >::iterator colsIter;
638  std::list<std::pair<unsigned int, double> >::iterator colsEnd
639  = rowsIter->second.end();
640  for (colsIter = rowsIter->second.begin();
641  colsIter != colsEnd; colsIter++) {
642  row.push_back(std::pair<unsigned int,double>(maxCol_+colsIter->first +1,
643  colsIter->second));
644  }
645  rows_[rowsIter->first] = row;
646  }
647 
648  if (H.numCol_ > 0){
649  maxCol_ = numCol_ + H.maxCol_;
650  numCol_ += H.numCol_;
651  }
652 
653  if (H.numRow_ > 0)
654  maxRow_ = MAX(maxRow_, H.maxRow_);
655 
656 // if (numCol_ < (maxCol_ + 1)){
657 // BIASWARNONCE("Append matrix exceeds current matrix dimensions. "
658 // << "Dimensions have been increased!")
659 // numCol_ = maxCol_ + 1;
660 // }
661 // if (numRow_ < (maxRow_ + 1)){
662 // BIASWARNONCE("Append matrix exceeds current matrix dimensions. "
663 // << "Dimensions have been increased!")
664 // numRow_ = maxRow_ + 1;
665 // }
666 
667 
668 }
669 
670 
671 int SparseMatrix::
673  BIAS::Vector<double> &result)
674 {
675  BIASASSERT ((numRow_ == numCol_) && (b.Size() == numRow_));
676 
677  // Augment matrix
678  for (unsigned int i = 0; i <= maxRow_; i++) {
679  // Add identity to the right
680  rows_[i].push_back(std::pair<unsigned int, double>(maxCol_+i+1, 1.0));
681  if (ABS(b[i]) > SPARSE_MATRIX_EPSILON) {
682  // Add vector b to the right
683  rows_[i].push_back(std::pair<unsigned int, double>(2*maxCol_+2, b[i]));
684  }
685  }
686 
687  // Perform Gauss-Jordan algorithm
688  int res = GaussJordan_();
689  if (res != 0) return res;
690 
691  // Write back results
692  inverse.newsize(maxRow_+1, maxCol_+1);
693  inverse.SetZero();
694  result.newsize(maxRow_+1);
695  result.SetZero();
696  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
697  iterator rowsIter;
698  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
699  iterator rowsEnd = rows_.end();
700  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
701  std::list<std::pair<unsigned int, double> >::iterator colsIter;
702  std::list<std::pair<unsigned int, double> >::iterator colsEnd
703  = rowsIter->second.end();
704  for (colsIter = rowsIter->second.begin();
705  colsIter != colsEnd && colsIter->first <= maxCol_; colsIter++);
706 #ifdef BIAS_DEBUG
707  if (colsIter == colsEnd) {
708  BIASERR("Sparse matrix is not consistent (contains empty rows)!");
709  }
710 #endif
711  for (; colsIter != colsEnd; colsIter++) {
712  if (colsIter->first < 2*maxCol_+2) {
713  inverse[rowsIter->first][colsIter->first-maxCol_-1] = colsIter->second;
714  } else {
715  result[rowsIter->first] = colsIter->second;
716  }
717  }
718  }
719 
720  // Update column number
721  maxCol_ = 2*maxCol_+2;
722 
723  if ((numCol_ < maxCol_ + 1)){
724  BIASWARNONCE("Call to 'InvertAndSolve' enlarged current matrix which now exceeds "
725  << "its dimensions. Dimensions have been increased!");
726  numCol_ = maxCol_ + 1;
727  }
728 
729 
730  return res;
731 }
732 
733 
734 int SparseMatrix::
736  BIAS::Vector<double> &result)
737 {
738  BIASASSERT ((numRow_ == numCol_) && (b.Size() == numRow_));
739 
740  // Augment matrix
741  for (unsigned int i = 0; i <= maxRow_; i++) {
742  // Add identity to the right
743  rows_[i].push_back(std::pair<unsigned int, double>(maxCol_+i+1, 1));
744  if (ABS(b[i]) > SPARSE_MATRIX_EPSILON) {
745  // Add vector b to the right
746  rows_[i].push_back(std::pair<unsigned int,double>(2*maxCol_+2, b[i]));
747  }
748  }
749 
750  // Perform Gauss-Jordan algorithm
751  int res = GaussJordan_();
752  if (res != 0) return res;
753 
754  // Write back results
755  result.newsize(maxRow_+1);
756  result.SetZero();
757  inverse.rows_.clear();
758  inverse.maxRow_ = maxRow_;
759  inverse.maxCol_ = maxCol_;
760  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
761  iterator rowsIter;
762  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
763  iterator rowsEnd = rows_.end();
764  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
765  std::list<std::pair<unsigned int, double> >::iterator colsIter;
766  std::list<std::pair<unsigned int, double> >::iterator colsEnd
767  = rowsIter->second.end();
768  for (colsIter = rowsIter->second.begin();
769  colsIter != colsEnd && colsIter->first <= maxCol_; colsIter++);
770 #ifdef BIAS_DEBUG
771  if (colsIter == colsEnd) {
772  BIASERR("Sparse matrix is not consistent (contains empty rows)!");
773  }
774 #endif
775  std::list<std::pair<unsigned int, double> > row;
776  for (; colsIter != colsEnd; colsIter++) {
777  if (colsIter->first < 2*maxCol_+2) {
778  row.push_back(std::pair<unsigned int, double>(colsIter->first-maxCol_-1,
779  colsIter->second));
780  } else {
781  result[rowsIter->first] = colsIter->second;
782  }
783  }
784  if (!row.empty()) inverse.rows_[rowsIter->first] = row;
785  }
786 
787  // Update column number
788  maxCol_ = maxCol_*2+2;
789 
790 
791  if ((numCol_ < maxCol_ + 1) || (numRow_ < maxRow_ + 1)){
792  BIASWARNONCE("Call to 'InvertAndSolve' enlarged current matrix which now exceeds "
793  << "its dimensions. Dimensions have been increased!");
794  numCol_ = maxCol_ + 1;
795  numRow_ = maxRow_ + 1;
796  }
797 
798  return 0;
799 }
800 
801 
802 int SparseMatrix::
804 {
805 // cout << "numRow " << numRow_ << " numCol " << numCol_ << " b size " << b.Size() << endl;
806  BIASASSERT ((numRow_ == numCol_) && (b.Size() == numRow_));
807 
808 
809  // Augment matrix
810  for (unsigned int i = 0; i <= maxRow_; i++) {
811  if (ABS(b[i]) > SPARSE_MATRIX_EPSILON) {
812  // Add vector b to the right
813  rows_[i].push_back(std::pair<unsigned int, double>(maxCol_+1, b[i]));
814  }
815  }
816 
817  // Perform Gauss-Jordan algorithm
818  int res = GaussJordan_();
819  if (res != 0) return res;
820 
821  // Write back results
822  result.newsize(maxRow_+1);
823  result.SetZero();
824  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
825  iterator rowsIter;
826  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
827  iterator rowsEnd = rows_.end();
828  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
829  std::pair<unsigned int, double> back = rowsIter->second.back();
830  if (back.first == maxCol_+1) {
831  result[rowsIter->first] = back.second;
832  }
833  }
834 
835  // Update column number
836  maxCol_++;
837 
838 
839  if (((numCol_ < maxCol_ + 1) || (numRow_ < maxRow_ + 1))){
840  BIASWARNONCE("Call to 'Invert' enlarged current matrix which now exceeds "
841  << "its dimensions. Dimensions have been increased!");
842  numCol_ = maxCol_ + 1;
843  numRow_ = maxRow_ + 1;
844  }
845 
846  return 0;
847 }
848 
849 
851 {
852  SparseMatrix pinv(numCol_, numRow_);
853  PseudoInverse(pinv);
854  pinv.GetAsDense(inverse);
855 
856  return 0;
857 }
858 
859 
860 void SparseMatrix::Reinit(unsigned rows, unsigned cols)
861 {
862  //clear old matrix
863  rows_.clear();
864  numCol_ = cols;
865  numRow_ = rows;
866  maxCol_ = 0;
867  maxRow_ = 0;
868 }
869 
871 
872 
873  if(numRow_ > numCol_){
874  SparseMatrix AT(numCol_, numRow_);
875  Transpose(AT);
876  SparseMatrix ATA(numCol_, numCol_);
877  AT.Multiply(*this, ATA);
878  SparseMatrix ATA_inv(numCol_, numCol_);
879  ATA.Invert(ATA_inv);
880  ATA_inv.MultiplyWithTransposeOf(*this, inverse);
881  } else {
882  SparseMatrix AAT(numRow_, numRow_);
883  MultiplyWithTransposeOf(*this, AAT);
884  SparseMatrix AAT_inv(numRow_, numRow_);
885  AAT.Invert(AAT_inv);
886  SparseMatrix AT(numCol_, numRow_);
887  Transpose(AT);
888  AT.Multiply(AAT_inv, inverse);
889  }
890 
891  return 0;
892 }
893 
894 
895 
896 
898 {
899  BIASASSERT(numRow_ == numCol_); // Only allowed for square matrices!
900 
901  // Augment matrix
902  for (unsigned int i = 0; i <= maxRow_; i++) {
903  // Add identity to the right
904  rows_[i].push_back(std::pair<unsigned int, double>(maxCol_+i+1, 1));
905  }
906 
907  // Perform Gauss-Jordan algorithm
908  int res = GaussJordan_();
909  if (res != 0) return res;
910 
911  // Write back results
912  inverse.newsize(numRow_, numCol_);
913  inverse.SetZero();
914  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
915  iterator rowsIter;
916  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
917  iterator rowsEnd = rows_.end();
918  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
919  std::list<std::pair<unsigned int, double> >::iterator colsIter;
920  std::list<std::pair<unsigned int, double> >::iterator colsEnd
921  = rowsIter->second.end();
922  for (colsIter = rowsIter->second.begin();
923  colsIter != colsEnd && colsIter->first <= maxCol_; colsIter++);
924 #ifdef BIAS_DEBUG
925  if (colsIter == colsEnd) {
926  BIASERR("Sparse matrix is not consistent (contains empty rows)!");
927  }
928 #endif
929  for (; colsIter != colsEnd; colsIter++) {
930  inverse[rowsIter->first][colsIter->first-maxCol_-1] = colsIter->second;
931  }
932  }
933 
934  // Update column number
935  maxCol_ = 2*maxCol_+1;
936 
937  if ((numCol_ < maxCol_ + 1) || (numRow_ < maxRow_)){
938  BIASWARNONCE("Call to 'Invert' enlarged current matrix which now exceeds "
939  << "its dimensions. Dimensions have been increased!");
940  numCol_ = maxCol_ + 1;
941  numRow_ = maxRow_ + 1;
942  }
943 
944 
945  return 0;
946 }
947 
948 
950 {
951 
952  cout << "numRow " << numRow_ << " numCol " << numCol_ << endl;
953  BIASASSERT (numRow_ == numCol_); // Only allowed for square matrices!
954 
955  // Augment matrix
956  for (unsigned int i = 0; i <= maxRow_; i++) {
957  // Add identity to the right
958  rows_[i].push_back(std::pair<unsigned int, double>(maxCol_+i+1, 1));
959  }
960 
961  // Perform Gauss-Jordan algorithm
962  int res = GaussJordan_();
963  if (res != 0) return res;
964 
965  // Write back results
966  inverse.rows_.clear();
967  inverse.maxRow_ = maxRow_;
968  inverse.maxCol_ = maxCol_;
969  inverse.numRow_ = numRow_;
970  inverse.numCol_ = numCol_;
971  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
972  iterator rowsIter;
973  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
974  iterator rowsEnd = rows_.end();
975  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
976  std::list<std::pair<unsigned int, double> >::iterator colsIter;
977  std::list<std::pair<unsigned int, double> >::iterator colsEnd
978  = rowsIter->second.end();
979  for (colsIter = rowsIter->second.begin();
980  colsIter != colsEnd && colsIter->first <= maxCol_; colsIter++);
981 #ifdef BIAS_DEBUG
982  if (colsIter == colsEnd) {
983  BIASERR("Sparse matrix is not consistent (contains empty rows)!");
984  }
985 #endif
986  std::list<std::pair<unsigned int, double> > row;
987  for (; colsIter != colsEnd; colsIter++) {
988  row.push_back(std::pair<unsigned int, double>(colsIter->first-maxCol_-1,
989  colsIter->second));
990  }
991  if (!row.empty()) inverse.rows_[rowsIter->first] = row;
992  }
993 
994  // Update column number
995  maxCol_ = 2*maxCol_+1;
996 
997  if ((numCol_ < maxCol_ + 1) || (numRow_ < maxRow_ + 1)){
998  BIASWARNONCE("Call to 'Invert' enlarged current matrix which now exceeds "
999  << "its dimensions. Dimensions have been increased! maxCol " << maxCol_+1 << " numCol " << numCol_ << " maxRows " << maxRow_+1 << " numRows " << numRow_ << endl);
1000  numCol_ = maxCol_ + 1;
1001  numRow_ = maxRow_ + 1;
1002  }
1003 
1004  return 0;
1005 }
1006 
1008 {
1009 #ifdef GAUSS_JORDAN_DEBUG
1010  cout << "-- SparseMatrix::GaussJordan_() : Debugging --" << endl << endl;
1011 #endif
1012 
1013  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
1014  iterator rowsIter1;
1015  for (rowsIter1 = rows_.begin(); rowsIter1 != rows_.end(); rowsIter1++) {
1016 #ifdef GAUSS_JORDAN_DEBUG
1017  cout << "- Processing line " << rowsIter1->first << endl << flush;
1018 #endif
1019  // Find pivot row
1020  double pivot_value = 0.0;
1021  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
1022  iterator pivot_index;
1023  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
1024  iterator rowsIter2;
1025  // Run over all rows below
1026  for (rowsIter2 = rowsIter1; rowsIter2 != rows_.end(); rowsIter2++) {
1027  // For each check if front element is at the current column (or behind)
1028  if (rowsIter2->second.empty()) continue;
1029 #ifdef GAUSS_JORDAN_DEBUG
1030  cout << " - Checking for row echelon form in line "
1031  << rowsIter2->first << endl << flush;
1032 #endif
1033  std::pair<unsigned int, double> front = rowsIter2->second.front();
1034  // If we have a first element in a column smaller than row iter1
1035  // something went wrong, because the first columns should be zero!
1036  BIASASSERT(front.first >= rowsIter1->first);
1037 
1038  if (front.first == rowsIter1->first) {
1039  if (ABS(front.second) > ABS(pivot_value)) {
1040 #ifdef GAUSS_JORDAN_DEBUG
1041  cout << " - Changed pivot index to " << rowsIter2->first
1042  << endl << flush;
1043 #endif
1044  pivot_value = front.second;
1045  pivot_index = rowsIter2;
1046  }
1047  }
1048  }
1049  if (pivot_value == 0.0) {
1050  BIASERR("Matrix is singular!");
1051  return -1;
1052  }
1053  // Exchange rows at iter1 and pivot row
1054  if (pivot_index != rowsIter1) {
1055  //std::list<std::pair<unsigned int, double> > temp = rowsIter1->second;
1056  //rowsIter1->second = pivot_index->second;
1057  //pivot_index->second = temp;
1058 #ifdef GAUSS_JORDAN_DEBUG
1059  cout << "- Swapping lines " << rowsIter1->first << " and "
1060  << pivot_index->first << " with sizes " << rowsIter1->second.size()
1061  << " and " << pivot_index->second.size() << "... " << flush;
1062 #endif
1063  swap(rowsIter1->second, pivot_index->second);
1064 #ifdef GAUSS_JORDAN_DEBUG
1065  cout << "done!" << flush << endl;
1066 #endif
1067  }
1068 #ifdef GAUSS_JORDAN_DEBUG
1069  cout << "- Eliminating column downwards..." << flush << endl;
1070 #endif
1071  // Eliminate column downwards
1072  rowsIter2 = rowsIter1;
1073  for (rowsIter2++; rowsIter2 != rows_.end(); rowsIter2++) {
1074  if (rowsIter2->second.empty()) continue;
1075  std::pair<unsigned int, double> front = rowsIter2->second.front();
1076  // Row iter2 has an entry in column iter1, which has to be eliminated for
1077  // row echolon form.
1078  if (front.first == rowsIter1->first) {
1079  rowsIter2->second.pop_front();
1080  double factor = front.second/pivot_value;
1081 
1082  // CORRECT ??????????????? Changed inequality!
1083 
1084  if (ABS(factor) < 1.0/(SPARSE_MATRIX_EPSILON*SPARSE_MATRIX_EPSILON)) {
1085  //BIASERR("Matrix is singular to working precision " << factor);
1086  //BIASABORT;
1087  //return -1;
1088  }
1089  std::list<std::pair<unsigned int, double> >::iterator colsIter1 =
1090  rowsIter1->second.begin();
1091  std::list<std::pair<unsigned int, double> >::iterator colsIter2 =
1092  rowsIter2->second.begin();
1093  colsIter1++;
1094  // Run over all elements in current row
1095  while (colsIter1 != rowsIter1->second.end()) {
1096  if (colsIter2 == rowsIter2->second.end()) {
1097  double value = -factor*colsIter1->second;
1098  if (ABS(value) > SPARSE_MATRIX_EPSILON) {
1099  rowsIter2->second.insert(colsIter2,
1100  std::pair<unsigned int, double>(colsIter1->first, value));
1101  }
1102  colsIter1++;
1103  } else if (colsIter1->first>colsIter2->first) {
1104  colsIter2++;
1105  } else if (colsIter1->first<colsIter2->first) {
1106  double value = -factor*colsIter1->second;
1107  if (ABS(value) > SPARSE_MATRIX_EPSILON) {
1108  rowsIter2->second.insert(colsIter2,
1109  std::pair<unsigned int, double>(colsIter1->first, value));
1110  }
1111  colsIter1++;
1112  } else {
1113  colsIter2->second -= factor*colsIter1->second;
1114  if (ABS(colsIter2->second) <= SPARSE_MATRIX_EPSILON) {
1115  colsIter2 = rowsIter2->second.erase(colsIter2);
1116  } else {
1117  colsIter2++;
1118  }
1119  colsIter1++;
1120  }
1121  }
1122  }
1123  }
1124 #ifdef GAUSS_JORDAN_DEBUG
1125  cout << "- Eliminating column upwards..." << flush << endl;
1126 #endif
1127  // Eliminate column upwards
1128  for (rowsIter2 = rows_.begin(); rowsIter2 != rowsIter1; rowsIter2++) {
1129  std::list<std::pair<unsigned int, double> >::iterator colsIter2 =
1130  rowsIter2->second.begin();
1131  colsIter2++;
1132  if (colsIter2 != rowsIter2->second.end()) {
1133  std::list<std::pair<unsigned int, double> >::iterator colsIter1 =
1134  rowsIter1->second.begin();
1135  if (colsIter2->first == colsIter1->first) {
1136  double factor = colsIter2->second/pivot_value;
1137 
1138  // CORRECT ??????????????? Changed inequality!
1139 
1140  if (ABS(factor) < 1.0/(SPARSE_MATRIX_EPSILON*SPARSE_MATRIX_EPSILON)) {
1141  //BIASERR("Matrix is singular to working precision " << factor);
1142  //BIASABORT;
1143  //return -1;
1144  }
1145  colsIter2 = rowsIter2->second.erase(colsIter2);
1146  colsIter1++;
1147  while (colsIter1 != rowsIter1->second.end()) {
1148  if (colsIter2 == rowsIter2->second.end()) {
1149  double value = -factor*colsIter1->second;
1150  if (ABS(value) > SPARSE_MATRIX_EPSILON) {
1151  rowsIter2->second.insert(colsIter2,
1152  std::pair<unsigned int, double>(colsIter1->first, value));
1153  }
1154  colsIter1++;
1155  } else if (colsIter1->first>colsIter2->first) {
1156  colsIter2++;
1157  } else if (colsIter1->first<colsIter2->first) {
1158  double value = -factor*colsIter1->second;
1159  if (ABS(value) > SPARSE_MATRIX_EPSILON) {
1160  rowsIter2->second.insert(colsIter2,
1161  std::pair<unsigned int, double>(colsIter1->first, value));
1162  }
1163  colsIter1++;
1164  } else {
1165  colsIter2->second -= factor*colsIter1->second;
1166  if (ABS(colsIter2->second) <= SPARSE_MATRIX_EPSILON) {
1167  colsIter2 = rowsIter2->second.erase(colsIter2);
1168  } else {
1169  colsIter2++;
1170  }
1171  colsIter1++;
1172  }
1173  }
1174  }
1175  }
1176  }
1177 #ifdef GAUSS_JORDAN_DEBUG
1178  cout << "- Normalizing row..." << flush << endl;
1179 #endif
1180  // Normalize row, i.e. set pivot element to 1
1181  std::list<std::pair<unsigned int, double> >::iterator colsIter1
1182  = rowsIter1->second.begin();
1183  while (colsIter1 != rowsIter1->second.end()) {
1184  colsIter1->second /= pivot_value;
1185  if (ABS(colsIter1->second) <= SPARSE_MATRIX_EPSILON) {
1186  colsIter1 = rowsIter1->second.erase(colsIter1);
1187  } else {
1188  colsIter1++;
1189  }
1190  }
1191  }
1192 
1193  // Remove empty row from resulting matrix
1194 #ifdef GAUSS_JORDAN_DEBUG
1195  cout << "- Removing empty rows from resulting matrix..." << flush << endl;
1196 #endif
1197  rowsIter1 = rows_.begin();
1198  while (rowsIter1 != rows_.end()) {
1199  if (rowsIter1->second.empty()) {
1200  rows_.erase(rowsIter1);
1201  } else {
1202  rowsIter1++;
1203  }
1204  }
1205  return 0;
1206 }
1207 
1208 
1210 {
1211  unsigned int maxRow = 0, maxCol = 0;
1212  unsigned int lastRow = 0;
1213  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
1214  const_iterator rowsIter;
1215  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
1216  const_iterator rowsEnd = rows_.end();
1217  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
1218  if (rowsIter != rows_.begin()) {
1219  if (rowsIter->first <= lastRow) {
1220  BIASERR("Sparse matrix has rows in wrong order: Row "
1221  << rowsIter->first << " follows row " << lastRow << "!");
1222  //BIASABORT;
1223  return false;
1224  }
1225  }
1226  lastRow = rowsIter->first;
1227  maxRow = MAX(maxRow, rowsIter->first);
1228 
1229  if (rowsIter->second.empty()) {
1230  BIASERR("Sparse matrix contains empty row " << rowsIter->first<< "!");
1231  //BIASABORT;
1232  return false;
1233  }
1234 
1235  unsigned int lastCol = 0;
1236  std::list<std::pair<unsigned int, double> >::const_iterator colsIter;
1237  std::list<std::pair<unsigned int, double> >::const_iterator colsEnd
1238  = rowsIter->second.end();
1239  for (colsIter = rowsIter->second.begin();
1240  colsIter != colsEnd; colsIter++) {
1241  if (colsIter != rowsIter->second.begin()) {
1242  if (colsIter->first <= lastCol) {
1243  BIASERR("Sparse matrix has columns in wrong order: Column "
1244  << colsIter->first << " follows column " << lastCol << "!");
1245  //BIASABORT;
1246  return false;
1247  }
1248  }
1249  lastCol = colsIter->first;
1250  maxCol = MAX(maxCol, colsIter->first);
1251 
1252  if (ABS(colsIter->second) <= SPARSE_MATRIX_EPSILON) {
1253  BIASERR("Sparse matrix contains to small value " << colsIter->second
1254  << " at [" << rowsIter->first << "][" << colsIter->first
1255  << "]!");
1256  //BIASABORT;
1257  return false;
1258  }
1259 
1260  }
1261  }
1262 
1263  if (maxRow > maxRow_ || maxCol > maxCol_) {
1264  BIASERR("Sparse matrix contains values out of bounds (max. row ="
1265  << maxRow_ << ", max. col = " << maxCol_ << ", value at ["
1266  << maxRow << "][" << maxCol << "] found!)");
1267  //BIASABORT;
1268  return false;
1269  }
1270  return true;
1271 }
1272 
1273 void SparseMatrix::
1274 GetAllElements(std::vector<unsigned int> &rows,
1275  std::vector<unsigned int> &cols,
1276  std::vector<double> &values) const
1277 {
1278  rows.clear();
1279  cols.clear();
1280  values.clear();
1281  unsigned int num = 0;
1282  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
1283  const_iterator rowsIter;
1284  std::map<unsigned int, std::list<std::pair<unsigned int, double> > >::
1285  const_iterator rowsEnd = rows_.end();
1286  for (rowsIter = rows_.begin(); rowsIter != rowsEnd; rowsIter++) {
1287  std::list<std::pair<unsigned int, double> >::const_iterator colsIter;
1288  std::list<std::pair<unsigned int, double> >::const_iterator colsEnd
1289  = rowsIter->second.end();
1290  for (colsIter = rowsIter->second.begin(); colsIter != colsEnd; colsIter++) {
1291  rows.push_back(rowsIter->first);
1292  cols.push_back(colsIter->first);
1293  values.push_back(colsIter->second);
1294  num++;
1295  }
1296  }
1297  BIASASSERT(rows.size() == num && cols.size() == num && values.size() == num);
1298 }
double GetElement(unsigned int row, unsigned int col) const
Returns value of an element.
void GetAllElements(std::vector< unsigned int > &rows, std::vector< unsigned int > &cols, std::vector< double > &values) const
Return rows, columns and values for all elements in matrix.
bool CheckConsistency()
Checks if this sparse matrix is still consistent, i.e.
void Reinit(unsigned rows, unsigned cols)
clears old matrix and reinits with given size
int Invert(BIAS::Matrix< double > &inverse)
Returns inverse matrix as dense matrix.
void Print(std::string const &name, std::ostream &stream=std::cout) const
Prints the contents of this matrix.
unsigned int maxRow_
Current max.
unsigned int numCol_
Matrix< T > & newsize(Subscript M, Subscript N)
Definition: cmat.h:269
std::map< unsigned int, std::list< std::pair< unsigned int, double > > > rows_
Maps row indices to mappings from column indices to values.
void Multiply(SparseMatrix &A, SparseMatrix &result)
Multiplies with A and returns result M*A.
unsigned int Size() const
length of the vector
Definition: Vector.hh:143
double GetMaxDiagonalElement() const
void SetZero()
equivalent to matrix call
Definition: Vector.hh:156
unsigned int GetRows() const
Returns the maximum number of rows (max non-zero entry).
Definition: SparseMatrix.hh:71
Implementation of sparse matrix operations.
Definition: SparseMatrix.hh:51
Vector< T > & newsize(Subscript N)
Definition: vec.h:220
SparseMatrix & operator=(const SparseMatrix &S)
void SetZero()
Sets all values to zero.
Definition: Matrix.hh:856
unsigned int numRow_
Indicates the current number of rows and clumns.
unsigned int GetRows() const
Definition: Matrix.hh:202
unsigned int GetCols() const
Returns the maximum number of columns (max non-zero entry).
Definition: SparseMatrix.hh:74
void MultiplyIP(const double multiplier)
Multiplies this elementwise with &#39;multiplier&#39;.
int GaussJordan_()
Performs Gauss-Jordan algorithm on sparse matrix.
void InsertElement_(unsigned int row, unsigned int col, double value)
Insert an element.
double GetMaxRowElement(unsigned int row, unsigned int &col) const
Returns maximum element at given row (at least zero).
unsigned int maxCol_
unsigned int GetCols() const
Definition: Matrix.hh:204
void MultiplyWithTransposeOf(SparseMatrix &A, SparseMatrix &result)
Multiplies with transpose of A and returns result M*A&#39;.
void GetAsDense(BIAS::Matrix< double > &M) const
Returns this matrix as dense BIAS matrix in M.
void MultiplyDiagonalBy(const double &value)
Runs across diagonal and multiplies diagonal element with value.
void SetSubMatrix(unsigned int row, unsigned int col, BIAS::Matrix< double > const &A, unsigned int startRowInA, unsigned int startColInA, unsigned int row_count, unsigned int col_count)
Sets a submatrix beginning at (row,col) from a dense matrix.
int Solve(BIAS::Vector< double > &b, BIAS::Vector< double > &result)
Returns solution of linear equation system A*x = b.
void AddToDiagonal(const double &value)
Runs across diagonal and adds value to diagonal elements.
SparseMatrix()
Default constructor for zero sparse matrix.
Definition: SparseMatrix.hh:56
void AppendMatrixRight(SparseMatrix &H)
double GetMaxColumnElement(unsigned int col, unsigned int &row) const
Returns maximum element at given column (at least zero).
unsigned int GetRowsNum() const
Returns the total number of rows (matrix size).
Definition: SparseMatrix.hh:77
void AppendMatrixBottom(SparseMatrix &H)
int PseudoInverse(BIAS::Matrix< double > &inverse)
computes pseudo inverse and returns result in inverse
void Transpose(SparseMatrix &result)
Returns transposed matrix in result (as sparse matrix).
int InvertAndSolve(BIAS::Vector< double > &b, BIAS::Matrix< double > &inverse, BIAS::Vector< double > &result)
Inverts matrix and returns inverse (as dense matrix) and solution of linear equation system A^(-1)*x ...
void SetElement(unsigned int row, unsigned int col, double val)
Sets a new element or changes the value of an existing element.
unsigned int GetColsNum() const
Returns the total number of columns (matrix size).
Definition: SparseMatrix.hh:80