Giter Club home page Giter Club logo

spectra's Introduction

Basic CI codecov

NOTE: Spectra 1.0.0 is released, with a lot of API-breaking changes. Please see the migration guide for a smooth transition to the new version.

NOTE: If you are interested in the future development of Spectra, please join this thread to share your comments and suggestions.

Spectra stands for Sparse Eigenvalue Computation Toolkit as a Redesigned ARPACK. It is a C++ library for large scale eigenvalue problems, built on top of Eigen, an open source linear algebra library.

Spectra is implemented as a header-only C++ library, whose only dependency, Eigen, is also header-only. Hence Spectra can be easily embedded in C++ projects that require calculating eigenvalues of large matrices.

Relation to ARPACK

ARPACK is a software package written in FORTRAN for solving large scale eigenvalue problems. The development of Spectra is much inspired by ARPACK, and as the full name indicates, Spectra is a redesign of the ARPACK library using the C++ language.

In fact, Spectra is based on the algorithm described in the ARPACK Users' Guide, the implicitly restarted Arnoldi/Lanczos method. However, it does not use the ARPACK code, and it is NOT a clone of ARPACK for C++. In short, Spectra implements the major algorithms in ARPACK, but Spectra provides a completely different interface, and it does not depend on ARPACK.

Common Usage

Spectra is designed to calculate a specified number (k) of eigenvalues of a large square matrix (A). Usually k is much smaller than the size of the matrix (n), so that only a few eigenvalues and eigenvectors are computed, which in general is more efficient than calculating the whole spectral decomposition. Users can choose eigenvalue selection rules to pick the eigenvalues of interest, such as the largest k eigenvalues, or eigenvalues with largest real parts, etc.

To use the eigen solvers in this library, the user does not need to directly provide the whole matrix, but instead, the algorithm only requires certain operations defined on A. In the basic setting, it is simply the matrix-vector multiplication. Therefore, if the matrix-vector product A * x can be computed efficiently, which is the case when A is sparse, Spectra will be very powerful for large scale eigenvalue problems.

There are two major steps to use the Spectra library:

  1. Define a class that implements a certain matrix operation, for example the matrix-vector multiplication y = A * x or the shift-solve operation y = inv(A - σ * I) * x. Spectra has defined a number of helper classes to quickly create such operations from a matrix object. See the documentation of DenseGenMatProd, DenseSymShiftSolve, etc.
  2. Create an object of one of the eigen solver classes, for example SymEigsSolver for symmetric matrices, and GenEigsSolver for general matrices. Member functions of this object can then be called to conduct the computation and retrieve the eigenvalues and/or eigenvectors.

Below is a list of the available eigen solvers in Spectra:

Examples

Below is an example that demonstrates the use of the eigen solver for symmetric matrices.

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

Sparse matrix is supported via classes such as SparseGenMatProd and SparseSymMatProd.

#include <Eigen/Core>
#include <Eigen/SparseCore>
#include <Spectra/GenEigsSolver.h>
#include <Spectra/MatOp/SparseGenMatProd.h>
#include <iostream>

using namespace Spectra;

int main()
{
    // A band matrix with 1 on the main diagonal, 2 on the below-main subdiagonal,
    // and 3 on the above-main subdiagonal
    const int n = 10;
    Eigen::SparseMatrix<double> M(n, n);
    M.reserve(Eigen::VectorXi::Constant(n, 3));
    for(int i = 0; i < n; i++)
    {
        M.insert(i, i) = 1.0;
        if(i > 0)
            M.insert(i - 1, i) = 3.0;
        if(i < n - 1)
            M.insert(i + 1, i) = 2.0;
    }

    // Construct matrix operation object using the wrapper class SparseGenMatProd
    SparseGenMatProd<double> op(M);

    // Construct eigen solver object, requesting the largest three eigenvalues
    GenEigsSolver<SparseGenMatProd<double>> eigs(op, 3, 6);

    // Initialize and compute
    eigs.init();
    int nconv = eigs.compute(SortRule::LargestMagn);

    // Retrieve results
    Eigen::VectorXcd evalues;
    if(eigs.info() == CompInfo::Successful)
        evalues = eigs.eigenvalues();

    std::cout << "Eigenvalues found:\n" << evalues << std::endl;

    return 0;
}

And here is an example for user-supplied matrix operation class.

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

Shift-and-invert Mode

When it is needed to find eigenvalues that are closest to a number σ, for example to find the smallest eigenvalues of a positive definite matrix (in which case σ = 0), it is advised to use the shift-and-invert mode of eigen solvers.

In the shift-and-invert mode, selection rules are applied to 1/(λ - σ) rather than λ, where λ are eigenvalues of A. To use this mode, users need to define the shift-solve matrix operation. See the documentation of SymEigsShiftSolver for details.

Documentation

The API reference page contains the documentation of Spectra generated by Doxygen, including all the background knowledge, example code and class APIs.

More information can be found in the project page https://spectralib.org.

Installation

An optional CMake installation is supported, if you have CMake with at least v3.10 installed. You can install the headers using the following commands:

mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX='intended installation directory' -DCMAKE_PREFIX_PATH='path where the installation of Eigen3 can be found' -DBUILD_TESTS=TRUE
make all && make tests && make install

By installing Spectra in this way, you also create a CMake target Spectra::Spectra that can be used in subsequent build procedures for other programs.

License

Spectra is an open source project licensed under MPL2, the same license used by Eigen.

spectra's People

Contributors

alexpghayes avatar annaaraslanova avatar felipez avatar guacke avatar jdbancal avatar jenswehner avatar jkflying avatar jschueller avatar kriolog avatar nicorenaud avatar pmoulon avatar ryanlevy avatar shivupa avatar v1kko avatar yixuan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spectra's Issues

How to define set_shift() in user supplied op class?

@yixuan. Hi, first thanks for your work on the spectra library, this makes me move from out-of-date ARPACK++ to your package.
I have a question for user-supplied matrix-vector multiplication case. I wonder how I should define the set_shift(sigma) function in Mymatrix class. What kind of transformation/information should I provide to implement the user-supplied shift-and-invert mode? I'm considering a standard problem with B = Identity Matrix.
Thank you in advance.

Decomposition precision [not urgent]

Hi @yixuan,

I have two questions regarding the precision of the eigenvalue/eigenvector computation in Spectra : I see that the code has a variable called m_prec (e.g. on line of GenEgsSolver.h), so I'm wondering

  • What is the difference between this variable and the tolerance tol (second argument of the function compute)? What should we expect when tol is larger than m_prec? What should we expect when tol is smaller than m_prec?

  • Second, why is the variable m_prec set to eps^(2/3) where eps is the precision of the Scalar type? In presence of doubles, this looks like it only guarantees 10 digits of precision, whereas doubles can in principle have ~15 digits of precision. Is the algorithm only stable for up to 10 digits of precision? Or is there another specific reason for that?

Link error with PGI compiler pgc++(version17.4) in Linux

Hi yixuan,
I met a compiling problem in Linux when using PGI compiler, which was fine in Windows and also fine with g++.

Eigen::internal::palign_impl<1, __m128d>::run(__m128d&, __m128d const&)':
/Eigen3.3.4/Eigen/src/Core/arch/SSE/PacketMath.h:706: undefined reference to _INTERNAL_71
::_mm_castpd_si128(__m128d)'
/Eigen3.3.4/Eigen/src/Core/arch/SSE/PacketMath.h:449: undefined reference to

I located the problem line:
SymGEigsSolver<double, SMALLEST_MAGN, SparseSymMatProd, SparseCholesky, GEIGS_CHOLESKY>
eigs( &op, &Bop, nev, ncv );
When I comment out this line, everything is ok.
I suspect there is something wrong with this line related to eigen 3.3.4.
Which version of Eigen should I use?
I also compiled with your test cases, and all cases met this compiling problem.
Do you have any idea to solve this?
thanks.

the sign of the eigenvectors returned by SymGEigsSolver is not correct

Hi Yixuan,
Recently I am using spectra to solve a general sparse Ax=lamdaBx problem. I compared the results with Matlab. I found the eigenvectors had the same value but the sign is messed up. Totally half value is different. I suspect there is something wrong with the code.

The code I used is from your example code.
typedef SparseSymMatProd OpType;
typedef SparseRegularInverse BOpType;
SymGEigsSolver<double, Spectra::SMALLEST_MAGN, OpType, BOpType, GEIGS_REGULAR_INVERSE> eigs( &op, &Bop, nev, ncv );
eigs.init( );
int nconv = eigs.compute( n*3); // maxit = 100 to reduce running time for failed cases
int niter = eigs.num_iterations( );
int nops = eigs.num_operations( );
Vector evals = eigs.eigenvalues( );
Matrix evecs = eigs.eigenvectors( );
could you help have a check?
Thanks.
data.zip

Compilation error if I #include <Windows.h> in stdafx.h

Here's my code in stdafx.h:

#pragma once

#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>  //if this line is excluded, then the compilation works!!!

My code in stdafx.cpp

#include "stdafx.h"

And my Spectra test code

#pragma once

#include "stdafx.h"
#include <Util\TypeTraits.h>
int main()
{
 return 0;
}

This code will fail with a list of compilation errors such as:

Severity	Code	Description	Project	File	Line	Suppression State
Error	C2059	syntax error : '<L_TYPE_raw>'	SpectraEigen	spectra\include\Util\TypeTraits.h	34	
Error	C2334	unexpected token(s) preceding ':'; skipping apparent function body	SpectraEigen	spectra\include\Util\TypeTraits.h	34	
Error	C2143	syntax error : missing ')' before '}'	SpectraEigen	spectra\include\Util\TypeTraits.h	37	
Error	C2143	syntax error : missing '}' before ')'	SpectraEigen	spectra\include\Util\TypeTraits.h	37	
Error	C2059	syntax error : ')'	SpectraEigen	spectra\include\Util\TypeTraits.h	37	
Error	C2143	syntax error : missing ';' before '}'	SpectraEigen	include\Util\TypeTraits.h	37	
Error	C2238	unexpected token(s) preceding ';'	SpectraEigen	spectra\include\Util\TypeTraits.h	37	
Error	C2143	syntax error : missing ';' before '}'	SpectraEigen	spectra\include\Util\TypeTraits.h	38	
Error	C2059	syntax error : ')'	SpectraEigen	spectra\include\Util\TypeTraits.h	44	
Error	C2334	unexpected token(s) preceding ':'; skipping apparent function body	spectra\include\Util\TypeTraits.h	44	
Error	C2143	syntax error : missing ')' before '}'	SpectraEigen	spectra\include\Util\TypeTraits.h	47	
Error	C2143	syntax error : missing '}' before ')'	SpectraEigen	spectra\include\Util\TypeTraits.h	47	
Error	C2059	syntax error : ')'	SpectraEigen	spectra\include\Util\TypeTraits.h	47	
Error	C2143	syntax error : missing ';' before '}'	SpectraEigen	spectra\include\Util\TypeTraits.h	47	
Error	C2238	unexpected token(s) preceding ';'	SpectraEigen	spectra\include\Util\TypeTraits.h	47	
Error	C2143	syntax error : missing ';' before '}'	SpectraEigen	spectra\include\Util\TypeTraits.h	48	

I really can't understand why it is so. And if I remove the #include<Windows.h> from the stdafx.h, then I can compile!

Is it possible to make Spectra to work together with Windows.h header file?

Testcase failures

On FreeBSD with clang-5, there are failures (version 0.6.2):

./QR.out
===============================================================================
All tests passed (48 assertions in 3 test cases)

./Eigen.out
elapsed time for UpperHessenbergEigen: 1.71094 secs
elapsed time for Eigen::EigenSolver: 1.70312 secs
elapsed time for TridiagEigen: 0.179688 secs
elapsed time for Eigen::SelfAdjointEigenSolver: 0.226562 secs
===============================================================================
All tests passed (2 assertions in 2 test cases)

./SymEigs.out
===============================================================================
All tests passed (60 assertions in 6 test cases)

./SymEigsShift.out

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SymEigsShift.out is a Catch v2.2.2 host application.
Run with -? for options

-------------------------------------------------------------------------------
Eigensolver of symmetric real matrix [10x10]
  Smallest Magnitude
-------------------------------------------------------------------------------
SymEigsShift.cpp:109
...............................................................................

SymEigsShift.cpp:75: 
warning:
  FAILED on this test

nconv = 2
niter = 151
nops  = 409
-------------------------------------------------------------------------------
Eigensolver of symmetric real matrix [10x10]
  Smallest Value
-------------------------------------------------------------------------------
SymEigsShift.cpp:113
...............................................................................

SymEigsShift.cpp:85: FAILED:
  REQUIRE( eigs.info() == SUCCESSFUL )
with expansion:
  2 == 0
with messages:
  nconv = 2
  niter = 151
  nops  = 322

-------------------------------------------------------------------------------
Eigensolver of symmetric real matrix [100x100]
  Smallest Magnitude
-------------------------------------------------------------------------------
SymEigsShift.cpp:109
...............................................................................

SymEigsShift.cpp:75: 
warning:
  FAILED on this test

nconv = 0
niter = 151
nops  = 1520
===============================================================================
test cases:  6 |  5 passed | 1 failed
assertions: 51 | 50 passed | 1 failed

gmake[1]: [Makefile:18: test] Error 1 (ignored)
./GenEigs.out

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GenEigs.out is a Catch v2.2.2 host application.
Run with -? for options

-------------------------------------------------------------------------------
Eigensolver of general real matrix [10x10]
  Smallest Magnitude
-------------------------------------------------------------------------------
GenEigs.cpp:107
...............................................................................

GenEigs.cpp:69: 
warning:
  FAILED on this test

nconv = 2
niter = 501
nops  = 881
-------------------------------------------------------------------------------
Eigensolver of general real matrix [100x100]
  Smallest Magnitude
-------------------------------------------------------------------------------
GenEigs.cpp:107
...............................................................................

GenEigs.cpp:69: 
warning:
  FAILED on this test

nconv = 1
niter = 501
nops  = 4648
-------------------------------------------------------------------------------
Eigensolver of general real matrix [100x100]
  Smallest Imaginary Part
-------------------------------------------------------------------------------
GenEigs.cpp:115
...............................................................................

GenEigs.cpp:69: 
warning:
  FAILED on this test

nconv = 7
niter = 501
nops  = 1776
-------------------------------------------------------------------------------
Eigensolver of general real matrix [1000x1000]
  Smallest Magnitude
-------------------------------------------------------------------------------
GenEigs.cpp:107
...............................................................................

GenEigs.cpp:69: 
warning:
  FAILED on this test

nconv = 8
niter = 501
nops  = 13086
-------------------------------------------------------------------------------
Eigensolver of general real matrix [1000x1000]
  Smallest Imaginary Part
-------------------------------------------------------------------------------
GenEigs.cpp:115
...............................................................................

GenEigs.cpp:69: 
warning:
  FAILED on this test

nconv = 19
niter = 501
nops  = 5654
-------------------------------------------------------------------------------
Eigensolver of sparse real matrix [10x10]
  Smallest Magnitude
-------------------------------------------------------------------------------
GenEigs.cpp:107
...............................................................................

GenEigs.cpp:69: 
warning:
  FAILED on this test

nconv = 0
niter = 501
nops  = 1392
-------------------------------------------------------------------------------
Eigensolver of sparse real matrix [100x100]
  Smallest Magnitude
-------------------------------------------------------------------------------
GenEigs.cpp:107
...............................................................................

GenEigs.cpp:69: 
warning:
  FAILED on this test

nconv = 2
niter = 501
nops  = 4404
-------------------------------------------------------------------------------
Eigensolver of sparse real matrix [1000x1000]
  Smallest Magnitude
-------------------------------------------------------------------------------
GenEigs.cpp:107
...............................................................................

GenEigs.cpp:69: 
warning:
  FAILED on this test

nconv = 0
niter = 501
nops  = 14534
-------------------------------------------------------------------------------
Eigensolver of sparse real matrix [1000x1000]
  Smallest Imaginary Part
-------------------------------------------------------------------------------
GenEigs.cpp:115
...............................................................................

GenEigs.cpp:69: 
warning:
  FAILED on this test

nconv = 19
niter = 501
nops  = 5762
===============================================================================
All tests passed (51 assertions in 6 test cases)

./GenEigsRealShift.out

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GenEigsRealShift.out is a Catch v2.2.2 host application.
Run with -? for options

-------------------------------------------------------------------------------
Eigensolver of general real matrix [100x100]
  Largest Real Part
-------------------------------------------------------------------------------
GenEigsRealShift.cpp:98
...............................................................................

GenEigsRealShift.cpp:78: FAILED:
  REQUIRE( eigs.info() == SUCCESSFUL )
with expansion:
  2 == 0
with messages:
  nconv = 9
  niter = 301
  nops  = 1679

-------------------------------------------------------------------------------
Eigensolver of general real matrix [100x100]
  Smallest Magnitude
-------------------------------------------------------------------------------
GenEigsRealShift.cpp:106
...............................................................................

GenEigsRealShift.cpp:68: 
warning:
  FAILED on this test

nconv = 8
niter = 301
nops  = 1683
-------------------------------------------------------------------------------
Eigensolver of general real matrix [100x100]
  Smallest Imaginary Part
-------------------------------------------------------------------------------
GenEigsRealShift.cpp:114
...............................................................................

GenEigsRealShift.cpp:68: 
warning:
  FAILED on this test

nconv = 6
niter = 301
nops  = 1850
-------------------------------------------------------------------------------
Eigensolver of general real matrix [1000x1000]
  Smallest Imaginary Part
-------------------------------------------------------------------------------
GenEigsRealShift.cpp:114
...............................................................................

GenEigsRealShift.cpp:68: 
warning:
  FAILED on this test

nconv = 17
niter = 301
nops  = 4400
-------------------------------------------------------------------------------
Eigensolver of sparse real matrix [10x10]
  Smallest Magnitude
-------------------------------------------------------------------------------
GenEigsRealShift.cpp:106
...............................................................................

GenEigsRealShift.cpp:68: 
warning:
  FAILED on this test

nconv = 0
niter = 301
nops  = 825
-------------------------------------------------------------------------------
Eigensolver of sparse real matrix [10x10]
  Smallest Imaginary Part
-------------------------------------------------------------------------------
GenEigsRealShift.cpp:114
...............................................................................

GenEigsRealShift.cpp:68: 
warning:
  FAILED on this test

nconv = 2
niter = 301
nops  = 611
-------------------------------------------------------------------------------
Eigensolver of sparse real matrix [1000x1000]
  Smallest Imaginary Part
-------------------------------------------------------------------------------
GenEigsRealShift.cpp:114
...............................................................................

GenEigsRealShift.cpp:68: 
warning:
  FAILED on this test

nconv = 18
niter = 301
nops  = 4364
===============================================================================
test cases:  6 |  5 passed | 1 failed
assertions: 53 | 52 passed | 1 failed

gmake[1]: [Makefile:20: test] Error 1 (ignored)
./GenEigsComplexShift.out

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GenEigsComplexShift.out is a Catch v2.2.2 host application.
Run with -? for options

-------------------------------------------------------------------------------
Eigensolver of general real matrix [100x100]
  Smallest Imaginary Part
-------------------------------------------------------------------------------
GenEigsComplexShift.cpp:78
...............................................................................

GenEigsComplexShift.cpp:31: 
warning:
  FAILED on this test

nconv = 4
niter = 101
nops  = 494
-------------------------------------------------------------------------------
Eigensolver of general real matrix [1000x1000]
  Smallest Imaginary Part
-------------------------------------------------------------------------------
GenEigsComplexShift.cpp:78
...............................................................................

GenEigsComplexShift.cpp:31: 
warning:
  FAILED on this test

nconv = 16
niter = 101
nops  = 1834
===============================================================================
All tests passed (28 assertions in 3 test cases)

./SymGEigsCholesky.out

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SymGEigsCholesky.out is a Catch v2.2.2 host application.
Run with -? for options

-------------------------------------------------------------------------------
Generalized eigensolver of symmetric real matrix [100x100]
  Smallest Magnitude
-------------------------------------------------------------------------------
SymGEigsCholesky.cpp:142
...............................................................................

SymGEigsCholesky.cpp:107: 
warning:
  FAILED on this test

nconv = 0
niter = 101
nops  = 1020
-------------------------------------------------------------------------------
Generalized eigensolver of symmetric real matrix [1000x1000]
  Smallest Magnitude
-------------------------------------------------------------------------------
SymGEigsCholesky.cpp:142
...............................................................................

SymGEigsCholesky.cpp:107: 
warning:
  FAILED on this test

nconv = 0
niter = 101
nops  = 3050
-------------------------------------------------------------------------------
Generalized eigensolver of sparse symmetric real matrix [100x100]
  Smallest Magnitude
-------------------------------------------------------------------------------
SymGEigsCholesky.cpp:142
...............................................................................

SymGEigsCholesky.cpp:107: 
warning:
  FAILED on this test

nconv = 0
niter = 101
nops  = 1020
-------------------------------------------------------------------------------
Generalized eigensolver of sparse symmetric real matrix [1000x1000]
  Smallest Magnitude
-------------------------------------------------------------------------------
SymGEigsCholesky.cpp:142
...............................................................................

SymGEigsCholesky.cpp:107: 
warning:
  FAILED on this test

nconv = 0
niter = 101
nops  = 3046
===============================================================================
All tests passed (80 assertions in 6 test cases)

./SymGEigsRegInv.out

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SymGEigsRegInv.out is a Catch v2.2.2 host application.
Run with -? for options

-------------------------------------------------------------------------------
Generalized eigensolver of sparse symmetric real matrix [10x10]
  Smallest Magnitude
-------------------------------------------------------------------------------
SymGEigsRegInv.cpp:101
...............................................................................

SymGEigsRegInv.cpp:67: 
warning:
  FAILED on this test

nconv = 2
niter = 101
nops  = 227
-------------------------------------------------------------------------------
Generalized eigensolver of sparse symmetric real matrix [100x100]
  Smallest Magnitude
-------------------------------------------------------------------------------
SymGEigsRegInv.cpp:101
...............................................................................

SymGEigsRegInv.cpp:67: 
warning:
  FAILED on this test

nconv = 0
niter = 101
nops  = 1020
===============================================================================
All tests passed (16 assertions in 2 test cases)

support for complex data type?

hi Yiyuan:
I tried out Spectra and it is really awesome. It is elegant and release me from the pain to install aprack.
Just wonder if you have already done sth or have any plan considering complex data type? That would be extremely helpful!
Thanks again for your nice work!

can spectra be used in visual studio?

can the spectra library be used in microsoft visual studio?
I tried to tell vs the path of spectra but there are still some functions can't be recognized. I can't fixed it up myself, can you give some suggestions?

Randomized SVD

I presume this is a long shot/not a priority, but do you have any plans to implement a randomized SVD solver? I see that there's https://github.com/erichson/rSVD but it's just in R at the moment.

I'd be willing to give this a shot in a couple weeks after finals are out, but would probably need a number of pointers on best practices for the C++ side of things.

Sorting of eigenvalues

I think your point is valid that all major libraries do return the eigenvalues in descending order.
However, would it be possible in the API to return the eigenvalues/vectors in a user specified order (either descending - default, or ascending) ? I think that would solve the problem. Maybe this can be a simple API addition to the file?

400x400 frank matrix eigenvalues for reference!

syms n i j Frank;
n=400;

Frank=vpa(zeros(n,n));

for j=1:n
for i=1:n
Frank(i,j)=vpa(n-max(i,j)+1);
end
end

eig(Frank)

%%
%eigenvalues:

