我正在使用 double 类型的 Eigen::SparseMatrix 矩阵。我想找到最大和最小的特征值。
该问题的解决方案是将其转换为稠密,然后找到其特征值。最后是频谱中的最大值和最小值。
有没有更有效的方法来做到这一点?让我们说
- 可能没有将其转换为密集
- 可能无需计算所有频谱
我正在使用 double 类型的 Eigen::SparseMatrix 矩阵。我想找到最大和最小的特征值。
该问题的解决方案是将其转换为稠密,然后找到其特征值。最后是频谱中的最大值和最小值。
有没有更有效的方法来做到这一点?让我们说
使用 Eigen 计算选定的(例如几个最大或最小的)特征值有两个相对方便的选项。
第一个是Spectra,这是一个基于 Eigen 的仅包含头文件的 C++ 库,它使用类似于 ARPACK(隐式重启的 Arnoldi)的算法来计算一些特征解。
由于它是仅头文件,因此您只需下载并包含适当的头文件。该站点包含几个示例问题,可帮助您入门。
如果您的矩阵是对称的,则第二个选项是 ARPACK 子集的接口,它是标准 Eigen 分布的一部分,并且非常易于使用。下面是一小段代码,让您了解如何使用此界面的基本概念
#include <unsupported/Eigen/ArpackSupport>
typedef Eigen::SparseMatrix<double> SparseMat;
typedef Eigen::SimplicialLDLT<SparseMat> SparseChol;
typedef Eigen::ArpackGeneralizedSelfAdjointEigenSolver <SparseMat, SparseChol> Arpack;
Arpack arpack;
// define sparse matrix A
SparseMat A;
//...
// calculate the two smallest eigenvalues
int nbrEigenvalues = 2;
arpack.compute(A, nbrEigenvalues, "SM");
cout << "arpack eigenvalues\n" << arpack.eigenvalues().transpose() << endl;
这种方法的缺点是您需要为您的特定系统构建一个 ARPACK 库。如果您需要自己构建 ARPACK,我建议使用ARPACK-NG这个版本,因为它与原始版本相比修复了许多错误,并且更多地支持在不同平台上构建。
您可以使用 arpack [1],它实现了用于计算特征对的 Arnoldi 算法。由于 arpack 仅通过矩阵向量积与客户端代码通信,因此您可以使用自己的矩阵类型(包括特征稀疏矩阵)。还有一个带有 C++ 绑定 [2] 的版本可能更容易与 eigen 一起使用。为了计算最小特征值,使用稀疏分解算法(SuperLU 用于非对称,CHOLDMOD 用于对称)分解矩阵可能很有趣,并使用分解来计算 M^-1 的最大特征值而不是最小特征值的 M(一种称为谱变换的技术,我不久前在 [3] 中使用过,在某些情况下会对性能产生巨大影响)。整个算法(包括与 SUPERLU 的耦合)在我的 OpenNL 库中实现 [4]
[1] http://www.caam.rice.edu/software/ARPACK/
[2] http://www.ime.unicamp.br/~chico/arpack++/
[3] http://alice.loria.fr/index.php/publications.html?Paper=ManifoldHarmonics@2008
[4] OpenNL:http ://alice.loria.fr/index.php/software/4-library/23-opennl.html