LAPACK(5)——矩阵广义特征值问题和QZ分解

摘要:
在Matlab中使用eig()解决了广义特征值问题Ax=Bx。[V,D]=eig,当A和B是方阵时,flag用于选择算法,'qz'用于选择qz算法。GGEV计算一对非对称度量的广义设计值和左和/或右广义设计向量。LAPACK也给出了QZ分解的函数dhgeqz,但需要H和T矩阵的输入。对于一般方阵,dgghrd可用于将输入方阵A和B转换为H和T矩阵。以下是这四个功能的原型和测试程序。

广义特征值问题,即Ax= LAPACK(5)——矩阵广义特征值问题和QZ分解第1张 Bx,

在Matlab中,使用eig()求解一般特征值问题和广义特征值。[V,D] = eig(A,B,flag), A和B时方阵,flag用来选择算法,'qz'表示选择使用QZ算法。

也可以直接调用qz()来求解,[AA,BB,Q,Z,V] = qz(A,B,flag), flag 表示使用复数或实数计算,默认取值为复数。

在Lapack中,有四个函数都是用来求解广义特征值的,

?GEGS  Computes the generalized eigenvalues, Schur form, and left and/or right Schur vectors for a pair of non-symmetric matrices.
?GGES  Computes the generalized eigenvalues, Schur form, and left and/or right Schur vectors for a pair of non-symmetric matrices.
?GEGV  Computes the generalized eigenvalues, and left and/or right generalized eigenvectors for a pair of non-symmetric matrices.
?GGEV  Computes the generalized eigenvalues, and left and/or right generalized eigenvectors for a pair of non-symmetric matrices.

区别在于前两个分解之后会输出舒尔形式,后两个则输出广义特征向量。而且gegs和gegv都被gges和ggev代替。两个都会用QZ分解求解广义特征值。

LAPACK也给出了QZ分解的函数dhgeqz,但要求输入H,T矩阵,对于一般的方阵,可以使用dgghrd将输入的方阵A,B变换成H,T矩阵。
下面给出这四个函数的原型和测试程序。

#include <iostream>
#include
<iomanip>
#include
<cmath>
#include
<complex>
using namespace std;
typedef complex
<double> dcomplex_t;

//lapacke headers
#include "lapacke.h"
#include
"lapacke_config.h"
#include
"lapacke_utils.h"

extern "C" {

lapack_int LAPACKE_dggev(
int matrix_order, char jobvl, char jobvr,
lapack_int n,
double* a, lapack_int lda, double* b,
lapack_int ldb,
double* alphar, double* alphai,
double* beta, double* vl, lapack_int ldvl, double* vr,
lapack_int ldvr );

lapack_int LAPACKE_dgges(
int matrix_order, char jobvsl, char jobvsr, char sort,
LAPACK_D_SELECT3 selctg, lapack_int n,
double* a,
lapack_int lda,
double* b, lapack_int ldb,
lapack_int
* sdim, double* alphar, double* alphai,
double* beta, double* vsl, lapack_int ldvsl,
double* vsr, lapack_int ldvsr );

lapack_logical selectg(
const double* AR,const double* AI,const double* B){
if(fabs(*AI)<1e-8)
return 0;
else
return 1;
}

lapack_int LAPACKE_dgghrd(
int matrix_order, char compq, char compz,
lapack_int n, lapack_int ilo, lapack_int ihi,
double* a, lapack_int lda, double* b, lapack_int ldb,
double* q, lapack_int ldq, double* z,
lapack_int ldz );

lapack_int LAPACKE_dhgeqz(
int matrix_order, char job, char compq, char compz,
lapack_int n, lapack_int ilo, lapack_int ihi,
double* h, lapack_int ldh, double* t, lapack_int ldt,
double* alphar, double* alphai, double* beta,
double* q, lapack_int ldq, double* z,
lapack_int ldz );
}

