cgma
|
00001 //- Class: CubitSparseMatrix 00002 //- 00003 //- Description: This file defines the CubitSparseMatrix class which is a 00004 //- sparse NxM Matrix. 00005 //- 00006 //- Author: Matt Staten 00007 //- Data: 4/15/2011 00008 //- Checked by: 00009 00010 #include "CubitSparseMatrix.hpp" 00011 #include "CubitMessage.hpp" 00012 #include "CubitDefines.h" 00013 #include "CubitFile.hpp" 00014 00015 #include <vector> 00016 #include <set> 00017 #include <stdexcept> 00018 #include <stdio.h> 00019 00020 using std::vector; 00021 using std::set; 00022 using std::map; 00023 00024 //============================================================================== 00025 // Description: Constructor 00026 // Notes: 00027 // Author: mlstate 00028 // Date: 4/19/2011 00029 //============================================================================== 00030 CubitSparseMatrix::CubitSparseMatrix 00031 ( 00032 int num_rows, 00033 int num_cols, 00034 vector<int> &is, 00035 vector<int> &js, 00036 vector<double> &es 00037 ) 00038 { 00039 numRows = numCols = 0; 00040 reset( num_rows, num_cols, is, js, es ); 00041 } 00042 00043 //============================================================================== 00044 // Description: Constructor 00045 // Notes: 00046 // Author: mlstate 00047 // Date: 4/19/2011 00048 //============================================================================== 00049 CubitSparseMatrix::CubitSparseMatrix() 00050 { 00051 numRows = numCols = 0; 00052 } 00053 00054 //============================================================================== 00055 // Description: 00056 // Notes: 00057 // Author: mlstate 00058 // Date: 4/19/2011 00059 //============================================================================== 00060 void CubitSparseMatrix::reset 00061 ( 00062 int num_rows, 00063 int num_cols, 00064 vector<int> &is, 00065 vector<int> &js, 00066 vector<double> &es 00067 ) 00068 { 00069 00070 if( is.size() != js.size() || 00071 is.size() != es.size() ) 00072 { 00073 throw std::invalid_argument("The sizes of is, js, and es must be the same" ); 00074 } 00075 00076 delete_data(); 00077 00078 int num_data = is.size(); 00079 00080 numRows = num_rows; 00081 numCols = num_cols; 00082 for ( int i = 0; i < num_data; i++ ) 00083 { 00084 add( is[i], js[i], es[i] ); 00085 } 00086 } 00087 00088 //============================================================================== 00089 // Description: Delete all data, free all memory, and set size to 0. 00090 // Notes: 00091 // Author: mlstate 00092 // Date: 4/19/2011 00093 //============================================================================== 00094 void CubitSparseMatrix::clear() 00095 { 00096 numRows = 0; 00097 numCols = 0; 00098 delete_data(); 00099 } 00100 00101 //============================================================================== 00102 // Description: 00103 // Notes: 00104 // Author: mlstate 00105 // Date: 4/19/2011 00106 //============================================================================== 00107 void CubitSparseMatrix::add( int row, int col, double data ) 00108 { 00109 if ( row+1 > numRows || 00110 col+1 > numCols ) 00111 { 00112 throw std::invalid_argument( "The dimensions of the 2 matrices must be the same." ); 00113 } 00114 00115 map<int,double> *submap = NULL; 00116 map<int,map<int,double>*>::iterator iter = matrixData.find( row ); 00117 if ( iter == matrixData.end() ) 00118 { 00119 submap = new map<int,double>; 00120 matrixData.insert( std::pair<int, map<int,double>*>(row, submap) ); 00121 } 00122 else 00123 { 00124 submap = iter->second; 00125 map<int,double>::iterator iter2 = submap->find( col ); 00126 if ( iter2 != submap->end() ) 00127 { 00128 iter2->second += data; 00129 return; 00130 } 00131 } 00132 submap->insert( std::pair<int, double>( col, data ) ); 00133 } 00134 00135 //============================================================================== 00136 // Description: destructor 00137 // Notes: 00138 // Author: mlstate 00139 // Date: 4/19/2011 00140 //============================================================================== 00141 CubitSparseMatrix::~CubitSparseMatrix() 00142 { 00143 delete_data(); 00144 } 00145 00146 //============================================================================== 00147 // Description: Delete all data in this matrix. 00148 // Notes: 00149 // Author: mlstate 00150 // Date: 4/19/2011 00151 //============================================================================== 00152 void CubitSparseMatrix::delete_data() 00153 { 00154 while ( !matrixData.empty() ) 00155 { 00156 map<int,double> *submap = matrixData.begin()->second; 00157 matrixData.begin()->second = NULL; 00158 matrixData.erase( matrixData.begin() ); 00159 delete submap; 00160 } 00161 } 00162 00163 // Create a matrix containing the rows and cols of this that are true in 00164 // rows_to_include and cols_to_include. 00165 //============================================================================== 00166 // Description: retrieve specified portions of this matrix. 00167 // Notes: 00168 // Author: mlstate 00169 // Date: 4/19/2011 00170 //============================================================================== 00171 void CubitSparseMatrix::sub_matrix 00172 ( 00173 const vector<bool> &rows_to_include, 00174 const vector<bool> &cols_to_include, 00175 CubitSparseMatrix &submatrix 00176 ) 00177 { 00178 if ( (int) rows_to_include.size() != numRows ) 00179 { 00180 throw std::invalid_argument( "The length of rows_to_include must the the same as the number of rows in the matrix." ); 00181 } 00182 if ( (int) cols_to_include.size() != numCols ) 00183 { 00184 throw std::invalid_argument( "The length of cols_to_include must the the same as the number of colums in the matrix." ); 00185 } 00186 00187 vector<int> is; 00188 vector<int> js; 00189 vector<double> es; 00190 int i; 00191 00192 int *row_indices = new int[numRows]; 00193 int *col_indices = new int[numCols]; 00194 int num_rows = 0; 00195 int num_cols = 0; 00196 for ( i = 0; i < numRows; i++ ) 00197 { 00198 if ( rows_to_include[i] ) 00199 { 00200 row_indices[i] = num_rows; 00201 num_rows++; 00202 } 00203 else 00204 { 00205 row_indices[i] = 0; 00206 } 00207 } 00208 00209 for ( i = 0; i < numCols; i++ ) 00210 { 00211 if ( cols_to_include[i] ) 00212 { 00213 col_indices[i] = num_cols; 00214 num_cols++; 00215 } 00216 else 00217 { 00218 col_indices[i] = 0; 00219 } 00220 } 00221 00222 map<int, map<int,double>*>::iterator iter1 = matrixData.begin(); 00223 while ( iter1 != matrixData.end() ) 00224 { 00225 int row = iter1->first; 00226 map<int,double>*submap = iter1->second; 00227 iter1++; 00228 00229 if ( !rows_to_include[row] ) 00230 continue; 00231 00232 map<int,double>::iterator iter2 = submap->begin(); 00233 while ( iter2 != submap->end() ) 00234 { 00235 int col = iter2->first; 00236 double data = iter2->second; 00237 iter2++; 00238 if ( !cols_to_include[col] ) 00239 continue; 00240 00241 is.push_back( row_indices[row] ); 00242 js.push_back( col_indices[col] ); 00243 es.push_back( data ); 00244 } 00245 } 00246 00247 delete [] col_indices; 00248 delete [] row_indices; 00249 00250 submatrix.reset( num_rows, num_cols, is, js, es ); 00251 } 00252 00253 //============================================================================== 00254 // Description: Multiply this matrix by a vector. 00255 // Notes: 00256 // Author: mlstate 00257 // Date: 4/19/2011 00258 //============================================================================== 00259 vector<double> CubitSparseMatrix::operator* (const vector<double> &vec ) const 00260 { 00261 if ( (int) vec.size() != numCols ) 00262 { 00263 throw std::invalid_argument( "The length of the input vector must be the same as the number of colums in the matrix." ); 00264 } 00265 00266 vector<double> ans( numRows ); 00267 00268 int i; 00269 for ( i = 0; i < numRows; i++ ) 00270 { 00271 ans[i] = 0.0; 00272 } 00273 00274 map<int, map<int,double>*>::const_iterator iter1 = matrixData.begin(); 00275 while ( iter1 != matrixData.end() ) 00276 { 00277 int row = iter1->first; 00278 map<int,double>*submap = iter1->second; 00279 iter1++; 00280 00281 map<int,double>::iterator iter2 = submap->begin(); 00282 while ( iter2 != submap->end() ) 00283 { 00284 int col = iter2->first; 00285 double data = iter2->second; 00286 iter2++; 00287 00288 ans[row] += data * vec[col]; 00289 } 00290 } 00291 return ans; 00292 } 00293 00294 //============================================================================== 00295 // Description: retrieve a row of this matrix. 00296 // Notes: 00297 // Author: mlstate 00298 // Date: 4/19/2011 00299 //============================================================================== 00300 const map<int,double> *CubitSparseMatrix::get_row( int row ) const 00301 { 00302 if ( row < 0 || row >= numRows ) 00303 { 00304 throw std::invalid_argument( "The row index must be greater than or equal to 0, and less than the number of rows in the matrix." ); 00305 } 00306 00307 map<int, map<int,double>*>::const_iterator iter = matrixData.find( row ); 00308 if ( iter == matrixData.end() ) 00309 return NULL; 00310 return iter->second; 00311 } 00312 00313 //============================================================================== 00314 // Description: debug print of this matrix. 00315 // Notes: 00316 // Author: mlstate 00317 // Date: 4/19/2011 00318 //============================================================================== 00319 void CubitSparseMatrix::print( char *filename ) const 00320 { 00321 printf( "CubitSparseMatrix::numRows: %d\n", numRows ); 00322 printf( "CubitSparseMatrix::numCols: %d\n", numCols ); 00323 int min, max; 00324 double ave; 00325 num_non_zeros_per_row( ave, max, min ); 00326 00327 printf( "CubitSparseMatrix::Average # Non Zeros per row: %f\n", ave ); 00328 printf( "CubitSparseMatrix::Minimum # Non Zeros per row: %d\n", min ); 00329 printf( "CubitSparseMatrix::Maximum # Non Zeros per row: %d\n", max ); 00330 00331 CubitFile fp; 00332 if ( filename ) 00333 fp.open( filename, "w" ); 00334 00335 map<int, map<int,double>*>::const_iterator iter1 = matrixData.begin(); 00336 while ( iter1 != matrixData.end() ) 00337 { 00338 int row = iter1->first; 00339 map<int,double>*submap = iter1->second; 00340 iter1++; 00341 00342 map<int,double>::iterator iter2 = submap->begin(); 00343 while ( iter2 != submap->end() ) 00344 { 00345 int col = iter2->first; 00346 double data = iter2->second; 00347 iter2++; 00348 00349 if ( fp.file() ) 00350 { 00351 fprintf( fp.file(), "%d %d %f\n", 00352 row, col, data ); 00353 } 00354 else 00355 { 00356 printf( "CubitSparseMatrix::(%d,%d) : %f\n", 00357 row, col, data ); 00358 } 00359 } 00360 } 00361 } 00362 00363 //============================================================================== 00364 // Description: debug print of this matrix. 00365 // Notes: 00366 // Author: mlstate 00367 // Date: 4/19/2011 00368 //============================================================================== 00369 void CubitSparseMatrix::num_non_zeros_per_row 00370 ( 00371 double &ave, 00372 int &max, 00373 int &min 00374 ) const 00375 { 00376 max = 0; 00377 min = numCols; 00378 ave = 0.0; 00379 00380 map<int, map<int,double>*>::const_iterator iter1 = matrixData.begin(); 00381 while ( iter1 != matrixData.end() ) 00382 { 00383 //iter1->first; 00384 map<int,double>*submap = iter1->second; 00385 iter1++; 00386 00387 int nz = submap->size(); 00388 ave += nz; 00389 00390 if ( nz > max ) max = nz; 00391 if ( nz < min ) min = nz; 00392 } 00393 if ( numCols > 0 ) 00394 ave /= numCols; 00395 } 00396 00397 //============================================================================== 00398 // Description: Add an identity matrix to this matrix. 00399 // Notes: 00400 // Author: mlstate 00401 // Date: 4/19/2011 00402 //============================================================================== 00403 void CubitSparseMatrix::plus_identity() 00404 { 00405 for ( int i = 0; i < numRows; i++ ) 00406 { 00407 if ( i > numCols ) break; 00408 add( i, i, 1.0 ); 00409 } 00410 } 00411 00412 //============================================================================== 00413 // Description: return the number of non-zeros in this matrix. 00414 // Notes: 00415 // Author: mlstate 00416 // Date: 4/19/2011 00417 //============================================================================== 00418 int CubitSparseMatrix::num_non_zeros( void ) const 00419 { 00420 int num_nz = 0; 00421 map<int, map<int,double>*>::const_iterator iter1 = matrixData.begin(); 00422 while ( iter1 != matrixData.end() ) 00423 { 00424 //iter1->first; 00425 map<int,double>*submap = iter1->second; 00426 if ( submap ) num_nz += submap->size(); 00427 iter1++; 00428 } 00429 return num_nz; 00430 } 00431