Constructing sparse tridiagonal matrix in Eigen - c++

How do I construct a sparse tridiagonal matrix in Eigen? The matrix that I want to construct looks like this in Python:
alpha = 0.5j/dx**2
off_diag = alpha*np.ones(N-1)
A_fixed = sp.sparse.diags([-off_diag,(1/dt+2*alpha)*np.ones(N),-off_diag],[-1,0,1],format='csc')
How do I do it in C++ using the Eigen package? It looks like I need to use the 'triplet' as documented here, but are there easier ways to do this, considering that this should be a fairly common operation?
Another side question is whether I should use row-major or column major. I want to solve the matrix equation Ax=b, where A is a tridiagonal matrix. When we do matrix-vector multiplication by hand, we usually multiply each row of the matrix by the column vector, so storing the matrix in row-major seems to make more sense. But what about a computer? Which one is preferred if I want to solve Ax=b?
Thanks

The triplets are the designated method of setting up a sparse matrix.
You could go the even more straightforward way and use A.coeffRef(row, col) = val or A.inser(row,col) = val, i.e. fill the matrix element-by-element.
Since you have a tridiagonal system you know the number of non-zeros of the matrix beforehand and can reserve the space using A.reserve(Nnz).
A dumb way, which nevertheless works, is:
uint N(1000);
CSRMat U(N,N);
U.reserve(N-1);
for(uint j(0); j<N-1; ++j)
U.insert(j,j+1) = -1;
CSRMat D(N,N);
D.setIdentity();
D *= 2;
CSRMat A = U + CSRMat(U.transpose()) + D;
As to the solvers and preferred storage order that is, as I recall, of minor importance. Whilst C(++) stores contiguous data in row-major format it is up to the algorithm whether the data is accessed in an optimal way (row-by-row for row-major storage order). The correctness of an algorithm does not, as a rule, depend on the storage order of the data. Its performance depends on compatibility of storage order and actual data access patterns.
If you intend to use Eigen's own solvers stick with its default choice (col-major). If you intend to interface with other libraries (e.g. ARPACK) choose the storage order the library prefers/requires.

Related

Preallocating memory for sparse matrix operations in Eigen

