How to access multiple elements in c++ Eigen array? - c++

I want to retrieve certain elements in an Eigen array and return them as a vector. I use the following code:
Eigen::ArrayXXi test;
test.resize(5,5);
test.setRandom();
Eigen::Matrix<int, 2, 3> inds;
inds<<0, 2, 3, 2, 3, 1;
auto res = test(inds.row(0), inds.row(1));
std::cout<<"test: \n"<<test <<std::endl;
std::cout<<"inds: \n"<<inds <<std::endl;
std::cout<<"res: \n"<<res <<std::endl;
The output is:
test:
730547559 -649503489 -48539462 893772102 -1038736613
-226810938 -353856438 276748203 291438716 -552146456
607950953 576018668 -290373134 466641602 -779039257
640895091 -477225175 28778235 -769652652 653214605
884005969 115899597 971155939 229713912 -737276042
inds:
0 2 3
2 3 1
res:
-48539462 893772102 -649503489
-290373134 466641602 576018668
28778235 -769652652 -477225175
The result is a matrix. I note that the diagonal of the matrix is the result I want. I could use res.diagonal() to retrieve the vector. However, I am still wondering if I can do the same thing in a more efficient way.

You can reshape the test Array to a column and then use the single-index access operator:
auto res = test.reshaped()(inds.row(0) + test.rows() * inds.row(1));
Generally, be careful when using auto with Eigen expressions (this case is fine, as long as test and inds are still valid when res is used).

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).

Map Eigen replicate Matrix

