![]() |
TAPs 0.7.7.3
|
00001 /****************************************************************************** 00002 SP_MatrixOperations.cpp 00003 00004 Operation on Matrix 00005 00006 SUKITTI PUNAK (07/14/2007) 00007 UPDATE (07/14/2007) 00008 ******************************************************************************/ 00009 #include "SP_MatrixOperations.h" 00010 // Using Inclusion Model (i.e. definitions are included in declarations) 00011 // (this name.cpp is included in name.hpp) 00012 // Each friend is defined directly inside its declaration. 00013 //----------------------------------------------------------------------------- 00014 // Member Fn: HouseHolderMatrix() --------------------------------------- 00015 // Desc: Find a HouseHolder matrix of a real square matrix only. 00016 SPtMatrix< double > MatrixOperations::HouseHolderMatrix( const SPtMatrix< double > &A, // I/P 00017 SPtMatrix< double > *ptrH, // O/P 00018 SPtMatrix< double > *ptrR ) // O/P 00019 { 00020 // only for square matrix 00021 if ( A.m_iRows != A.m_iCols ) return NULL; 00022 if ( ptrR != NULL ) { 00023 if ( ptrR->m_iRows != A.m_iRows || ptrR->m_iCols != A.m_iCols ) return false; 00024 } 00025 00026 SPtMatrix< double > B( A ); 00027 SPtMatrix< double > H( A ); 00028 00029 int i, k; 00030 double g, s; 00031 int n = H.m_iRows; 00032 SPtMatrix< double > W( n, 1 ); 00033 //SPtMatrix< double > V( n, 1 ); 00034 SPtMatrix< double > U( n, 1 ); 00035 00036 // Create Identity matrix 00037 SPtMatrix< double > I( n, n ); 00038 I.SetToIdentity(); 00039 00040 00041 for ( k = 0; k < n-1; k++ ) { 00042 //cout << "\nk = " << k << "\n"; 00043 00044 // Step 1: Set W_i = 0 for i = 0, ... , k-2 00045 for ( i = 0; i < k; i++ ) { 00046 W.m_tElement[i][0] = 0.0; 00047 } 00048 00049 // Step 2.1: Find g 00050 g = 0; 00051 for ( i = k; i < n; i++ ) { 00052 g += B.m_tElement[i][k] * B.m_tElement[i][k]; 00053 } 00054 g = sqrt(g); 00055 00056 // Step 2.2: Find s 00057 s = sqrt( 2 * g * ( g + fabs(B.m_tElement[k][k]) ) ); 00058 00059 // Step 3.1: Set W_k 00060 W.m_tElement[k][0] = ( B.m_tElement[k][k] + (B.m_tElement[k][k] >= 0.0 ? +1.0 : -1.0)*g ) / s; 00061 00062 // Step 3.2: Set W_i 00063 for ( i = k+1; i < n; i++ ) { 00064 W.m_tElement[i][0] = B.m_tElement[i][k] / s; 00065 } 00066 00067 //cout << "W" << endl; 00068 //W.DisplayElements(); 00069 00070 U = 2 * B.GetTranspose() * W; 00071 00072 //cout << "W*U'" << endl; 00073 //(W*U.GetTranspose()).DisplayElements(); 00074 00075 //H -= W*U.GetTranspose(); 00076 00077 H = I - ( 2 * W * W.GetTranspose() ); 00078 if ( ptrH != NULL ) ptrH[k] = H; 00079 00080 B = H*B; 00081 } 00082 00083 if ( ptrR != NULL ) *ptrR = B; 00084 00085 return H; 00086 } // END Member Fn: HouseHolderMatrix() 00087 //----------------------------------------------------------------------------- 00088 // Member Fn: QRFactorization() --------------------------------------- 00089 // Desc: Find a QR Factorization of a real square matrix only. 00090 bool MatrixOperations::QRFactorization( const SPtMatrix< double > &A, // I/P 00091 SPtMatrix< double > &Q, SPtMatrix< double > &R ) // O/P 00092 { 00093 // only square matrix 00094 if ( A.m_iRows != A.m_iCols ) return false; 00095 if ( Q.m_iRows != A.m_iRows || Q.m_iCols != A.m_iCols ) return false; 00096 if ( R.m_iRows != A.m_iRows || R.m_iCols != A.m_iCols ) return false; 00097 00098 int n = A.m_iRows; 00099 int k; 00100 00101 // Define R_(0) = A 00102 //R = A; 00103 SPtMatrix< double > *arrayH = new SPtMatrix< double >[ n-1 ]; 00104 00105 // For k = 1,...,n-1 00106 for ( k = 0; k < n-1; k++ ) { 00107 // Find H_(k) in order to reduce positions k+1,...,n, 00108 // in the k_th column of R_(k-1) to zero 00109 HouseHolderMatrix( A, arrayH, &R ); 00110 //R = ptrH[n-2] * R; 00111 } 00112 00113 // Define Q = I; 00114 // For k = n-1,...,1 00115 // Q = H_(k) * Q 00116 Q.SetToIdentity(); 00117 for ( k = n-2; k >= 0; k-- ) { 00118 Q = arrayH[k]*Q; 00119 } 00120 00121 //cout << "R is\n"; 00122 //R.DisplayElements(); 00123 //cout << "Q is\n"; 00124 //Q.DisplayElements(); 00125 //cout << "Q'*Q is "; 00126 //(Q.GetTranspose()*Q).DisplayElements(); 00127 //cout << "Q*R is\n"; 00128 //(Q*R).DisplayElements(); 00129 00130 delete [] arrayH; 00131 00132 return true; 00133 } // END Member Fn: QRFactorization() 00134 //----------------------------------------------------------------------------- 00135 // Member Fn: EigenValsByQRFactorization() --------------------------- 00136 // Desc: Find all eigen values of a real square matrix only. 00137 // I/P: A is a real square matrix. 00138 // I/P: (default = 6), times is the number of iterations. 00139 // O/P: (default = NULL), ptrO is a pointer to a matrix with will be the same 00140 // order as I/P Matrix, A. Its diagonal are the approximated eigen values. 00141 // Return: A column vector (n-by-1 matrix) contains all approximated eigenvalues. 00142 SPtMatrix< double > MatrixOperations::EigenValsByQRFactorization( const SPtMatrix< double > &A, // I/P 00143 int times, // Number of iterations 00144 SPtMatrix< double > *ptrO ) // O/P 00145 { 00146 // only square matrix 00147 if ( A.m_iRows != A.m_iCols ) return NULL; 00148 00149 // Given a real n-by-n matrix A: 00150 // Define A_(1) = A 00151 // For k = 1 to times 00152 // Factor A_(k) = Q_(k)R_(k) (so that Q_(k)'A_(k) = R_(k)) 00153 // Define A_(k+1) = R_(k)Q_(k) (so that A_(k+1) = Q_(k)'A_(k)Q_(k)) 00154 // end. 00155 double errThreshold = 1.0; 00156 int limit = 10000; 00157 int n = A.m_iRows; 00158 SPtMatrix< double > M( A ), Q( n, n ), R( n, n ); 00159 if ( times < 0 ) { 00160 errThreshold = pow( 10.0, times ); 00161 times = limit; 00162 } 00163 00164 for ( int k = 0; k < times; k++ ) { 00165 //cout << k << " "; 00166 00167 //M.DisplayElements(); 00168 00169 QRFactorization( M, Q, R ); 00170 00171 //cout << "R is \n"; 00172 //R.DisplayElements(); 00173 //cout << "Q is \n"; 00174 //Q.DisplayElements(); 00175 00176 M = R*Q; 00177 00178 if ( 1.0 > errThreshold ) { 00179 bool isEnough = true; 00180 for ( int r = n/2; r < n; r++ ) { 00181 for ( int c = 0; c <= n/2; c++ ) { 00182 if ( r > c ) { 00183 //cout << "(" << r << ", " << c << ") "; 00184 if ( fabs(M.m_tElement[r][c]) > errThreshold ) { 00185 isEnough = false; 00186 break; 00187 } 00188 } 00189 } 00190 } 00191 if ( isEnough ) { 00192 cout << "Stopped at Iteration# " << k << "\n"; 00193 break; 00194 } 00195 } 00196 } 00197 //cout << "M_(" << k << ")\n"; 00198 //M.DisplayElements(); 00199 00200 if ( ptrO != NULL ) *ptrO = M; 00201 00202 SPtMatrix< double > outMatrix( n, 1 ); 00203 for ( int i = 0; i < n; i++ ) { 00204 outMatrix.m_tElement[i][0] = M.m_tElement[i][i]; 00205 } 00206 00207 return M; 00208 //return outMatrix; 00209 } // END Member Fn: EigenValsByQRFactorization() 00210 //----------------------------------------------------------------------------- 00211 //34567890123456789012345678901234567890123456789012345678901234567890123456789 00212 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----