To find the 10 smallest eigenvalue of a sparse matrix 'A', the minimal code below works well:
g++ -std=c++17 -o test_sparse.o -c test_sparse.cpp
g++ -std=c++17 -o myapp test_sparse.o -larmadillo -larpack
#include <armadillo>
#include <iostream>
int main(){
arma::SpMat<double> A = arma::sprandu(100,100,0.1) ;
A = A.t()*A ;
arma::dvec e = arma::eigs_sym(A,10,"sm") ;
std::cout << e ;
return 0 ;
}
But when I change A to a complex sparse matrix, like:
#include <armadillo>
#include <iostream>
#include <complex>
int main(){
arma::SpMat<arma::cx_double> A = arma::sprandu<arma::SpMat<arma::cx_double>>(100,100,0.1) ;
A = A.t()*A ;
arma::dvec e = arma::eigs_sym(A,1,"sm") ;
std::cout << e ;
return 0 ;
}
with the same compilation flags, I get the following no matching function error:
g++ -std=c++17 -o test_sparse.o -c test_sparse.cpp
test_sparse.cpp:8:43: error: no matching function for call to ‘eigs_sym(arma::SpMat<std::complex<double> >&, int, const char [3])’
8 | arma::dvec e = arma::eigs_sym(A,1,"sm") ; ^
make: *** [Makefile:47: test_sparse.o] Error 1
I know from http://arma.sourceforge.net/docs.html#config_hpp that
ARMA_USE_ARPACK Enable use of ARPACK, or a high-speed replacement for ARPACK. Armadillo requires ARPACK for the eigen decomposition of complex sparse matrices, ie. eigs_gen(), eigs_sym() and svds()
so I change the config.hpp file and here is the corresponding line in my config.hpp
file:
#if !defined(ARMA_USE_NEWARP)
#define ARMA_USE_NEWARP
#endif
#if !defined(ARMA_USE_ARPACK)
#define ARMA_USE_ARPACK
#endif
#if !defined(ARMA_USE_SUPERLU)
#define ARMA_USE_SUPERLU
#endif
more info: I can run arpack from gfortran with no problem.
Any idea how to do the trick? Thank you for your help in advance.
It is an inherent limitation of the library. According to the documentation (emphasis mine):
eigs_sym limited number of eigenvalues & eigenvectors of sparse symmetric real matrix
eigs_gen limited number of eigenvalues & eigenvectors of sparse general square matrix
You should rather use eigs_gen
which allows for complex matrices.
Or you should convert the matrix to a dense one and use eig_sym
.