void PrintM(int M,int N,double* A){
int i = 0, j = 0;
for(i=0;i<M;i++){
for(j=0;j<N;j++)
cout
<< setw(10) << A[i*N+j] << " ";
cout
<< endl;
}
}

int main(){
int N = 4;
double A[16] = {3.9, 12.5, -34.5, -0.5,
4.3, 21.5, -47.5, 7.5,
4.3, 21.5, -43.5, 3.5,
4.4, 26.0, -46.0, 6.0};
double B[16] = {1.0, 2.0, -3.0, 1.0,
1.0, 3.0, -5.0, 4.0,
1.0, 3.0, -4.0, 3.0,
1.0, 3.0, -4.0, 4.0};
double alphar[4];
double alphai[4];
double beta[4];
int sdim[1];
int info = LAPACKE_dgges(LAPACK_ROW_MAJOR,'N', 'N',
'S', selectg,
N, A, N, B, N,
sdim,alphar,alphai,beta,
NULL,N,NULL,N);
cout
<< "dgges result:" << endl;
cout
<< "info = " << info << endl;
cout
<< "sdim = " << sdim[0] << endl;
cout
<< "alpha:" << endl;
PrintM(
1,4,alphar);
PrintM(
1,4,alphai);
cout
<< "beta:" << endl;
PrintM(
1,4,beta);
cout
<< "eigenvalue:" << endl;
for(int i=0;i<4;i++)
cout
<< dcomplex_t(alphar[i]/beta[i],alphai[i]/beta[i]) << " ";
cout
<< endl;

int k = 0;
for(k=0;k<N;k++){
alphar[k]
= 0;
alphai[k]
= 0;
beta[k]
= 0;
}

// dggev
info = LAPACKE_dggev(LAPACK_ROW_MAJOR,'N','N',
N,A,N,B,N,
alphar,alphai,beta,
NULL,N,NULL,N);
cout
<< "dggev result:" << endl;
cout
<< "info = " << info << endl;
cout
<< "alpha:" << endl;
PrintM(
1,4,alphar);
PrintM(
1,4,alphai);
cout
<< "beta:" << endl;
PrintM(
1,4,beta);
cout
<< "eigenvalue:" << endl;
for(int i=0;i<4;i++)
cout
<< dcomplex_t(alphar[i]/beta[i],alphai[i]/beta[i]) << " ";
cout
<< endl;

// using QZ iteration method to get eigenvalue
cout << "QZ method" << endl;
int NA = N;

info
= LAPACKE_dgghrd(LAPACK_ROW_MAJOR,'N','N',
NA,
1,NA,
A,NA,B,NA,NULL,NA,NULL,NA);
if(info!=0){
cout
<< "error when reduce A/B to H/T" << endl;
exit(
-1);
}
for(k=0;k<N;k++){
alphar[k]
= 0;
alphai[k]
= 0;
beta[k]
= 0;
}
info
= LAPACKE_dhgeqz(LAPACK_ROW_MAJOR,'E','N','N',
NA,
1,NA,A,NA,B,NA,
alphar,alphai,beta,
NULL,NA,NULL,NA);
if(info!=0){
}
cout
<< "alpha:" << endl;
PrintM(
1,4,alphar);
PrintM(
1,4,alphai);
cout
<< "beta:" << endl;
PrintM(
1,4,beta);
cout
<< "eigenvalue:" << endl;
for(int i=0;i<4;i++)
cout
<< dcomplex_t(alphar[i]/beta[i],alphai[i]/beta[i]) << " ";
cout
<< endl;

return 0;
}

结果如下,

dgges result:
info = 0
sdim = 2
alpha:
  0.857143   0.857143   0.617213          4 
   1.14286   -1.14286          0          0 
beta:
  0.285714   0.285714   0.308607          1 
eigenvalue:
(3,4)    (3,-4)    (2,0)    (4,0)    
dggev result:
info = 0
alpha:
   8.23538    3.54123   0.617213          4 
   10.9805   -4.72164          0          0 
