Initialize an Eigen::MatrixXd from a 2d std::vector - c++

This should hopefully be pretty simple but i cannot find a way to do it in the Eigen documentation.
Say i have a 2D vector, ie
std::vector<std::vector<double> > data
Assume it is filled with 10 x 4 data set.
How can I use this data to fill out an Eigen::MatrixXd mat.
The obvious way is to use a for loop like this:
#Pseudo code
Eigen::MatrixXd mat(10, 4);
for i : 1 -> 10
mat(i, 0) = data[i][0];
mat(i, 1) = data[i][1];
...
end
But there should be a better way that is native to Eigen?

Sure thing. You can't do the entire matrix at once, because vector<vector> stores single rows in contiguous memory, but successive rows may not be contiguous. But you don't need to assign all elements of a row:
std::vector<std::vector<double> > data;
MatrixXd mat(10, 4);
for (int i = 0; i < 10; i++)
mat.row(i) = VectorXd::Map(&data[i][0],data[i].size());

Related

Permute Columns of Matrix in Eigen

I read this answer Randomly permute rows/columns of a matrix with eigen
But they initialize the permutation matrix as the identity matrix and do a random shuffle. I'm wondering how I can initialize the matrix to a specific permutation.
For example, if I have a vector of integers where each (index, value) pair means I want to move column "index" to column "value" how can I do this?
Eigen::MatrixXi M = Eigen::MatrixXi::Random(3,3);
std::vector<int> my_perm = {1,2,0};
some_function to return Matrix [M.col(1), M.col(2), M.col(0)]
EDIT: dtell kindly answered my original question below.
ADDITIONAL INFO:
For anyone else looking at this -- if you want to permute a matrix with a vector of unknown (at compile time) quanties, you can do the following:
Eigen::VectorXi indices(A.cols());
for(long i = 0; i < indices.size(); ++i) {
indices[i] = vector_of_indices[i];
}
Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic> perm;
perm.indices() = indices;
Eigen::MatrixXd A_permute = A * perm; \\ permute the columns
If I understand you correctly, the answer to your question is this slight modification of the answer you have linked
Matrix3i A = Matrix3i::Random();
PermutationMatrix<3, 3> perm;
// Your permutation
perm.indices() = { 1, 2, 0 };
// Permutate rows
A = perm * A;

How could I subtract a 1xN eigen matrix from a MxN matrix, like numpy does?

I could not summarize a 1xN matrix from a MxN matrix like I do in numpy.
I create a matrix of np.arange(9).reshape(3,3) with eigen like this:
int buf[9];
for (int i{0}; i < 9; ++i) {
buf[i] = i;
}
m = Map<MatrixXi>(buf, 3,3);
Then I compute mean along row direction:
m2 = m.rowwise().mean();
I would like to broadcast m2 to 3x3 matrix, and subtract it from m, how could I do this?
There is no numpy-like broadcasting available in Eigen, what you can do is reuse the same pattern that you used:
m.colwise() -= m2
(See Eigen tutorial on this)
N.B.: m2 needs to be a vector, not a matrix. Also the more fixed the dimensions, the better the compiler can generate efficient code.
You need to use appropriate types for your values, MatrixXi lacks the vector operations (such as broadcasting). You also seem to have the bad habit of declaring your variables well before you initialise them. Don't.
This should work
std::array<int, 9> buf;
std::iota(buf.begin(), buf.end(), 0);
auto m = Map<Matrix3i>(buf.data());
auto v = m.rowwise().mean();
auto result = m.colwise() - v;
While the .colwise() method already suggested should be preferred in this case, it is actually also possible to broadcast a vector to multiple columns using the replicate method.
m -= m2.replicate<1,3>();
// or
m -= m2.rowwise().replicate<3>();
If 3 is not known at compile time, you can write
m -= m2.rowwise().replicate(m.cols());

Eigen::Vector; Initialize Vector with Values of Eigen::Matrix3f in a function, bigger than 4 entries