I'm writing a program using Eigen (an optimizer to be precise) that has a "hot loop" within which I'd like to avoid memory allocation whenever possible.
When using Eigen/Dense I've been able to organize things so that all my memory allocation is performed in the constructor (with judicious usage of .noalias() and inplace LLT factorizations) by computing the sizes of all the workspaces I need in advance and preallocating.
I'd like to do something similar with the Eigen/Sparse variant of the code (to the extent that it is possible). The constructor will require the user to supply sparsity patterns for all the data which I can use to determine the sizes and sparsity patterns for all the subsequent matrices I need, workspaces included. I need to perform 4 kinds of operations:
Sparse matrix-vector products
Cholesky factorizations
Schur complements of the form E = H + A' * B * A where B is a diagonal matrix and H,A are general sparse matrices.
My current understanding is as follows:
I can use x.noalias() = A*y (A is sparse, x,y dense vectors) for matrix vector products with no problems
I can perform matrix addition using coefficient wise tricks by padding with explicit zeros as in e.g.,How to avoid memory allocations in sparse expressions with Eigen. This is mostly for operations like B = A + s I where A is sparse and sI is a scalar multiple of identity. I can just make sure the main diagonal is included in the sparsity pattern of B and perform the addition in a loop.
As of 2017, there is no way to avoid temporary allocation in sparse matrix products e.g., C = A*B (https://forum.kde.org/viewtopic.php?f=74&t=140031&p=376933&hilit=sparse+memory#p376933), and I don't see any inplace functions for sparse matrices yet so I'll have to bite the bullet on this one and accept the temporary creation.
For licensing reasons, I'm using an eigen external LDL' factorization package which allows me to preallocate based on a symbolic analysis stage.
Can anyone suggest a fast way to organize the Schur computation E = H + A' * B * A? (exploiting that I know its sparsity structure in advance)

Armadillo complex sparse matrix inverse

I'm writing a program with Armadillo C++ (4.400.1)
I have a matrix that has to be sparse and complex, and I want to calculate the inverse of such matrix. Since it is sparse it could be the pseudoinverse, but I can guarantee that the matrix has the full diagonal.
In the API documentation of Armadillo, it mentions the method .i() to calculate the inverse of any matrix, but sp_cx_mat members do not contain such method, and the inv() or pinv() functions cannot handle the sp_cx_mat type apparently.
sp_cx_mat Y;
/*Fill Y ensuring that the diagonal is full*/
sp_cx_mat Z = Y.i();
or
sp_cx_mat Z = inv(Y);
None of them work.
I would like to know how to compute the inverse of matrices of sp_cx_mat type.
Sparse matrix support in Armadillo is not complete and many of the factorizations/complex operations that are available for dense matrices are not available for sparse matrices. There are a number of reasons for this, the largest being that efficient complex operations such as factorizations for sparse matrices is still very much an open research field. So, there is no .i() function available for cx_sp_mat or other sp_mat types. Another reason for this is lack of time on the part of the sparse matrix developers (...which includes me).
Given that the inverse of a sparse matrix is generally going to be dense, then you may simply be better off turning your cx_sp_mat into a cx_mat and then using the same inversion techniques that you normally would for dense matrices. Since you are planning to represent this as a dense matrix anyway, then it's a fair assumption that you have enough RAM to do that.

sparse or dense storage of a matrix

I'm working with large sparse matrices that are not exactly very sparse and I'm always wondering how much sparsity is required for storage of a matrix as sparse to be beneficial? We know that sparse representation of a reasonably dense matrix could have a larger size than the original one. So is there a threshold for the density of a matrix so that it would be better to store it as sparse? I know that the answer to this question usually depends on the structure of the sparsity, etc but I was wondering if there is just some guidelines? for example I have a very large matrix with density around 42%. should I store this matrix as dense or sparse?
scipy.coo_matrix format stores the matrix as 3 np.arrays. row and col are integer indices, data has the same data type as the equivalent dense matrix. So it should be straight forward to calculate the memory it will take as a function of overall shape and sparsity (as well as the data type).
csr_matrix may be more compact. data and indices are the same as with coo, but indptr has a value for each row plus 1. I was thinking that indptr would be shorter than the others, but I just constructed a small matrix where it was longer. An empty row, for example, requires a value in indptr, but none in data or indices. The emphasis with this format is computational efficiency.
csc is similar, but working with columns. Again you should be able to the math to calculate this size.
Brief discussion of memory advantages from MATLAB (using similar storage options)
http://www.mathworks.com/help/matlab/math/computational-advantages.html#brbrfxy
background paper from MATLAB designers
http://www.mathworks.com/help/pdf_doc/otherdocs/simax.pdf
SPARSE MATRICES IN MATLAB: DESIGN AND IMPLEMENTATION

Determinant Value For Very Large Matrix

I have a very large square matrix of order around 100000 and I want to know whether the determinant value is zero or not for that matrix.
What can be the fastest way to know that ?
I have to implement that in C++
Assuming you are trying to determine if the matrix is non-singular you may want to look here:
https://math.stackexchange.com/questions/595/what-is-the-most-efficient-way-to-determine-if-a-matrix-is-invertible
As mentioned in the comments its best to use some sort of BLAS library that will do this for you such as Boost::uBLAS.
Usually, matrices of that size are extremely sparse. Use row and column reordering algorithms to concentrate the entries near the diagonal and then use a QR decomposition or LU decomposition. The product of the diagonal entries of the second factor is - up to a sign in the QR case - the determinant. This may still be too ill-conditioned, the best result for rank is obtained by performing a singular value decomposition. However, SVD is more expensive.
There is a property that if any two rows are equal or one row is a constant multiple of another row we can say that determinant of that matrix is zero.It is applicable to columns as well.
From my knowledge your application doesnt need to calculate determinant but the rank of matrix is sufficient to check if system of equations have non-trivial solution : -
Rank of Matrix

C++ equivalent of R list

Looking for something in C++ for easy storage and access of matrices of different sizes. I typically use R, and in R I can use a loop and store a matrix in a list as follows (toy example)
myList <- list(1)
for(i in 1:10){
myList[[i]] <- matrix(rnorm(i^2),i,i)
}
This gives me a list where myList[[i]] will then give me the i-th matrix. Is there anything like this in C++? I have seen Boost functions that can do arrays of varying sizes, but fail to apply them to matrices. Trying to use either Eigen or Armadillo if that helps narrow responses.
There is 2 parts to the answer you're looking for, i.e.
The matrices.
The container holding all these matrices.
So, for the matrices: If you are planning on doing linear algebra operations I'd recommend using some special libraries, such as Armadillo which comes with a lot of pre-defined matrix functions (e.g. eigenvalue, matrix multiplication, etc.). If it's just basic 2D data storage with no special operation, then I'd recommend using a STL vector of vector to represent your matrices. These containers are dynamic in size (can be changed at will during execution) and all elements are accessible by index. As Patrick said, more info can be found here: cppreference.com.
An example of a 3x3 matrix of integer filled with 1s would be
std::vector< std::vector<int,int> > matrix(3,std::vector<int>(3,1));
Then, you have to store these matrices somewhere. For this, it is really going to depend on your needs. The simplest solution would be a vector of matrices (so a vector of vector of vector, really). Your code would behave exactly as in R, and you would be able to access matrix by index. The equivalent C++ code is
#include<vector>
using namespace std;
typedef vector< vector<int,int> > int_matrix_t;
...
vector<int_matrix_t> my_vector_of_matrices(10);
for (int i = 0; i<10; ++i) {
my_vector_of_matrices[i] = some_function_that_outputs_a_matrix(i);
}
But there is a lot of other container available. You should survey this chart and choose for yourself!
I believe you can use std::vector.
http://en.cppreference.com/w/cpp/container/vector
std::vector<Matrix> matrices;
matrices[i] = Matrix(data);