cgma
CubitSparseMatrix.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines