Преобразовать собственную матрицу в форму триплета C++

Я думаю, что Эйген использует сжатые методы для хранения разреженных матриц. Есть ли способ, которым я могу извлечь векторы в формате Triplet из собственной разреженной матрицы из std::vectors?

Благодарю.

Дополнительная информация (пример триплетного формата) Триплетный формат матрицы:

A=
3 0 4 0
0 0 1 0
0 2 0 5
4 0 0 0

i = 1 1 2 3 3 4  // row
j = 1 3 3 2 4 1 // column
S = 3 4 1 2 5 4  // values

2 ответа

Решение

Просто, как показано в руководстве:

#include <Eigen/Sparse>
#include <iostream>

using namespace Eigen;
using std::cout;
using std::endl;

typedef Triplet<int> Trip;

int main(int argc, char *argv[]){

    std::vector<Trip> trp, tmp;

    // I subtracted 1 from the indices so that the output matches your question
    trp.push_back(Trip(1-1,1-1,3));
    trp.push_back(Trip(1-1,3-1,4));
    trp.push_back(Trip(2-1,3-1,1));
    trp.push_back(Trip(3-1,2-1,2));
    trp.push_back(Trip(3-1,4-1,5));
    trp.push_back(Trip(4-1,1-1,4));

    int rows, cols;
    rows = cols = 4;
    SparseMatrix<int> A(rows,cols);

    A.setFromTriplets(trp.begin(), trp.end());
    cout << "Matrix from triplets:" << endl;
    cout << A << endl;            

    cout << endl << "Triplets:" << endl;
    cout << "Row\tCol\tVal" <<endl;
    for (int k=0; k < A.outerSize(); ++k)
    {
        for (SparseMatrix<int>::InnerIterator it(A,k); it; ++it)
        {
            cout << 1+it.row() << "\t"; // row index
            cout << 1+it.col() << "\t"; // col index (here it is equal to k)
            cout << it.value() << endl;
        }
    }

    return 0;
}

Ответ на вопрос, а именно:

// Is there some method such as:

std::vector<Eigen::Triplet<double>> T = SparseMat.to_triplets();

// in Eigen?

Нет, похоже, такой функции не существует.

Вместо,

std::vector<Eigen::Triplet<double>> to_triplets(Eigen::SparseMatrix<double> & M){
    std::vector<Eigen::Triplet<double>> v;
    for(int i = 0; i < M.outerSize(); i++)
        for(typename Eigen::SparseMatrix<double>::InnerIterator it(M,i); it; ++it)
            v.emplace_back(it.row(),it.col(),it.value());
    return v;
}

auto t = to_triplets(SparseMat);

И если вы хотите сделать это быстрее, откройте его в IDE, посмотрите на указатели на массивы данных и напишите сложную функцию, которая не будет влиять на время выполнения, поскольку матрица разрежена, а копирование линейно с точки зрения ненулевые элементы.

Другие вопросы по тегам