Map two-dimensional array to Eigen::Matrix - c++

I can't figure out if and how it's possible to map a two-dimensional double array to an Eigen::Matrix.
Is it possible to map an array double d[][] which I receive as double** p to an Eigen::Matrix?
While one-dimensinal arrays work fine, I wasn't able to map p to Eigen::Map<Eigen::Matrix<double, n, n>>. Is that possible and how could it be done? The size n is not really constant, but I could accept a hard coded size.
I tried several versions, but none worked. I thought the following should work (assume the size n would be 4).
Eigen::Map<Eigen::Matrix<double, 4, 4>> p_OUTPUT(&p[0][0]);
The code compiles and runs, but only the elements of the first column and the first element of the second column map the correct values. Using p[0] as argument yields the same result.
Other versions I tried (for example without the &) did not compile.

For the sake of completeness, I found a solution. As mentioned here or here the storage in not contiguous memory is the problem.
The following solution worked for me.
Eigen::MatrixXd ConvertToEigenMatrix(std::vector<std::vector<double>> data)
{
Eigen::MatrixXd eMatrix(data.size(), data[0].size());
for (int i = 0; i < data.size(); ++i)
eMatrix.row(i) = Eigen::VectorXd::Map(&data[i][0], data[0].size());
return eMatrix;
}

The answer you gave yourself is kind of a clue: Eigen, by default, stores matrices in column-major format, meaning that elements from this matrix:
m(0,0) m(0,1) m(0,2)
m(1,0) m(1,1) m(1,2)
m(2,0) m(2,1) m(2,2)
Are stored in a big linear array as:
[m(0,0), m(1,0), m(2,0), m(0,1), m(1,1), m(2,1), m(0,2), m(1,2), m(2,2)]
Your data (judging from your answer) is in row-major format, which is why you're pulling out memory-contiguous rows from your array and assigning them into rows in your result. You can tell Map that your data is in RowMajor format, and it should read your data correctly:
Eigen::Map<Eigen::Matrix<double, 4, 4, Eigen::RowMajor>> p_OUTPUT(p);

Related

Writing data into Eigen::Matrix row

