Apply a large Matrix on QR decomposed - c++

I have to convert the MATLAB code to C++ on eigen library,but I have some problems at QR decomposed, matlab has a function:
[Q,R]=qr(A,0); // A is m-by-n
It produces the economy-size decomposition.If m>n,only the first n columns of Q and the first n rows of R are computed. If m<=n,this is the same as [Q,R]=qr(A).
I have tried to compute it on eigen library. But the A is 20000x1000, so there is always a application crash at QR decomposed.And I don't know how to produce the economy-size decomposition on eigen or other ways.
How can I convert [Q,R]=qr(A,0) to C++/Eigen?

MatrixXd A(m,n);
HouseholderQR<MatrixXd> qr;
qr.compute(A);
temp= qr.matrixQR().triangularView<Upper>();
Q= qr.householderQ() * Eigen::MatrixXd::Identity(m, n);
R=temp.topRows(n);

Related

Eigen c++ triangular from

I use C++ 14 and Eigen. For n x n matrix A how can I extract Q and R matrices using QR decomposition in Eigen, I tried to read the documentation but I'm disorientated
I've obtain only R:
HouseholderQR<MatrixXd> qr(A);
qr.compute(A);
MatrixXd R = qr.matrixQR().template triangularView<Upper>();
Anyway, I just want to convert matrix A into a triangular matrix (in a efficient way, around O(n^3) I think), which have the determinant equal to determinant of A, in this way accept any other methods to do this in Eigen. (or another Linear Algebra library, if you know some good libraries I waiting for suggestions )
You can get Q and R as follows:
Eigen::MatrixXd Q = qr.householderQ();
Eigen::MatrixXd QR = qr.matrixQR();
The R matrix is in the upper triangular portion of matrix QR. You can compute the determinant of R as R.diagonal().prod() which is equal in magnitude to A.determinant(). If you want to isolate the upper triangular
portion you can do this:
Eigen::MatrixXd T = R.triangularView<Eigen::UnitUpper>();

Efficient sparse matrix addition in Armadillo

I am trying to construct a sparse matrix L of the form
L and Hi are respectively a very sparse matrix and row vector. The final L matrix should have a density of around 1 % .
Armadillo provides a arma::sp_mat class that seems to suit my needs. The assembly of L then looks like this
arma::sp_mat L(N,N);
arma::sp_mat Hi(1,N);
for (int i = 0; i < p; ++ i){
// The non-zero terms in Hi are populated here
L += Hi.t() * Hi;
}
The number of non-zero elements in Hi is constant with i. I do not have much experience with sparse matrices but I was expecting the incremental assembly of L to be relatively constant in speed.
Yet, it seems that the speed at which Hi.t() * Hi is added to L decreases over time. Am I doing something wrong in the way I assemble L? Should I preconstruct L by specifying which of its components I know will not be zero?
It seems that L is not initialized so that it effectively changes size when incremented with Hi.t() * Hi. This was likely the cause for the decrease in the speed.

Extract first N columns of Q from `ColPivHouseholderQR`

I am trying to implement canonical correlation analysis in C++ using the Eigen linear algebra library.
Part of the algorithm involves QR decomposition using the column pivot method. For that piece I am using the ColPivHouseholderQR class. This class contains an object of type HouseholderSequenceType which I would like to use to extract only the first N columns of the matrix rather than the entire Q matrix.
The full Q matrix has as many columns as rows and quickly fills memory for even modest dataset sizes. Furthermore, I don't need the full matrix, but just a subset of the first N columns.
How can I extract only the first N columns from this object?
My code:
// Set up the class and compute the QR decomposition
Eigen::ColPivHouseholderQR< Eigen::MatrixXd > qr;
qr.setThreshold(threshold);
qr.compute(mat);
int rk = qr.rank();
Eigen::ColPivHouseholderQR< Eigen::MatrixXd >::HouseholderSequenceType seq = qr.householderQ();
seq.setLength(rk);
// return the matrix
return (Eigen::MatrixXd) seq;

Eigen linear algebra solvers seem slow

I want to solve a linear algebraic equation Ax = b using Eigen solvers.
In my case, A is a complex sparse matrix(26410*26410), b is a real vector (26410*1).
I use mex file in MATLAB to map the sparse matrix A and vector b to Eigen accepted format. The reason why I use Eigen solver is to hope it would be faster than solving directly in MATLAB using x = A\b.
However, after tried LDLT, SparseLU, CG and BiCGSTAB, I found the results are not very satisfying:
LDLT takes 1.462s with norm(A*x - b)/norm(b) = 331;
SparseLU takes 37.994s with 1.5193e-4;
BiCGSTAB takes 95.217s with 4.5977e-4;
On the contrast, directly use x = A\b in MATLAB consumes 13.992s with norm of the error 2.606e-5.
I know it is a little stupid and also time consuming to map the sparse matrix A and vector b in MATLAB workspace to Eigen. But I am wondering whether the results I got are the best results which Eigen can give? Anyone can give me some pointers? Should I try some other linear equation solvers? Thanks a lot in advance! The following is the main part of codes.
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
//input vars
//temp var
size_t nrows;
//output vars
//double *x;
//GetData
/* check inputs
...*/
//"mxArray2SCM" is a sub-function for map the complex sparse matrix in Eigen
SpCMat A = mxArray2SCM(prhs[0]);
//SpMat A = mxArray2SM(prhs[0]);
//"mxArray2ECV" is a sub-function for map the real vector in Eigen
Eigen::VectorXcd b = mxArray2ECV(prhs[1]);
//Eigen::VectorXd b = mxArray2EV(prhs[1]);
nrows = b.size();
//Computation
Eigen::VectorXcd x(nrows);
//SparseLU<SparseMatrix<CD> > solver;
BiCGSTAB<SparseMatrix<CD>,IncompleteLUT<CD> > BiCG;
//BiCG.preconditioner().setDroptol(0.001);
BiCG.compute(A);
if(BiCG.info()!=Success){
//decomposition failed
return;
}
x = BiCG.solve(b);
//Output results
plhs[0] = ECV2mxArray(x);
}
Have you considered using PetSc for Krylov solvers or SLEPc to compute eigenvalues?
Make sure you analyze the eigenspectrum before using a specific Krylov solver (CG works only for symmetric positive definite matrices).
PETSc has quite a few solvers that you can try out based on your eigenspectrum.
You can check Y. Saad's book on how these solvers work.
If your matrix is not symmetric positive definite GMRES is a good option.

Thin QR decomposition in c++

Is there an easy to use c++ library for "thin" QR decomposition of a rectangular matrix?
Eigen seems to only support full Q matrices. I can take a full Q and discard some columns, but would it be more efficient to not compute them to begin with?
Newmat does exactly what you want.
To decompose A into QR, you can do:
Matrix Q = A;
UpperTriangularMatrix R;
QRZ(Q, R)
If A is a 3x5 matrix, R will be 3x3 and Q will be 3x5 as well.
Even though this question is a bit old, for the record: Eigen does not explicitly compute the Q matrix, but a sequence of Householder vectors, which can directly be multiplied with any matrix (with the correct number of rows).
If you actually explicitly want the thin Q matrix, just multiply by an identity-matrix of the desired size:
#include <Eigen/QR>
#include <iostream>
int main()
{
using namespace Eigen;
MatrixXf A(MatrixXf::Random(5,3));
HouseholderQR<MatrixXf> qr(A);
MatrixXf thinQ = qr.householderQ() * MatrixXf::Identity(5,3);
std::cout << thinQ << '\n';
}