I am trying to bring code from Matlab to C++. There is some information related to my case in the KDE Eigen Forums.
What I try to achieve is related to Matlab's meshgrid, for which the solution given over there is
X = RowVectorXd::LinSpaced(1,3,3).replicate(5,1);
Y = VectorXd::LinSpaced(10,14,5).replicate(1,3);
i.e., .replicate the vectors the amount of the other dimension. In my case I have two existing (n x 1) vectors and want to create a (n^2, 2) matrix which contains all combinations of vector elements, that is:
[1 3 6]^T and [7 8]^T ==> [1 7, 3 7, 6 7, 1 8, 3 8, 6 8]^T
where ^T just means transposed, lines are comma-separated. (In my case the vectors use floats, but that shouldn't matter).
The first column of the matrix [1 3 6 1 3 6]^T is easily created by Eigen's .replicate function. However, I struggle to create the second column [7 7 7 8 8 8]^T.
My idea was to use .replicate in the other dimension (obtaining a matrix) and then use a rowWise Eigen::Map to bring it to a linear (vector) view (as suggested in the docs), but I understand the arising compiler error such that Eigen::Map doesn't work with an Eigen::Replicate type.
#include <Eigen/Core>
using namespace Eigen;
int main()
{
MatrixXd reptest1(1, 5);
reptest1 << 1, 2, 3, 4, 5;
auto result2 = reptest1.replicate(2, 1); // cols, rows: 5, 2
auto result3 = Map<Matrix<double, 1, Dynamic, Eigen::RowMajor> >(result2); // this doesn't work
return 0;
}
VS2017 complains: error C2440: '<function-style-cast>': cannot convert from 'Eigen::Replicate<Derived,-1,-1>' to 'Eigen::Map<Eigen::Matrix<double,1,-1,1,1,-1>,0,Eigen::Stride<0,0>>'
GCC also complains. no matching function for call (can't copy&paste exact message as it is on another machine).
Am I doing this too complicated? Should using Map work?
Map can only work on matrices, not on expressions. So replace auto result2 by MatrixXd result2, and you're done. See common pitfalls.

Determine all square sub matrices of a given NxN matrix in C++

GIven an NxN square matrix, I would like to determine all possible square sub matrices by removing equal number of rows and columns.
In order to determine all possible 2x2 matrices I need to loop 4 times. Similarly for 3x3 matrices I need to loop 6 times and so on. Is there a way to generate code in C++ so that the code for the loops is generated dynamically? I have checked some answers related to code generation in C++, but most of them use python in it. I have no idea regarding python. So, is it possible to write code to generate code in C++?
If I get what you are saying, you mean you require M loops to choose M rows, and M loops for M columns for an M x M sub matrix, 1 <= M <= N
You don't need 2*M loops to do this. No need to dynamically generate code with an ever-increasing number of loops!
Essentially, you need to "combine" all possible combinations of i_{1}, i_{2}, ..., i_{M} and j_{1}, j_{2}, ..., j_{M} such that 1 <= i_{1} < i_{2} < ... < i_{M} <= N (and similarly for j)
If you have all possible combinations of all such i_{1}, ..., i_{M} you are essentially done.
Say for example you are working with a 10 x 10 matrix and you require 4 x 4 sub matrices.
Suppose you selected rows {1, 2, 3, 4} and columns {1, 2, 3, 4} initially. Next select column {1, 2, 3, 5}. Next {1, 2, 3, 6} and so on till {1, 2, 3, 10}. Next select {1, 2, 4, 5}, next {1, 2, 4, 6} and so on till you reach {7, 8, 9, 10}. This is one way you could generate all ("10 choose 4") combinations in a sequence.
Go ahead, write a function that generates this sequence and you are done. It can take as input M, N, current combination (as an array of M values) and return the next combination.
You need to call this sequence to select the next row and the next column.
I have put this a little loosely. If something is not clear I can edit to update my answer.
Edit:
I will be assuming loop index starts from 0 (the C++ way!). To elaborate the algorithm further, given one combination as input the next combination can be generated by treating the combination as a "counter" of sorts (except that no digit repeats).
Disclaimer : I have not run or tested the below snippet of code. But the idea is there for you to see. Also, I don't use C++ anymore. Bear with me for any mistakes.
// Requires M <= N as input, (N as in N x N matrix)
void nextCombination( int *currentCombination, int M, int N ) {
int *arr = currentCombination;
for( int i = M - 1; i >= 0; i-- ) {
if( arr[i] < N - M + i ) {
arr[i]++;
for( i = i + 1, i < M; i++ ) {
arr[i] = arr[i - 1] + 1;
}
break;
}
}
}
// Write code for Initialization: arr = [0, 1, 2, 3]
nextCombination( arr, 4, 10 );
// arr = [0, 1, 2, 4]
// You can check if the last combination has been reached by checking if arr[0] == N - M + 1. Please incorporate that into the function if you wish.
Edit:
Actually I want to check singularity of all possible sub matrices. My approach is to compute all submatrices and then find their determinants. How ever after computing the determinant of 2x2 matrices , I'll store them and use while computing determinants of 3x3 matrices. And so on. Can you suggest me a better approach. I have no space and time constraints. – vineel
A straight-forward approach using what you suggest is to index the determinants based on the the rows-columns combination that makes a sub matrix. At first store determinants for 1 x 1 sub matrices in a hash map (basically the entries themselves).
So the hash map would look like this for the 10 x 10 case
{
"0-0" : arr_{0, 0},
"0-1" : arr_{0, 1},
.
.
.
"1-0" : arr_{1, 0},
"1-1" : arr_{1, 1},
.
.
.
"9-9" : arr_{9, 9}
}
When M = 2, you can calculate determinant using the usual formula (the determinants for 1 x 1 sub matrices having been initialized) and then add to the hash map. The hash string for a 2 x 2 sub matrix would look something like 1:3-2:8 where the row indices in the original 10 x 10 matrix are 1,3 and the column indices are 2, 8. In general, for m x m sub matrix, the determinant can be determined by looking up all necessary (already) computed (m - 1) x (m - 1) determinants - this is a simple hash map lookup. Again, add the determinant to hash map once calculated.
Of course, you may need to slightly modify the nextCombination() function - it currently assumes row and column indices run from 0 to N - 1.
On another note, since all sub matrices are to be processed starting from 1 x 1, you don't need something like a nextCombination() function. Given a 2 x 2 matrix, you just need to select one more row and column to form a 3 x 3 matrix. So you need to select one row-index (that's not part of the row indices that make the 2 x 2 sub matrix) and similarly one column-index. But doing this for every 2 x 2 matrix will generate duplicate 3 x 3 matrices - you need to think of some way to eliminate duplicates. One way to avoid duplicates is by choosing only such row/column whose index is greater than the highest row/column index in the sub matrix.
Again I have loosely defined the idea. You can build upon it.

How to count unique integers in unordered_set?

A question that might appear trivial, but I am wondering if there's a way of obtaining the count of integers made unique after I transform an array containing repeated integers into an unordered_set. To be clear, I start with some array, turn into an unordered set, and suddenly, the unordered_set only contains unique integers, and I am simply after the repeat number of the integers in the unordered_set.
Is this possible at all? (something like unordered_set.count(index) ?)
A question that might appear trivial, but I am wondering if there's a way of obtaining the count of integers made unique after I transform an array containing repeated integers into an unordered_set.
If the container is contiguous, like an array, then I believe you can use ptrdiff_t to count them after doing some iterator math. I'm not sure about non-contiguous containers, though.
Since you start with an array:
Call unique on the array
unique returns iter.end()
Calculate ptrdiff_t count using iter.begin() and iter.end()
Remember that the calculation in step 3 needs to be adjusted for the sizeof and element.
But to paraphrase Beta, some containers lend themselves to this, and other do not. If you have an unordered set (or a map or a tree), then the information will not be readily available.
According to your answer to the user2357112's question I will write a solution.
So, let's assume that instead of unordered_set we will use a vector and our vector has values like this:
{1, 1, 1, 3, 4, 1, 1, 4, 4, 5, 5};
So, we want to get numbers (in different vector I think) of how many times particular value appears in the vector, right? And in this specific case result would be: 1 appears 5 times, 3 appears one time, 4 appears 3 times and 5 appears 2 times.
To get this done, one possible solution can be like this:
Get unique entries from source vector and store them in different vector, so this vector will contain: 1, 3, 4, 5
Iterate through whole unique vector and count these elements from source vector.
Print result
The code from point 1, can be like this:
template <typename Type>
vector<Type> unique_entries (vector<Type> vec) {
for (auto iter = vec.begin (); iter != vec.end (); ++iter) {
auto f = find_if (iter+1, vec.end (), [&] (const Type& val) {
return *iter == val;
});
if (f != vec.end ()) {
vec.erase (remove (iter+1, vec.end (), *iter), vec.end ());
}
}
return vec;
}
The code from point 2, can be like this:
template <typename Type>
struct Properties {
Type key;
long int count;
};
template <typename Type>
vector<Properties<Type>> get_properties (const vector<Type>& vec) {
vector<Properties<Type>> ret {};
auto unique_vec = unique_entries (vec);
for (const auto& uv : unique_vec) {
auto c = count (vec.begin (), vec.end (), uv); // (X)
ret.push_back ({uv, c});
}
return ret;
}
Of course we do not need Properties class to store key and count value, you can return just a vector of int (with count of elements), but as I said, it is one of the possible solutions. So, by using unique_entries we get a vector with unique entries ( :) ), then we can iterate through the whole vector vec (get_properties, using std::count marked as (X)), and push_back Properties object to the vector ret.
The code from point 3, can be like this:
template <typename Type>
void show (const vector<Properties<Type>>& vec) {
for (const auto& v : vec) {
cout << v.key << " " << v.count << endl;
}
}
// usage below
vector<int> vec {1, 1, 1, 3, 4, 1, 1, 4, 4, 5, 5};
auto properties = get_properties (vec);
show (properties);
And the result looks like this:
1 5
3 1
4 3
5 2
What is worth to note, this example has been written using templates to provide flexibility of choosing type of elements in the vector. If you want to store values of long, long long, short, etc, instead of int type, all you have to do is to change definition of source vector, for example:
vector<unsigned long long> vec2 {1, 3, 2, 3, 4, 4, 4, 4, 3, 3, 2, 3, 1, 7, 2, 2, 2, 1, 6, 5};
show (get_properties (vec2));
will produce:
1 3
3 5
2 5
4 4
7 1
6 1
5 1
which is desired result.
One more note, you can do this with vector of string as well.
vector<string> vec_str {"Thomas", "Rick", "Martin", "Martin", "Carol", "Thomas", "Martin", "Josh", "Jacob", "Jacob", "Rick"};
show (get_properties (vec_str));
And result is:
Thomas 2
Rick 2
Martin 3
Carol 1
Josh 1
Jacob 2
I assume you're trying to get a list of unique values AND the number of their occurences. If that's the case, then std::map provides the cleanest and simplest solution:
//Always prefer std::vector (or at least std::array) over raw arrays if you can
std::vector<int> myInts {2,2,7,8,3,7,2,3,46,7,2,1};
std::map<int, unsigned> uniqueValues;
//Get unique values and their count
for (int val : myInts)
++uniqueValues[val];
//Output:
for (const auto & val : uniqueValues)
std::cout << val.first << " occurs " << val.second << " times." << std::endl;
In this case it doesn't have to be std::unordered_set.

