New user self-registration is currently disabled. Please email eigen-core-team @ lists.tuxfamily.org if you need an account.
Bug 1224 - .sparseView fails on matrix products
.sparseView fails on matrix products
Status: RESOLVED FIXED
Product: Eigen
Classification: Unclassified
Component: Sparse
3.3 (current stable)
All All
: Normal Compilation Problem
Assigned To: Nobody
:
Depends on:
Blocks: 3.3
  Show dependency treegraph
 
Reported: 2016-05-10 17:02 UTC by Rasmus Munk Larsen
Modified: 2016-05-18 16:04 UTC (History)
2 users (show)



Attachments

Description Rasmus Munk Larsen 2016-05-10 17:02:26 UTC
The following expression used to compile with 3.2, but fails to compile with the dev branch (I am synced at commit 6203649a0399):

rotation_matrix_ = (encoder_matrix_ * decoder_matrix_).sparseView(kReference, kEpsilon);

encoded and decoder matrices are fixed-size dense matrices. I get the following error message:

In file included from XXX.cc:1:
In file included from YYY.h:7:
In file included from ZZZ/Eigen/SparseCore:42:
ZZZ/Eigen/src/SparseCore/SparseMatrix.h:1075:36: error: no type named 'InnerIterator' in 'Eigen::internal::evaluator<Eigen::SparseView<Eigen::Product<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, 0> > >'
      for (typename OtherCopyEval::InnerIterator it(otherCopyEval, j); it; ++it)
           ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
XXX.cc:53:20: note: in instantiation of function template specialization 'Eigen::SparseMatrix<float, 0, int>::operator=<Eigen::SparseView<Eigen::Product<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, 0> > >' requested here
  rotation_matrix_ = (encoder_matrix_ * decoder_matrix_).sparseView(kReference, kEpsilon);
                   ^
In file included from XXX.cc:1:
In file included from YYY.h:7:
In file included from ZZZ/Eigen/SparseCore:42:
ZZZ/Eigen/src/SparseCore/SparseMatrix.h:1094:36: error: no type named 'InnerIterator' in 'Eigen::internal::evaluator<Eigen::SparseView<Eigen::Product<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, 0> > >'
      for (typename OtherCopyEval::InnerIterator it(otherCopyEval, j); it; ++it)
           ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
In file included from XXX.cc:1:
In file included from YYY.h:7:
In file included from ZZZ/Eigen/SparseCore:57:
ZZZ/Eigen/src/SparseCore/SparseProduct.h:145:12: error: static_cast from 'Eigen::internal::evaluator<Eigen::SparseView<Eigen::Product<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, 0> > > *' to 'Base *' (aka 'evaluator<SparseMatrix<float, Flags & RowMajorBit ? RowMajor : ColMajor, long> > *'), which are not related by inheritance, is not allowed
    ::new (static_cast<Base*>(this)) Base(m_result);
           ^~~~~~~~~~~~~~~~~~~~~~~~
ZZZ/Eigen/src/SparseCore/SparseMatrix.h:1067:19: note: in instantiation of member function 'Eigen::internal::evaluator<Eigen::SparseView<Eigen::Product<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, 0> > >::evaluator' requested here
    OtherCopyEval otherCopyEval(otherCopy);
                  ^
XXX.cc:53:20: note: in instantiation of function template specialization 'Eigen::SparseMatrix<float, 0, int>::operator=<Eigen::SparseView<Eigen::Product<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, 0> > >' requested here
  rotation_matrix_ = (encoder_matrix_ * decoder_matrix_).sparseView(kReference, kEpsilon);
                   ^
Comment 1 Rasmus Munk Larsen 2016-05-10 17:04:50 UTC
BTW: Changing the code to 

  Eigen::Matrix<MyScalarType,
                Eigen::Dynamic, Eigen::Dynamic>
      tmp = (encoder_matrix_ * decoder_matrix_);
  rotation_matrix_ = tmp.sparseView(kReference, kEpsilon);

is a functioning workaround, but it seems like an unnecessary regression.
Comment 2 Christoph Hertzberg 2016-05-10 17:56:01 UTC
This also fails for dynamic matrix-products.

An easier workaround is to write:
  res = (A*B).eval().sparseView();

The regression is not entirely unmotivated, since it is generally not good to access products coefficient-wise. However, 
  A.lazyProduct(B)
should be accessible coefficient-wise (and thus have an inner iterator), and we should certainly let sparseView() evaluate its argument when necessary (even though this is actually not good, if the matrix is big).
Comment 3 Rasmus Munk Larsen 2016-05-10 18:16:24 UTC
I agree that this is to be discouraged in the documentation, but breaking legacy code is not good.
Comment 4 Gael Guennebaud 2016-05-18 12:27:12 UTC
It also fails with lazyProduct.

I had a hard time finding the origin of the problem. It actually comes from the following specialization:

struct evaluator<SparseView<Product<Lhs, Rhs, Options> > >

which is supposed to handle (sparse*sparse).prune()...

Of course, it should be enabled for sparse products only. I'll fix it.
Comment 5 Gael Guennebaud 2016-05-18 14:54:14 UTC
Fixed: https://bitbucket.org/eigen/eigen/commits/376c43a09a7c
Comment 6 Rasmus Munk Larsen 2016-05-18 16:04:30 UTC
Thanks!

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