I would like to write the (row-major ordered) data into a row of an Eigen::Matrix. I found a way, but to me it looks inefficient. Is there a faster/more concise way?
// 24 x 16 D Matrix
Eigen::Matrix<double, JOINT_NUM, 16> Mat;
// 4 x 4 D Matrix, stored in row major order to paste data correctly
Eigen::Matrix<double, 4, 4, Eigen::RowMajor> row0_rowMajor = row0;
// copy data from row major Matrix into first row of Mat
Mat.row(0) = Eigen::Map<Eigen::RowVectorXd>(row0_rowMajor.data(), row0_rowMajor.size());
Thanks!
Edit:
Here is a minimal working example, you can compile it with g++ -I/usr/include/eigen3 file.cpp and run with ./a.out:
#include <Eigen/Core>
#include <iostream>
int main(int argc, const char* argv[]) {
// 24 x 16 D Matrix
Eigen::Matrix<double, 2, 16> Mat_rowMajor;
Eigen::Matrix<double, 2, 16> Mat;
Mat.setZero();
Mat_rowMajor.setZero();
Eigen::Matrix4d row0;
row0 << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15;
// 4 x 4 D Matrix, stored in row major order to paste data correctly
Eigen::Matrix<double, 4, 4, Eigen::RowMajor> row0_rowMajor = row0;
// copy data from row major Matrix into first row of Mat
Mat.row(0) = Eigen::Map<Eigen::RowVectorXd>(row0.data(), row0.size());
Mat_rowMajor.row(0) = Eigen::Map<Eigen::RowVectorXd>(row0_rowMajor.data(), row0_rowMajor.size());
std::cout << "row0:\n" << row0 << std::endl;
std::cout << "Matrix:\n" << Mat << std::endl;
std::cout << "Matrix Row-Major:\n" << Mat_rowMajor << std::endl;
return 1;
}
My aim is to get rid of the copying into the Eigen::Matrix<double, 4, 4, Eigen::RowMajor>, and work directly with row0, and remove the Eigen::Map... by just a simple copy if possible. It just makes the code much more readable, concise, and less prone to errors. Also, the copying is slow for larger matrices, which I'd like to avoid.
Eigen doesn't come with a vector-like view of a matrix, as far as I know. So the approach of using a Map is already pretty good. However, it is also very brittle.
Since your ultimate goal is to store into a row of a column-major matrix, vectorization is out of the question. That's why I don't think you can improve performance by doing something fancy. So you can go for something simple instead. Like this:
Eigen::Matrix<double, JOINT_NUM, 16> Mat;
const Eigen::Matrix4d row0 = ...;
auto out_row = Mat.row(0);
for(Eigen::Index i = 0; i < row0.rows(); ++i)
out_row.segment(i * row0.cols(), row0.cols()) = row0.row(i);
At least this makes it clear what is going on.
Side note: The reason why Eigen doesn't have a convenient view is likely that this keeps you stuck between a rock and a hard place when you want to support the general case:
Practically all methods should work on both block expressions and full matrices. In a block expression, the Map approach doesn't work because there is a gap between consecutive columns (in a column-major matrix).
So instead you would need a custom view type to translate indices. However, now you are translating from a 1D index to a 2D index, which requires a costly division on every access.
Other linear algebra packages like Numpy have the same issue. However, Numpy for example is more liberal in its memory allocations and would create a copy if it needs to. The only Eigen type that does copies if required, is Eigen::Ref and that comes with its own set of problems.
With Eigen 3.4 you can simply use the reshaped<>() mechanism:
Mat.row(0) = row0.reshaped<Eigen::RowMajor>();
Prior to Eigen 3.4, you can manually create a map (onto the data of Mat.row(0)), but you need to manually calculate some strides. E.g., if Mat is a column-major matrix, the index difference between two columns would be Mat.rows() (which would correspond to the "outer stride"), the difference between two rows would be 4*Mat.rows() (corresponding to the "inner stride"):
Eigen::Matrix4d::Map(Mat.row(0).data(), // address of first element
Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic> // stride object
(Mat.rows(), // column-stride/"outer stride"
4*Mat.rows()) // row-stride/"inner stride"
) = row0; // end of `Map()` and assignment of a 4x4 matrix `row0`
Alternatively, you could create a Map from a row-major 4x4 matrix, which would switch the meaning of inner and outer stride.
Overall, if you intend to store matrices in rows of Mat you should also consider making Mat itself row-major. In that case, each row of Mat would be stored in 16 consecutive bytes making the Map easier to create (and having memory locality is often advantageous anyway).

C++: storing a matrix in a 1D array

