11
votes

I'm working in C++ with a sparse matrix in Eigen. I would like to read the data stored in a specific row and column index just like I would with a regular eigen matrix.

std::vector<Eigen::Triplet<double>> tripletList;

// TODO: populate triplet list with non-zero entries of matrix

Eigen::SparseMatrix<double> matrix(nRows, nCols);
matrix.setFromTriplets(tripletList.begin(), tripletList.end());

// TODO:  set iRow and iCol to be valid indices.

// How to read the value at a specific row and column index?
// double value = matrix(iRow, iCol);  // Compiler error

How do I go about performing this type of indexing operation?

3
One possible solution is to construct a dense matrix from the sparse matrix (Eigen::MatrixXd dense = Eigen::MatrixXd(sparse);), but this has a large computational cost and is undesirable in most applications.MattKelly

3 Answers

19
votes

Try coeff:

double value = matrix.coeff(iRow, iCol);

If you want a non-const version use coeffRef instead. Note that when using coeffRef if the element doesn't exist, it will be inserted.

1
votes

This Code work for me

for (int i=0; i<matrix.rows(); ++i){
     for(int j=0; i<matrix.cols(); ++j)
        cout << " i,j=" << i << "," 
             << j << " value=" 
             << matrix.coeff(i,j) 
             << std::endl;
}

-1
votes

Here is how to do it in the raw:

The methods you want are innerIndexPtr, outerIndexPtr, InnerNNZs and valuePtr.

struct sparseIndex {
  std::size_t row, col;
  template<class SparseMatrix, class Scalar=typename SparseMatrix::Scalar>
  Scalar get_from( SparseMatrix const& m, Scalar def={} ) const {
    if ((std::size_t)m.cols() >= col) return def;
    auto* inner_index_start = m.innerIndexPtr()+m.outerIndexPtr()[col];
    auto* inner_index_end = inner_index_start;
    if (auto* nzp = m.innerNonZeroPtr()) { // returns null if compressed
      inner_index_end += nzp[col];
    } else {
      inner_index_end = m.innerIndexPtr()+m.outerIndexPtr()[col+1];
    }
    auto search_result = std::equal_range(
      inner_index_start,
      inner_index_end,
      (typename SparseMatrix::StorageIndex)row
    );
    if (search_result.first == search_result.second) return def;
    if ((std::size_t)*search_result.first != row) return def;
    return m.valuePtr()[search_result.first-m.innerIndexPtr()];
  }
};      

Use:

auto r = sparseIndex{2,2}.get_from( sparseMatrix );

Code not tested. Based off these docs and these docs which disagree in some details.

I suspect I just reimplmeented .coeff, so take this with a grain of salt. :)