How to calculate matrix power using Eigen library? - c++

I need to calculate power of some matrix and then get its eigenvectors. I know that there is method pow() but it is unclear for me how to use it.
For now, my code is:
Eigen::Matrix3d mat2 = mat1.pow(0.5);
return getEigenvalues(mat2);
Method getEigenvalues() takes Eigen::Matrix type which is not what pow() returns.

That's the wrong order of operations. You first calculate the eigenvalues and next exponentiate those.
The reason is that eigenvalues of the exponentiated matrix are equal to the exponentiated eigenvalues of the original matrix. EDIT: provided the eigenvalues of the original matrix exist.
So, for example, to get the eigenvalues of your matrix mat2 you write:
Eigen::VectorXd ev = getEigenvalues(mat1).unaryExpr([](double d) {return std::pow(d, 0.5);});
In case of exponent one-half, you can also better use std::sqrt.
I forgot to mention that the eigenvectors are identical for the original and the exponentiated matrix, see here for example.

Related

How to optimize matrix product of sparse and dense matrices in eigen when the result is selfadjoint

I am working with square matrices of type std::complex<double>. In particular, a sparse matrix S and a self-adjoint, dense matrix H, and I would like to compute the product of the form S*H*S.adjoint() and add it to another dense, self-adjoint matrix J. So a straight-forward way to do this in Eigen would be:
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <complex>
Eigen::Matrix<std::complex<double>, Eigen::Dynamic, Eigen::Dynamic> J, H;
Eigen::SparseMatrix<std::complex<double>> S;
// ...
// Set H, and J to be some self-adjoint matrices of the same size, and S also same
// size, but not necessarily self-adjoint.
// ...
J += S*H*S.adjoint();
But because H and J are self-adjoint and by the form of the product S*H*S.adjoint(), we know that J will remain self-adjoint after the operation. So there is really no need to compute the entire dense matrix result S*H*S.adjoint() and we could probably save some computation time by only computing the lower- or upper-triangular part of the result and adding that to the corresponding part of the matrix J. Eigen provides an API for this sort of optimization, but I'm not able to use it in this case. For example if instead of the sparse matrix S we had a dense matrix D, then doing
J += D*H*D.adjoint();
should be less efficient than
J.triangularView<Eigen::Lower>() = D*H*D.adjoint();
or
J.triangularView<Eigen::Lower>() = D*H.selfadjointView<Eigen::Lower>()*H.adjoint();
but the API doesn't seem to provide this level of optimization when computing the former product with a sparse matrix S instead of the dense matrix D. That is,
J.triangularView<Eigen::Lower>() = S*H*S.adjoint();
doesn't compile. So my question is: is there a way to tell Eigen to only compute the lower- (or upper-) triangular part of the matrix S*H*S.adjoint() and add it to the lower- (or upper-) triangular part of the self-adjoint matrix J to improve performance?
Perhaps even better would be an overload of a rank 1 update that looked something like
J.selfadjointView<Eigen::Lower>().rankUpdate(S,H);
Of course the current API doesn't support this form and to get the desired result would require taking the square root of H, call it G and do
J.selfadjointView<Eigen::Lower>().rankUpdate(S*G);
but although this should give the correct result, taking the square root is probably super expensive compared to the rest, so this would probably be slower.
The best performance I've found so far is
J.noalias() += S*H*S.adjoint();

Eigen solver for sparse matrix product

I want to use Eigen to compute L_1^{-1}L_2, where both L_1 and L_2 are lower triangular matrices and are stored as column oriented sparse matrices in Eigen.
I tried the Eigen triangular solver. However, that requires L_2 to be dense.
The solve method in fact is not overloaded for sparse rhs, however you can use the solveInPlace method like so (I did not actually try this):
Eigen::SparseMatrix<double> foo(Eigen::SparseMatrix<double> const& L1, Eigen::SparseMatrix<double> const& L2)
{
Eigen::SparseMatrix<double> res = L2;
L1.triangularView<Eigen::Lower>().solveInPlace(res);
return res;
}
Still you should consider if you actually need the full matrix.

Can Armadillo efficiently multiply sparse-by-sparse and sparse-by-dense matrices into a dense result?

