Hermitian矩阵的Eigen中的共轭梯度

时间:2018-05-05 19:28:11

标签: eigen

在文献中,共轭梯度法通常用于实对称正定矩阵。但是,在Eigen库中的CG方法的描述中: https://eigen.tuxfamily.org/dox/group__IterativeLinearSolvers__Module.html 人们可以找到声明: “ConjugateGradient for selfadjoint(hermitian)matrices”

这意味着它也应该适用于Hermitian(复杂的,而不是纯粹的)矩阵。是这样的吗?

一个最小的例子表明它实际上不能用Hermitian矩阵天真地工作。是否有人需要知道的技巧或描述中的错误?

我的最小例子使用自旋3/2矩阵Sx(实对称)和Sy(复Hermitian),其特征值知道为-1.5,-0.5,0.5,1.5。

真实对称情况的结果很好,但在复杂的情况下,它会产生NaN。

#include <iostream> 
#include <complex>
#include <Eigen/Core>
#include <Eigen/IterativeLinearSolvers>

int main(int args, char **argv){

  Eigen::VectorXcd b=Eigen::VectorXcd::Ones(4);    
  Eigen::VectorXcd x;

  std::complex<double> i_unit(0,1);

//Hermitian matrix:
  Eigen::MatrixXcd A(4,4);
  A<<0,-i_unit*sqrt(3.)/2., 0 ,0,  \
     i_unit*sqrt(3.)/2., 0 ,-i_unit, 0,\
     0,i_unit,0,-i_unit*sqrt(3.)/2.,\
     0,0,i_unit*sqrt(3.)/2.,0;

//Real symmetric matrix:
  Eigen::MatrixXcd B(4,4);
  B<<0,sqrt(3.)/2., 0 ,0,  \
     sqrt(3.)/2., 0 ,1, 0,\
     0,1,0,sqrt(3.)/2.,\
     0,0,sqrt(3.)/2.,0;

  Eigen::ConjugateGradient< Eigen::MatrixXcd, Eigen::Lower|Eigen::Upper> cg;
  cg.compute(A);
  x = cg.solve(b);

  std::cout<<"Hermitian matrix:"<<std::endl;
  std::cout<<"A: "<<std::endl<<A<<std::endl;
  std::cout<<"b: "<<std::endl<<b<<std::endl;
  std::cout<<"x: "<<std::endl<<x<<std::endl;
  std::cout<<"(b-A*x).norm(): "<<(b-A*x).norm()<<std::endl;
  std::cout<<"cg.error(): "<<cg.error()<<std::endl;
  std::cout<<std::endl;

  cg.compute(B);
  x = cg.solve(b);
  std::cout<<"Real symmetric matrix:"<<std::endl;
  std::cout<<"B: "<<std::endl<<B<<std::endl;
  std::cout<<"b: "<<std::endl<<b<<std::endl;
  std::cout<<"x: "<<std::endl<<x<<std::endl;
  std::cout<<"(b-B*x).norm(): "<<(b-B*x).norm()<<std::endl;
  std::cout<<"cg.error(): "<<cg.error()<<std::endl;
  std::cout<<std::endl;
  return 0;
}

1 个答案:

答案 0 :(得分:0)

Hermitian是不够的,它也需要正定,这不是你的情况,因为你的矩阵有正负特征值。无论如何,CG设计用于处理非常大的稀疏矩阵,对于4x4矩阵,更好地使用密集分解。在您的情况下,LDLT会很好。