00001
00028 #include <string>
00029 #include <cstring>
00030 #include <fstream>
00031 #include <iostream>
00032 #include <cmath>
00033
00034 #include "isam/util.h"
00035
00036 #include "isam/SparseMatrix.h"
00037
00038 using namespace std;
00039 using namespace Eigen;
00040
00041 namespace isam {
00042
00043
00044 const int MIN_NUM_COLS = 10;
00045 const int MIN_NUM_ROWS = 10;
00046
00047 void SparseMatrix::_allocate_SparseMatrix(int num_rows, int num_cols, int max_num_rows, int max_num_cols, bool init_rows) {
00048 _num_rows = num_rows;
00049 _num_cols = num_cols;
00050 _max_num_rows = max_num_rows;
00051 _max_num_cols = max_num_cols;
00052 _rows = new SparseVector_p[_max_num_rows];
00053 if (init_rows) {
00054 for (int row=0; row<_num_rows; row++) {
00055 _rows[row] = new SparseVector();
00056 }
00057 }
00058 }
00059
00060 void SparseMatrix::_copy_from_SparseMatrix(const SparseMatrix& mat) {
00061 _allocate_SparseMatrix(mat._num_rows, mat._num_cols, mat._num_rows, mat._num_cols, false);
00062 for (int row=0; row<_num_rows; row++) {
00063 _rows[row] = new SparseVector(*mat._rows[row]);
00064 }
00065 }
00066
00067 void SparseMatrix::_dealloc_SparseMatrix() {
00068 for (int row=0; row<_num_rows; row++) {
00069 delete _rows[row];
00070 _rows[row] = NULL;
00071 }
00072 delete[] _rows;
00073 _rows = NULL;
00074 }
00075
00076 SparseMatrix::SparseMatrix(int num_rows, int num_cols) {
00077 requireDebug(num_rows>=0 && num_cols>=0, "SparseMatrix constructor: Index out of range");
00078
00079 _allocate_SparseMatrix(num_rows, num_cols, max(MIN_NUM_ROWS, 2*num_rows), max(MIN_NUM_COLS, 2*num_cols));
00080 }
00081
00082 SparseMatrix::SparseMatrix(const SparseMatrix& mat) {
00083 _copy_from_SparseMatrix(mat);
00084 }
00085
00086 SparseMatrix::SparseMatrix(const SparseMatrix& mat, int num_rows, int num_cols, int first_row, int first_col) {
00087 _allocate_SparseMatrix(num_rows, num_cols, num_rows, num_cols);
00088 for (int row=0; row<num_rows; row++) {
00089
00090 *_rows[row] = SparseVector(*mat._rows[row+first_row], num_rows, first_row);
00091 }
00092 }
00093
00094 SparseMatrix::SparseMatrix(int num_rows, int num_cols, SparseVector_p* rows) {
00095 _num_rows = num_rows;
00096 _num_cols = num_cols;
00097 _max_num_rows = num_rows;
00098 _max_num_cols = num_cols;
00099 _rows = new SparseVector_p[_max_num_rows];
00100 for (int row=0; row<_num_rows; row++) {
00101 _rows[row] = rows[row];
00102 }
00103 }
00104
00105 SparseMatrix::~SparseMatrix() {
00106 _dealloc_SparseMatrix();
00107 }
00108
00109 const SparseMatrix& SparseMatrix::operator= (const SparseMatrix& mat) {
00110
00111 if (this==&mat)
00112 return *this;
00113
00114
00115 _dealloc_SparseMatrix();
00116
00117
00118 _copy_from_SparseMatrix(mat);
00119
00120
00121 return *this;
00122 }
00123
00124 double SparseMatrix::operator()(int row, int col) const {
00125 requireDebug((row>=0) && (row<_num_rows) && (col>=0) && (col<_num_cols),
00126 "SparseMatrix::operator(): Index out of range.");
00127 return (*_rows[row])(col);
00128 }
00129
00130 void SparseMatrix::set(int row, int col, const double val, bool grow_matrix) {
00131 requireDebug(row>=0 && col>=0, "SparseMatrix::set: Invalid index.");
00132 if (grow_matrix) {
00133 ensure_num_rows(row+1);
00134 ensure_num_cols(col+1);
00135 } else {
00136 requireDebug(row<_num_rows && col<_num_cols, "SparseMatrix::set: Index out of range.");
00137 }
00138 _rows[row]->set(col, val);
00139 }
00140
00141 void SparseMatrix::append_in_row(int row, int col,const double val) {
00142 requireDebug(row>=0 && col>=0 && row<_num_rows && col<_num_cols,
00143 "SparseMatrix::append_in_row: Index out of range.");
00144 _rows[row]->append(col, val);
00145 }
00146
00147 int SparseMatrix::nnz() const {
00148 int nnz = 0;
00149 for (int row=0; row<_num_rows; row++) {
00150 nnz+=_rows[row]->nnz();
00151 }
00152 return nnz;
00153 }
00154
00155 int SparseMatrix::max_nz() const {
00156 int max_nz = 0;
00157 for (int row=0; row<_num_rows; row++) {
00158 max_nz = max(max_nz, _rows[row]->nnz());
00159 }
00160 return max_nz;
00161 }
00162
00163 void SparseMatrix::print(ostream& out) const {
00164 out << "%triples: (" << _num_rows << "x" << _num_cols << ", nnz:" << nnz() << ")" << endl;
00165 out.precision(12);
00166 for (int row=0; row<_num_rows; row++) {
00167 for (SparseVectorIter iter(*_rows[row]); iter.valid(); iter.next()) {
00168 double val;
00169 int col = iter.get(val);
00170 out << row << " " << col << " " << val << endl;
00171 }
00172 }
00173 }
00174
00175 void SparseMatrix::print(const string& file_name) const {
00176 ofstream out(file_name.c_str());
00177 print(out);
00178 out.close();
00179 }
00180
00181 void SparseMatrix::print_stats() const {
00182 cout << num_rows() << "x" << num_cols() << " nnz:" << nnz() << endl;
00183 }
00184
00185 void SparseMatrix::print_pattern() const {
00186 for (int row=0; row<_num_rows; row++) {
00187 for (int col=0; col<_num_cols; col++) {
00188 double val = operator()(row, col);
00189 if (val!=0) {
00190 cout << "x";
00191 } else {
00192 cout << ".";
00193 }
00194 }
00195 cout << endl;
00196 }
00197 }
00198
00199 void SparseMatrix::save_pattern_eps(const string& file_name) const {
00200 int x = num_cols();
00201 int y = num_rows();
00202
00203 int m = max(x,y);
00204 double scale = 1.;
00205 for (; scale*m >= 10000.; scale*=0.1);
00206
00207 ofstream out(file_name.c_str());
00208 out << "%!PS-Adobe-3.0 EPSF-3.0\n"
00209 "%%BoundingBox: 0 0 " << x*scale << " " << y*scale << "\n"
00210 "/BP{" << scale << " " << -scale << " scale 0 " << -y << " translate}bind def\n"
00211 "BP\n"
00212 "150 dict begin\n"
00213 "/D/dup cvx def/S/stroke cvx def\n"
00214 "/L/lineto cvx def/M/moveto cvx def\n"
00215 "/RL/rlineto cvx def/RM/rmoveto cvx def\n"
00216 "/GS/gsave cvx def/GR/grestore cvx def\n"
00217 "/REC{M 0 1 index RL 1 index 0 RL neg 0 exch RL neg 0 RL}bind def\n"
00218 "0 0 150 setrgbcolor\n"
00219 "0.01 setlinewidth\n";
00220 for (int row=0; row<_num_rows; row++) {
00221 for (SparseVectorIter iter(*_rows[row]); iter.valid(); iter.next()) {
00222 double val;
00223 int col = iter.get(val);
00224 out << "1 1 " << col << " " << row << " REC GS fill GR S" << endl;
00225 }
00226 }
00227 out.close();
00228 }
00229
00230 const SparseVector& SparseMatrix::get_row(int row) const {
00231 requireDebug(row>=0 && row<_num_rows, "SparseMatrix::get_row: Index out of range.");
00232 return *_rows[row];
00233 }
00234
00235 void SparseMatrix::set_row(int row, const SparseVector& new_row) {
00236 requireDebug(row>=0 && row<_num_rows, "SparseMatrix::set_row: Index out of range.");
00237 *_rows[row] = new_row;
00238 }
00239
00240 void SparseMatrix::import_rows(int num_rows, int num_cols, SparseVector_p* rows) {
00241 _dealloc_SparseMatrix();
00242 _num_rows = num_rows;
00243 _num_cols = num_cols;
00244 _max_num_rows = num_rows;
00245 _max_num_cols = num_cols;
00246 _rows = new SparseVector_p[_max_num_rows];
00247 for (int row=0; row<_num_rows; row++) {
00248 _rows[row] = rows[row];
00249 }
00250 }
00251
00252 void SparseMatrix::append_new_rows(int num) {
00253 requireDebug(num>=1, "SparseMatrix::append_new_rows: Cannot add less than one row.");
00254 int pos = _num_rows;
00255 if (_num_rows+num > _max_num_rows) {
00256
00257 int new_max_num_rows = max(2*_max_num_rows, _num_rows+num);
00258 SparseVector_p* new_rows = new SparseVector_p[new_max_num_rows];
00259 memcpy(new_rows, _rows, _num_rows*sizeof(SparseVector*));
00260 delete[] _rows;
00261 _max_num_rows = new_max_num_rows;
00262 _rows = new_rows;
00263 }
00264 for (int row=pos; row<=pos-1+num; row++) {
00265 _rows[row] = new SparseVector();
00266 }
00267 _num_rows += num;
00268 }
00269
00270 void SparseMatrix::append_new_cols(int num) {
00271 requireDebug(num>=1, "SparseMatrix::append_new_cols: Cannot add less than one column.");
00272 if (_num_cols+num > _max_num_cols) {
00273
00274 _max_num_cols = max(2*_max_num_cols, _num_cols+num);
00275 }
00276 _num_cols += num;
00277 }
00278
00279 void SparseMatrix::ensure_num_rows(int num_rows) {
00280 requireDebug(num_rows>0, "SparseMatrix::ensure_num_rows: num_rows must be positive.");
00281 if (_num_rows < num_rows) {
00282 append_new_rows(num_rows - _num_rows);
00283 }
00284 }
00285
00286 void SparseMatrix::ensure_num_cols(int num_cols) {
00287 requireDebug(num_cols>0, "SparseMatrix::ensure_num_cols: num_cols must be positive.");
00288 if (_num_cols < num_cols) {
00289 append_new_cols(num_cols - _num_cols);
00290 }
00291 }
00292
00293 void SparseMatrix::remove_row() {
00294 requireDebug(_num_rows>0, "SparseMatrix::remove_row called on empty matrix.");
00295
00296 delete _rows[_num_rows-1];
00297 _rows[_num_rows-1] = NULL;
00298 _num_rows--;
00299 }
00300
00301 void SparseMatrix::apply_givens(int row, int col, double* c_givens, double* s_givens) {
00302 requireDebug(row>=0 && row<_num_rows && col>=0 && col<_num_cols, "SparseMatrix::apply_givens: index outside matrix.");
00303 requireDebug(row>col, "SparseMatrix::apply_givens: can only zero entries below the diagonal.");
00304 const SparseVector& row_top = *_rows[col];
00305 const SparseVector& row_bot = *_rows[row];
00306 double a = row_top(col);
00307 double b = row_bot(col);
00308 double c, s;
00309 givens(a, b, c, s);
00310 if (c_givens) *c_givens = c;
00311 if (s_givens) *s_givens = s;
00312
00313 int n = row_bot.nnz() + row_top.nnz();
00314
00315 SparseVector_p new_row_top = new SparseVector(n);
00316 SparseVector_p new_row_bot = new SparseVector(n);
00317 SparseVectorIter iter_top(row_top);
00318 SparseVectorIter iter_bot(row_bot);
00319 bool top_valid = iter_top.valid();
00320 bool bot_valid = iter_bot.valid();
00321 while (top_valid || bot_valid) {
00322 double val_top = 0.;
00323 double val_bot = 0.;
00324 int idx_top = (top_valid)?iter_top.get(val_top):-1;
00325 int idx_bot = (bot_valid)?iter_bot.get(val_bot):-1;
00326 int idx;
00327 if (idx_bot<0) {
00328 idx = idx_top;
00329 } else if (idx_top<0) {
00330 idx = idx_bot;
00331 } else {
00332 idx = min(idx_top, idx_bot);
00333 }
00334 if (top_valid) {
00335 if (idx==idx_top) {
00336 iter_top.next();
00337 } else {
00338 val_top = 0.;
00339 }
00340 }
00341 if (bot_valid) {
00342 if (idx==idx_bot) {
00343 iter_bot.next();
00344 } else {
00345 val_bot = 0.;
00346 }
00347 }
00348 double new_val_top = c*val_top - s*val_bot;
00349 double new_val_bot = s*val_top + c*val_bot;
00350
00351 if (fabs(new_val_top) >= NUMERICAL_ZERO) {
00352
00353
00354 new_row_top->append(idx, new_val_top);
00355 }
00356 if (fabs(new_val_bot) >= NUMERICAL_ZERO) {
00357 new_row_bot->append(idx, new_val_bot);
00358 }
00359 top_valid = iter_top.valid();
00360 bot_valid = iter_bot.valid();
00361 }
00362
00363 delete _rows[col];
00364 delete _rows[row];
00365
00366 _rows[col] = new_row_top;
00367 _rows[row] = new_row_bot;
00368 _rows[row]->remove(col);
00369 }
00370
00371 int SparseMatrix::triangulate_with_givens() {
00372 int count = 0;
00373 for (int row=0; row<_num_rows; row++) {
00374 while (true) {
00375 int col = _rows[row]->first();
00376 if (col >= row || col < 0) {
00377 break;
00378 }
00379 apply_givens(row, col);
00380 count++;
00381 }
00382 }
00383 return count;
00384 }
00385
00386 const VectorXd operator*(const SparseMatrix& lhs, const VectorXd& rhs) {
00387 requireDebug(lhs.num_cols()==rhs.rows(), "SparseMatrix::operator* matrix and vector incompatible.");
00388 VectorXd res(lhs.num_rows());
00389 res.setZero();
00390 for (int row=0; row<lhs.num_rows(); row++) {
00391 for (SparseVectorIter iter(lhs.get_row(row)); iter.valid(); iter.next()) {
00392 double val;
00393 int col = iter.get(val);
00394 res(row) += val * rhs(col);
00395 }
00396 }
00397 return res;
00398 }
00399
00400 VectorXd mul_SparseMatrixTrans_Vector(const SparseMatrix& lhs, const VectorXd& rhs) {
00401 requireDebug(lhs.num_rows()==rhs.rows(), "SparseMatrix::mul_SparseMatrixTrans_Vector matrix and vector incompatible.");
00402 VectorXd res(lhs.num_cols());
00403 res.setZero();
00404 for (int row=0; row<lhs.num_rows(); row++) {
00405 for (SparseVectorIter iter(lhs.get_row(row)); iter.valid(); iter.next()) {
00406 double val;
00407 int col = iter.get(val);
00408 res(col) += val * rhs(row);
00409 }
00410 }
00411 return res;
00412 }
00413
00414 SparseMatrix sparseMatrix_of_matrix(const MatrixXd& m) {
00415 SparseMatrix s(m.rows(), m.cols());
00416 for (int r=0; r<m.rows(); r++) {
00417 for (int c=0; c<m.cols(); c++) {
00418 s.set(r, c, m(r,c));
00419 }
00420 }
00421 return s;
00422 }
00423
00424 MatrixXd matrix_of_sparseMatrix(const SparseMatrix& s) {
00425 MatrixXd m(s.num_rows(), s.num_cols());
00426 for (int r=0; r<s.num_rows(); r++) {
00427 for (int c=0; c<s.num_cols(); c++) {
00428 m(r, c) = s(r,c);
00429 }
00430 }
00431 return m;
00432 }
00433
00434 }
00435