C++ Multiplying elements in a vector

I have been looking for a more optimal solution to the following and I cannot seem to find one.
Let's say I have a vector:
std::vector<double> vars = {1, 2, 3}
I want to perform 1 * 2 * 3 I know that I can do the following:
int multi = 1;
for(int i = 0; (i < vars.size()-1); i++)
{
multi *= vars[i];
}
But, is there a more "C++11" way to do this? I really wanted to do this using lambda and so that I can calculate the multiply (product) of the vector without having another function inside the class, I'd rather have it calculated inside the function.
Yes, as usual, there is an algorithm (though this one's in <numeric>), std::accumulate (live example):
using std::begin;
using std::end;
auto multi = std::accumulate(begin(vars), end(vars), 1, std::multiplies<double>());
std::multiplies is in <functional>, too. By default, std::accumulate uses std::plus, which adds two values given to operator(). std::multiplies is a functor that multiplies them instead.
In C++14, you can replace std::multiplies<double> with std::multiplies<>, whose operator() is templated and will figure out the type. Based on what I've seen with Eric Niebler's Ranges proposal, it could possibly later look like vars | accumulate(1, std::multiplies<>()), but take that with a grain of salt.
You can use a ranged based for loop like:
std::vector<double> vars = {1, 2, 3}
int multi = 1;
for (const auto& e: vars)
multi *= e;
Another way is using inclusive_scan (C++17 and above)
The advantage is you can get multiplies of first "N" elements in a vector.
Below is the code. Explanation in comments.
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>
int main()
{
//INPUT VECTOR
std::vector<int> data{ 3, 1, 4, 1, 5, 9, 2, 6 };
//OUTPUT VECTOR WITH MULTIPLIES
//FIRST ELEMENT - 3
//SECOND ELEMENT - 3 * 1
//THIRD ELEMENT - 3 * 1 * 4
//FOURTH ELEMENT - 3 * 1 * 4 * 1
// ..
// ..
//LAST ELEMENT - 3 * 1 * 4 * 1 * 5 * 9 * 2 * 6
std::vector<int> multiplies(data.size());
//Multiply all numbers in given vector.
inclusive_scan(data.begin(), data.end(),
multiplies.begin(),
std::multiplies<>{});
//PRODUCT OF FIRST 5 ELEMENTS.
std::cout << "Product of first 5 elements :: " << multiplies[4] << std::endl;
//PRODUCT OF ALL ELEMENTS
std::cout << "Product of all elements :: " << multiplies[data.size() - 1] << std::endl;
}
Also there is an overload where the execution policy can be specified.
Sequential execution or Parallel execution. Need to include "execution" header.
//MULTIPLY ALL NUMBERS IN VECTOR WITH PARALLEL EXECUTION.
inclusive_scan(std::execution::par,data.begin(), data.end(),
multiplies.begin(),
std::multiplies<>{});