I am very new to C++, but I have the task of translating a section of C++ code into python.
Going through the file, I found this section of code, which confuses me:
int n_a=(e.g 10)
int n_b=n_a-1;
int l_b[2*n_b];
int l_c[3*n_b];
int l_d[4*n_b];
for (int i=0; i<n_b; i++){
for (int j=0; j<2; j++) l_b[i*2+j]=0;
for (int j=0; j<3; j++) l_c[i*3+j]=0;
for (int j=0; j<4; j++) l_d[i*4+j]=0;
I know that it creates 3 arrays, the length of each defined by the action on the n_b variable, and sets all the elements to zero, but I do not understand what exactly this matrix is supposed to look like, e.g. if written on paper.
A common way to store a matrix with R rows and C columns is to store all elements in a vector of size R * C. Then when you need element (i, j) you just index the vector with i*C + j. This is not the only way your "matrix" could be stored in memory, but it is a common one.
In this code there are 3 C arrays that declared and initialized with zeros. The l_b array seems to be storage for a n_a x 2 matrix, the l_c array for a n_a x 3 matrix and the l_d array for a n_a x 4 matrix.
Of course, this is only an impression since to be sure we would need to see how these arrays are used later.
As in the comments, if you are going to convert this to python then you should probably use numpy for the matrices. In fact, the numpy arrays will store the elements in memory exactly like indexing I mentioned (by default, but you can also choose an alternative way passing an extra argument). You could do the same of this C++ code in oython with just
import numpy as np
n_a = (e.g 10)
l_b = np.zeros(shape=(n_a, 2))
l_c = np.zeros(shape=(n_a, 3))
l_d = np.zeros(shape=(n_a, 4))
These variables in numpy are 2D arrays and you can index them as usual.
Ex:
l_d[2, 1] = 15.5
We can also have a nice syntax for working with vector, matrices and linear algebra in C++ by using one of the available libraries. One such library is armadillo. We can create the three previous matrices of zeros using armadillo as
#include <armadillo>
int main(int argc, char *argv[]) {
unsigned int n_a = 10;
// A 10 x 3 matrix of doubles with all elements being zero
// The 'arma::fill::zeros' argument is optional and without it the matrix
// elements will not be initialized
arma::mat l_b(n_a, 2, arma::fill::zeros);
arma::mat l_c(n_a, 3, arma::fill::zeros);
arma::mat l_d(n_a, 4, arma::fill::zeros);
// We use parenthesis for index, since "[]" can only receive one element in C/C++
l_b(2, 1) = 15.5;
// A nice function for printing, but it also works with operator<<
l_b.print("The 'l_b' matrix is");
return 0;
}
If you inspect armadillo types in gdb you will see that it has a mem atribute which is a pointer. This is in fact a C array for the internal elements of the matrix and when you index the matrix in armadillo it will translate the indexes into the proper index in this internal 1D array.
You can print the elements in this internal arry in gdb. For instance, print l_b.mem[0] will print the first element, print l_b.mem[1] will print the second element, and so one.

How to auto-generate and assign variables corresponding to elements in a matrix?

I am working on a binary linear program problem.
I am not really familiar with any computer language(just learned Java and C++ for a few months), but I may have to use computer anyway since the problem is quite complicated.
The first step is to declare variables m_ij for every entry in (at least 8 X 8) a matrix M.
Then I assign corresponding values of each element of a matrix to each of these variables.
The next is to generate other sets of variables, x_ij1, x_ij2, x_ij3, x_ij4, and x_ij5, whenever the value of m_ij is not 0.
The value of x_ijk variable is either 0 or 1, and I do not have to assign values for x_ijk variables.
Probably the simplest way to do it is to declare and assign a value to each variable, e.g.
int* m_11 = 5, int* m_12 = 2, int* m_13 = 0, ... int* m_1n = 1
int* m_21 = 3, int* m_12 = 1, int* m_13 = 2, ... int* m_2n = 3
and then pick variables, the value of which is not 0, and declare x_ij1 ~ x_ij5 accordingly.
But this might be too much work, especially since I am going to consider many different matrices for this problem.
Is there any way to do this automatically?
I know a little bit of Java and C++, and I am considering using lp_solve package in C++(to solve binary integer linear program problem), but I am willing to use any other language or program if I could do this easily.
I am sure there must be some way to do this(probably using loops, I guess?), and this is a very simple task, but I just don't know about it because I do not have much programming language.
One of my cohort wrote a program for generating a random matrix satisfying some condition we need, so if I could use that matrix as my input, it might be ideal, but just any way to do this would be okay as of now.
Say, if there is a way to do it with MS excel, like putting matrix entries to the cells in an excel file, and import it to C++ and automatically generate variables and assign values to them, then this would simplify the task by a great deal!
Matlab indeed seems very suitable for the task. Though the example offered by #Dr_Sam will indeed create the matrices on the fly, I would recommend you to initialize them before you assign the values. This way your code still ends up with the right variable if something with the same name already existed in the workspace and also your variable will always have the expected size.
Assuming you want to define a square 8x8 matrix:
m = zeros(8)
Now in general, if you want to initialize a three dimensional matrixh of size imax,jmax,kmax:
imax = 8;
jmax = 8;
kmax = 5;
x = zeros(imax,jmax,kmax);
Now assigning to or reading from these matrices is very easy, note that length and with of m have been chosen the same as the first dimensions of x:
m(3,4) = 4; %Assign a value
myvalue = m(3,4) %read the value
m(:,1) = 1:8 *Assign the values 1 through 8 to the first column
x(2,4,5) = 12; %Assign a single value to the three dimensional matrix
x(:,:,2) = m+1; Assign the entire matrix plus one to one of the planes in x.
In C++ you could use a std::vector of vectors, like
std::vector<std::vector<int>> matrix;
You don't need to use separate variables for the matrix values, why would you when you have the matrix?
I don't understand the reason you need to get all values where you evaluate true or false. Instead just put directly into a std::vector the coordinates where your condition evaluates to true:
std::vector<std::pair<int, int> true_values;
for (int i = 0; i < matrix.size(); i++)
{
for (int j = 0; j < matrix[i].size(); j++)
{
if (some_condition_for_this_matrix_value(matrix[i][j], i, j) == true)
true_values.emplace_back(std::make_pair(i, j));
}
}
Now you have a vector of all matrix coordinates where your condition is true.
If you really want to have both true and false values, you could use a std::unordered_map with a std::pair containing the matrix coordinates as key and bool as value:
// Create a type alias, as this type will be used multiple times
typedef std::map<std::pair<int, int>, bool> bool_map_type;
bool_map_type bool_map;
Insert into this map all values from the matrix, with the coordinates of the matrix as the key, and the map value as true or false depending on whatever condition you have.
To get a list of all entries from the bool_map you can remove any false entries with std::remove_if:
std::remove_if(bool_map.begin(), bool_map.end(),
[](const bool_map_type::value_type& value) {
return value.second == false;
};
Now you have a map containing only entries with their value as true. Iterate over this map to get the coordinates to the matrix
Of course, I may totally have misunderstood your problem, in which case you of course are free to disregard this answer. :)
I know both C++ and Matlab (not Python) and in your case, I would really go for Matlab because it's way easier to use when you start programming (but don't forget to come back to C++ when you will find the limitations to Matlab).
In Matlab, you can define matrices very easily: just type the name of the matrix and the index you want to set:
m(1,1) = 1
m(2,2) = 1
gives you a 2x2 identity matrix (indices start with 1 in Matlab and entries are 0 by default). You can also define 3d matrices the same way:
x(1,2,3) = 2
For the import from Excel, it is possible if you save your excel file in CSV format, you can use the function dlmread to read it in Matlab. You could also try later to implement your algorithm directly in Matlab.
Finally, if you want to solve your binary integer programm, there is already a built-in function in Matlab, called bintprog which can solve it for you.
Hope it helps!

