Reputation: 22366
I'm using Eigen v3.2.7.
I have a medium-sized rectangular matrix X
(170x17) and row vector Y
(170x1) and I'm trying to solve them using Eigen. Octave solves this problem fine using X\Y
, but Eigen is returning incorrect values for these matrices (but not smaller ones) - however I suspect that it's how I'm using Eigen, rather than Eigen itself.
auto X = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>{170, 17};
auto Y = Eigen::Matrix<T, Eigen::Dynamic, 1>{170};
// Assign their values...
const auto theta = X.colPivHouseholderQr().solve(Y).eval(); // Wrong!
According to the Eigen documentation, the ColPivHouseholderQR
solver is for general matrices and pretty robust, but to make sure I've also tried the FullPivHouseholderQR
. The results were identical.
Is there some special magic that Octave's mldivide
does that I need to implement manually for Eigen?
This spreadsheet has the two input matrices, plus Octave's and my result matrices.
Replacing auto
doesn't make a difference, nor would I expect it to because construction cannot be a lazy operation, and I have to call .eval()
on the solve result because the next thing I do with the result matrix is get at the raw data (using .data()
) on tail and head operations. The expression template versions of the result of those block operations do not have a .data()
member, so I have to force evaluation beforehand - in other words theta
is the concrete type already, not an expression template.
The result for (X*theta-Y).norm()/Y.norm()
is:
2.5365e-007
And the result for (X.transpose()*X*theta-X.transpose()*Y).norm() / (X.transpose()*Y).norm()
is:
2.80096e-007
As I'm currently using single precision float for my basic numerical type, that's pretty much zero for both.
Upvotes: 0
Views: 1536
Reputation: 29225
According to your verifications, the solution you get is perfectly fine. If you want more accuracy, then use double
floating point numbers. Note that MatLab/Octave use double precision by default.
Moreover, it might also likely be that your problem is not full rank, in which case your problem admit an infinite number of solution. ColPivHouseholderQR picks one, somehow arbitrarily. On the other hand, mldivide will pick the minimal norm one that you can also obtain with Eigen::BDCSVD
(Eigen 3.3), or the slower Eigen::JacobiSVD
.
Upvotes: 1