im interested in building up a 1x6 Vector, which i want to concatenate with another 1x6 Vector to a 2x6 Matrix. I know it will be a Row Vector, so therefore i thought about initializing a Eigen::RowVectorXf vec, but maybe a simple Eigen::VectorXf would be enough, idk.
(Further on, this should be concatenated to an even bigger 2Nx6 Matrix, for SVD-Operations)
My Input is a 3x3 Matrix of type Eigen::Matrix3f Mat
I thought of using a function, because i have in total ~20 (number isn't that important) input matrices, for each i do have to build 2 vectors, in this manner ( Yep, this will be a 40x6 Matrix in the end):
Question:
How do i initialize vec with entries of mat, especially if its not only the entries, but the products of entries, or sums of products of entries.
Example:
// Inputvalue Mat, which i have
Eigen::Matrix<float, 3, 3> mat = [ 1 2 3; 4 5 6; 7 8 9];
// Outputvalue vec, which i need
Eigen::RowVectorXf = ( mat(0,0)*mat(1,1), mat(1,2)*mat(2,1)+mat(1,0)*mat(0,1), .... );
My inputs of mat(col,row) are arbitrary, but i have a pattern for col,row, which i want to test, and therefore i want to build up those vectors. I've already done it in MATLAB, but im interested in doing it with Eigen in C++.
RowVectorXf build_Vec(Eigen::Matrix3f Mat)
{
Eigen::RowVectorCf vec = ( ..., ..., ..., ..., ..., ...;);
return vec;
}
Anyone some hints for me?
Thanks in advance
For dynamically filling a big matrix at runtime you can't use the CommaInitializer (without abusing it). Just allocate a matrix large enough and set individual blocks:
Matrix<float, Dynamic, 6> Vges(2*views, 6);
for(int i=0; i<views; ++i) {
Matrix<float, 2, 6> foo;
foo << 1,2,3,4,5,6,7,8,9,10,11,12; // or combine from two Matrix<float, 1, 6>
Vges.middleRows<2>(2*i) = foo;
}
You may also consider computing Vges.transpose() * Vges on-the-fly (i.e., by accumulating foo.transpose()*foo into a 6x6 matrix and do a SelfAdjointEigendecomposition instead of a SVD (perhaps use double instead of single precision then).
Eigen::Matrix<double, 6, 6> VtV; VtV.setZero();
for(int i=0; i<views; ++i) {
foo = ...;
VtV.selfadjointView<Upper>().rankUpdate(foo);
}

Eigen SparseMatrix - set row values

I write a simulation with Eigen and now I need to set a list of rows of my ColumnMajor SparseMatrix like this:
In row n:
for column elements m:
if m == n set value to one
else set value to zero
There is always the element with column index = row index inside the sparse matrix. I tried to use the InnerIterator but it did not work well since I have a ColumnMajor matrix. The prune method that was suggested in https://stackoverflow.com/a/21006998/3787689 worked but i just need to set the non-diagonal elements to zero temporarily and prune seems to actually delete them which slows a different part of the program down.
How should I proceed in this case?
Thanks in advance!
EDIT: I forgot to make clear: the sparse matrix is already filled with values.
Use triplets for effective insertion:
const int N = 5;
const int M = 10;
Eigen::SparseMatrix<double> myMatrix(N,M); // N by M matrix with no coefficient, hence this is the null matrix
std::vector<Eigen::Triplet<double>> triplets;
for (int i=0; i<N; ++i) {
triplets.push_back({i,i,1.});
}
myMatrix.setFromTriplets(triplets.begin(), triplets.end());
I solved it like this: Since I want to stick to a ColumnMajor matrix I do a local RowMajor version and use the InnerIterator to assign the values to the specific rows. After that I overwrite my matrix with the result.
Eigen::SparseMatrix<float, Eigen::RowMajor> rowMatrix;
rowMatrix = colMatrix;
for (uint i = 0; i < rowTable.size(); i++) {
int rowIndex = rowTable(i);
for (Eigen::SparseMatrix<float, Eigen::RowMajor>::InnerIterator
it(rowMatrix, rowIndex); it; ++it) {
if (it.row() == it.col())
it.valueRef() = 1.0f;
else
it.valueRef() = 0.0f;
}
}
colMatrix = rowMatrix;
For beginners, the simplest way set to zero a row/column/block is just to multiply it by 0.0.
So to patch an entire row in the way you desire it is enough to do:
A.row(n) *= 0; //Set entire row to 0
A.coeffRef(n,n) = 1; //Set diagonal to 1
This way you don't need to change your code depending of RowMajor/ColMajor orders. Eigen will do all the work in a quick way.
Also, if you are really interested in freeing memory after setting the row to 0, just add a A.prune(0,0) after you have finished editing all the rows in your matrix.

C++ Filling an 1D array to represent a n-dimensional object based on a straight line segment

READ FIRST: I have rewritten this question with the help of a friend to be hopefully more specific in what is required. It can be found here
I'm not very clear on n-cubes, but I believe they are what I am referring to as the square family.
New Question Wording:
Perhaps I wasn't clear enough. What I'm asking, is how to set a 1D array to hold data for a cloud of a number of evenly-spaced points that form the most complete representation of the space occupied by an n-cube of n dimensions.
In 1D this would simply fill the array with a series of 1D co-ordinates creating a line segment. A 1-cube.
In 2D however this would fill every first co-ordinate to the x value and the every second to the y, generating the most complete square possible for that spacing and number of particles. The most complete possible 2-cube.
In 3D, this would fill ever first with x, every second with y and every third with z, generating the most complete possible cube for that spacing and number of particles. The most complete possible 3-cube.
I wish to be able to do this for any reasonable combination of number of particles, spacing and dimensions. Ideally I could do at least up to a 4-cube using a generic fill algorithm for all n-cubes initialised to double * parts_
Yet another definition of what kind of object I'm trying to represent:
In 1D its a line. Sweep it through the second dimension it becomes a square. Sweep that square through the third, it becomes a cube. I presume this behaviour extends past three dimensions and wish to store a cloud of points representing the space taken up by one of these objects of any reasonable dimension, spacing and number of points in a 1D array.
The original wording of the question:
I'm struggling to find a good way to put this question but here goes. I'm making a system that uses a 1D array implemented as double * parts_ = new double[some_variable];. I want to use this to hold co-ordinates for a particle system that can run in various dimensions.
What I want to be able to do is write a generic fill algorithm for filling this in n-dimensions with a common increment in all direction to a variable size. Examples will serve best I think.
Consider the case where the number of particles stored by the array is 4
In 1D this produces 4 elements in the array because each particle only has one co-ordinate.
1D:
{0, 25, 50, 75};
In 2D this produces 8 elements in the array because each particle has two co-ordinates..
2D:
{0, 0, 0, 25, 25, 0, 25, 25}
In 3D this produces 12 elements in the array because each particle now has three co-ordinates
{0, 0, 0, 0, 0, 25, 0, 0, 50, ... }
These examples are still not quite accurate, but they hopefully will suffice.
The way I would do this normally for two dimensions:
int i = 0;
for(int x = 0; x < parts_size_ / dims_ / dims_ * 25; x += 25) {
for(int y = 0; y < parts_size_ / dims_ / dims_ * 25; y += 25) {
parts_[i] = x;
parts_[i+1] = y;
i+=2;
}
}
How can I implement this for n-dimensions where 25 can be any number?
The straight line part is because it seems to me logical that a line is a somewhat regular shape in 1D, as is a square in 2D, and a cube in 3D. It seems to me that it would follow that there would be similar shapes in this family that could be implemented for 4D and higher dimensions via a similar fill pattern. This is the shape I wish to set my array to represent.
EDIT: Apparently I'm trying to fill this array to represent the n-cube with the fewest missing elements for the given n, spacing and number of elements. If that makes my goal any clearer.
As I understand it, you aren't sure how to process every element in multi-dimensional array (stored as 1D array), where N is arbitrary number of dimensions.
Processing of multidimensional array with arbitrary number of dimensions goes like this:
#include <stdio.h>
#include <vector>
using std::vector;
int main(int argc, char** argv){
int index = 0;
const int numDimensions = 10;
vector<int> counters;
vector<int> dimensionSizes;
counters.resize(numDimensions);
dimensionSizes.resize(numDimensions);
for (int i = 0; i < numDimensions; i++){
counters[i] = 0;
dimensionSizes[i] = 13;
}
long long arraySize = 1;
for (int i = 0; i < numDimensions; i++)
arraySize *= dimensionSizes[i];
printf("%d\n", arraySize);
for (int elementIndex = 0; elementIndex < arraySize; elementIndex++){
fprintf(stderr, "element %08d: ", elementIndex);
for (int i = 0; i < numDimensions; i++)
fprintf(stderr, "%04d ", counters[i]);
fprintf(stderr, "\n");
//at this point you have 1D element index
//AND all n-dimensional coordinates stored in counters array.
//Just use them to for your data
//"counters" is N-dimensional coord. XYZW etc.
for (int i = 0; i < numDimensions; i++){
counters[i] = counters[i] + 1;
if (counters[i] < dimensionSizes[i])
break;
else
counters[i] = 0;
}
}
return 0;
}
Just make an array of structs you need to access in N dimensions, and access them using calculated index somewhere after comment. It is better to use array of structs representing the data you want to be stored in N dimensionals. If you don't want to do that, you'll have to multiply elementIndex by number of doubles per element.