% 0.25000384573341398319801475374902
% 0.25001538340693614914697308653393
% 0.25003461444053092158453293771667
% 0.25006154120121831120825284938392
% 0.25009616700369306687032564163826
% 0.25013849611119187637251014395588
% 0.25018853373660900630388892882308
% 0.25024628604386088209135689676149
% 0.25031176014950022150410114191957
% 0.25038496412458044734591048752705
% 0.25046590699677121806050758160021
% 0.25055459875272602854326800286893
% 0.250651050340702947676282856338
% 0.25075527367343967406197741951142
% 0.25086728163128420720338040675629
% 0.25098708806558254804740557910736
% 0.25111470780232496045279644163564
% 0.25125015664605244384929109113032
% 0.2513934513840251872027246475652
% 0.2515446097906548954769630853453
% 0.2517036506322030021737272711585
% 0.25187059367174690532278987289421
% 0.25204545967441648957636720524703
% 0.2522282704129033239229167245704
% 0.2524190486732450530686920899861
% 0.25261781826088763083366908000271
% 0.2528246040070281760669660298308
% 0.25303943177524136570263119677329
% 0.25326232846839241574860827457413
% 0.25349332203583983933083868543528
% 0.25373244148093131150400790626407
% 0.25397971686879611349586991063822
% 0.2542351793344377744812635307886
% 0.25449886109113067699525625080416
% 0.25477079543912454280533822697887
% 0.2550510167746608695860240551257
% 0.25533956059930554519426967901977
% 0.25563646352960202585246201523864
% 0.25594176330704962723222776545343
% 0.2562554988084116434250673808039
% 0.25657771005635817821642044742398
% 0.25690843823044874608336812879769
% 0.25724772567845987705167781232227
% 0.25759561592806314011809879782301
% 0.25795215369885918451559841470996
% 0.25831738491477358682369822148483
% 0.25869135671682048495876060847314
% 0.25907411747624017758011973290425
% 0.25946571680801706958227238983775
% 0.25986620558478455128085959471794
% 0.26027563595112361081598910378775
% 0.26069406133826219637109165264035
% 0.26112153647918256722511692363341
% 0.26155811742414410061246455373374
% 0.26200386155662925505671190860865
% 0.26245882760972063047538754984811
% 0.26292307568291731113479016638548
% 0.26339666725939892968407582775231
% 0.26387966522374614924158311204379
% 0.26437213388012652607611806402403
% 0.2648741389709549880618912855244
% 0.26538574769603844403624149507641
% 0.26590702873221432671081274592816
% 0.26643805225349316714479763630964
% 0.26697888995171560225759074505383
% 0.26752961505773452872150757782417
% 0.2680903023631334371267047636728
% 0.26866102824249228985387076713885
% 0.2692418706762126449400320083425
% 0.26983290927391407670436047846401
% 0.27043422529841430235108059714147
% 0.2710459016903057925343072568316
% 0.27166802309314202331618836204611
% 0.27230067587924691744929678072983
% 0.27294394817616142485450742109857
% 0.27359792989374160594830982737561
% 0.27426271275192300751493915774137
% 0.27493839030916655955033989066326
% 0.27562505799160167337409957048843
% 0.27632281312288268677585902992429
% 0.27703175495477528151521698976705
% 0.27775198469848999262754734570143
% 0.27848360555678043821977387017926
% 0.27922672275682442330669956582825
% 0.27998144358390661229683628603258
% 0.28074787741592202256470639465903
% 0.28152613575872016674406609705571
% 0.28231633228231026456601475501064
% 0.28311858285794855689386265131696
% 0.28393300559612938574406300224204
% 0.28475972088550235522642808720459
% 0.28559885143273856021111986741623
% 0.28645052230336956288647432248022
% 0.28731486096362351299179245540028
% 0.28819199732328354620453378898848
% 0.28908206377959435777543300212789
% 0.28998519526224363591467958725893
% 0.29090152927944585254884070055284
% 0.29183120596515674883919068030432
% 0.29277436812744772026276530509852
% 0.29373116129807020213236377808376
% 0.29470173378324108223652797353638
% 0.29568623671568112392376282523844
% 0.29668482410793937159021254720621
% 0.2976976529070375323567029730375
% 0.29872488305046938398833978848518
% 0.29976667752359135111753569767753
% 0.30082320241844152093250117356129
% 0.30189462699402553709658583056091
% 0.3029811237381090182362490399224
% 0.30408286843055739640447261068625
% 0.30520004020826536308320983978152
% 0.30633282163171944719047996554149
% 0.30748139875323863293185328566083
% 0.30864596118693935698178969758488
% 0.30982670218047270627294887597681
% 0.31102381868858317156592711857622
% 0.31223751144853990000568713263132
% 0.31346798505749303416892078314291
% 0.31471544805180942788434171811306
% 0.31598011298844379267623805865556
% 0.31726219652840315545094430909339
% 0.31856191952236440053094018796332
% 0.31987950709850662996599637446435
% 0.32121518875262210795349355168273
% 0.32256919844057166103888789094173
% 0.32394177467315258852595361444415
% 0.32533316061344940032009777739779
% 0.32674360417674004550974797649844
% 0.32817335813303272775807118673477
% 0.32962268021231092657906354055103
% 0.33109183321256686051613939340539
% 0.33258108511070634300207146186242
% 0.33409070917641079830550695617864
% 0.33562098408904512769358067640954
% 0.33717219405770314918692279165081
% 0.33874462894448548267896539498592
% 0.34033858439110802057404243803526
% 0.34195436194894251752886399275233
% 0.34359226921259435665351651585399
% 0.34525261995712620918038199227008
% 0.34693573427904010593902075887736
% 0.34864193874113438804944955562736
% 0.35037156652135610741701804587084
% 0.35212495756577371152971644570051
% 0.35390245874579927868782494406527
% 0.35570442401979417643119330088763
% 0.35753121459919680521326608167941
% 0.35938319911931606931068271160993
% 0.36126075381493939594460300172827
% 0.3631642627009095104209071299252
% 0.36509411775782977899270819993666
% 0.36705071912306376177975242857497
% 0.36903447528720068558643954303755
% 0.37104580329616486148118825483247
% 0.37308512895915364569561550157819
% 0.37515288706259538648449870037519
% 0.37724952159032592634944582951334
% 0.37937548595018965137532455692624
% 0.38153124320727881090868378230238
% 0.38371726632403288565178633957613
% 0.38593403840742817540202796905468
% 0.38818205296349652483878562391163
% 0.39046181415942122345091817960549
% 0.39277383709346762125366534967446
% 0.39511864807301591359842995423209
% 0.39749678490097388530682738137272
% 0.39990879717085818672707596495896
% 0.40235524657084396332941324296155
% 0.40483670719709439844759037009151
% 0.40735376587669397922498528955817
% 0.40990702250052208346206311596815
% 0.41249709036641683591938738663807
% 0.41512459653299312412192684928827
% 0.41779018218449322471283739000597
% 0.42049450300706370234195547360865
% 0.42323822957686813600672263880404
% 0.42602204776046183648491493827328
% 0.4288466591278720786379978944726
% 0.43171278137884552149308692906745
% 0.43462114878274346676093869139723
% 0.4375725126325854546291182477117
% 0.440567641713762458407564795774
% 0.44360732278796266347354599763049
% 0.44669236109287555013923931069519
% 0.44982358085826379648006651079944
% 0.45300182583901743067324773054464
% 0.45622795986583075096670023311178
% 0.45950286741416985628760740108788
% 0.46282745419222725646735939718484
% 0.46620264774859002658288878120657
% 0.46962939810037940742197604641459
% 0.473108678382652710198773463445
% 0.47664148551989293946604486727314
% 0.4802288409204477895295085402994
% 0.48387179119481768745334743895445
% 0.4875714088987324462129778790536
% 0.49132879330199795667826202750192
% 0.49514507118413829496220532782992
% 0.49902139765790476679517597492872
% 0.50295895702177187443842865677314
% 0.50695896364259110304954066347486
% 0.51102266286962691901904894288155
% 0.51515133198125559764174025440677
% 0.51934628116566660552195069991936
% 0.52360885453696841781678674915114
% 0.52794043118816602543535562664186
% 0.53234242628254616712908462824782
% 0.53681629218507870211205142688774
% 0.54136351963551872890884744066613
% 0.54598563896497427724440678629929
% 0.55068422135778888781985544192771
% 0.55546088016067740074973606191802
% 0.56031727224114706445023455620981
% 0.56525509939733493737669222696601
% 0.57027610982149678827764588356782
% 0.57538209961949262950034373390358
% 0.58057491438872998657953334114024
% 0.58585645085714838291886042190889
% 0.59122865858595769235329674819151
% 0.59669354173897940252880440248472
% 0.60225316092158388428224316491966
% 0.60790963509236895271217189845801
% 0.61366514355088584302598064679949
% 0.61952192800488875203303576375457
% 0.6254822947207638953111478026002
% 0.63154861676098422188663845233016
% 0.63772333631263717736224747221771
% 0.64400896711128592406645278656983
% 0.65040809696464997445190783489253
% 0.65692339038083008717589905145535
% 0.66355759130605538783867723787317
% 0.67031352597719894480760014460445
% 0.67719410589459245918899036813363
% 0.68420233092097239413341096630671
% 0.69134129251270992840597105926129
% 0.6986141770898168137642448847363
% 0.70602426955157987834561663732818
% 0.71357495694505998152021845853763
% 0.72126973229409822949859584459897
% 0.72911219859690486159865299216254
% 0.73710607300076619646049857350307
% 0.74525519116289430383371389008829
% 0.75356351180696470657869598893518
% 0.76203512148544164487196265284549
% 0.77067423955838064935414102855351
% 0.77948522340002695933221233504167
% 0.78847257384519847761311749637593
% 0.79764094088815648840112468418828
% 0.80699512964742953328609157704106
% 0.8165401066108691591165593506921
% 0.82628100617608452202571962564
% 0.83622313750233016590936874133353
% 0.84637199169091214103640575508295
% 0.85673324931223680723816637173719
% 0.86731278829875939578951054878105
% 0.87811669222430134215779600517491
% 0.88915125899150268382493507307823
% 0.90042300995056510110070347328857
% 0.91193869947392969259168137871296
% 0.9237053250131291731155870130351
% 0.93573013766576539547667842768609
% 0.94802065328239921132622130983076
% 0.96058466414511080201881062228949
% 0.97343025125160572751405624671986
% 0.98656579724101704451677502397234
% 1.0
% 1.0137418869903472665460066617286
% 1.0278008303421850106915619623491
% 1.04218656275986026993356671727
% 1.0569091942909167343549378666057
% 1.0719792300120994024834195914822
% 1.0874075886901509451555226631819
% 1.1032056224792883206679751328904
% 1.1193851377217039321141901510835
% 1.1359584169222506792736580534794
% 1.1529382419736767644738416762155
% 1.1703379187144093564813536467161
% 1.1881713029069849904927821215252
% 1.2064528277318315563773612776599
% 1.2251975328982688747789669983343
% 1.2444210954823639314112856999934
% 1.2641398626097098910571126663388
% 1.2843708861103580036050139154131
% 1.3051319592830879732617652082851
% 1.3264416559170321353972693535282
% 1.3483193717304568798758871558293
% 1.3707853683993452888694464136415
% 1.3938608203624222082988156746778
% 1.4175678646045326083052248809003
% 1.4419296536369545050521346968257
% 1.466970411911441574161376126398
% 1.4927154959247065435207369438041
% 1.5191914582918511280713910334737
% 1.5464261160911184625374464371433
% 1.5744486238085092066023699615991
% 1.6032895512395078186014834500068
% 1.6329809667366848260682899367966
% 1.6635565262265807123496161422061
% 1.6950515684573805058824622238167
% 1.7275032169808401183258953664188
% 1.7609504894181578605663112924855
% 1.7954344146104827316305874554706
% 1.8309981583110610479940759822639
% 1.867687158138259746467764769139
% 1.9055492685775617394988688295148
% 1.9446349168968889856473696298835
% 1.9849972709241575312508934416457
% 2.0266924197298074512335871259233
% 2.0697795683613146895100733293642
% 2.1143212478926696518149838443675
% 2.1603835421809630804443845080563
% 2.2080363328662191958138793183478
% 2.2573535643113577053113805737661
% 2.3084135303588164062541822580244
% 2.3612991849814005317189339770107
% 2.4160984791301773827202236869329
% 2.4729047263349534569241368698192
% 2.5318169998967856775127556345974
% 2.5929405648313772307025695324929
% 2.6563873480820320772560511058404
% 2.7222764509267904484064207965338
% 2.7907347079630287728238893484832
% 2.8618972975718097729812299989719
% 2.9359084093524604853012143889544
% 3.0129219746855209076898360089448
% 3.0931024673413171419263086709411
% 3.1766257819159387197894051272905
% 3.2636801988626691187624064021992
% 3.3544674460140587822359136094559
% 3.4492038677802945806339378385401
% 3.548121714689723400458445454166
% 3.6514705676384752069444220129199
% 3.7595189131749086660239771723567
% 3.8725558884046697939595861946922
% 3.9908932167152836272999066039323
% 4.1148673585470220372622886084776
% 4.2448419049528646169431965211662
% 4.3812102457827175124349971549794
% 4.5243985491013004834875105678607
% 4.6748690940323553308921182401021
% 4.833124005767457936020838406278
% 4.9997094491714029637290286413772
% 5.1752203464833205206007929081719
% 5.3603056953279957168629660214516
% 5.5556745759509188995374041590265
% 5.7621029516849839480382558409218
% 5.9804413846530096565081415102281
% 6.211623810234060301420482600585
% 6.4566775396486652939168022898848
% 6.7167346911141738165172122691577
% 6.9930452875936391982175428118904
% 7.2869923047248586650987705716478
% 7.6001090079805968698031300911927
% 7.9340989858958148749652829511222
% 8.2908593693815896066212224104098
% 8.6725078296657449076513148143836
% 9.0814140743187924488313204078236
% 9.5202367186830243285389652238924
% 9.9919666073265022274266379219583
% 10.499977908011235033790391457902
% 11.048088613723986129689289969609
% 11.640632485937819262824599431087
% 12.282544980273252511106942314081
% 12.979466348776370336764265357749
% 13.737865958019555431847084404798
% 14.565192963088002947372567327879
% 15.47005992212325846894449336692
% 16.462467846321346951999626142423
% 17.554083726693164713727603128465
% 18.758585002557231827570462401389
% 20.092090081914881948528909380128
% 21.573700387640078842677105700311
% 23.226188212007418533278240472583
% 25.076876989777656784523244260259
% 27.158778057487502813890746378396
% 29.512073003325824635402474744806
% 32.186067111356565820399710004015
% 35.241793106933122421134761340777
% 38.755524915125537479138054886236
% 42.823583934030819029475939942266
% 47.569011179007192315792196295542
% 53.150981496995704691879417586151
% 59.778327647524041781144380302115
% 67.729360361257515858911800976493
% 77.38157126733501432947964646463
% 89.257279593866916442524206278624
% 104.09580980170613029405733187706
% 122.97140646808182201964309888839
% 147.49327713084840206004867704797
% 180.16028929139429651874473849106
% 225.02374198496724884681668403177
% 289.00678218381139451337812015292
% 384.7447213623916243201039893501
% 537.33766130515398411245046094888
% 802.64843415623439991663406609308
% 1326.77257619055810033000105685
% 2600.3942447800325365446370950441
% 7223.1691945888079872614968747679
% 65007.856079504984768212164294493

syntax seems a little odd

