Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages | Examples

matrixFunctionInterface.cpp

Go to the documentation of this file.
00001 //////////////////////////////////////////////////////////////////////////////
00002 /*! \file matrixFunctionInterface.cpp
00003  *  \brief Miscellaneous matrix functions
00004  *  \author     $Author: jayhawk_hokie $
00005  *  \version $Revision: 1.3 $
00006  *  \date    $Date: 2007/07/24 08:40:44 $
00007 *////////////////////////////////////////////////////////////////////////////
00008 /*
00009 */
00010 #include "matrixFunctionInterface.h"
00011 
00012 using namespace std;
00013 
00014 using namespace O_SESSAME;
00015 
00016 /*! \brief Takes in a square matrix and returns, by reference, the Real and Imaginary Eigenvalues and the Eigenvectors for that matrix
00017  *      This function does not normalize the Eigenvectors.
00018  *  @param _Matrix is a matrix passed to find the eigenvalues and eigenvectors
00019  *  @return _EigenVectors is a matrix of the eigen vectors
00020  *  @return _RealEigenValues is a vector of the real eigenvalues of matrix _Matrix
00021  *  @return _ImaginaryEigenValues is a vector of the imaginary eigenvalues of matrix _Matrix
00022  */
00023 void eigenValues( Matrix _Matrix, Matrix &_EigenVectors, Vector &_RealEigenValues, Vector &_ImaginaryEigenValues )
00024 {
00025         // Get matrix size.
00026         int rows = _Matrix[1].getIndexCount();
00027         int columns = _Matrix[2].getIndexCount();
00028 
00029         // Check for a square matrix.
00030         if ( rows != columns )
00031         {
00032                 cerr << "WARNING: Not a square matrix. Not able to determine EigenValues in the eigenValues function." <<endl;
00033                 return;
00034         }       
00035 
00036         // Initialize the REAL ** matrices and REAL * vectors for the eigen function.
00037         void *vmblock;
00038         REAL **matrix;
00039         REAL **eigenVectors;
00040         REAL *realEigenValues;
00041         REAL *imaginaryEigenValues;
00042         int *count;
00043 
00044         // Copies _Matrix into matrix for the eigen function.
00045         vmblock = vminit();
00046         matrix = (REAL **) vmalloc( vmblock, MATRIX, rows, columns );
00047         matrix = convertMatrix( _Matrix );
00048         eigenVectors = (REAL **) vmalloc( vmblock, MATRIX, rows, columns );
00049         realEigenValues = (REAL *) vmalloc( vmblock, VEKTOR, rows, 0 );
00050         imaginaryEigenValues = (REAL *) vmalloc( vmblock, VEKTOR, rows, 0 );
00051         count = (int *) vmalloc( vmblock, VVEKTOR, rows, sizeof( *count ) );
00052         
00053         // Takes the matrix of size (rows, rows) and finds the real and imaginary eigenvalues and the eigenvectors.
00054         eigen( 1, 1, 1, rows, matrix, eigenVectors, realEigenValues, imaginaryEigenValues, count );
00055 
00056         // Copies the Eigenvalues and Eigenvectors into a usable form (of type Matrix and Vector).
00057         _EigenVectors = convertMatrix(eigenVectors, rows);
00058         _RealEigenValues = convertVector(realEigenValues, rows);
00059         _ImaginaryEigenValues = convertVector(imaginaryEigenValues, rows);
00060 
00061         return;
00062 }
00063 
00064 
00065 /* /brief Calculate the greatest eigenvalue of a real
00066  *  square matrix and the associated eigenvector
00067  *  by the power method.
00068  *  @param _Matrix is a matrix passed to find the greatest eigenvalue and associated eigenvector
00069  *  @return _EigenValue the largest eigenvalue of _Matrix
00070  *  @return _EigenVector the eigenvector associated with _EigenValue
00071  *  @param _MaxIterations is the maximum iterations this function will use in finding _EigenValue                     
00072  */
00073 bool greatestEigenValue( Matrix _Matrix, double &_EigenValue, Vector &_EigenVector, int _MaxIterations ) 
00074 {
00075         // Maximum size of the matrix being passed in 
00076         int NMAX = 26;
00077         
00078         // The smallest double 
00079         double eps = .0000000001;
00080 
00081         // Required precision
00082         double dta = .00001;
00083         
00084         // Used to find any errors while calculating the greatest eigenvalue
00085         int isError;    
00086                 
00087         // Get matrix size.
00088         int rows = _Matrix[1].getIndexCount();
00089         int columns = _Matrix[2].getIndexCount();
00090 
00091         // Check for a square matrix.
00092         if ( rows != columns )
00093         {
00094                 cerr << "WARNING: Not a square matrix. Not able to determine EigenValues in the eigenValues function." <<endl;
00095                 return false;
00096         }       
00097         
00098         // Used in the for loops
00099         int i, j, iterator;
00100         
00101         // phi and s are used to check the precision of the eigenvalue
00102         double phi, s;
00103 
00104         // Temporary eigenvector
00105         Vector eigenVectorTemp( NMAX );
00106 
00107         // Initialize _EigenVector to the right size
00108         _EigenVector = eigenVectorTemp;
00109  
00110         for( i = 1; i <= rows; i++ )
00111                 eigenVectorTemp(i) = 1.0 / sqrt( double(i) );
00112         isError = -1; 
00113         iterator = 1;
00114 
00115         while ( isError == -1 && iterator <= _MaxIterations )
00116         {
00117                 _EigenValue = 0.0;
00118                 for ( i = 1; i <= rows; i++ )
00119                 {
00120                         _EigenVector(i) = 0.0;
00121                         for ( j = 1; j <= rows; j++ )
00122                                 _EigenVector(i) += _Matrix(i,j) * eigenVectorTemp(j);
00123                         if ( fabs( _EigenVector(i) ) > fabs( _EigenValue ) ) 
00124                                 _EigenValue = _EigenVector(i);
00125                 }
00126 
00127                 if ( fabs( _EigenValue ) < eps ) 
00128                         isError = 0;
00129                 else
00130                 {
00131                         for ( i = 1; i <= rows; i++ )  
00132                                 _EigenVector(i) /= _EigenValue;
00133                         phi = 0.0;
00134                         for ( i = 1; i <= rows; i++ ) 
00135                         {
00136                                 s = fabs( _EigenVector(i) - eigenVectorTemp(i) );
00137                                 if ( s > phi )
00138                                         phi = s;
00139                         }
00140                         if ( phi < dta )
00141                                 isError = 1;
00142                         else
00143                         {
00144                                 for ( i = 1; i <= rows; i++ ) 
00145                                         eigenVectorTemp(i) = _EigenVector(i);
00146                                 iterator++;
00147                         }
00148                  }
00149  
00150         }
00151         
00152         // Check to see if any errors had occured
00153         switch(isError+1) {
00154                 case 0: cerr << "WARNING: No convergence.\n";
00155                                 return false;
00156                 case 1: cerr << "WARNING: Method does not apply.\n"; break;
00157                                 return false;
00158         }
00159 
00160         // If there were no errors, return true
00161         return true;
00162 }
00163 
00164 
00165 /*! \brief Takes in a square matrix and returns the norm of the matrix, which is the square root of the largest eigenvalue of A(transpose)*A 
00166  *  @param _Matrix is a matrix passed to find the norm
00167  *  @return norm2 is the norm of the matrix _Matrix
00168  */
00169 double norm2( Matrix _Matrix )
00170 {
00171         // Variables to me used in the eigenValue function
00172         Vector eigenVector;
00173         double largestEigenValue = 0;
00174         
00175         // Find the transpose of _Matrix
00176         Matrix transposeMatrix = ~_Matrix;
00177         
00178         // Variables used in this function to find the norm
00179         double norm2;
00180         
00181         // Find the greatest eigenvalues and its associated eigenvector
00182         if( greatestEigenValue( ( transposeMatrix * _Matrix ), largestEigenValue, eigenVector, 20 ) )
00183         {
00184                 // Solve for the norm of _Matrix
00185                 //norm2 = sqrt( largestEigenValue );
00186         }
00187         else
00188         {
00189                 cerr << "Trying alternate method for max eigenvalue." << endl;
00190                 Matrix _EigenVectors(3,3);
00191                 Vector _RealEigenValues(3);
00192                 Vector _ImaginaryEigenValues(3);
00193                 eigenValues( transposeMatrix * _Matrix, _EigenVectors, _RealEigenValues, _ImaginaryEigenValues );
00194 
00195                 largestEigenValue = _RealEigenValues.maxAbs( );
00196                 
00197                 if( largestEigenValue < 1e-4 )
00198                 {
00199                         // Error if the eigenvalue function returns false
00200                         cerr << "WARNING: Largest eigenvalue cannot be found. Set to zero." << endl;
00201                 }
00202         }
00203         
00204         // Solve for the norm of _Matrix
00205         norm2 = sqrt( largestEigenValue );
00206         
00207         return( norm2 );
00208         
00209 }
00210 
00211 /*! \brief Takes in a Matrix and returns a REAL ** with the same values 
00212  *  @param _Matrix is a Matrix 
00213  *  @return finalMatrix the Matrix in REAL **
00214  */
00215 REAL ** convertMatrix( Matrix _Matrix )
00216 {
00217         int n = _Matrix[1].getIndexCount();
00218         void *vmblock;
00219         REAL **finalMatrix;
00220 
00221         vmblock = vminit();
00222         finalMatrix = (REAL **) vmalloc( vmblock, MATRIX, n, n );
00223 
00224         for( int i = 1; i <= n ; i++ )
00225         {
00226                 for( int j = 1; j <= n ; j++ )
00227                 {
00228                         finalMatrix[i-1][j-1] = _Matrix(i,j);
00229                 }
00230         }
00231         return finalMatrix;
00232 }
00233 
00234 /*! \brief Takes in a Vector and returns a REAL * with the same values 
00235  *  @param _Matrix is a Vector 
00236  *  @return finalMatrix the Matrix in REAL *
00237  */
00238 REAL * convertVector( Vector _Vector )
00239 {
00240         int n = _Vector.getIndexCount();
00241         void *vmblock;
00242         REAL *finalVector;
00243 
00244         vmblock = vminit();
00245         finalVector = (REAL *) vmalloc( vmblock, VEKTOR, n, 0 );
00246 
00247         for( int i = 1; i <= n; i++ )
00248         {
00249                 finalVector[i-1] = _Vector(i);
00250         }
00251         return finalVector;
00252 }
00253 
00254 /*! \brief Takes in a REAL ** and returns a Matrix with the same values 
00255  *  @param finalMatrix the Matrix in REAL **
00256  *  @return _Matrix is a Matrix 
00257  */
00258 Matrix convertMatrix( REAL **_Matrix, int n )
00259 {
00260         Matrix finalMatrix(n,n);
00261 
00262         for( int i = 1; i <= n ; i++ )
00263         {
00264                 for( int j = 1; j <= n ; j++ )
00265                 {
00266                         finalMatrix(i,j) = _Matrix[i-1][j-1];
00267                 }
00268         }
00269         return finalMatrix;
00270 }
00271 
00272 /*! \brief Takes in a REAL * and returns a Vector with the same values 
00273  *  @param finalMatrix the Matrix in REAL *
00274  *  @return _Matrix is a Vector 
00275  */
00276 Vector convertVector( REAL *_Vector, int n )
00277 {
00278         Vector finalVector(n);
00279 
00280         for( int i = 1; i <= n; i++ )
00281         {
00282                 finalVector(i) = _Vector[i-1];
00283         }
00284         return finalVector;
00285 }
00286 
00287 /*! \brief Determines the inverse of a 3x3 matrix
00288  *  @param _A matrix is a 3x3 matrix to be inverted
00289  *  @return _Ainv is a 3x3 Matrix
00290  */
00291 Matrix matrixInv3x3( Matrix _A )
00292 {
00293         /* Determine cofactor Matrix */
00294         Matrix _coFactor(3,3);
00295         Matrix _temp(2,2);
00296                 _temp(_(1,2),_(1,2) ) = _A( _(2,3),_(2,3) );
00297         _coFactor(1,1) = matrixDet( _temp );
00298                 _temp( _(1,2),1 ) = _A( _(2,3),1 ); 
00299                 _temp(_(1,2),2) = _A( _(2,3),3 ); 
00300         _coFactor(1,2) = matrixDet( _temp );
00301                 _temp(_(1,2),_(1,2) ) = _A( _(2,3),_(1,2) );
00302         _coFactor(1,3) = matrixDet( _temp );
00303         
00304                 _temp( 1,_(1,2) ) = _A( 1,_(2,3) );
00305                 _temp( 2,_(1,2) ) = _A( 3,_(2,3) );
00306         _coFactor(2,1) = matrixDet( _temp );
00307                 _temp(1,1) = _A(1,1);
00308                 _temp(1,2) = _A(1,3);
00309                 _temp(2,1) = _A(3,1);
00310                 _temp(2,2) = _A(3,3);
00311         _coFactor(2,2) = matrixDet( _temp );
00312                 _temp( 1,_(1,2) ) = _A( 1,_(1,2) );
00313                 _temp( 2,_(1,2) ) = _A( 3,_(1,2) );
00314         _coFactor(2,3) = matrixDet( _temp );
00315 
00316                 _temp(_(1,2),_(1,2) ) = _A( _(1,2),_(2,3) );
00317         _coFactor(3,1) = matrixDet( _temp );
00318                 _temp(_(1,2),1) = _A( _(1,2),1 ); 
00319                 _temp(_(1,2),2) = _A( _(1,2),3 ); 
00320         _coFactor(3,2) = matrixDet( _temp );
00321                 _temp(_(1,2),_(1,2) ) = _A( _(1,2),_(1,2) );
00322         _coFactor(3,3) = matrixDet( _temp );
00323         
00324         /* Determine Determinate of A */
00325         double det = _A(1,1)*_coFactor(1,1) - _A(2,1)*_coFactor(2,1) + _A(3,1)*_coFactor(3,1);
00326 
00327         /* Apply alternating signs */
00328         _coFactor(1,2) = -_coFactor(1,2);
00329         _coFactor(2,1) = -_coFactor(2,1);
00330         _coFactor(2,3) = -_coFactor(2,3);
00331         _coFactor(3,2) = -_coFactor(3,2);
00332 
00333         /* Transpose */
00334         Matrix invPart = ~_coFactor;
00335 
00336         /* Inverse */
00337         Matrix _Ainv = invPart/det;
00338         
00339         return ( _Ainv );
00340 } 
00341 
00342 /*! \brief Determines the determinate of a matrix up to 3x3 
00343  *  @param _A matrix is a nxn matrix where n<=3
00344  *  @return _det is a double
00345  */
00346 double matrixDet( Matrix _A )
00347 {
00348         /* Check Size */
00349         int rows = _A[1].getIndexCount( );
00350         double _det;
00351         Matrix _Aa(2,2);
00352         switch (rows)
00353         {
00354                 case 1:
00355                         _det = _A(1,1);
00356                         break;
00357                 case 2:
00358                         _det = matrixDet2x2( _A );
00359                         break;
00360                 case 3:
00361                         _Aa(1,1) = _A(2,1); _Aa(1,2) = _A(2,3);
00362                         _Aa(2,1) = _A(3,1); _Aa(2,2) = _A(3,3);
00363                         _det = _A(1,1)*matrixDet2x2( _A( _(2,3),_(2,3) ) ) - _A(1,2)*matrixDet2x2( _Aa ) + _A(1,3)*matrixDet2x2( _A( _(2,3), _(1,2) ) );
00364                         break;
00365                 default:
00366                         cerr << "Error: Matrix dimension exceeds current ability of det." << endl;
00367                         _det = 0;
00368                         break;
00369         }
00370         return ( _det );
00371 }
00372 
00373 /*! \brief Determines the determinate of a 2x2 matrix 
00374  *  @param _A matrix is a 2x2 matrix
00375  *  @return _det is a double
00376  */
00377 double matrixDet2x2( Matrix _A )
00378 {
00379         double _det = _A(1,1)*_A(2,2)-_A(1,2)*_A(2,1);
00380         return ( _det );
00381 }
00382 
00383 // Do not change the comments below - they will be added automatically by CVS
00384 /*****************************************************************************
00385 *       $Log: matrixFunctionInterface.cpp,v $
00386 *       Revision 1.3  2007/07/24 08:40:44  jayhawk_hokie
00387 *       Modified matrix norm2 function. Hard coded inverse of 3x3 matrix and det.
00388 *
00389 *       Revision 1.2  2007/06/19 19:30:18  jayhawk_hokie
00390 *       Added function to determine inverse for 3x3 matrix. Added function to determine det(A).
00391 *
00392 *       Revision 1.1  2007/04/13 16:47:52  bleslie
00393 *       Initial submission of the matrix function interface files
00394 *
00395 *       Revision 1.6  2006/07/05 20:59:13  jayhawk_hokie
00396 *       *** empty log message ***
00397 *
00398 *
00399 *
00400 *
00401 ******************************************************************************/
00402 

Generated on Wed Sep 5 12:54:22 2007 for DSACSS Operational Code by  doxygen 1.3.9.1