我试图确定一个稀疏阵列的本征值和本征向量。由于我需要计算所有的特征向量和特征值,而我无法使用不支持的ArpackSupport模块来完成这一工作,所以我选择将系统转换为密集矩阵,并使用SelfAdjointEigenSolver来计算本征系统(我知道我的矩阵是实的,并且具有实的特征值)。在我的矩阵大小为1024*1024之前,这种方法工作得很好,但随后我开始得到与预期结果有偏差的结果。
在本模块的文档(https://eigen.tuxfamily.org/dox/classeigen_1_1selfadjointeigensolver.html)中,根据我的理解,可以更改最大迭代次数:
const int m_maxIterations静态最大迭代数。
如果算法在m_maxIterations*n次迭代内不收敛,则该算法终止,其中n表示矩阵的大小。此值当前设置为30(从LAPACK复制)。
但是,我不明白你是如何实现这一点的,用他们的例子:
SelfAdjointEigenSolver<Matrix4f> es;
Matrix4f X = Matrix4f::Random(4,4);
Matrix4f A = X + X.transpose();
es.compute(A);
cout << "The eigenvalues of A are: " << es.eigenvalues().transpose() << endl;
es.compute(A + Matrix4f::Identity(4,4)); // re-use es to compute eigenvalues of A+I
cout << "The eigenvalues of A+I are: " << es.eigenvalues().transpose() << endl
为了改变最大迭代次数,您将如何修改它?
另外,这会解决我的问题吗,还是我应该尝试找到一个替代函数或算法来解决本征系统?
我提前表示感谢。
增加迭代次数不太可能有帮助。另一方面,从
如果这无济于事,请更具体地说明“与预期结果的偏差”。
因此,您唯一的选择是更改头文件中的值并重新编译程序。
但是,在这样做之前,我要尝试一下奇异值分解。据主页介绍,它的精确度是“卓越--出处”(excellent-proven)。此外,它还能克服由于矩阵在数值上不完全对称而引起的问题。
我通过编写Jacobi算法解决了这个问题,该算法改编自《数值食谱:
void ROTATy(MatrixXd &a, int i, int j, int k, int l, double s, double tau)
{
double g,h;
g=a(i,j);
h=a(k,l);
a(i,j)=g-s*(h+g*tau);
a(k,l)=h+s*(g-h*tau);
}
void jacoby(int n, MatrixXd &a, MatrixXd &v, VectorXd &d )
{
int j,iq,ip,i;
double tresh,theta,tau,t,sm,s,h,g,c;
VectorXd b(n);
VectorXd z(n);
v.setIdentity();
z.setZero();
for (ip=0;ip<n;ip++)
{
d(ip)=a(ip,ip);
b(ip)=d(ip);
}
for (i=0;i<50;i++)
{
sm=0.0;
for (ip=0;ip<n-1;ip++)
{
for (iq=ip+1;iq<n;iq++)
sm += fabs(a(ip,iq));
}
if (sm == 0.0) {
break;
}
if (i < 3)
tresh=0.2*sm/(n*n);
else
tresh=0.0;
for (ip=0;ip<n-1;ip++)
{
for (iq=ip+1;iq<n;iq++)
{
g=100.0*fabs(a(ip,iq));
if (i > 3 && (fabs(d(ip))+g) == fabs(d[ip]) && (fabs(d[iq])+g) == fabs(d[iq]))
a(ip,iq)=0.0;
else if (fabs(a(ip,iq)) > tresh)
{
h=d(iq)-d(ip);
if ((fabs(h)+g) == fabs(h))
{
t=(a(ip,iq))/h;
}
else
{
theta=0.5*h/(a(ip,iq));
t=1.0/(fabs(theta)+sqrt(1.0+theta*theta));
if (theta < 0.0)
{
t = -t;
}
c=1.0/sqrt(1+t*t);
s=t*c;
tau=s/(1.0+c);
h=t*a(ip,iq);
z(ip)=z(ip)-h;
z(iq)=z(iq)+h;
d(ip)=d(ip)- h;
d(iq)=d(iq) + h;
a(ip,iq)=0.0;
for (j=0;j<ip;j++)
ROTATy(a,j,ip,j,iq,s,tau);
for (j=ip+1;j<iq;j++)
ROTATy(a,ip,j,j,iq,s,tau);
for (j=iq+1;j<n;j++)
ROTATy(a,ip,j,iq,j,s,tau);
for (j=0;j<n;j++)
ROTATy(v,j,ip,j,iq,s,tau);
}
}
}
}
}
}
函数jacoby接收方阵n的大小,方阵n是我们要计算的矩阵,我们要求解的矩阵(a),一个矩阵将接收每一列的特征向量,一个向量将接收特征值。它有点慢,所以我尝试用OpenMp并行化它(请参阅:Jacobi算法的并行化使用eigen C++使用OpenMp),但不幸的是,对于4096x4096大小的矩阵,我并不意味着计算时间的改善。