I am looking for a sparse eigen solver based on Eigen, spectra does the job. However I found the usage is a little odd to me, instead of following syntax

DenseSymMatProd<double> op(M);
// Construct eigen solver object, requesting the largest three eigenvalues
SymEigsSolver< double, LARGEST_ALGE, DenseSymMatProd<double> > eigs(&op, 3, 6);
eigs.init();
eigs.compute();
VectorXd ses.eigenvalues();
MatrixXd ses.eigenvectors();

can we simplify above to

SymEigsSolver<MatrixXd> ses(A, LARGEST_ALGE, 3); // compute largest three eigenvalues
VectorXd ses.eigenvalues();
MatrixXd ses.eigenvectors();

like how Eigen::SelfAdjointEigenSolver does?

SymEigsSolver segfaults with row major matrices

Hello,

I have found that using SymEigsSolver results in a segfault when using Eigen::RowMajor for moderately sized matrices. I have personally found that anything above 2000x2000 produces this result with Eigen 3.3.4. I have put together a minimum working example below which reliably reproduces the error. If I remove the Eigen::RowMajor specification from my matrix_t type, it runs fine. Once I add it in, it segfaults. I am using row major matrices because I use the matrix elsewhere where row major access is preferred.

I have also included a backtrace below.

#include <Eigen/Core>
#include <spectra/SymEigsSolver.h>

using namespace Spectra;

using matrix_t = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>; 

int main(int argc, char* argv[])
{
	matrix_t dd = matrix_t::Random(3000, 3000);
	matrix_t du = dd + dd.transpose();
	
	DenseSymMatProd<double> op(du);
	SymEigsSolver<double, LARGEST_ALGE, DenseSymMatProd<double>> eigs(&op, 3, 6);

	eigs.init();
	eigs.compute();
	
	return 0;
}
Program received signal SIGSEGV, Segmentation fault.
0x000000000069a287 in Eigen::internal::real_default_impl<double, false>::run (x=@0x7ffff1580020: <error reading variable>)
    at /home/hsidky/Code/include/Eigen/src/Core/MathFunctions.h:82
82          return x;
(gdb) bt
#0  0x000000000069a287 in Eigen::internal::real_default_impl<double, false>::run (
    x=@0x7ffff1580020: <error reading variable>) at /home/hsidky/Code/include/Eigen/src/Core/MathFunctions.h:82
#1  0x0000000000695d9f in Eigen::numext::real<double> (x=@0x7ffff1580020: <error reading variable>)
    at /home/hsidky/Code/include/Eigen/src/Core/MathFunctions.h:877
#2  0x00000000006ae126 in Eigen::internal::selfadjoint_matrix_vector_product<double, long, 0, 1, false, false, 0>::run (
    size=3000, lhs=0x7ffff1580020, lhsStride=3000, rhs=0x9f9b40, res=0x9ff920, alpha=1)
    at /home/hsidky/Code/include/Eigen/src/Core/products/SelfadjointMatrixVector.h:91
#3  0x00000000006a6b52 in Eigen::internal::selfadjoint_product_impl<Eigen::Map<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 0, Eigen::Stride<0, 0> > const, 17, false, Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1> const, 0, Eigen::Stride<0, 0> >, 0, true>::run<Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1>, 0, Eigen::Stride<0, 0> > > (dest=..., a_lhs=...,
    a_rhs=..., alpha=@0x7ffffffddcd8: 1)
    at /home/hsidky/Code/include/Eigen/src/Core/products/SelfadjointMatrixVector.h:225
#4  0x00000000006a2c4d in Eigen::internal::generic_product_impl<Eigen::SelfAdjointView<Eigen::Map<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 0, Eigen::Stride<0, 0> > const, 1u>, Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1> const, 0, Eigen::Stride<0, 0> >, Eigen::SelfAdjointShape, Eigen::DenseShape, 7>::scaleAndAddTo<Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1>, 0, Eigen::Stride<0, 0> > > (dst=..., lhs=..., rhs=..., alpha=@0x7ffffffddcd8: 1)
    at /home/hsidky/Code/include/Eigen/src/Core/ProductEvaluators.h:746
#5  0x000000000069e7ce in Eigen::internal::generic_product_impl_base<Eigen::SelfAdjointView<Eigen::Map<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 0, Eigen::Stride<0, 0> > const, 1u>, Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1> const, 0, Eigen::Stride<0, 0> >, Eigen::internal::generic_product_impl<Eigen::SelfAdjointView<Eigen::Map<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 0, Eigen::Stride<0, 0> > const, 1u>, Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1> const, 0, Eigen::Stride<0, 0> >, Eigen::SelfAdjointShape, Eigen::DenseShape, 7> >::scaleAndAddTo<Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1>, 0, Eigen::Stride<0, 0> > > (dst=..., lhs=..., rhs=..., alpha=@0x7ffffffddcd8: 1)
    at /home/hsidky/Code/include/Eigen/src/Core/ProductEvaluators.h:361
#6  0x000000000069a4f9 in Eigen::internal::generic_product_impl_base<Eigen::SelfAdjointView<Eigen::Map<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 0, Eigen::Stride<0, 0> > const, 1u>, Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1> const, 0, Eigen::Stride<0, 0> >, Eigen::internal::generic_product_impl<Eigen::SelfAdjointView<Eigen::Map<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 0, Eigen::Stride<0, 0> > const, 1u>, Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1> const, 0, Eigen::Stride<0, 0> >, Eigen::SelfAdjointShape, Eigen::DenseShape, 7> >::evalTo<Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1>, 0, Eigen::Stride<0, 0> > > (dst=..., lhs=..., rhs=...) at /home/hsidky/Code/include/Eigen/src/Core/ProductEvaluators.h:349
#7  0x0000000000695f48 in Eigen::internal::Assignment<Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1>, 0, Eigen::Stride<0, 0> >, Eigen::Product<Eigen::SelfAdjointView<Eigen::Map<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 0, Eigen::Stride<0, 0> > const, 1u>, Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1> const, 0, Eigen::Stride<0, 0> >, 0>, Eigen::internal::assign_op<double, double>, Eigen::internal::Dense2Dense, void>::run (dst=..., src=...)
    at /home/hsidky/Code/include/Eigen/src/Core/ProductEvaluators.h:148
#8  0x0000000000691c93 in Eigen::internal::call_assignment_no_alias<Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1>, 0, Eigen::Stride<0, 0> >, Eigen::Product<Eigen::SelfAdjointView<Eigen::Map<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 0, Eigen::Stride<0, 0> > const, 1u>, Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1> const, 0, Eigen::Stride<0, 0> >, 0>, Eigen::internal::assign_op<double, double> > (dst=..., src=..., func=...)
    at /home/hsidky/Code/include/Eigen/src/Core/AssignEvaluator.h:836
#9  0x000000000068d613 in Eigen::NoAlias<Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1>, 0, Eigen::Stride<0, 0> >, Eigen::MatrixBase>::operator=<Eigen::Product<Eigen::SelfAdjointView<Eigen::Map<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 0, Eigen::Stride<0, 0> > const, 1u>, Eigen::Map<Eigen::Matrix<double, -1, 1, 0, -1, 1> const, 0, Eigen::Stride<0, 0> >, 0> > (
    this=0x7ffffffdddd0, other=...) at /home/hsidky/Code/include/Eigen/src/Core/NoAlias.h:42
#10 0x00000000006883c4 in Spectra::DenseSymMatProd<double, 1>::perform_op (this=0x7ffffffde020, x_in=0x9f9b40,
    y_out=0x9ff920) at /home/hsidky/Code/include/spectra/MatOp/DenseSymMatProd.h:69
#11 0x00000000006843e8 in Spectra::SymEigsSolver<double, 3, Spectra::DenseSymMatProd<double, 1> >::init (
    this=0x7ffffffde080, init_resid=0x9edc60) at /home/hsidky/Code/include/spectra/SymEigsSolver.h:543
#12 0x000000000068247e in Spectra::SymEigsSolver<double, 3, Spectra::DenseSymMatProd<double, 1> >::init (
    this=0x7ffffffde080) at /home/hsidky/Code/include/spectra/SymEigsSolver.h:562
#13 0x00000000007321e9 in main (argc=1, argv=0x7ffffffde248) at /home/hsidky/Code/main.cpp:17

partial singular value decomposition

Hello, I just found your library and it looks like a very nice complement to Eigen for sparse matrix eigenvalue computation! Thanks a lot for sharing 👍

I'm wondering whether you also have some code around to compute just a few singular values. The sibling project RSpectra seems to have somethin along these lines (see file svds.cpp in https://github.com/yixuan/RSpectra/blob/master/src ). Do you think it could be possible to port this code to Spectra? Or is there a better option in your opinion?

std::complex

Hi,

Your library is really great.
I would like to know if there is any plan to support SparseMatrix composed of complex numbers?

Thank you!

How to compute eigenvectors simutaneously

Hi, Yixuan

Your code is great and very helpful.
I need to solve eigenvalue and eigenvectors simutaneously. While I believe Spectra could do this, I fail to find the explicit way in given examples.

2nd question is I test your example2 but larger scale like 1000*1000 sparse matrix.
The computation time takes much longer than Armadillo's. Is there any thing I miss?

#include <Eigen/Core>
#include <Eigen/SparseCore>
#include <GenEigsSolver.h>
#include <MatOp/SparseGenMatProd.h>
#include <iostream>

using namespace Spectra;

