Разреженные собственные значения с использованием eigen3/sparse

Существует ли четкий и эффективный способ нахождения собственных значений и собственных векторов действительной, симметричной, очень большой, скажем, 10000x10000, разреженной матрицы в Eigen3? Существует решатель собственных значений для плотных матриц, но он не использует свойство матрицы, например. это симметрия. Кроме того, я не хочу хранить матрицу в плотном виде.

Или (альтернатива) есть лучшая (+ лучше документированная) библиотека для этого?


person Philipp    schedule 12.05.2015    source источник


Ответы (2)


Armadillo сделает это, используя eigs_sym

Обратите внимание, что вычисление всех собственных значений является очень дорогостоящей операцией, что бы вы ни делали, обычно нужно найти только k самых больших или наименьших собственных значений (что и будет сделано).

person Simon Gibbons    schedule 12.05.2015
comment
Это именно то, что я искал, и, кроме того, это быстрая библиотека. Поскольку это ответ на мой вопрос, я отмечу его как принятый, но есть ли у вас опыт использования Eigen для такого рода задач? - person Philipp; 12.05.2015
comment
Боюсь, личного опыта использования Eigen для таких вещей нет. Я склонен использовать броненосца исключительно для линейной алгебры в С++. Из беглого взгляда на документы мне не показалось, что есть какой-то другой способ сделать то, что вы хотите, без ручного кодирования чего-либо с использованием QR-разложения с разреженными матрицами. - person Simon Gibbons; 12.05.2015

Для Eigen есть библиотека под названием Spectra. Как описано на его веб-странице, Spectra представляет собой переработанную библиотеку ARPACK с использованием языка C++.

В отличие от Armadillo, предложенного в другом ответе, Spectra поддерживает long double и любой другой реальный тип с плавающей запятой (например, boost::multiprecision::float128).

Вот пример использования (такой же, как и в документации, но адаптированный для экспериментов с разными типами с плавающей запятой):

#include <Eigen/Core>
#include <SymEigsSolver.h>  // Also includes <MatOp/DenseSymMatProd.h>
#include <iostream>
#include <limits>

int main()
{
    using Real=long double;
    using Matrix=Eigen::Matrix<Real, Eigen::Dynamic, Eigen::Dynamic>;

    // We are going to calculate the eigenvalues of M
    const auto A = Matrix::Random(10, 10);
    const Matrix M = A + A.transpose();

    // Construct matrix operation object using the wrapper class DenseGenMatProd
    Spectra::DenseSymMatProd<Real> op(M);

    // Construct eigen solver object, requesting the largest three eigenvalues
    Spectra::SymEigsSolver<Real,
                           Spectra::LARGEST_ALGE,
                           Spectra::DenseSymMatProd<Real>> eigs(&op, 3, 6);

    // Initialize and compute
    eigs.init();
    const auto nconv = eigs.compute();
    std::cout << nconv << " eigenvalues converged.\n";

    // Retrieve results
    if(eigs.info() == Spectra::SUCCESSFUL)
    {
        const auto evalues = eigs.eigenvalues();
        std::cout.precision(std::numeric_limits<Real>::digits10);
        std::cout << "Eigenvalues found:\n" << evalues << '\n';
    }
}
person Ruslan    schedule 10.02.2018