雅可比迭代法法

在图形图像中不少地方用到求矩阵的特征值和特征向量,好比主成分分析、OBB包围盒等。编程时通常都是用数值分析的方法来计算,这里介绍一下雅可比迭代法求解特征值和特征向量。雅可比迭代法的原理,网上资料不少,详细可见参考资料1。这里咱们简单介绍求解矩阵S特征值和特征向量的步骤:ios

初始化特征向量为对角阵V,即主对角线的元素都是1.其余元素为0。

在S的非主对角线元素中,找到绝对值最大元素 Sij。

用下 式计算tan2θ,求 cosθ、sinθ 及旋转矩阵Gij 。

用下面公式求S‘;用当前特征向量矩阵V乘以矩阵Gij获得当前的特征向量V。

若当前迭代前的矩阵A的非主对角线元素中最大值小于给定的阈值e时,中止计算;不然, 令S =S‘, 重复执行(2) ~ (5)。 中止计算时,获得特征值 li≈(S‘) ij ,i,j= 1,2,…,n.以及特征向量V。

这一步可选。根据特征值的大小从大到小的顺序从新排列矩阵的特征值和特征向量。

代码实现

用C++实现,并与参考资料1示例对比。web

#include

#include

#include

#include

using namespace std;

/**

* @brief Jacobi eigenvalue algorithm

* @param matrix n*n array

* @param dimdim represent n

* @param eigenvectorsn*n array

* @param eigenvaluesn*1 array

* @param precision precision requirements

* @param maxmax number of iterations

* @return

*/

bool Jacobi(double* matrix, int dim, double* eigenvectors, double* eigenvalues, double precision, int max)

{

for (int i = 0; i < dim; i++) {

eigenvectors[i*dim + i] = 1.0f;

for (int j = 0; j < dim; j++) {

if (i != j)

eigenvectors[i*dim + j] = 0.0f;

}

}

int nCount = 0;//current iteration

while (1) {

//find the largest element on the off-diagonal line of the matrix

double dbMax = matrix[1];

int nRow = 0;

int nCol = 1;

for (int i = 0; i < dim; i++) {//row

for (int j = 0; j < dim; j++) {//column

double d = fabs(matrix[i*dim + j]);

if ((i != j) && (d > dbMax)) {

dbMax = d;

nRow = i;

nCol = j;

}

}

}

if (dbMax < precision) //precision check

break;

if (nCount > max) //iterations check

break;

nCount++;

double dbApp = matrix[nRow*dim + nRow];

double dbApq = matrix[nRow*dim + nCol];

double dbAqq = matrix[nCol*dim + nCol];

//compute rotate angle

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);

matrix[nRow*dim + nRow] = dbApp*dbCosTheta*dbCosTheta +

dbAqq*dbSinTheta*dbSinTheta + 2 * dbApq*dbCosTheta*dbSinTheta;

matrix[nCol*dim + nCol] = dbApp*dbSinTheta*dbSinTheta +

dbAqq*dbCosTheta*dbCosTheta - 2 * dbApq*dbCosTheta*dbSinTheta;

matrix[nRow*dim + nCol] = 0.5*(dbAqq - dbApp)*dbSin2Theta + dbApq*dbCos2Theta;

matrix[nCol*dim + nRow] = matrix[nRow*dim + nCol];

for (int i = 0; i < dim; i++) {

if ((i != nCol) && (i != nRow)) {

int u = i*dim + nRow;//p

int w = i*dim + nCol;//q

dbMax = matrix[u];

matrix[u] = matrix[w] * dbSinTheta + dbMax*dbCosTheta;

matrix[w] = matrix[w] * dbCosTheta - dbMax*dbSinTheta;

}

}

for (int j = 0; j < dim; j++) {

if ((j != nCol) && (j != nRow)) {

int u = nRow*dim + j;//p

int w = nCol*dim + j;//q

dbMax = matrix[u];

matrix[u] = matrix[w] * dbSinTheta + dbMax*dbCosTheta;

matrix[w] = matrix[w] * dbCosTheta - dbMax*dbSinTheta;

}

}

//compute eigenvector

for (int i = 0; i < dim; i++) {

int u = i*dim + nRow;//p

int w = i*dim + nCol;//q

dbMax = eigenvectors[u];

eigenvectors[u] = eigenvectors[w] * dbSinTheta + dbMax*dbCosTheta;

eigenvectors[w] = eigenvectors[w] * dbCosTheta - dbMax*dbSinTheta;

}

}

//sort eigenvalues

std::map mapEigen;

for (int i = 0; i < dim; i++) {

eigenvalues[i] = matrix[i*dim + i];

mapEigen.insert(make_pair(eigenvalues[i], i));

}

double *pdbTmpVec = new double[dim*dim];

std::map::reverse_iterator iter = mapEigen.rbegin();

for (int j = 0; iter != mapEigen.rend(), j < dim; ++iter, ++j){

for (int i = 0; i < dim; i++) {

pdbTmpVec[i*dim + j] = eigenvectors[i*dim + iter->second];

}

eigenvalues[j] = iter->first;

}

for (int i = 0; i < dim; i++) {

double dSumVec = 0;

for (int j = 0; j < dim; j++)

dSumVec += pdbTmpVec[j * dim + i];

if (dSumVec < 0) {

for (int j = 0; j < dim; j++)

pdbTmpVec[j * dim + i] *= -1;

}

}

memcpy(eigenvectors, pdbTmpVec, sizeof(double)*dim*dim);

delete[]pdbTmpVec;

return true;

}

int main()