int main()
{
    // A band matrix with 1 on the main diagonal, 2 on the below-main subdiagonal,
    // and 3 on the above-main subdiagonal
    const int n =  1000;
    Eigen::SparseMatrix<double> M(n,n);
    M.reserve(Eigen::VectorXi::Constant(n, 3));
    for (int i = 0; i < n; i++)
    {
        M.insert(i, i) = 1.0;
        if (i > 0)
            M.insert(i - 1, i) = 3.0;
        if (i < n - 1)
        M.insert(i + 1, i) = 2.0;
    }
    //M = A + A.transpose();

    // Construct matrix operation object using the wrapper class SparseGenMatProd
    SparseGenMatProd<double> op(M);

    // Construct eigen solver object, requesting the largest three eigenvalues
    GenEigsSolver< double, LARGEST_MAGN, SparseGenMatProd<double> > eigs(&op,  800, 850);

    // Initialize and compute
    eigs.init();
    int nconv = eigs.compute();

    // Retrieve results
    Eigen::VectorXcd evalues;
    if (eigs.info() == SUCCESSFUL)
        evalues = eigs.eigenvalues();

    std::cout << "Eigenvalues found:\n" << evalues << std::endl;
    system("pause");
    return 0;
}

Would you pls help?
Thank you.

min/max macro collides

on Windows the min/max functions used in file TypeTraits.h collides with min/max macros.

I had to add these two lines
#undef min
#undef max

I am aware that this is a msvc issue rather than a real issue.

Modifying the code to take in a C++ delegate ( for progress bar) and filtering mechanism

I'm thinking about modifying the Spectra so that

  1. It takes in a C++ delegate for progress bar cancellation purpose while iterating over maxit ( at SymEigsSolver.Compute function)
  2. For breaking criteria, instead of just hardcoding the num_converged, I want to pass in a delegate or an appropriate interface, that determines when the termination should happen.

I'm not too sure whether my such pull request will be accepted. What do you think?

Diagnostics for SparseCholesky

Hi. We are using Spectra and Eigen here at LimitState and it has been invaluable to our application for carrying out elastic buckling analysis and modal analysis of truss structures. To do this, we use Spectra to solve the generalized eigenvalue problem.

The problem I'm having is that we don't know in advance if our B matrix is positive-definite (it can sometimes be semi-definite). If B is singular, the Spectra::SparseCholesky factorization will obviously fail - I can see this in the Visual Studio debugger - Spectra::SparseCholesky::m_decomp::m_info shows as 'NumericalIssue'. If this is the case, we simply want to inform the user.

I can't see a way to programmatically determine whether the factorization passed or failed as the field m_decomp is private. Our software will therefore obliviously attempt to use Spectra::SymGEigsSolver, passing in the invalid Cholesky factorization. This results in an assertion which we can't handle very gracefully.

The most obvious way to check if B is positive definite is (of course!) to attempt the Cholesky factorization. Unfortunately, I can't see how to get the return status from Spectra::SparseCholesky. I can use Eigen::LLT to do the factorization (it has a public function called info() to check for success). But I ultimately have to throw this away as I can't feed it into Spectra::SymGEigsSolver as it doesn't have the requisite upper_triangular_solve() function).

Would it be possible to add a public function to Spectra::SparseCholesky to detect whether a NumericalIssue has been encoutered?

Many thanks,

Tom

Any plans for the complex matrices?

Hi yixuan,
This header-only C++ library is really useful, and so friendly to people like me who suffered from installing libraries on different machines. Thank you so much.
I've just tried shift-invert method in spectra and it works quite well. I just wondering, do you already have or have any plan for the complex version?

performance compared with matlab's eigs

general real eigs case:

matlab eigs:

A=rand(1000);
tic;d=eigs(A,50);toc
时间已过 2.155860 秒。
tic;d=eigs(A,50);toc
时间已过 2.260002 秒。
tic;d=eigs(A,50);toc
时间已过 1.447940 秒。

benchmark.out:

2018-07-05_202504

the time unit is second?

SymEigsShiftSolver returns Eigenvalues but does not return Eigenvectors.

I am leveraging the Spectra library to solve for the eigenvalues and vectors for a sparse and symmetric 60,000 X 60,000 Laplacian matrix. I have been using the SymEigsShiftSolver since that would be apt for the symmetric sparse matrix that I have. I can obtain the eigenvalues inside a minute but I do not get the eigenvectors at all. Is there an alternative that is both performance and time efficient?

       int main()
        {
          	SparseMatrix<double> Lpl(10,10);
        Lpl.reserve(Eigen::VectorXi::Constant(10, 3));
       for(int i = 0; i < 10; i++)
       {
            Lpl.insert(i, i) = 1.0;
            if(i > 0)
                 Lpl.insert(i - 1, i) = 3.0;
            if(i < 10 - 1)
                 Lpl.insert(i + 1, i) = 2.0;
        }


        SparseSymShiftSolve<double> op(Lpl);
  	SymEigsShiftSolver< double, SMALLEST_MAGN, SparseSymShiftSolve<double> >
  		        eigs(&op, 3, 4, 0.0);
  	eigs.init();
  	int nconv = eigs.compute();
  	VectorXd evalues;
  	evalues.resize(3);
  	if(eigs.info() == SUCCESSFUL)
  		evalues = eigs.eigenvalues();
  	cout << "Eigenvalues found:\n" << evalues << endl;
  	cout <<"\nHere is the matrix whose columns are eigenvectors of the Laplacian Matrix \n"
  		 <<"corresponding to these eigenvalues: \n"
  		 <<eigs.eigenvectors()<<endl;
        return 0;
        }

rank deficient matrices

Hi @yixuan ,
Can I ask you what is the expected behavior of SymEigsShiftSolver in presence of matrices with some zero eigenvalues? It seems that SparseSymShiftSolve relies on Eigen::SparseLU , which can have a problem on line 83 of SparseGenRealShiftDolver.h : y.noalias() = m_solver.solve(x); for non-invertible matrices...

func returning condition number

Since Spectra is very efficient to get largest and smallest eigenvalues, I wonder if there is buildin func to caculate large matrix' condition number?

Thank you.

{Sym/Gen}GEigs{Real/Complex}Shift

Hello @yixuan ,

Is there any plan on releasing the following operations :

  • SymGEigsRealShift
  • SymGEigsComplexShift
  • GenGEigsRealShift
  • GenGEigsComplexShift

I'm particulary interested in the first one.

Cannot extract all eigenpairs

For certain cases (on small problems) I need all the eigenpairs, ie. N for an NxN matrix.

Currently I get exceptions thrown if I try to set nev and nec to N, although this should be possible, even if the performance might be bad.

Here is a patch that fixes it for me. I've tested locally using my own application, but you might want to add a test for this.

I've made this an issue instead of a pull request in case I missed something and there is a reason the last eigenpair shouldn't be calculated.

diff --git a/src/libcore/include/libcore/spectra/SymEigsSolver.h b/src/libcore/include/libcore/spectra/SymEigsSolver.h
index a32234b..2e036b1 100644
--- a/src/libcore/include/libcore/spectra/SymEigsSolver.h
+++ b/src/libcore/include/libcore/spectra/SymEigsSolver.h
@@ -489,11 +489,11 @@ public:
         m_eps(Eigen::NumTraits<Scalar>::epsilon()),
         m_approx_0(Eigen::numext::pow(m_eps, Scalar(2.0) / 3))
     {
-        if(nev_ < 1 || nev_ > m_n - 1)
-            throw std::invalid_argument("nev must satisfy 1 <= nev <= n - 1, n is the size of matrix");
+        if(!(1 <= nev_ && nev_ <= m_n))
+            throw std::invalid_argument("nev must satisfy 1 <= nev <= n, n is the size of matrix");
 
-        if(ncv_ <= nev_ || ncv_ > m_n)
-            throw std::invalid_argument("ncv must satisfy nev < ncv <= n, n is the size of matrix");
+        if(!(nev_ <= ncv_ && ncv_ <= m_n))
+            throw std::invalid_argument("ncv must satisfy nev <= ncv <= n, n is the size of matrix");
     }
 
     ///

fail to find eigenvalue for some cases

I have a matrix of size 30000x30000, very sparse, denote as A. We know A's rank should be 29998.
I need to compute serveral singular values (ones close to 0) of A and corresponding right singular vectors. This equivalents to compute eigenvalues of AA=A'*A and corresponding right eigenvectors. My code is as following

Eigen::SparseMatrix<double> AA = A.transpose()*A;
Spectra::SparseSymMatProd<double> op(AA);
Spectra::SymEigsSolver< double, Spectra::SMALLEST_ALGE, Spectra::SparseSymMatProd<double>> eigs(&op, kd, max(3 * kd, 20)); // kd = 2
eigs.init();
int nconv = eigs.compute();

I got no eigenvalue converged and takes more then 10 seconds.

We can use matlab to do this:

