Armadillo eigs_sym(A,k) per matrice sparsa complessa A

Aug 20 2020

Per trovare i 10 autovalori più piccoli di una matrice sparsa 'A', il codice minimo qui sotto funziona bene:

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 ;
}

Ma quando cambio A in una matrice sparsa complessa, come:

#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 ;
}

con gli stessi flag di compilazione, ottengo il seguente errore di funzione senza corrispondenza:

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

lo so dahttp://arma.sourceforge.net/docs.html#config_hppQuello

ARMA_USE_ARPACK Abilita l'uso di ARPACK, o un sostituto ad alta velocità per ARPACK. Armadillo richiede ARPACK per la decomposizione automatica di matrici sparse complesse, ad es. eigs_gen(), eigs_sym() e svds()

quindi cambio il file config.hpp ed ecco la riga corrispondente nel mio config.hppfile:

#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

maggiori informazioni: posso eseguire arpack da gfortran senza problemi.

Qualche idea su come fare il trucco? Grazie in anticipo per il tuo aiuto.

Risposte

francesco Aug 20 2020 at 17:43

È un limite intrinseco della biblioteca. Secondo la documentazione (sottolineatura mia):

eigs_sym numero limitato di autovalori e autovettori di matrice reale simmetrica sparsa

eigs_gen numero limitato di autovalori e autovettori di matrice quadrata generale sparsa

Dovresti piuttosto usare eigs_genwhich consente matrici complesse. Oppure dovresti convertire la matrice in una densa e usare eig_sym.