Permute Columns of Matrix in Eigen - c++

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;

Related

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);
}

C++ Eigen Library: Mutliplying vector with elements from row vector

I am trying to obtain a matrix consisting of the product between a vector and respective elements from a row vector like this:
Eigen::Vector3f vec;
vec << 1,
2,
3;
Eigen::RowVectorXf val;
val.setLinSpaced(5, 1, 5); //val = [1,2,3,4,5]
//result should be
//1,2,3,4,5
//2,4,6,8,10
//3,6,9,12,15
After seeing this question, I have tried
val.array().colwise()*vec.array()
and
vec.array().rowwise()*val.array()
but they just don't work.
val is a 1xn vector.
You want a standard matrix product:
MatrixXf res = vec * val;

Eigen: random binary vector with t 1s

I want to compute K*es where K is an Eigen matrix (dimension pxp) and es is a px1 random binary vector with 1s.
For example if p=5 and t=2 a possible es is [1,0,1,0,0]' or [0,0,1,1,0]' and so on...
How do I easily generate es with Eigen?
I came up with even a better solution, which is a combination of std::vector, Egien::Map and std::shuffle.
std::vector<int> esv(p,0);
std::fill_n(esv.begin(),t,1);
Eigen::Map<Eigen::VectorXi> es (esv.data(), esv.size());
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(std::begin(esv), std::end(esv), g);
This solution is memory efficient (since Eigen::Map doesn't copy esv) and has the big advantage that if we want to permute es several times (like in this case), then we just need to repeat std::shuffle(std::begin(esv), std::end(esv), g);
Maybe I'm wrong, but this solution seems more elegant and efficient than the previous ones.
So you're using Eigen. I'm not sure what matrix type you're using, but I'll go off the class Eigen::MatrixXd.
What you need to do is:
Create a 1xp matrix that's all 0
Choose random spots to flip from 0 to 1 that are between 0-p, and make sure that spot is unique.
The following code should do the trick, although you could implement it other ways.
//Your p and t
int p = 5;
int t = 2;
//px1 matrix
MatrixXd es(1, p);
//Initialize the whole 1xp matrix
for (int i = 0; i < p; ++i)
es(1, i) = 0;
//Get a random position in the 1xp matrix from 0-p
for (int i = 0; i < t; ++i)
{
int randPos = rand() % p;
//If the position was already a 1 and not a 0, get a different random position
while (es(1, randPos) == 1)
randPos = rand() % p;
//Change the random position from a 0 to a 1
es(1, randPos) = 1;
}
When t is close to p, Ryan's method need to generate much more than t random numbers. To avoid this performance degrade, you could solve your original problem
find t different numbers from [0, p) that are uniformly distributed
by the following steps
generate t uniformly distributed random numbers idx[t] from [0, p-t+1)
sort these numbers idx[t]
idx[i]+i, i=0,...,t-1 are the result
The code:
VectorXi idx(t);
VectorXd es(p);
es.setConstant(0);
for(int i = 0; i < t; ++i) {
idx(i) = int(double(rand()) / RAND_MAX * (p-t+1));
}
std::sort(idx.data(), idx.data() + idx.size());
for(int i = 0; i < t; ++i) {
es(idx(i)+i) = 1.0;
}

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.

Initialize an Eigen::MatrixXd from a 2d std::vector

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());