[V,D] = eigs(A'*A,2,'SM')

it takes about 0.3 second and successfully obtained 2 eigenvalues 4.2590e-18 and -5.7298e-17
Matlab makes a call to arpack internally to compute eigenvalues.

The matrix is here: https://1drv.ms/u/s!AoRwrBYa5axzleIlJ2KzlxF1Fged8w, it stores in COO format.

In another case with a matrix of 2298x2304, spectra did succeed to compute eigenvalues. So I wonder if size or matrix structures matters (two matrix have similar structure)

Calculate eigenvalues in multiple steps?

I am trying to find the largest K eigenvalues of a real symmetric matrix, where K is unknown, but is such that their sum is greater than some value. I am using SymEigsSolver.

Is there some way to calculate the largest N eigenvalues, and then if necessary calculate the next M largest, without starting 'from scratch' and calculating the first N + M?

Ideally, I would like to efficiently calculate as few as possible in order to satisfy some arbitrary condition on those currently calculated.

Compilation in VS2013

I got strange compilation errors for Spectra example code here in Visual Studio 2013, with Eigen 3.3.5:

Code: Select all
Error 1 error C2039: 'Constant': is not a member of 'Eigen::SparseMatrix<double,0,int>' eigen\src\plugins\MatrixCwiseBinaryOps.h 91 1
Error 2 error C3861: 'Constant': identifier not found eigen\src\plugins\MatrixCwiseBinaryOps.h 91 1

I cannot find a suitable solution in this forum or elsewhere. "Constant" is not defined in ArrayBase and neither in SparseMatrix.h. I already tried by copying the defintions of "Constant" I found in DenseBase, but nothing helps. It seems an Eigen compilation error, but I tried to get help with no success.

Can you help on this? thanks in advance

Eigenvalues are different for direct EIGEN implementation vs Spectra based EIGEN implementation.

Hi,
Thanks for the fastest tool for EIGEN implementation, it's so useful for very large matrices. I am working with a FE project which is related to solving eigenvalues of a system.

I am getting different eigen values with Spectra vs direct EIGEN/MATLAB implementation. For the same matrices check.txt as A and Mcheck.txt as MM, I solved using Spectra and Eigen as follows,
The both matrices are symmetric and positive definite.

//-----------------in -----Spectra ----------
MatrixXd A(n,n);
//some file reading code here and memcpy into A and M_lin matrices here.
DenseSymMatProd op(A);
SparseMatrix MM(n,n);
MM.reserve(Eigen::VectorXi::Constant(n, 3));

SparseCholesky Bop(MM);
int num_eigval_want = 1398;
int converge_speed = 1400;
SymGEigsSolver<double, WHICH_SM, DenseSymMatProd, SparseCholesky, GEIGS_CHOLESKY>geigs(&op, &Bop, num_eigval_want, converge_speed);
geigs.init();
int nconv = geigs.compute();
VectorXd evalues;
MatrixXd evecs;
if(geigs.info() == SUCCESSFUL){
evalues = geigs.eigenvalues();
evecs = geigs.eigenvectors();}
std::cout << "Generalized eigenvalues found:\n" << evalues << std::endl;
//std::cout << "Generalized eigenvectors found:\n" << evecs.topRows(num_eigval_want) << std::endl;

//-----------------in -----direct Eigen ----------
MatrixXd A(n,n);
MatrixXd MM(n,n);
//file copying code here into A and MM
GeneralizedEigenSolver ges;
ges.compute(A, MM);
cout << "The (complex) generalzied eigenvalues are (alphas./beta): " << ges.eigenvalues().transpose() << endl;

Can you please correct me, if I am doing something wrong here. The attached eig.txt (contains (freq)^2) is the values obtained by direct EIGEN/MATLAB implementation. Seig.txt (contains (freq)^2 in first column) is Spectra implementation, which is having different eigenvalues than direct EIGEN/MATLAB.

Thanks in advance.

check.txt
eig.txt
Mcheck.txt
Seig.txt

Passing argument as `Ref<const _MatrixType>` instead of `const _MatrixType&`

I'm a first-time user of Eigen and Spectra, so what I'm experiencing may not be critical, even not correct, anyway...

I need to solve a Generalized Eigenvalue Problem on CSR-format matrices.
I already have CSR arrays so I would like to wrap them in a Eigen::SparseMatrix in order to feed the Spectra::SymGEigsSolver by mean of Spectra::SparseSymMatProd and Spectra::SparseCholesky.

To wrap CSR C-style arrays I would use Map<SparseMatrix<double>>(...CSRmatrixdata...),
but then I came to an empasse. How can I call the SparseSymMatProd constructor? There are few ways...

  1. pass the Map<> itself
  2. pass a Ref<> to the Map<>
  3. pass an Eigen::SparseMatrix& referring to Map<>
  4. pass an Eigen::SparseMatrix& referring to Ref<> that refers to the Map<>

What happens?
Fact 1) inside the SparseSymMatProd constructor, a const Eigen::SparseMatrix& is initialized with the argument of the constructor.
i.e. const Eigen::SparseMatrix& m_mat = _argument_

Fact 2a) these passages do not call copy*
Map<>(CSRarrays)
Ref<> = Map<>
and obviously Eigen::SparseMatrix& = Eigen::SparseMatrix&

Fact 2b) these passages do call copy*
Eigen::SparseMatrix& = Ref<>
Eigen::SparseMatrix& = Map<>

*in order to prove that, I compared the valuePtr() address with the original CSR value address

Now:
in [1] and [2]: the reference-initialization inside the constructor forces a copy, but suddenly the destructors of SparseMatrix first and CompressedStorage after are called and they destroy the arrays of m_mat that have just been created! The matrix is invalidated an no product can be actually performed.

in [3] and [4]: everything works fine, the reference-initialization called inside the constructor is of the last case of Fact 2a, so there is no copy and avoid this strange behaviour above, but there do is a copy in the reference initialization that is made before calling the constructor.

So:
I would recommend to change the first lines of Spectra::SparseSymMatProd
from

private:
  const SparseMatrix& m_mat;
public:
    SparseSymMatProd(const SparseMatrix& mat_) :
        m_mat(mat_) { }

to

private:
  Eigen::Ref<const SparseMatrix> m_mat;
public:
    SparseSymMatProd(Eigen::Ref<const SparseMatrix> mat_) :
        m_mat(mat_) { }

This is retro-compatible: it works with Eigen::SparseMatrix
and it should works also with Refs
and it doesn't force a copy.

I'm not aware of all the implications and if this is actually correct.
If you, instead, have a better way to pass some arrays to the eigen solver without this mess and that doesn't force copies, please tell me!

SymGEigsSolver settings for large sparse problem

Hello,

I am trying to use the library to solve for a structural eigenfrequency probem. This gives me a sparse (60kx60k) generalized eigenvalue problem.

I am using the Spectra::SparseCholesky and Spectra::SparseSymMatProd
I am looking for the 5 lowest eigenvalues, however the solution with the Spectra lib fails.

I transfered the matrices A and B to python and solved the eigenvalue problem using the scipy "eigs" function, that, as far as i know uses the ARPACK library.

from scipy.sparse.linalg import eigs
evals_small, evecs_small = eigs(A, 5, B, sigma=0, which='LM')

There i was able to obtain the correct eigenvalues.

Is there a way to use the SymGEigsSolver with shift mode?

Thanks!

Using spectra library

Can anybody help me how to use spectra library? Main page says we need to define a class that implements a certain matrix operation and create an object of one of eigen solver classes. I dont understand what it means. Any kind of help is appreciated.

Speedup for spectra for matrix sizes of around 1M!

Hi Yixuan,

I would like to appreciate your help for taking care of the issue I had with the EigenSymShiftSolver. I have tried to leverage these techniques to try and calculate the eigenvalues of a sparse 40,000 x 40,000 matrix. The spectra library fails to generate the eigenvalues for some reason. The same source code manages to return the eigenvalues for a 30,000 x 30,000 matrix. Is it a limitation of the library?

       int main()
       {
           SparseMatrix<double> Lpl(40000,40000);
           Lpl.reserve(Eigen::VectorXi::Constant(40000, 3));
           for(int i = 0; i < 10; i++)
               {
                   Lpl.insert(i, i) = 1.0;
                 if(i > 0)
                      Lpl.insert(i - 1, i) = 3.0;
                 if(i < 10 - 1)
                        Lpl.insert(i + 1, i) = 2.0;
                  }

             SparseGenMatProd<double> op(Lpl);
           GenEigsSolver< double, LARGEST_MAGN, SparseGenMatProd<double> > eigs(&op, 3, 6);
             eigs.init();
            int nconv = eigs.compute();
            VectorXcd evalues;
            evalues.resize(3);
             if(eigs.info() == SUCCESSFUL)
                   evalues = eigs.eigenvalues();
             cout << "Eigenvalues found:\n" << evalues << endl;

             cout <<"\nHere is the matrix whose columns are eigenvectors of the Laplacian Matrix \n"
            <<"corresponding to these eigenvalues: \n"
               << eigs.eigenvectors() <<endl;

              return 0;
          }

Incremental / Warm-start

Is there some way in the code to Use an existing set of eigenvectors to compute the eigenvectors of a freshly arrived set? If not, where in the code can we make the change to implement this?

Shift-invert on sparse matrices

Can SymEigsShiftSolver find the eigenvalues of a SparseGenMatProd operation? When I use:

SparseGenMatProd<double> op(mat);
SymEigsShiftSolver< double, LARGEST_MAGN, 
SparseGenMatProd<double> > eigs(&op, 3, 6, 0.0);

I receive this error:

spectra/include/SymEigsSolver.h:855:21: error: no member named 'set_shift' in
      'Spectra::SparseGenMatProd<double>'
       this->m_op->set_shift(sigma);

Missing include in SparseCholesky.h

Compilation fails when I try using SparseCholesky module. My client code is the following:

using OpType = Spectra::SparseSymMatProd;
OpType op(A);
using BOpType = Spectra::SparseCholesky;
BOpType bop(B);

using SpectraEigenSolver = Spectra::SymGEigsSolver<double, Spectra::SMALLEST_MAGN, OpType, BOpType, Spectra::GEIGS_CHOLESKY>;
SpectraEigenSolver eigen_solver(&op, &bop, 3, 6);

The error is the following:
spectra/include/MatOp/SparseCholesky.h:54:18: error: ‘SUCCESSFUL’ was not declared in this scope
spectra/include/MatOp/SparseCholesky.h:55:18: error: ‘NUMERICAL_ISSUE’ was not declared in this scope

When I add ' #include "Util/CompInfo.h" ' to the SparseCholesky.h source file, the code compiles.

I use master branch and gcc compiler (gcc version 6.4.0 20170704 (Debian 6.4.0-1)).

Tolerance parameter seems to have limited effect

I'm trying to calculate first 3 eigenpairs of a test 2500x2500 matrix, and Spectra appears to give quite low precision. See this code, accompanied by the reference eigenvectors file, which you'll pass to the program. On my system I get the following output:

Eigenvalues found in 5424 iterations, 13820 operations:
0.493480219899482
0.493480218260062
0.197392088025424
Difference from reference eigenvalues:
-1.54972090715688e-10
-1.79439174630147e-09
3.65107943878229e-12
Standard deviations of H*v-lambda*v for computed eigenvectors:
5.92741914152269e-11
1.57294241003771e-10
2.39031776387999e-13
Standard deviations of H*v-lambda*v for reference eigenvectors:
3.35950672288886e-16
3.6369535193841e-16
3.63594787451443e-16