I am using Armadillo for some linear algebra problems. It has SpMat<float> for sparse matrices and Mat<float> for dense matrices.
Suppose I have sparse matricesS_a and S_b, and a dense matrix D. I need to compute the produces S_a*S_b and S_a*D, the results will be dense in both cases.
I can convert the sparse matrices into dense matrices and then multiply, but that will be inefficient (these matrices are very large). Is there a way to tell Armadillo to store the results into a dense matrix without performing an intermediate conversion step?
You can use the mat constructor which takes a sparse matrix and converts its data to a dense one:
arma::mat out1(S_a * S_b);
arma::mat out2(S_b * D);
Both multiplication operators for the sparse class (sparse-sparse and sparse-dense) will produce a sparse matrix object as output. (Whether or not it's really sparse will depend on the structure of the inputs.) This can be converted to a dense matrix using the dense matrix constructor with signature: arma::mat(arma::sp_mat).

Armadillo integer eigen decomposition

I am trying to use Armadillo to decompose a matrix consisting of integers (i.e. arma::Mat<int>) into eigenvalues and eigenvectors
However, it always gives me compile error no matter what I put as input matrix and output vector/matrix type
It works when i declare the input matrix as arma::Mat<double>, output vector(eigenvalues) as arma::Col<std::complex<double>> and output matrix(eigenvectors) as arma::Mat<std::complex<double>>
I have tried using int and/or std::complex<int> as types for the inputs and the outputs but neither of them worked.
Is there a way that I can do decompose matrices of integer values?
Thanks
First convert the integer matrix to a double matrix using the conv_to function. For example, imat A = ...; mat B = conv_to<mat>::from(A);. Then you can do eigen decomposition on the converted matrix.

Use Eigen library to perform sparseLU and display L & U?

I'm a new to Eigen and I'm working with sparse LU problem.
I found that if I create a vector b(n), Eigen could compute the x(n) for the Ax=b equation.
Questions:
How to display the L & U, which is the factorization result of the original matrix A?
How to insert non-zeros in Eigen? Right now I just test with some small sparse matrix so I insert non-zeros one by one, but if I have a large-scale matrix, how can I input the matrix in my program?
I realize that this question was asked a long time ago. Apparently, referring to Eigen documentation:
an expression of the matrix L, internally stored as supernodes The only operation available with this expression is the triangular solve
So there is no way to actually convert this to an actual sparse matrix to display it. Eigen::FullPivLU performs dense decomposition and is of no use to us here. Using it on a large sparse matrix, we would quickly run out of memory while trying to convert it to dense, and the time required to compute the factorization would increase several orders of magnitude.
An alternative solution is using the CSparse library from the Suite Sparse as:
extern "C" { // we are in C++ now, since you are using Eigen
#include <csparse/cs.h>
}
const cs *p_matrix = ...; // perhaps possible to use Eigen::internal::viewAsCholmod()
css *p_symbolic_decomposition;
csn *p_factor;
p_symbolic_decomposition = cs_sqr(2, p_matrix, 0); // 1 = ordering A + AT, 2 = ATA
p_factor = cs_lu(p_matrix, m_p_symbolic_decomposition, 1.0); // tol = 1.0 for ATA ordering, or use A + AT with a small tol if the matrix has amostly symmetric nonzero pattern and large enough entries on its diagonal
// calculate ordering, symbolic decomposition and numerical decomposition
cs *L = p_factor->L, *U = p_factor->U;
// there they are (perhaps can use Eigen::internal::viewAsEigen())
cs_sfree(p_symbolic_decomposition); cs_nfree(p_factor);
// clean up (deletes the L and U matrices)
Note that although this does not use expliit vectorization as some Eigen functions do, it is still fairly fast. CSparse is also very compact, it is just a single header and about thirty .c files with no external dependencies. Easy to incorporate in any C++ project. There is no need to actually include all of Suite Sparse.
If you'll use Eigen::FullPivLU::matrixLU() to the original matrix, you'll receive LU decomposition matrix. To display L and U separately, you can use method triangularView<mode>. In Eigen wiki you can find good example of it. Inserting nonzeros into matrices depends on numbers, which you wan't to put. Eigen has convenient syntax, so you can easily insert values in loop:
for(int i=0;i<size;i++)
{
for(int j=size;j>someNumber;j--)
{
matrix(i,j)=yourClass.getNextNumber();
}
}