{

double a[4][4] = { {4, -30, 60, -35}, {-30, 300, -675, 420},{ 60, -675, 1620, -1050},{ -35, 420, -1050, 700}};

int n = 4;

double eps = 1e-10;

int T = 10000;

double p[4][4] = { 0 };

double v[4] = { 0 };

bool re = Jacobi(&a[0][0], n, &p[0][0], v, eps, T);

if (re){

cout << "Matrix:" << endl;

for (int i = 0; i < n; i++){

for (int j = 0; j < n; j++)

cout << setw(15) << a[i][j];

cout << endl;

}

cout << "eigenvectors:" << endl;

for (int i = 0; i < n; i++){

for (int j = 0; j < n; j++)

cout << setw(15) << p[i][j];

cout << endl;

}

cout << "eigenvalues:" << endl;

for (int i = 0; i < n; i++){

cout << setw(15) << v[i];

cout << endl;

}

}

else

cout << "false" << endl;

system("pause");

}

运行结果:

参考资料1示例结果:

参考资料

雅可比算法求矩阵特征值C语言源代码,雅可比(Jacobi)计算特征值和特征向量相关推荐

  1. python求雅可比矩阵_雅可比算法求矩阵的特征值和特征向量

    目的 求一个实对称矩阵的所有特征值和特征向量. 前置知识 对于一个实对称矩阵\(A\),必存在对角阵\(D\)和正交阵\(U\)满足$$D=U^TAU$$\(D\)的对角线元素为\(A\)的特征值,\ ...

  2. 雅可比算法求方阵的全部特征值和特征向量

    ValVect.h #include <iostream>class ValVect { public :ValVect(void);void clear(void);//~ValVect ...

  3. matlab 用古典雅可比方法求矩阵特征根 (仅使用基础函数)

    我们先看看<数值计算方法>这本书上关于古典雅可比方法的例题: %author FoddcusL FAFU %The Jacobi For root%输入:目标矩阵(input):目标接近的 ...

  4. 蚁群算法求最值c语言实现,蚁群算法代码(求函数最值)

    <蚁群算法代码(求函数最值)>由会员分享,可在线阅读,更多相关<蚁群算法代码(求函数最值)(4页珍藏版)>请在人人文库网上搜索. 1.function F=F(x1,x2) % ...

  5. 雅可比(Jacobi)计算特征值和特征向量

    雅可比迭代法法 在图形图像中很多地方用到求矩阵的特征值和特征向量,比如主成分分析.OBB包围盒等.编程时一般都是用数值分析的方法来计算,这里介绍一下雅可比迭代法求解特征值和特征向量.雅可比迭代法的原理 ...

  6. WarShall算法求矩阵传递闭包关系

    离散知识 给了你一个矩阵,你如何求他的传递闭包呢? //求出如下矩阵的传递闭包 1 0 1 0 0 1 1 1 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 利用WarShall ...

  7. 分治算法求最大最小值c语言,[蓝桥杯][算法提高VIP]和最大子序列 (C语言代码)分治法...

    解题思路: 注意事项: 参考代码:#include #include #include #include #include #include using namespace std; const in ...

  8. 大数求乘法逆元c语言,乘法逆元(编程计算)+两道版题

    前言 看到这里的小盆友们千万不要以为这个东西很难,其实就是个1+1->1(1个定义+1个定理->1坨乘法逆元).Let's begin.web 有关乘法逆元定义 这个咱们就不要玩笑了,来, ...

  9. QR分解求矩阵全部特征值

    QR算法求矩阵全部特征值的基本思想是利用矩阵的QR分解通过迭代格式 将A=A1化成相似的上三角阵,从而求出矩阵A的全部特征值. QR方法的计算步骤如下: 下面就依次进行介绍. 一. 将一般矩阵化为上H ...

最新文章

  1. Elasticsearch入门Demo(一)
  2. 网络编程 socket模块 tcp协议 udp协议
  3. 计算机网络第六章ppt课件,计算机网络与通信(第6章).ppt
  4. 谷歌Android系统在美成宠儿
  5. 注意事项,不定期更新
  6. php byte stringbuffer,重拾java基础(十三):String姐妹StringBuffer、StringBuilder总结
  7. KR C与ANSI C
  8. 025_MapReduce样例Hadoop TopKey算法
  9. Apache Struts2高危漏洞(S2-057CVE-2018-11776)
  10. win7电脑桌面便签哪个好用
  11. 支付安全不能说的那些事
  12. 马哥python课堂笔记_马哥教育PYTHON相关基础 笔记
  13. 小游戏---java版2048(2048 go go go)
  14. 说说用笔记本电脑的惨痛经历
  15. 罗马数字转化阿拉伯数字
  16. pascal voc2012数据集与主机制作数据集(目标检测篇)
  17. 统一社会信用代码正则表达式
  18. SDN和Openflow flowvisor NOX
  19. 求近似数最值_求近似数的方法
  20. 在CIELab颜色空间下使用八方向Sobel算子实现边缘检测

热门文章

  1. 使用蒙特卡洛模拟进行var计算
  2. ASP.NET 多媒体电子报刊设计思路
  3. Flask——xinge中文文档
  4. php zitian虚拟主机配置_建设网站怎么选择虚拟主机
  5. 深度学习-网络训练技巧
  6. 判断STM32 GPIO输入口的输入状态(高电平或低电平)
  7. ERROR in Template execution failed: ReferenceError: process is not defined(使用electron-vue出现的错误)
  8. 古有书山“勤”为径,现今升职加薪何为“径”?
  9. 平台多样化:Gavin Grover的Groovy之路
  10. 【设计模式】行为型02模板方法模式(Template Method Patten)