-2

I would like to do the following matrix product using Eigen:

Eigen::VectorXd vector = Eigen::VectorXd::Random(1000000); // a given long vector
Eigen::MatrixXd product = vector * vector.transpose();

I'm not sure Eigen will create a copy of vector when calling vector.transpose() or just a view. I experimented by creating a vector and its transpose then modify the value of original vector:

Eigen::VectorXd vector(3);
vector << 1, 2, 3;
Eigen::VectorXd vectorTranspose = vector.transpose();
vector(0) = 10;
std::cout << vector << "\n"; // shows col vector [10, 2, 3]
std::cout << vectorTranspose << "\n"; // still shows col vector [1, 2, 3]
std::cout << vector * vectorTranspose << "\n"; // this gives the error of "invalid matrix product"
std::cout << vector * vector.transpose() << "\n"; // this gives the correct behavior

so my questions are:

  1. For a column vector with shape n by 1, why does transpose still give a column vector instead of row vector?
  2. Is calling vector * vector.transpose() causing a waste due to the creation of vector.transpose() or does Eigen do something clever about it?
DiveIntoML
  • 2,347
  • 2
  • 20
  • 36
  • Looks like they provide a `transposeInPlace` option but `vector.transpose` will have to create a copy – Mitch Jan 21 '20 at 00:14
  • If you want to save some memory though since you're dealing with a column vector I think a self dot product will work for you. – Mitch Jan 21 '20 at 00:17
  • @MitchelPaulin what do you mean by "self dot product"? The result should be a matrix instead of a scalar. – DiveIntoML Jan 21 '20 at 02:46
  • 1
    Does this answer your question: https://stackoverflow.com/questions/42712307/efficient-matrix-transpose-matrix-multiplication-in-eigen ? – Damien Jan 21 '20 at 09:00

1 Answers1

0

I want to answer just the first part (not enough reputation to simply comment).

The problem is that vectorTranspose is declared as VectorXd, which represents a column vector. Dynamic-size row vectors are instead of type RowVectorXd. Try the following:

Eigen::VectorXd v(3);
v << 1,2,3;
Eigen::VectorXd wrong = v.transpose();
Eigen::RowVectorXd correct = v.transpose();
std::cout << "v: " << v.rows() << "x" << v.cols() << std::endl;
std::cout << "wrong: " << wrong.rows() << "x" << wrong.cols() << std::endl;
std::cout << "correct: " << correct.rows() << "x" << correct.cols() << std::endl;

which should print:

v: 3x1
wrong: 3x1
correct: 1x3

Eigen allows vectors to be copied in other vectors even if they have different layouts, i.e., colVec = rowVec will work by copying the elements of the row vector into the column vector, without changing the layout of the column vector. The reason why the layout of the column vector cannot change is that VectorXd is actually the same as Matrix<double,Dynamic,1>: it must have a single column. I believe that such "strange" copy (row into column vector and vice versa) is meant a convenience.

ffusco
  • 68
  • 5