00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef _SPARSE_MATRIX_H
00012 #define _SPARSE_MATRIX_H
00013
00023 extern const unsigned int SM_MAX_ROWS;
00024 extern const unsigned int SM_MAX_COLUMNS;
00025 extern const unsigned int SM_RESERVE;
00026
00027 template< class T > class Triplet {
00028 public:
00029 Triplet()
00030 {;}
00031
00032 Triplet( T a, unsigned int b, unsigned int c )
00033 : a_( a ), b_( b ), c_( c )
00034 {;}
00035 bool operator< ( const Triplet< T >& other ) const {
00036 return ( c_ < other.c_ );
00037 }
00038 static bool cmp( const Triplet< T >& p, const Triplet< T >& q ) {
00039 if ( p.b_ == q.b_ )
00040 return ( p.c_ < q.c_ );
00041 else if ( p.b_ < q.b_ )
00042 return true;
00043 return false;
00044 }
00045
00046 T a_;
00047 unsigned int b_;
00048 unsigned int c_;
00049 };
00050
00051
00052 typedef vector< class T >::const_iterator constTypeIter;
00053 template < class T > class SparseMatrix
00054 {
00055 public:
00057
00059 SparseMatrix()
00060 : nrows_( 0 ), ncolumns_( 0 ), rowStart_( 1, 0 )
00061 {
00062 N_.resize( 0 );
00063 N_.reserve( SM_RESERVE );
00064 colIndex_.resize( 0 );
00065 colIndex_.reserve( SM_RESERVE );
00066 }
00067
00068 SparseMatrix( unsigned int nrows, unsigned int ncolumns )
00069 {
00070 setSize( nrows, ncolumns );
00071 }
00072
00074
00076
00077 unsigned int nRows() const {
00078 return nrows_;
00079 }
00080
00081 unsigned int nColumns() const {
00082 return ncolumns_;
00083 }
00084
00085 unsigned int nEntries() const {
00086 return N_.size();
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00107
00109
00113 void setSize( unsigned int nrows, unsigned int ncolumns ) {
00114 if ( nrows == 0 || ncolumns == 0 ) {
00115 N_.clear();
00116 rowStart_.resize( 1 );
00117 rowStart_[0] = 0;
00118 colIndex_.clear();
00119 nrows_ = 0;
00120 ncolumns_ = 0;
00121 return;
00122 }
00123 if ( nrows < SM_MAX_ROWS && ncolumns < SM_MAX_COLUMNS ) {
00124 N_.clear();
00125 N_.reserve( 2 * nrows );
00126 nrows_ = nrows;
00127 ncolumns_ = ncolumns;
00128 rowStart_.clear();
00129 rowStart_.resize( nrows + 1, 0 );
00130 colIndex_.clear();
00131 colIndex_.reserve( 2 * nrows );
00132 } else {
00133 cerr << "Error: SparseMatrix::setSize( " <<
00134 nrows << ", " << ncolumns << ") out of range: ( " <<
00135 SM_MAX_ROWS << ", " << SM_MAX_COLUMNS << ")\n";
00136 }
00137 }
00138
00143 void set( unsigned int row, unsigned int column, T value )
00144 {
00145 if ( nrows_ == 0 || ncolumns_ == 0 )
00146 return;
00147 vector< unsigned int >::iterator i;
00148 vector< unsigned int >::iterator begin =
00149 colIndex_.begin() + rowStart_[ row ];
00150 vector< unsigned int >::iterator end =
00151 colIndex_.begin() + rowStart_[ row + 1 ];
00152
00153 if ( begin == end ) {
00154 unsigned long offset = begin - colIndex_.begin();
00155 colIndex_.insert( colIndex_.begin() + offset, column );
00156 N_.insert( N_.begin() + offset, value );
00157 for ( unsigned int j = row + 1; j <= nrows_; j++ )
00158 rowStart_[ j ]++;
00159 return;
00160 }
00161
00162 if ( column > *( end - 1 ) ) {
00163 unsigned long offset = end - colIndex_.begin();
00164 colIndex_.insert( colIndex_.begin() + offset, column );
00165 N_.insert( N_.begin() + offset, value );
00166 for ( unsigned int j = row + 1; j <= nrows_; j++ )
00167 rowStart_[ j ]++;
00168 return;
00169 }
00170 for ( i = begin; i != end; i++ ) {
00171 if ( *i == column ) {
00172 N_[ i - colIndex_.begin()] = value;
00173 return;
00174 } else if ( *i > column ) {
00175 unsigned long offset = i - colIndex_.begin();
00176 colIndex_.insert( colIndex_.begin() + offset, column );
00177 N_.insert( N_.begin() + offset, value );
00178 for ( unsigned int j = row + 1; j <= nrows_; j++ )
00179 rowStart_[ j ]++;
00180 return;
00181 }
00182 }
00183 }
00184
00188 void unset( unsigned int row, unsigned int column )
00189 {
00190 if ( nrows_ == 0 || ncolumns_ == 0 )
00191 return;
00192 vector< unsigned int >::iterator i;
00193 vector< unsigned int >::iterator begin =
00194 colIndex_.begin() + rowStart_[ row ];
00195 vector< unsigned int >::iterator end =
00196 colIndex_.begin() + rowStart_[ row + 1 ];
00197
00198 if ( begin == end ) {
00199 return;
00200 }
00201
00202 if ( column > *( end - 1 ) ) {
00203 return;
00204 }
00205 for ( i = begin; i != end; i++ ) {
00206 if ( *i == column ) {
00207 unsigned long offset = i - colIndex_.begin();
00208 colIndex_.erase( i );
00209 N_.erase( N_.begin() + offset );
00210 for ( unsigned int j = row + 1; j <= nrows_; j++ )
00211 rowStart_[ j ]--;
00212 return;
00213 } else if ( *i > column ) {
00214 return;
00215 }
00216 }
00217 }
00218
00223 T get( unsigned int row, unsigned int column ) const
00224 {
00225 if ( nrows_ == 0 || ncolumns_ == 0 )
00226 return 0;
00227 assert( row < nrows_ && column < ncolumns_ );
00228 vector< unsigned int >::const_iterator i;
00229 vector< unsigned int >::const_iterator begin =
00230 colIndex_.begin() + rowStart_[ row ];
00231 vector< unsigned int >::const_iterator end =
00232 colIndex_.begin() + rowStart_[ row + 1 ];
00233
00234 i = find( begin, end, column );
00235 if ( i == end ) {
00236 return 0;
00237 } else {
00238 return N_[ rowStart_[row] + (i - begin) ];
00239 }
00240 }
00242
00244
00255 unsigned int getRow( unsigned int row,
00256 const T** entry, const unsigned int** colIndex ) const
00257 {
00258 if ( row >= nrows_ || ncolumns_ == 0 ) {
00259 entry = 0;
00260 colIndex = 0;
00261 return 0;
00262 }
00263 unsigned int rs = rowStart_[row];
00264 if ( rs >= N_.size() ) {
00265 entry = 0;
00266 colIndex = 0;
00267 return 0;
00268 }
00269 *entry = &( N_[ rs ] );
00270 *colIndex = &( colIndex_[rs] );
00271 return rowStart_[row + 1] - rs;
00272 }
00273
00279 unsigned int getRow( unsigned int row,
00280 vector< T >& e, vector< unsigned int >& c ) const
00281 {
00282 e.clear();
00283 c.clear();
00284 if ( row >= nrows_ || ncolumns_ == 0 ) {
00285 return 0;
00286 }
00287 unsigned int rs = rowStart_[row];
00288 if ( rs >= N_.size() ) {
00289 return 0;
00290 }
00291 unsigned int ret = rowStart_[row + 1] - rs;
00292 e.insert( e.begin(),
00293 N_.begin() + rs, N_.begin() + rs + ret );
00294 c.insert( c.begin(),
00295 colIndex_.begin() + rs, colIndex_.begin() + rs + ret );
00296 return ret;
00297 }
00298
00299
00305 unsigned int getColumn( unsigned int col,
00306 vector< T >& entry,
00307 vector< unsigned int >& rowIndex ) const
00308 {
00309 entry.resize( 0 );
00310 rowIndex.resize( 0 );
00311
00312 unsigned int row = 0;
00313 for ( unsigned int i = 0; i < N_.size(); ++i ) {
00314 if ( col == colIndex_[i] ) {
00315 entry.push_back( N_[i] );
00316 while ( rowStart_[ row + 1 ] <= i )
00317 row++;
00318 rowIndex.push_back( row );
00319 }
00320 }
00321 return entry.size();
00322 }
00323
00324 void rowOperation( unsigned int row, unary_function< T, void>& f )
00325 {
00326 assert( row < nrows_ );
00327
00328 constTypeIter i;
00329
00330 unsigned int rs = rowStart_[row];
00331 vector< unsigned int >::const_iterator j = colIndex_.begin() + rs;
00332
00333 constTypeIter end =
00334 N_.begin() + rowStart_[ row + 1 ];
00335
00336
00337 for ( i = N_.begin() + rs; i != end; ++i )
00338 f( *i );
00339 }
00340
00346 void addRow( unsigned int rowNum, const vector< T >& row ) {
00347 assert( rowNum < nrows_ );
00348 assert( rowStart_.size() == (nrows_ + 1 ) );
00349 assert( N_.size() == colIndex_.size() );
00350 if ( ncolumns_ == 0 )
00351 return;
00352 for ( unsigned int i = 0; i < ncolumns_; ++i ) {
00353 if ( row[i] != T( ~0 ) ) {
00354 N_.push_back( row[i] );
00355 colIndex_.push_back( i );
00356 }
00357 }
00358 rowStart_[rowNum + 1] = N_.size();
00359 }
00360
00366 void addRow( unsigned int rowNum,
00367 const vector < T >& entry,
00368 const vector< unsigned int >& colIndexArg )
00369 {
00370 assert( rowNum < nrows_ );
00371 assert( rowStart_.size() == (nrows_ + 1 ) );
00372 assert( rowStart_[ rowNum ] == N_.size() );
00373 assert( entry.size() == colIndexArg.size() );
00374 assert( N_.size() == colIndex_.size() );
00375 if ( ncolumns_ == 0 )
00376 return;
00377 N_.insert( N_.end(), entry.begin(), entry.end() );
00378 colIndex_.insert( colIndex_.end(),
00379 colIndexArg.begin(), colIndexArg.end() );
00380 rowStart_[rowNum + 1] = N_.size();
00381 }
00383
00385
00386 void clear() {
00387 N_.resize( 0 );
00388 colIndex_.resize( 0 );
00389 assert( rowStart_.size() == (nrows_ + 1) );
00390 rowStart_.assign( nrows_ + 1, 0 );
00391 }
00392
00393
00398 void transpose() {
00399 vector< Triplet< T > > t;
00400
00401 unsigned int rowIndex = 0;
00402 if ( rowStart_.size() < 2 )
00403 return;
00404
00405
00406
00407
00408
00409
00410 unsigned int rs = rowStart_[0];
00411 for ( unsigned int i = 0; i < N_.size(); ++i ) {
00412 while( rs == rowStart_[ rowIndex + 1 ] ) {
00413 rowIndex++;
00414 }
00415 rs++;
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 Triplet< T > x( N_[i], rowIndex, colIndex_[i] );
00426 t.push_back( x );
00427 }
00428
00429
00430 stable_sort( t.begin(), t.end() );
00431
00432
00433 unsigned int j = ~0;
00434 rowStart_.resize( 0 );
00435 rowStart_.push_back( 0 );
00436 unsigned int ci = 0;
00437 for ( unsigned int i = 0; i < N_.size(); ++i ) {
00438 N_[i] = t[i].a_;
00439 colIndex_[i] = t[i].b_;
00440
00441 while ( ci != t[i].c_ ) {
00442 rowStart_.push_back( i );
00443 ci++;
00444 }
00445
00446
00447
00448
00449
00450
00451
00452 }
00453 for ( j = ci; j < ncolumns_; ++j )
00454 rowStart_.push_back( N_.size() );
00455
00456 j = nrows_;
00457 nrows_ = ncolumns_;
00458 ncolumns_ = j;
00459 assert( rowStart_.size() == nrows_ + 1 );
00460 }
00461
00470 void reorderColumns( const vector< unsigned int >& colMap )
00471 {
00472 unsigned int numNewColumns = colMap.size();;
00473 SparseMatrix< T > old = *this;
00474 setSize( nrows_, numNewColumns );
00475 if ( numNewColumns == 0 )
00476 return;
00477 for ( unsigned int i = 0; i < old.nrows_; ++i ) {
00478 const T* entry;
00479 const unsigned int* colIndex;
00480 unsigned int n = old.getRow( i, &entry, &colIndex );
00481
00482 vector< T > newEntry( numNewColumns );
00483 vector< bool > isNewEntry( numNewColumns, false );
00484 unsigned int numOccupiedEntries = 0;
00485 for ( unsigned int j = 0; j < n; ++j ) {
00486 assert( colIndex[j] < old.ncolumns_ );
00487 for ( unsigned int q = 0; q < colMap.size(); ++q ) {
00488 if ( colMap[q] == colIndex[j] ) {
00489 isNewEntry[q] = true;
00490 newEntry[q] = entry[j];
00491 ++numOccupiedEntries;
00492 }
00493 }
00494 }
00495
00496 vector< T > sparseEntry;
00497 vector< unsigned int > sparseCols;
00498 sparseEntry.reserve( numOccupiedEntries );
00499 sparseCols.reserve( numOccupiedEntries );
00500 for ( unsigned int q = 0; q < numNewColumns; ++q ) {
00501 if ( isNewEntry[q] ) {
00502 sparseEntry.push_back( newEntry[q] );
00503 sparseCols.push_back( q );
00504 }
00505 }
00506 addRow( i, sparseEntry, sparseCols );
00507 }
00508 }
00509
00511
00513
00514 void tripletFill( const vector< unsigned int >& row,
00515 const vector< unsigned int >& col,
00516 const vector< T >& z )
00517 {
00518 unsigned int len = row.size();
00519 if ( len > col.size() ) len = col.size();
00520 if ( len > z.size() ) len = z.size();
00521 vector< Triplet< T > > trip( len );
00522 for ( unsigned int i = 0; i < len; ++i )
00523 trip[i]= Triplet< T >(z[i], row[i], col[i] );
00524 sort( trip.begin(), trip.end(), Triplet< T >::cmp );
00525 unsigned int nr = trip.back().b_ + 1;
00526 unsigned int nc = 0;
00527 for ( typename vector< Triplet< T > >::iterator i =
00528 trip.begin(); i != trip.end(); ++i ) {
00529 if ( nc < i->c_ )
00530 nc = i->c_;
00531 }
00532 nc++;
00533 setSize( nr, nc );
00534
00535 vector< unsigned int > colIndex( nc );
00536 vector< T > entry( nc );
00537
00538 typename vector< Triplet< T > >::iterator j = trip.begin();
00539 for ( unsigned int i = 0; i < nr; ++i ) {
00540 colIndex.clear();
00541 entry.clear();
00542 while( j != trip.end() && j->b_ == i ) {
00543 colIndex.push_back( j->c_ );
00544 entry.push_back( j->a_ );
00545 j++;
00546 }
00547 addRow( i, entry, colIndex );
00548 }
00549 }
00550
00551 void pairFill( const vector< unsigned int >& row,
00552 const vector< unsigned int >& col, T value )
00553 {
00554 vector< T > z( row.size(), value );
00555 tripletFill( row, col, z );
00556 }
00557
00559
00561
00562 void printTriplet( const vector< Triplet< T > >& t )
00563 {
00564 for ( unsigned int i = 0; i < t.size(); ++i ) {
00565 cout << i << " " << t[i].a_ << " " << t[i].b_ <<
00566 " " << t[i].c_ << endl;
00567 }
00568 }
00569
00573 void print() const {
00574 for ( unsigned int i = 0; i < nrows_; ++i ) {
00575 unsigned int k = rowStart_[i];
00576 unsigned int end = rowStart_[i + 1];
00577 unsigned int nextColIndex = colIndex_[k];
00578 for ( unsigned int j = 0; j < ncolumns_; ++j ) {
00579 if ( j < nextColIndex ) {
00580 cout << "0 ";
00581 } else if ( k < end ) {
00582 cout << N_[k] << " ";
00583 ++k;
00584 nextColIndex = colIndex_[k];
00585 } else {
00586 cout << "0 ";
00587 }
00588 }
00589 cout << endl;
00590 }
00591 }
00592
00596 void printInternal() const {
00597 unsigned int max = (nrows_ < N_.size() ) ? N_.size() : nrows_+1;
00598 cout << "# ";
00599 for ( unsigned int i = 0; i < max; ++i )
00600 cout << i << " ";
00601 cout << "\nrs ";
00602 for ( unsigned int i = 0; i < rowStart_.size(); ++i )
00603 cout << rowStart_[i] << " ";
00604 cout << "\ncol ";
00605 for ( unsigned int i = 0; i < N_.size(); ++i )
00606 cout << colIndex_[i] << " ";
00607 cout << "\nN ";
00608 for ( unsigned int i = 0; i < N_.size(); ++i )
00609 cout << N_[i] << " ";
00610 cout << endl;
00611 }
00612
00613
00614 protected:
00615 unsigned int nrows_;
00616 unsigned int ncolumns_;
00617 vector< T > N_;
00618
00619
00620
00621
00622
00623 vector< unsigned int > colIndex_;
00624
00626 vector< unsigned int > rowStart_;
00627 };
00628
00629 #endif // _SPARSE_MATRIX_H