beta:
   2.74513    1.18041   0.308607          1 
eigenvalue:
(3,4)    (3,-4)    (2,0)    (4,0)    
QZ method
alpha:
   8.23538    3.54123   0.617213          4 
   10.9805   -4.72164          0          0 
beta:
   2.74513    1.18041   0.308607          1 
eigenvalue:
(3,4)    (3,-4)    (2,0)    (4,0)

代码中调用dhgeqz的时候,没有使用迭代,暂时还没有弄清楚在dhgeqz内部有没有实现迭代,测试中结果是对的。需要注意的是,Matlab的qz函数会给出S,T矩阵,但Lapack的dgges给出的S-T结果并不一致,原因还没有弄明白的。  

关于dgges这个函数的一个参数LAPACK_D_SELECT3 selctg,有个参考,http://software.intel.com/sites/products/documentation/hpc/mkl/mklman/lle/lle_cinterface.htm

这里用到了函数指针,http://www.upsdn.net/html/2004-11/40.html

免责声明:文章转载自《LAPACK(5)——矩阵广义特征值问题和QZ分解》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇9 个基于JavaScript 和 CSS 的 Web 图表框架Citrix Netscaler版本管理和选择下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

遍历螺旋矩阵的技巧

遇见过挺多次,总结了一下方法,以后写的时候就不需要再慢慢想怎么模拟了 螺旋遍历数组方法: 按层模拟,从最外层开始 每次从第一个元素开始,→ ↓ ← ↑ 为一轮,通过进行操作的总次数判断是否结束 定义up,down,left,right表示 → ↓ ← ↑ 对应行的边界 up = 0; down = matrix.length-1 ; left = 0 ;...

VTK 空间几何变换(Transform),平移、旋转和缩放

先看下面的模型,这是一个Cow的三维模型, 在使用中,你是否会有下面的操作? 1.将Cow移动到某个位置——平移 2.转动到Cow背面——旋转 3.改变它大小——缩放 等等 可能你会说,这还不简单,通过操作相机就好了。然而并不是这样,操作相机,只使得相机的空间位置发生了变化,对三维物体并没有改变,要想改变模型,就需要对模形本身做空间变换。 空间变换的基础...

移植UE4的Spline与SplineMesh组件到Unity5

一个月前,想开始看下UE4的源码,刚开始以为有Ogre1.9与Ogre2.1源码的基础 ,应该还容易理解,把源码下起后,发现我还是想的太简单了,UE4的代码量对比Ogre应该多了一个量级,毕竟Ogre只是一个渲染引擎,而UE4包含渲染,AI,网络,编辑器等等,所以要理解UE4的源码,应该带着目地去看,这样容易理解。 在看UE4提供的ContentExamp...

SpringBoot如何使用Slf4j日志与logback-spring.xml配置详解

一、SpringBoot如何使用Slf4j日志   springboot是默认使用slf4j进行日志管理的,所以集成也比较方便。 1、添加依赖 (1)spring-boot-starter-web依赖,用于自动导入日志框架的依赖 <dependency> <groupId>org.springframework.boot&l...

node获取代码的svn版本号,并打包的时候,输出指定文件到打包后的项目里面

1、需要安装generate-asset-webpack-plugin插件,npm install generate-asset-webpack-plugin --save-dev 2、配置 webpack.prod.config.js 文件,让其打包的时候输出可配置的文件 3、在我们输入 npm run build 打包之后,在根目录就会生成versio...

求伪逆矩阵c++代码(Eigen库)

非方阵的矩阵的逆矩阵  pseudoInverse 伪逆矩阵是逆矩阵的广义形式,广义逆矩阵 matlab中是pinv(A)--》inv(A)。 #include "stdafx.h" #include<iostream> #include<Eigen/Core> #include<Eigen/SVD>...