Notice that reference eigenvectors are much better fit than what Spectra can find. I tried increasing ncv_, and it somewhat improved the precision, but after some value the precision got worse again.
Notice also that tol here was set to a ridiculously small value (originally it was simply ...epsilon(), only in later attempts to get higher precision I multiplied by that 1e-300 constant), but still Spectra doesn't appear to be able to converge to a good approximation for eigenvectors, nor to report any failure.

m_ritz_val[nev_new] with nev_new=m_ncv

Hey @yixuan,

Me again ;-) I have some trouble with GenEigsSolver : the method nev_adjusted sometimes tries to access m_ritz_val[nev_new] with a value of nev_new which is larger than the size of the array, thus resulting in a fatal error.

From what I can see, the m_ritz_val vector contains m_ncv elements. At the same time, in the beginning of function nev_adjusted it looks like nev_new can take values up to m_ncv (first value m_nev, and then potentially increase up to m_ncv in the loop). When this happens, m_ritz_val[nev_new] leads to a segmentation fault...

The occurence of this behavior seems to be linked with the decrease of the value of nconv between two iterations. At least both things happen jointly. Is the algorithm safe if nconv decreases for some iterations (I guess only momentarily...)? Is it normal to allow for nev_new to take values up to m_ncv?

Cheers!

input matrix from hard disk

Hi,
Can spectra calculate smallest/largest eigenvalues and the corresponding eigenvectors directly on matrices stored on hard disk without loading them into memory?

Best

Zhixing

Generalized Eigenvalue Solvers - Possibility to indicate null rows/cols for symmetric matrices

Dear all,

I`ve been trying Eigen and Spectra to solve Generalzed Eigenvalue problems where the A and B matrices are sparse and symmetric.

After applying boundary conditions many rows/cols of matrix A become null. In that case I have to do many tricks in the Eigen::SparseMatrix to remove the null rows and columns, in a process remove_null_rows_cols where I must copy all non-null elements of matrices A and B, as shown in the code below:

        A = remove_null_rows_cols(A, non_null_indices);
        B = remove_null_rows_cols(B, non_null_indices);
        SparseSymMatProd<double> op(A);
	SparseCholesky<double> Bop(B);
	SymGEigsSolver<double, LARGEST_ALGE, SparseSymMatProd<double>, SparseCholesky<double>, GEIGS_CHOLESKY> geigs(&op, &Bop, store, 6);
	geigs.init();
	int nconv = geigs.compute();

Is there a way to pass non_null_indices directly to SymGEigsSolver in order to handle the null rows/cols?

With Regards
Saullo

computing time

What can be the factors that affect computing time? I have two 1000 x 1000 matrices to diagonalize and find 100 eigenvectors of both matrices. Then, I repeat the process for 100 times. How long should it take to do this? Its taking long time for my code to do this.

my code:

#include <Eigen/Core>
#include <Eigen/SparseCore>
#include <Spectra/SymEigsSolver.h>
#include <Spectra/MatOp/SparseSymMatProd.h>
#include
#include
#include<math.h>

using namespace Spectra;
using namespace std;
double fxn1(double x)
{
if (x <= 0.5) { return -8.0x + 4.0; }
if (x > 0.5) { return 0; }
}
double fxn2(double x)
{
if (x < 0.5) { return 0; }
if (x >= 0.5) { return 8.0
x - 4.0; }
}

int main()
{
ofstream density1;
ofstream density2;
density1.open("rho1.txt");
density2.open("rho2.txt");
int n, N1, N2, t1;
cout << "how many grid points you want?" << endl;
cin >> n;
cout << "how many particles you want for psi1?" << endl;
cin >> N1;
//N1 and N2 maxm. is n/2....
cout << "how many particles you want for psi2?" << endl;
cin >> N2;
cout << "how many iterations you want?" << endl;
cin >> t1;
density1 << "#number of grid points=" << n << endl;
density1 << "#number of particles for psi1=" << N1 << endl;
density1 << "#number of particles for psi2=" << N2 << endl;
density1 << "#number of iterations=" << t1 << endl;

double xi = 0.0; double xf = 1.0; double delx = (xf - xi) / n;
double g12 = 1000.0; double mass1 = 1.0; double mass2 = 1.0;
Eigen::VectorXd rho1(n + 1);
Eigen::VectorXd rho2(n+1);
//find initial densities with fxn defined above
for (int i = 0; i < n + 1; ++i)
{
	rho1(i) = N1 * fxn1(delx*i);
	rho2(i) = N2 * fxn2(delx*i);
}
Eigen::SparseMatrix<double> M1(n + 1, n + 1);	//defining a sparse matrix
M1.reserve(Eigen::VectorXi::Constant(n + 1, 3)); // reserving 3 nonzero elements in n+1 columns
Eigen::SparseMatrix<double>M2(n + 1, n + 1);
M2.reserve(Eigen::VectorXi::Constant(n + 1, 3));

//iteration starts from here
for (int t = 1; t < t1; ++t)
{
	for (int i = 0; i < n + 1; ++i)
	{
		M1.insert(i, i) = 2.0 / (mass1*delx*delx) + g12 * rho2(i);
		if (i > 0) { M1.insert(i - 1, i) = -1.0 / (mass1*delx*delx); }
		if (i < n) { M1.insert(i + 1, i) = -1.0 / (mass1*delx*delx); }

		M2.insert(i, i) = 2.0 / (mass2*delx*delx) + g12 * rho1(i);
		if (i > 0) { M2.insert(i - 1, i) = -1.0 / (mass2*delx*delx); }
		if (i < n) { M2.insert(i + 1, i) = -1.0 / (mass2*delx*delx); }
	}
	// Construct matrix operation object using the wrapper class SparseGenMatProd
	Spectra::SparseSymMatProd<double> op1(M1);
	Spectra::SparseSymMatProd<double> op2(M2);

	// Construct eigen solver object, requesting the smallest ... eigenvalues
	Spectra::SymEigsSolver< double, SMALLEST_ALGE, SparseSymMatProd<double> > eigs1(&op1, N1, 2 * N1 + 1);
	//N1 is nev=no. of eigenvalues ncv>=2.nev and nev<ncv<=n
	Spectra::SymEigsSolver< double, SMALLEST_ALGE, SparseSymMatProd<double> > eigs2(&op2, N2, 2 * N2 + 1);
	//eigs is the initial residual vector

	// Initialize and compute
	eigs1.init();  //initialize residual vector eigs
	int nconv1 = eigs1.compute();

	eigs2.init();
	int nconv2 = eigs2.compute();

	// Retrieve results
	Eigen::VectorXd evalues1;
	Eigen::MatrixXd evectors1;
	if (eigs1.info() == SUCCESSFUL)
		evalues1 = eigs1.eigenvalues();
	evectors1 = eigs1.eigenvectors();

	// Retrieve results
	Eigen::VectorXd evalues2;
	Eigen::MatrixXd evectors2;
	if (eigs2.info() == SUCCESSFUL)
		evalues2 = eigs2.eigenvalues();
	evectors2 = eigs2.eigenvectors();

	density1 << "rho1:" << endl;
	density2 << "rho2:" << endl;
	for (int i = 0; i < n + 1; ++i)
	{
		double sum1 = 0.0;
		double sum2 = 0.0;
		for (int j = 0; j < N1; ++j)
		{
			sum1 += pow(evectors1(i, j), 2.0);
			sum2 += pow(evectors2(i, j), 2.0);
		}
		rho1(i) = sum1 / delx;
		rho2(i) = sum2 / delx;
		density1 << rho1(i) << endl;
		density2 << rho2(i) << endl;
	}
	density1 << endl << endl;		
	density2 << endl << endl;

	
	M1.setZero();
	M2.setZero();
}
return 0;

}

SymGEigsSolver fails on a (large ?) system

Hi Yihuan !

I'm interested in solving a generalized eigenvalue problem for Finite Element Method.
If the solver works well on small systems, it fails to extract the eigenvalues on a large sparse system (~70k x 70k).

I was wondering if I'm doing something wrong somewhere.
I attach my test file (main.cpp) and matrices (CantileverClamped_[k|m]Matrix.txt):

https://www.dropbox.com/s/tnshw4yh4y98trr/Archive.zip?dl=0

Would you (or someone else who reads this post) have some time to test it and give me a feedback ?

Thanks in advance !
Cédric

Successive calculation of eigenvalues

I could not figure out how to do this efficiently: If the first eigenvalue (in general the first few) I calculated does not satisfy an additional criteria, I need to repeatedly calculate the next one until I find one that satisfies my conditions.
Example: Calculate the lowest (magnitude) eigenvalue above a certain threshold.
It would be a great waste of time to init and compute successively for 1, 2, 3, ..., n eigenvalues.

Is this what the init(const Scalar * init_resid) is meant for?
Is there any other way to use the already calculated values etc. in the next iteration?

Feature request: info() for success of decomposition

Great library! I have been long searching for something that has this capability and flexibility.

It would be really great if an info() method was implemented similar to Eigen's info() for various linear solvers. This would really help to know if the user can trust the results (i.e, the arnoldi iterations converged properly, etc.) and would be consistent with the Eigen-style of things.

Failure of test cases with spectra-0.2.0 and eigen-3.2.8

Hello,
I am using spectra-0.2.0 and eigen-3.2.8 versions. I am facing issues with test cases supplied in spectra-0.2.0/test. I would like to see that all the test cases are passing successfully. As a start my interest is in successful execution of GenEigs.cpp, as i want to use GenEigsSolver. None of the test cases are passing provided along with the test suite. Attached the output of GenEigs.out file:
GenEigs Test Failure log.txt
Looks like the Eigen values are not converging at all with this data.

Since i am using older version (non-c++11) of C++, i updated the test/Makefile CXXFLAGS to
-std=c++0x mentioning the c++ version explicitly. Apart from that i have not made any changes to GenEigs.cpp.

Any solution would be helpful.

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.