I have been googling for a while now, but cant find the answer to this simple question.
In matlab i can do this:
rows = [1 3 5 9];
A = rand(10);
B = A(rows, : );
How do i do this in eigen? It does not seem like it is possible. The closest thing i have found is
MatrixXd a(10,10);
a.row(1);
,but I want to get multiple rows/cols. Another user has also asked the question here: How to extract a subvector (of a Eigen::Vector) from a vector of indices in Eigen? , but I think there must some built in way of doing this because it is a really common operation I think.
Thanks.
While this was not possible at the time this question was asked, it has since been added in the development branch!
It's very straight forward:
Eigen::MatrixXf matrix;
Eigen::VectorXi columns;
Eigen::MatrixXf extracted_cols = matrix(Eigen::all, columns);
So I'm guessing this will be in the 3.3.5 3.4 stable release. Until then the development branch is the way to go.
Unfortunately, this is still not directly supported even in Eigen 3.3. There has been this feature request for a while:
http://eigen.tuxfamily.org/bz/show_bug.cgi?id=329
Gael linked to an example implementation in one of the comments there:
http://eigen.tuxfamily.org/dox-devel/TopicCustomizing_NullaryExpr.html#title1
Ok, say for example you have a 3x3 matrix:
m = [3 -1 1; 2.5 1.5 6; 4 7 1]
and say you want to extract following rows from m matrix:
[0 2], // row 0 and row 2
essentially giving out following matrix:
new_extracted_matrix = [3 -1 1; 4 7 1] // row 0 and row 2 of matrix m
Main thing here is, let's create a vector v having contents [0 2], means we would extract following row indices from matrix m.
Here is what i did:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
Matrix3f m;
m(0,0) = 3;
m(0,1) = -1;
m(0,2) = 1;
m(1,0) = 2.5;
m(1,1) = m(1,0) + m(0,1);
m(1,2) = 6;
m(2,0) = 4;
m(2,1) = 7;
m(2,2) = 1;
std::cout << "Here is the matrix m:\n" << m << std::endl; // Creating a random 3x3 matrix
VectorXf v(2);
v(0) = 0; // Extracting row 0
v(1) = 2; // Extracting row 2
MatrixXf r(1,v.size());
for (int i=0;i<v.size();i++)
{
r.col(i) << v(i); // Creating indice vector
}
cout << "The extracted row indicies of above matrix: " << endl << r << endl;
MatrixXf N = MatrixXf::Zero(r.size(),m.cols());
for (int z=0;z<r.size();z++)
{
N.row(z) = m.row(r(z));
}
cout << "Extracted rows of given matrix: " << endl << N << endl;
}
This would give us following output:
Here is the matrix m:
[3 -1 1; 2.5 1.5 6; 4 7 1]
The extracted row indicies of above matrix:
[0 2]
Extracted rows of given matrix:
[3 -1 1; 4 7 1]
Related
I've been struggling with a simple class representing a matrix in C++. Instead of using a multidimensional array, I've decided to use a flat array and access the values by calculating the index of the according cell by [row * x_dim + col]. I want to use 2D matrices only.
Ideally, I would also create getter and setter functions, but as I am already having troubles I skipped those for now.
The main problem is, that after setting values, those values seem to be corrupted somewhere along the way as when printing them out again, I'm reading different values then what I've actually stored.
Here's the (simplified) header MyMatrix.h:
class MyMatrix{
public:
int x_dim, y_dim;
float *my_matrix;
MyMatrix(int x, int y);
~MyMatrix();
};
Here is MyMatrix.cpp:
#include "MyMatrix.h"
MyMatrix::MyMatrix(int x, int y){
x_dim = x;
y_dim = y;
my_matrix = new float[x * y];
}
MyMatrix::~MyMatrix(){
delete[] my_matrix;
}
Now when creating a new instance of MyMatrix, filling the array with ascending numbers and then printing the values again, I am getting different values for some cells in the (flat) matrix. Here's what I did:
#include "MyMatrix.h"
#include <iostream>
int main(){
MyMatrix test(3, 4);
//filling the array in test with ascending numbers
for(int row = 0; row < test.x_dim; row++){
for(int col = 0; col < test.y_dim; col++){
test.my_matrix[row * test.x_dim + col] = col+1;
}
}
for(int row = 0; row < test.x_dim; row++){
std::cout << "Row " << row << ": ";
for(int col = 0; col < test.y_dim; col++){
std::cout << test.my_matrix[row * test.x_dim + col] << " ";
}
std::cout << std::endl;
}
}
So what my output should look like is this:
Row 0: 1 2 3 4
Row 1: 1 2 3 4
Row 2: 1 2 3 4
But instead, it looks like this:
Row 0: 1 2 3 1
Row 1: 1 2 3 1
Row 2: 1 2 3 4
As one can see, the first two rows have a 1 instead of a 4 in column 3.
I've really been struggling with identifying the underlying issue here and I can't figure it out so I would appreciate any help!
Thanks!
I am using clang version 13.0.0 on an M1 Pro and the g++ compiler.
This is the wrong index:
row * test.x_dim + col
Suppose you are in the last iteration of the outer loop then row == x_dim-1 and you get:
(x_dim-1) * x_dim + col
while it should be (supposed x is rows):
(y_dim-1) * x_dim + col
Tip: Your variable naming col vs x_dim and row vs y_dim can be made better. x, x_dim and y, y_dim or col, num_columns and row, num_rows would be less errorprone.
This slices MatrixXd with a Array<bool, Dynamic, 1>, just like in Matlab you can do A(A>5), here you can do slice(A, A.array() > 5). I'd like to turn this into a templated version, so that it can take any type of matrices or vectors, for instance Matrix3i or VectorXi. This page tell me to use MatrixBase<Derived>, but I was not able to get very far with it. Idk how to declare a templated matrix of a certain size.
https://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html
#include <Eigen/Dense>
using namespace Eigen;
MatrixXd slice(const MatrixXd & mat, const Array<bool, Dynamic, 1> & ind)
{
assert(mat.cols() == ind.size());
// find out dimensions of the matrix going out
int _cols = 0;
for(int i = 0; i < ind.size(); ++i)
{
if(ind[i] == 1)
{
_cols += 1;
}
}
//populate the matrix going out, in a column major way
int _pos = 0;
MatrixXd out = MatrixXd::Zero(mat.rows(), _cols);
for(int i = 0; i < ind.size(); ++i)
{
if(ind[i] == 1)
{
out.col(_pos) = mat.col(i);
_pos += 1;
}
}
return out;
}
And usage is like this:
MatrixXd A(4, 4);
A << 1,2,3,4,
5,6,7,8,
1,5,6,3,
9,8,6,5;
VectorXd b(4);
b << 23,-4,1234,3;
cout << A << endl;
cout << (b.array() > 5) << endl;
cout << slice(A, b.array() > 5) << endl;
Output is as such:
1 2 3 4
5 6 7 8
1 5 6 3
9 8 6 5
1
0
1
0
1 3
5 7
1 6
9 6
I'd appreciate if anyone would show me how to do this!
PS: There seems to be a similar functionality in the docs:
https://eigen.tuxfamily.org/dox-devel/group__TutorialSlicingIndexing.html
But I was literally unable to find the keyword all in Eigen/Core, as
std::vector<int> ind{4,2,5,5,3};
MatrixXi A = MatrixXi::Random(4,6);
cout << "Initial matrix A:\n" << A << "\n\n";
cout << "A(all,ind):\n" << A(all,ind) << "\n\n";
And my IDE is unable to resolve it either.
I am passing a small sparse matrix(for testing) to a C++ function from R. The matrix belongs to the class dgCMatrix as shown below:
5 x 5 sparse Matrix of class "dgCMatrix"
[1,] . . . . .
[2,] 1 1 . . .
[3,] . . . . .
[4,] . . 1 . .
[5,] . 1 . . .
I am iterating this matrix as mentioned in the documentation here.
My function prints out the value of the iterator and the row index, column index.
The c++ function is defined below:
#include <RcppEigen.h>
// [[Rcpp::depends(RcppEigen)]]
using Eigen::MappedSparseMatrix;
using Eigen::SparseMatrix;
using Eigen::VectorXi;
using Eigen::Map;
using namespace Rcpp;
using namespace std;
// [[Rcpp::export]]
void createRec(RObject sparse_mat, IntegerVector sparse_vec) {
const MappedSparseMatrix<int> spmat(as<MappedSparseMatrix<int> >(sparse_mat));
long int nrow = spmat.rows();
long int ncol = spmat.cols();
NumericVector sim(nrow);
for(int k=0;k<spmat.outerSize();k++){
for(SparseMatrix<int,Eigen::ColMajor>::InnerIterator it(spmat,k);it;++it){
cout<<"k="<<k<<endl;
cout<<"value="<<it.value()<<endl;
cout<<"it.row="<<it.row()<<endl;
cout<<"it.col="<<it.col()<<endl;
cout<<"index="<<it.index()<<endl;
}
}
}
For the matrix given above the following results are printed:
k=0
value=156148016
it.row=66211520
it.col=0
index=66211520
k=1
value=0
it.row=0
it.col=1
index=0
k=1
value=1
it.row=4
it.col=1
index=4
k=2
value=1
it.row=3
it.col=2
index=3
1.) Any explanation for the values corresponding to k=0? Could these be due to passing the matrix in a wrong manner?
2.) k is iterating over outerSize, which is equal to 5, why is it not iterating for k=3,4? Considering it is a sparseMatrix, this behaviour was expected from the iterator.
Whenever you see very large numbers like 156148016 or 66211520, chances are you either have an undefined behavior (UB) or a value was not appropriately initialized. In this case, it is the later. Specifically, the dgCMatrix class' underlying type is that of a double not an int.
The dgCMatrix class is a class of sparse numeric matrices in the compressed, sparse, column-oriented format. In this implementation the non-zero elements in the columns are sorted into increasing row order. dgCMatrix is the "standard" class for sparse numeric matrices in the Matrix package.
Thus, when you are trying to create a map to the memory location of the underlying RObject there is an additional step required to recreate the object anew in the requested different type. After adding the const term, I'm willing to bet the entries are then as expected since the compiler likely keeps in memory the intermediary object.
So, the changing following:
MappedSparseMatrix<int> spmat(as<MappedSparseMatrix<int> >(sparse_mat));
to:
MappedSparseMatrix<double> spmat(as<MappedSparseMatrix<double> >(sparse_mat));
should be sufficient.
The linked example uses a SparseMatrix matrix, here you are using a MappedSparseMatrix but do not setup an appropriate MappedSparseMatrix::InnerIterator for the second loop.
Thus, we have:
for(SparseMatrix<int,Eigen::ColMajor>::InnerIterator it(spmat,k);it;++it){
Going to:
for(MappedSparseMatrix<double>::InnerIterator it(spmat,k);it;++it){
Also, note that the use of Eigen::ColMajor within the SparseMatrix<int, Eigen::ColMajor>::InnerIterator is not needed as that is the default initialization. So, I've removed this statement.
Regarding your second question, on the iteration of k.
k does iterate over both k=3,4 but there are no elements within those columns. Therefore, the inner loop where k is output does not get called.
This is easy to see if we put two k declarative output statements in the outer and inner loops.
e.g.
for(int k = 0; k < spmat.outerSize(); ++k) {
Rcpp::Rcout << "Overall k = " << k << std::endl << std::endl;
for(MappedSparseMatrix<double>::InnerIterator it(spmat,k); it; ++it) {
Rcpp::Rcout << "Inner k = " << k << std::endl;
}
}
Avoid using namespace std;
Adding in namespace sometimes has unintended consequences, especially one as large as std.
Taking the points from above and slightly simplifying your example, we have the following bare bones working example:
#include <RcppEigen.h>
// [[Rcpp::depends(RcppEigen)]]
using Eigen::MappedSparseMatrix;
using Eigen::SparseMatrix;
using Eigen::VectorXi;
using Eigen::Map;
// [[Rcpp::export]]
void createRec(Rcpp::RObject sparse_mat) {
MappedSparseMatrix<double> spmat(Rcpp::as<MappedSparseMatrix<double> >(sparse_mat));
long int nrow = spmat.rows();
Rcpp::NumericVector sim(nrow);
for(int k = 0; k < spmat.outerSize(); ++k) {
Rcpp::Rcout << "Overall k = " << k << std::endl << std::endl;
for(MappedSparseMatrix<double>::InnerIterator it(spmat,k); it; ++it) {
Rcpp::Rcout << "Inner k = " << k << std::endl
<< "value = " << it.value() << std::endl
<< "it.row = " << it.row() << std::endl
<< "it.col = " << it.col() << std::endl
<< "index = " << it.index() << std::endl;
}
}
}
/***R
# Setup values
id_row = c(2, 2, 4, 5)
id_col = c(1, 2, 3, 2)
vals = rep(1,4)
# Make the matrix
x = sparseMatrix(id_row, id_col, x = vals, dims = c(5, 5))
# Test the function
createRec(x)
*/
Output:
Overall k = 0
Inner k = 0
value = 1
it.row = 1
it.col = 0
index = 1
Overall k = 1
Inner k = 1
value = 1
it.row = 1
it.col = 1
index = 1
Inner k = 1
value = 1
it.row = 4
it.col = 1
index = 4
Overall k = 2
Inner k = 2
value = 1
it.row = 3
it.col = 2
index = 3
Overall k = 3
Overall k = 4
For more details on sparse matrices in Eigen and Rcpp, you may wish to read the Rcpp Gallery: Using iterators for sparse vectors and matrices by Soren Hojsgaard and Doug Bates.
I have implemented the first part of this problem but failed to achieve the second part. What I'm trying to do is that I have two vectors
std::vector<double> A = {1,1,2,2};
std::vector<double> B = {3,3,4,4,5,5};
I have to go through two loops and make subtraction of two math vectors. For example,
For the first iteration:
C = [1;1] (Note: the first two elements of A vector)
Because C is 2x1, I have to construct from B three math vectors of the same size, therefore the output for the first iteration is
1 - 3
1 - 3
------
1 - 4
1 - 4
------
1 - 5
1 - 5
For the second iteration, the C matrix is expanded by two elements per iteration , therefore the new C matrix is C = [1;1;2;2]. Now we need to make the subtraction again, the output for the second iteration is
1 - 3
1 - 3
2 - 4
2 - 4
------
1 - 4
1 - 4
2 - 5
2 - 5
------
1 - 5
1 - 5
2 - 3
2 - 3
As you can see, the second math vector is shifted by two elements where the first math vector remains as it is.
A and B matrices have this assumption size % 2 = 0 where 2 is the size of C matrix.
Replicating your ouput, for first iteration you would have:
std::vector<double> A = {1,1,2,2};
std::vector<double> B = {3,3,4,4,5,5};
std::vector<double> C (A.begin(), A.begin()+2);
// bg - index of group of 2 elements in B
for (int bg = 0; bg < 3; ++bg) {
for (int ci = 0; ci < int(C.size()); ++ci) {
// bi - index of element in B
int bi = (2*bg + ci) % int(B.size());
std::cout << C[ci] << " - " << B[bi] << std::endl;
}
std::cout << "------" << std::endl;
}
For second iteration you would have to change one line:
// line changed...
std::vector<double> C (a.begin(), a.begin()+4);
Edit: OK, here's more general form that outputs both cases you specified for the change of iteration counter it. Hope it works when you extend the vectors.
for (int it = 1; it <= int(A.size())/2; ++it) {
std::vector<double> C (A.begin(), A.begin()+it*2);
// bg - index of group of 2 elements in B
for (int bg = 0; bg < int(B.size())/2; ++bg) {
for (int ci = 0; ci < int(C.size()); ++ci) {
// bi - index of element in B
int bi = (2*bg + ci) % int(B.size());
std::cout << C[ci] << " - " << B[bi] << std::endl;
}
std::cout << "------" << std::endl;
}
std::cout << std::endl;
}
I am a python programmer, and I am trying to understand boost.
Here is what I got:
>>> import numpy as np
>>> a
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
>>> b
array([[20, 21, 22],
[23, 24, 25]])
>>> a[[0,2]] = b
>>> a
array([[20, 21, 22], # first row of b
[ 3, 4, 5],
[23, 24, 25], # second row of b
[ 9, 10, 11]])
I can do this using boost:
#include <iostream>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
using namespace std;
int main()
{
using namespace boost::numeric::ublas;
matrix<double> a (4, 3);
for (unsigned i = 0; i < a.size1 (); ++ i)
for (unsigned j = 0; j < a.size2 (); ++ j)
a (i, j) = a.size2() * i + j;
matrix<double> b (2,3);
for (unsigned i = 0; i < b.size1 (); ++ i)
for (unsigned j = 0; j < b.size2 (); ++ j)
b (i, j) = b.size2() * i + j + 20;
cout << "matrix a : " << a << endl;
cout << "matrix b : " << b << endl;
// replace row 0 in a with row 0 in b
// replace row 2 in a with row 1 in b
unsigned rows[] = {0,2};
int length = sizeof(rows) / sizeof(rows[0]);
for(int i = 0; i < length; i++)
for(int j = 0; j < a.size2(); j++)
a(rows[i], j) = b(i, j);
cout << "matrix a : " << a << endl;
return 0;
}
However, I am not sure whether this is the best way to do it. Looking at the documentation I did not see a built in method for indexing, so it looks like looping is the only option, am I missing anything?
However, looping in C++ might not be that bad. Looping in python in python is slow, and my above example looping takes place at the C level. But looping is not slow in C++, and hence even if we have to manually loop, the code is still efficient is that correct?
Please let me know if my understanding is correct and/or I am missing a better way to implement the above.
Boost.MultiArray is better suited for this sort of indexing. Your Python example can be reproduced as follows:
// helper type for a 2d matrix of ints
using array_type = boost::multi_array<int, 2>;
array_type a(boost::extents[4][3]); // 4x3 matrix
array_type b(boost::extents[2][3]); // 2x3 matrix
Now fill these matrices
std::iota(a.data(), a.data() + a.num_elements(), 0);
std::iota(b.data(), b.data() + b.num_elements(), 20);
Then define a lambda function that'll print a 2d matrix, so we can see the contents
auto array_printer = [](array_type const& arr) {
for(auto const &row : arr) {
for(auto const& elem : row) {
std::cout << std::setw(2) << elem << ' ';
}
std::cout << '\n';
}
std::cout << '\n';
};
Let's print what we have so far
std::cout << "Before:\na =\n";
array_printer(a);
std::cout << "b =\n";
array_printer(b);
Output:
Before:
a =
0 1 2
3 4 5
6 7 8
9 10 11
b =
20 21 22
23 24 25
Time to create a 2d view of the array
using range_type = boost::multi_array_types::index_range;
using view_type = array_type::array_view<2>::type;
// Create a 2d view of a
// - the rows of the view consist of rows [0, 3) with a stride of 2
// - the columns of the view consist of all columns of a
view_type a_view = a[boost::indices[range_type(0,3,2)][range_type()]];
Now assign b to the view we created, and print the result
a_view = b;
std::cout << "After:\na =\n";
array_printer(a);
Output:
After:
a =
20 21 22
3 4 5
23 24 25
9 10 11
Live demo