算法原理
算法涉及数据: 矩阵V:存储特征向量。 矩阵A:表示需要求特征向量的实对称矩阵。 算法过程: (1)初始化V为对角矩阵,即主对角线的元素是1,其他元素都为0。 (2)在A的非主对角线元素中,找到绝对值最大的元素 Apq ,即使用p、q代表A中绝对值最大元素的下标。 (3)计算tan2φ
算法实现
bool CPCAAlg :: JacbiCor ( double * pMatrix, int nDim, double * pdblVects, double * pdbEigenValues, double dbEps, int nJt)
{ for ( int i = 0 ; i < nDim; i ++ ) { pdblVects[ i* nDim+ i] = 1.0f ; for ( int j = 0 ; j < nDim; j ++ ) { if ( i != j) pdblVects[ i* nDim+ j] = 0.0f ; } } int nCount = 0 ; while ( 1 ) { double dbMax = pMatrix[ 1 ] ; int nRow = 0 ; int nCol = 1 ; for ( int i = 0 ; i < nDim; i ++ ) { for ( int j = 0 ; j < nDim; j ++ ) { double d = fabs ( pMatrix[ i* nDim+ j] ) ; if ( ( i!= j) && ( d> dbMax) ) { dbMax = d; nRow = i; nCol = j; } } } if ( dbMax < dbEps) break ; if ( nCount > nJt) break ; nCount++ ; double dbApp = pMatrix[ nRow* nDim+ nRow] ; double dbApq = pMatrix[ nRow* nDim+ nCol] ; double dbAqq = pMatrix[ nCol* nDim+ nCol] ; double dbAngle = 0.5 * atan2 ( - 2 * dbApq, dbAqq- dbApp) ; double dbSinTheta = sin ( dbAngle) ; double dbCosTheta = cos ( dbAngle) ; double dbSin2Theta = sin ( 2 * dbAngle) ; double dbCos2Theta = cos ( 2 * dbAngle) ; pMatrix[ nRow* nDim+ nRow] = dbApp* dbCosTheta* dbCosTheta + dbAqq* dbSinTheta* dbSinTheta + 2 * dbApq* dbCosTheta* dbSinTheta; pMatrix[ nCol* nDim+ nCol] = dbApp* dbSinTheta* dbSinTheta + dbAqq* dbCosTheta* dbCosTheta - 2 * dbApq* dbCosTheta* dbSinTheta; pMatrix[ nRow* nDim+ nCol] = 0.5 * ( dbAqq- dbApp) * dbSin2Theta + dbApq* dbCos2Theta; pMatrix[ nCol* nDim+ nRow] = pMatrix[ nRow* nDim+ nCol] ; for ( int i = 0 ; i < nDim; i ++ ) { if ( ( i!= nCol) && ( i!= nRow) ) { int u = i* nDim + nRow; int w = i* nDim + nCol; dbMax = pMatrix[ u] ; pMatrix[ u] = pMatrix[ w] * dbSinTheta + dbMax* dbCosTheta; pMatrix[ w] = pMatrix[ w] * dbCosTheta - dbMax* dbSinTheta; } } for ( int j = 0 ; j < nDim; j ++ ) { if ( ( j!= nCol) && ( j!= nRow) ) { int u = nRow* nDim + j; int w = nCol* nDim + j; dbMax = pMatrix[ u] ; pMatrix[ u] = pMatrix[ w] * dbSinTheta + dbMax* dbCosTheta; pMatrix[ w] = pMatrix[ w] * dbCosTheta - dbMax* dbSinTheta; } } for ( int i = 0 ; i < nDim; i ++ ) { int u = i* nDim + nRow; int w = i* nDim + nCol; dbMax = pdblVects[ u] ; pdblVects[ u] = pdblVects[ w] * dbSinTheta + dbMax* dbCosTheta; pdblVects[ w] = pdblVects[ w] * dbCosTheta - dbMax* dbSinTheta; } } std:: map< double , int > mapEigen; for ( int i = 0 ; i < nDim; i ++ ) { pdbEigenValues[ i] = pMatrix[ i* nDim+ i] ; mapEigen. insert ( make_pair ( pdbEigenValues[ i] , i ) ) ; } double * pdbTmpVec = new double [ nDim* nDim] ; std:: map< double , int > :: reverse_iterator iter = mapEigen. rbegin ( ) ; for ( int j = 0 ; iter != mapEigen. rend ( ) , j < nDim; ++ iter, ++ j) { for ( int i = 0 ; i < nDim; i ++ ) { pdbTmpVec[ i* nDim+ j] = pdblVects[ i* nDim + iter-> second] ; } pdbEigenValues[ j] = iter-> first; } for ( int i = 0 ; i < nDim; i ++ ) { double dSumVec = 0 ; for ( int j = 0 ; j < nDim; j ++ ) dSumVec += pdbTmpVec[ j * nDim + i] ; if ( dSumVec< 0 ) { for ( int j = 0 ; j < nDim; j ++ ) pdbTmpVec[ j * nDim + i] *= - 1 ; } } memcpy ( pdblVects, pdbTmpVec, sizeof ( double ) * nDim* nDim) ; delete [ ] pdbTmpVec; return 1 ;
}
算法原理