Spectra: Sparse Eigenvalue Computation Toolkit
repository·master·Indexed 21 days ago
https://github.com/yixuan/spectraA C++ header-only library for large-scale eigenvalue problems, designed as a modern redesign of the FORTRAN ARPACK library. Built on top of the Eigen linear algebra library, Spectra provides various solvers including SymEigsSolver, GenEigsSolver, and HermEigsSolver for symmetric, general, and Hermitian matrices. It supports both standard and shift-and-invert modes and is designed for efficiency with sparse matrices by requiring only specific operations like matrix-vector multiplication.
What's inside Spectra
- Spectra (Sparse Eigenvalue Computation Toolkit) is a header-only C++ library designed for large-scale eigenvalue problems. It is a redesigned version of the FORTRAN-based ARPACK, implemented in C++ and built on top of the Eigen linear algebra library. Because both Spectra and Eigen are header-only, Spectra can be easily embedded into existing C++ projects without complex build dependencies.
How shift-and-invert mode works
masterWhen you need to find eigenvalues closest to a specific value
σ(for example, the smallest eigenvalues of a positive definite matrix by settingσ = 0), use the shift-and-invert mode.In this mode, selection rules are applied to
1/(λ - σ)instead ofλ(whereλare the eigenvalues ofA). To use this, you must define a shift-solve matrix operation (e.g.,y = inv(A - σ * I) * x). Refer to the documentation forSymEigsShiftSolverfor implementation details.How to use Spectra for eigenvalue problems
masterSpectra calculates a specified number (
k) of eigenvalues of a large square matrix (A). Instead of requiring the full matrix, the algorithms only require specific operations, most commonly matrix-vector multiplication (A * x). This makes Spectra highly efficient for sparse matrices.To use the library, follow these two steps:
- Define a matrix operation class: Implement a class that performs the required operation (e.g.,
y = A * xor the shift-solvey = inv(A - σ * I) * x). You can use Spectra's built-in helper classes (likeDenseGenMatProdorSparseSymMatProd) or define your own custom class. - Create and run an eigen solver: Instantiate a solver class (such as
SymEigsSolverfor symmetric matrices orGenEigsSolverfor general matrices), initialize it, and call its computation methods to retrieve eigenvalues and eigenvectors.
- Define a matrix operation class: Implement a class that performs the required operation (e.g.,
Use Shift-and-invert mode
masterTo find eigenvalues closest to a specific number $\sigma$ (for example, the smallest eigenvalues of a positive definite matrix by setting $\sigma=0$), use the shift-and-invert mode.
In this mode, selection rules are applied to $1/(\lambda-\sigma)$ instead of $\lambda$. To use this, you must use a solver designed for shift-and-invert (e.g.,
SymEigsShiftSolver) and define a shift-solve matrix operation (e.g., $y=(A-\sigma I)^{-1}x$).How to use Spectra eigen solvers
masterSpectra calculates a specified number ($k$) of eigenvalues of a large square matrix ($A$). Instead of requiring the full matrix, the algorithm only requires certain operations (like matrix-vector multiplication $Ax$).
To use the library, follow these two steps:
- Define a matrix operation class: This class must implement the required operation (e.g., $y=Ax$ or the shift-solve $y=(A-\sigma I)^{-1}x$). You can use Spectra's built-in helper classes (like
DenseSymMatProdorSparseGenMatProd) or implement your own custom class. - Create and run a solver object: Instantiate one of the available solver classes (e.g.,
SymEigsSolverfor symmetric matrices) by passing the operation object, the number of eigenvalues requested, and the number of Lanczos vectors. Call.init()and.compute()to perform the calculation, then use.eigenvalues()or.eigenvectors()to retrieve results.
- Define a matrix operation class: This class must implement the required operation (e.g., $y=Ax$ or the shift-solve $y=(A-\sigma I)^{-1}x$). You can use Spectra's built-in helper classes (like
Migrate from Spectra 0.9.0 to 1.0.0
masterSpectra 1.0.0 introduced several breaking API changes. To migrate from version 0.9.0, you must update your toolchain requirements, modify user-defined matrix operation classes, refactor Eigen solver instantiation, and update enumeration usage to useenum classsyntax.Implement a custom matrix operation class
masterIf you have a custom matrix or a specific way to compute $y=Ax$, you can implement your own operation class. Your class must provide:
- A
using Scalar = ...;typedef. int rows() constandint cols() constmethods.- A
void perform_op(const Scalar *x_in, Scalar *y_out) constmethod that performs the multiplication.
#include <Eigen/Core> #include <Spectra/SymEigsSolver.h> #include <iostream> using namespace Spectra; // M = diag(1, 2, ..., 10) class MyDiagonalTen { public: using Scalar = double; // A typedef named "Scalar" is required int rows() const { return 10; } int cols() const { return 10; } // y_out = M * x_in void perform_op(const double *x_in, double *y_out) const { for(int i = 0; i < rows(); i++) { y_out[i] = x_in[i] * (i + 1); } } }; int main() { MyDiagonalTen op; SymEigsSolver<MyDiagonalTen> eigs(op, 3, 6); eigs.init(); eigs.compute(SortRule::LargestAlge); if(eigs.info() == CompInfo::Successful) { Eigen::VectorXd evalues = eigs.eigenvalues(); std::cout << "Eigenvalues found:\n" << evalues << std::endl; } return 0; }- A
Install Spectra via CMake
masterSpectra supports installation via CMake (requires version 3.10 or higher). Installing via CMake creates the
Spectra::SpectraCMake target, which allows you to easily link against the library in other projects usingfind_package(Spectra).Standard Installation
mkdir build && cd build cmake .. -DCMAKE_INSTALL_PREFIX='intended installation directory' -DBUILD_TESTS=TRUE make all && make test && make installConfiguring Eigen Path
If Eigen is already installed on your system, you can specify its location using
CMAKE_PREFIX_PATHorEigen3_ROOTto ensure Spectra finds it correctly:cmake .. -DCMAKE_INSTALL_PREFIX='intended installation directory' -DCMAKE_PREFIX_PATH='path where the installation of Eigen3 can be found' -DBUILD_TESTS=TRUEInstall and integrate Spectra
masterSpectra is a header-only C++ library designed for large-scale eigenvalue problems. It is built on top of the Eigen linear algebra library. Because both Spectra and Eigen are header-only, Spectra can be easily embedded into existing C++ projects by including its headers and ensuring the Eigen library is available in your include path.Control Eigen download behavior via environment variables
masterWhen building Spectra, you can use the following environment variables to control how the Eigen dependency is handled via CPM:
CPM_DOWNLOAD_ALL=ON: Forces the download of Eigen even if an installation is already present on the system.CPM_LOCAL_PACKAGES_ONLY=ON: Forces the build to use only locally installed packages (prevents downloading Eigen).CPM_SOURCE_CACHE: Sets the directory used for downloading and caching source files.
Calculate eigenvalues of a symmetric matrix
masterThis example uses
DenseSymMatProdto wrap a dense Eigen matrix andSymEigsSolverto find the largest three eigenvalues.#include <Eigen/Core> #include <Spectra/SymEigsSolver.h> // <Spectra/MatOp/DenseSymMatProd.h> is implicitly included #include <iostream> using namespace Spectra; int main() { // We are going to calculate the eigenvalues of M Eigen::MatrixXd A = Eigen::MatrixXd::Random(10, 10); Eigen::MatrixXd M = A + A.transpose(); // Construct matrix operation object using the wrapper class DenseSymMatProd DenseSymMatProd<double> op(M); // Construct eigen solver object, requesting the largest three eigenvalues SymEigsSolver<DenseSymMatProd<double>> eigs(op, 3, 6); // Initialize and compute eigs.init(); int nconv = eigs.compute(SortRule::LargestAlge); // Retrieve results Eigen::VectorXd evalues; if(eigs.info() == CompInfo::Successful) evalues = eigs.eigenvalues(); std::cout << "Eigenvalues found:\n" << evalues << std::endl; return 0; }Work with complex-valued matrices
masterSpectra supports complex-valued matrices using
HermEigsSolverfor Hermitian matrices andGenEigsSolverfor general complex matrices. Note that for Hermitian matrices, eigenvalues are real-valued while eigenvectors are complex-valued.#include <Eigen/Core> #include <Spectra/HermEigsSolver.h> #include <Spectra/GenEigsSolver.h> #include <iostream> using namespace Spectra; int main() { std::srand(0); // We are going to calculate the eigenvalues of H and G Eigen::MatrixXcd G = Eigen::MatrixXcd::Random(10, 10); // H is Hermitian Eigen::MatrixXcd H = G + G.adjoint(); // Construct matrix operation objects using the wrapper // classes DenseHermMatProd and DenseGenMatProd using OpHType = DenseHermMatProd<std::complex<double>>; using OpGType = DenseGenMatProd<std::complex<double>>; OpHType opH(H); OpGType opG(G); // Construct solver object for H, requesting the largest three eigenvalues HermEigsSolver<OpHType> eigsH(opH, 3, 6); // Initialize and compute eigsH.init(); int nconvH = eigsH.compute(SortRule::LargestAlge); // Retrieve results // Eigenvalues are real-valued, and eigenvectors are complex-valued if (eigsH.info() == CompInfo::Successful) { Eigen::VectorXd evaluesH = eigsH.eigenvalues(); std::cout << "Eigenvalues of H found:\n" << evaluesH << std::endl; Eigen::MatrixXcd evecsH = eigsH.eigenvectors(); std::cout << "Eigenvectors of H:\n" << evecsH << std::endl; } // Similar procedure for matrix G GenEigsSolver<OpGType> eigsG(opG, 3, 6); eigsG.init(); int nconvG = eigsG.compute(SortRule::LargestMagn); // Retrieve results Eigen::VectorXcd evaluesG; if (eigsG.info() == CompInfo::Successful) { evaluesG = eigsG.eigenvalues(); std::cout << "Eigenvalues of G found:\n" << evaluesG << std::endl; Eigen::MatrixXcd evecsG = eigsG.eigenvectors(); std::cout << "Eigenvectors of G:\n" << evecsG << std::endl; } return 0; }