Double buffer vs double array c++

I was asked to create a matrix with 5 rows and unknown column.
And my boss want me to use a 1 dimensional buffer. concatenated by 5 rows buffer.
I don't get what is that mean, can some one provide me a simple example please!
With array I can do
double[][] arr = new double[5][someNumber];
But he says then the size would be limited.
So I don't know what he means by using a DOUBLE buffer, I am not very good #C++
Thank you very much, an example would be nice!
For R rows and C columns declare double arr[R * C], and arr[i * C + j] is the element at cell [i, j].
This generalizes to arbitrary dimensions.
Flattening out an array like that can be a very useful optimization, especially when you use dynamic arrays such as std::vector, where you can get a single dynamic array rather than one for each row.
Sounds like you're saying
double *arr[5];
for(unsigned int x = 0; x < 5; ++x)
{
arr[x] = new double[someNumber];
}
Since, you know that you have 5 for sure, and an unknown part my assumption is this is how you're referring to it.

C++ Vectors Problem

well i have most probably an extremly stupid problem but could not figure it out and I m about to lose my sanity hope someone can help
vector<CvMat*> sample;
for(int x = 0; x < 29; x += 2)
{
for(int b = 0; b < 22; b += 2)
{
cvmSet(g, 0, b, cvmGet(NormalVector, 0, x + b));
cvmSet(g, 0, b + 1, cvmGet(NormalVector, 0, x + b + 1));
}
sample.push_back(g);
}
Well i m using OpenCv for some matrix calculations basiacllay what I m doing is I m creating some small matrices from a big matrix and putting them into a Vector called "sample" in here.First loop is just a counter based thing and second loop for creating the small matrices after the second loop i m putting them to the vector
But the problem is after these loops when i try to reach one of the matrices in the vector I always get the one that was put into the vector at last.
I use these methods to access the vector elements
sample[0];
sample.at(6);
For these two I get the same matrix that was added to the vector at the end .What is the thing I am doing wrong?
Since your sample vector is a list of pointers, you will need to make sure that you create a new instance of CvMat for each element that you add to the vector. Otherwise, it sounds like all your elements are pointing to the same thing (g).
If CvMat has a copy constructor, you may be able to fix it by doing this:
vector <CvMat> sample;
for(int x =0 ; x<29; x+=2) {
// ...
sample.push_back(*g);
}
This creates a vector of CvMat objects, and the push_back(*g) makes a copy of the matrix and pushes it on to the back of the vector.
vector < CvMat*> sample;
is a vector of pointers to CvMat, and you are continously pushing 'g' into it. You need to be creating new instances of CvMat and adding those to your vector, not adding 'g' to it every time.