New user self-registration is disabled due to spam. Please email eigen-core-team @ if you need an account.
Before reporting a bug, please make sure that your Eigen version is up-to-date!
Bug 1574 - Adding a diagonal matrix to a sparse matrix causes assertion failed
Summary: Adding a diagonal matrix to a sparse matrix causes assertion failed
Alias: None
Product: Eigen
Classification: Unclassified
Component: Core - general (show other bugs)
Version: 3.4 (development)
Hardware: All All
: Normal Crash
Assignee: Nobody
Depends on:
Blocks: 3.4
  Show dependency treegraph
Reported: 2018-07-17 13:25 UTC by taroxd
Modified: 2019-01-29 08:13 UTC (History)
3 users (show)


Description taroxd 2018-07-17 13:25:55 UTC
I am not able to convert a diagonal matrix to sparse matrix. Nor can I add a diagonal matrix to sparse matrix.

For example, the code:
#include <Eigen/Dense>
#include <Eigen/Sparse>
int main() {
    int n = 10;
    SparseMatrix<double> A(n, n);
    A += VectorXd::Ones(n).asDiagonal();

The program stopped and outputs
Assertion failed: p!=Dynamic && "written coefficient does not exist", file path\to\eigen\src\sparsecore\sparsecompressedbase.h, line 312

This problem exists both in Version 3.3 and in git head (currently 991ece51446ebb9214393bed838879536c800fe2). The compiler used is Microsoft Visual Studio.

I am also surprised that I cannot find a method to view a diagonal matrix as a sparse matrix (method `sparseView` does not exist). In my opinion, viewing a triangular matrix as a sparse matrix should be trivial (at least simpler than viewing a dense matrix as a sparse matrix).

If that is not a bug, how could I update the diagonal of a sparse matrix, given that the coefficients at diagonal does not exist?
Comment 1 Christoph Hertzberg 2018-07-18 11:41:19 UTC
Not super-urgent, but should be fixable until 3.4.
A similar issue is Bug 610.
Comment 2 Gael Guennebaud 2018-10-08 21:07:30 UTC
This was on purpose and this limitation is documented:

Removing this limitation is not straightforward regarding the strategy to adopt regarding memory reallocation and copies.
Comment 3 Gael Guennebaud 2019-01-25 10:52:54 UTC
I implemented an evaluator for Diagonal* so that vec.asDiagonal().sparseView() can work. Sadly, this only works with column-major sparse matrices because mixing row and column major sparse expressions is not allowed, e.g.:

row_major_sparse += vec.asDiagonal().sparseView()

won't work because by default vec.asDiagonal() is seen as column-major expression. This is a pity because here we really don't care about the storage order. This could be handled through a "symmetric" bit flag stating that calling coeff(i,j) or coeff(j,i) is exactly the same.

Actually, we already have a similar problem with sparseView on dense expressions:

   row_major_sparse + col_major_dense.sparseView()

is not allowed though it could easily be accomplished as dense expressions can be traversed row-wise or column-wise. Here the fix would be more complicated as the col_major_dense.sparseView() would has to say "can be traversed in both direction", and the iterator should have to be instantiated with the chosen order.

In both cases, that's a lot of internal design changes, so not asDiagonal().sparseView() for 3.4.
Comment 4 Gael Guennebaud 2019-01-29 08:13:53 UTC
The code is quite sophisticated but it could be reused to implement smarter versions of SparseMatrix's =, +=, -= working in-place if possible.

Note You need to log in before you can comment on or make changes to this bug.