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);
Related
I'm exclusively using Armadillo matrices in my C++ code for both 2D and 1D arrays for the sake of simplicity and ease of maintenance. For instance, I make use of the vector initializer list
but immediately convert it to a matrix before it is actually used:
mat bArray = mat(colvec({0.1, 0.2, 0.3}));
Most of my code consists of 1D arrays and there are only a few places where I truly need the 2D Armadillo matrix.
Would I gain a significant performance increase if I converted all (nx1) Armadillo matrices to (nx1) Armadillo column vectors? Are there any other nuances between these two data structures that I should know about?
An arma::vec is the same as arma::colvec and they are just typedefs for Col<double>. You can see this in the typedef_mat.hpp file in armadillo source code. Also, arma::Col<T> inherits from Mat<T>, as can been seem in the Col_bones.hpp file. Essentially, a colvec is just a matrix with a single column. You wouldn't gain anything, except that you would avoid the unnecessary copy from the temporary vector to the matrix. Although maybe that is a move, since the colvec is a temporary, and thus even that gain could be marginal.
Nevertheless, if you want a 1D array use a colvec instead of mat at least for the sake of being clear about it.
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.
I started using Armadillo relatively recently, and although I like it a lot, it would be useful if it had ways of storing 4D matrices. Is there something I'm missing, or a workaround for this?
The last dimension would just have a size of three, so in theory I could have something like:
std::vector<arma::cube> 4Dmatrix(3);
for (int index=0; index<3; index++)
4Dmatrix[index] = cube(size1, size2, size3);
However, it feels like there must be a better way.
Thanks in advance!
You could potentially use the field class which stores arbitrary objects as elements in a vector, matrix or cube structure. E.g. (from the documentation) to create a field containing vec vectors:
// create a field containing vectors
field<vec> F(3,2);
No, there is no built-in way. If you look at the source, you will see that there are individual implementations for vectors, matrices and cubes.
Maybe a Boost multi array could be of use to you.
I use Eigen for most of my code but I would like to use Miser or Vegas monte-carlo integration from GSL. I need to convert Eigen's vectors to c arrays of doubles
what would be the best way to do it?
Matrix<double,3,1> --> c_array []
I have worked with Eigen before...
Usually, for simple access to the internal array data, like mentioned by user janneb in this thread, you just want to invoke data():
Vector3d v;
// Operations to add values to the vector.
double *c_ptr = v.data();
If you wish to iterate the individual values to perform some operation, you want to iterate every line (.row(index)) and column (.col(index)), depending on the matrix order that you want to lay down in the destination vector.
In your specific example, you need only iterate the rows:
Matrix<double,3,1> --> c_array []
You would want to call .col(0). Should similar needs arise, the specific documentation is always helpful!
So you would end up with something like (assuming you wish to use a three-line single-column matrix):
Vector3d v;
// Operations to add values to the vector.
for (int i=0; i<v.rows(); ++i)
c_array[i] = v(i,0);
Hope that helped.
I'm doing a simulation where I must calculate many averages and I thought that using boost::accumulators would be a good idea. The problem is that one of the quantities I want to average is a symmetric matrix, whose diagonal is known beforehand. SO I just need to calculate the averages for Q[i][j] if i < j.
At first I got the impression that I could use a
using namespace boost::accumulators;
using namespace boost::numeric::ublas;
typedef accumulator_set<double, stats<tag::mean> > accumulator;
symmetric_matrix<accumulator, lower> foo; // a symmetric matrix of accumulators
to hold my accumulators. But then it occurred to me that this symmetric_matrix structure might be adequate to hold numerical values only (they have arithmetic operations defined) or are optimized for this kind of data in some way. Is this right?
If symmetric_matrix from boost are not adequate, I need a data structure that can hold the lower triangle of a symmetric matrix without the diagonal, and it must be suitable to hold the accumulators and have a nice matrix like syntax. Is this readily available from some library? If not, is there an easy implementation for this kind of structure around?
Try the Boost uBLAS Triangular matrix. Here is an example.