日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

矩阵的特征值和特征向量的雅克比算法C/C++实现

發(fā)布時(shí)間:2025/3/21 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 矩阵的特征值和特征向量的雅克比算法C/C++实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

矩陣的特征值和特征向量是線性代數(shù)以及矩陣論中非常重要的一個(gè)概念。在遙感領(lǐng)域也是經(jīng)常用到,比如多光譜以及高光譜圖像的主成分分析要求解波段間協(xié)方差矩陣或者相關(guān)系數(shù)矩陣的特征值和特征向量。

根據(jù)普通線性代數(shù)中的概念,特征值和特征向量可以用傳統(tǒng)的方法求得,但是實(shí)際項(xiàng)目中一般都是用數(shù)值分析的方法來(lái)計(jì)算,這里介紹一下雅可比迭代法求解特征值和特征向量。

雅克比方法用于求實(shí)對(duì)稱(chēng)陣的全部特征值、特征向量。

對(duì)于實(shí)對(duì)稱(chēng)陣?A,必有正交陣?U,使

U?TA U = D。

其中?D?是對(duì)角陣,其主對(duì)角線元?li?是?A?的特征值. 正交陣?U?的第?j?列是?A?的屬于?li?的特征向量。

原理:Jacobi 方法用平面旋轉(zhuǎn)對(duì)矩陣?A?做相似變換,化A?為對(duì)角陣,進(jìn)而求出特征值與特征向量。

既然用到了旋轉(zhuǎn),這里就介紹一下旋轉(zhuǎn)矩陣。

對(duì)于?p?≠?q,下面定義的?n?階矩陣Upq?平面旋轉(zhuǎn)矩陣。


容易驗(yàn)證?Upq是正交陣。對(duì)于向量x,Upq?x?相當(dāng)于把坐標(biāo)軸Oxp和?Oxq?于所在的平面內(nèi)旋轉(zhuǎn)角度?j?.

變換過(guò)程: 在保證相似條件下,使主對(duì)角線外元素趨于零!

記?n?階方陣A?= [aij],? 對(duì)?A?做下面的變換:

A1=?UpqTAUpq, ? ? ? ? ? ? ? ? ? ? ? ??

????????? A1?仍然是實(shí)對(duì)稱(chēng)陣,因?yàn)?#xff0c;UpqT?=Upq-1,知A1與?A?的特征值相同。

?

前面說(shuō)了雅可比是一種迭代算法,所以每一步迭代時(shí),需要求出旋轉(zhuǎn)后新的矩陣,那么新的矩陣元素如何求,這里給出具體公式如下:


由上面的一組公式可以看到:

(1)矩陣A1?的第p?行、列與第?q?行、列中的元素發(fā)生了變化,其它行、列中的元素不變。

(2)p、q分別是前一次的迭代矩陣A的非主對(duì)角線上絕對(duì)值最大元素的行列號(hào)

(3)?j是旋轉(zhuǎn)角度,可以由下面的公式計(jì)算:


歸納可以得到雅可比迭代法求解矩陣特征值和特征向量的具體步驟如下:

(1)?初始化特征向量為對(duì)角陣V,即主對(duì)角線的元素都是1.其他元素為0。

(2)?在A的非主對(duì)角線元素中,找到絕對(duì)值最大元素?apq?

(3)?用式(3.14)計(jì)算tan2j,求 cosj,?sinj?及矩陣Upq .

(4)?用公式(1)-(4)求A1;用當(dāng)前特征向量矩陣V乘以矩陣Upq得到當(dāng)前的特征向量V。

(5)?若當(dāng)前迭代前的矩陣A的非主對(duì)角線元素中最大值小于給定的閾值e時(shí),停止計(jì)算;否則, 令A(yù)?=?A1?, 重復(fù)執(zhí)行(2) ~ (5)。 停止計(jì)算時(shí),得到特征值li≈(A1)?ij?,i,j= 1,2,…,n.以及特征向量V。

(6) 這一步可選。根據(jù)特征值的大小從大到小的順序重新排列矩陣的特征值和特征向量。

?

到現(xiàn)在為止,每一步的計(jì)算過(guò)程都十分清楚了,寫(xiě)出代碼也就不是難事了,具體代碼如下:


/** * @brief 求實(shí)對(duì)稱(chēng)矩陣的特征值及特征向量的雅克比法 * 利用雅格比(Jacobi)方法求實(shí)對(duì)稱(chēng)矩陣的全部特征值及特征向量 * @param pMatrix 長(zhǎng)度為n*n的數(shù)組,存放實(shí)對(duì)稱(chēng)矩陣 * @param nDim 矩陣的階數(shù) * @param pdblVects 長(zhǎng)度為n*n的數(shù)組,返回特征向量(按列存儲(chǔ)) * @param dbEps 精度要求 * @param nJt 整型變量,控制最大迭代次數(shù) * @param pdbEigenValues 特征值數(shù)組 * @return */ 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; //迭代次數(shù)while(1){//在pMatrix的非對(duì)角線上找到最大元素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) //迭代次數(shù)超過(guò)限制break;nCount++;double dbApp = pMatrix[nRow*nDim+nRow];double dbApq = pMatrix[nRow*nDim+nCol];double dbAqq = pMatrix[nCol*nDim+nCol];//計(jì)算旋轉(zhuǎn)角度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; //p int w = i*nDim + nCol; //qdbMax = 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; //pint w = nCol*nDim + j; //qdbMax = pMatrix[u]; pMatrix[u]= pMatrix[w]*dbSinTheta + dbMax*dbCosTheta; pMatrix[w]= pMatrix[w]*dbCosTheta - dbMax*dbSinTheta; } }//計(jì)算特征向量for(int i = 0; i < nDim; i ++) { int u = i*nDim + nRow; //p int w = i*nDim + nCol; //qdbMax = pdblVects[u]; pdblVects[u] = pdblVects[w]*dbSinTheta + dbMax*dbCosTheta; pdblVects[w] = pdblVects[w]*dbCosTheta - dbMax*dbSinTheta; } }//對(duì)特征值進(jìn)行排序以及重新排列特征向量,特征值即pMatrix主對(duì)角線上的元素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;}//設(shè)定正負(fù)號(hào)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; }


from:?http://blog.csdn.net/zhouxuguang236/article/details/40212143

總結(jié)

以上是生活随笔為你收集整理的矩阵的特征值和特征向量的雅克比算法C/C++实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。