How to extract a subvector (from Eigen :: Vector) from an index vector in Eigen?

Let's pretend that

Eigen :: VectorXd x; // {1,2,3,4,5,6,7,8}

and

Eigen :: VectorXd ind_vec; // {0,2,4,5}

Is there a simple way to extract ind_vec elements from x?

Something like: x.extract (ind_vec), returning {1, 3, 5, 6}

Thanks.

+5
source share
3 answers

Since the current answer was unsatisfactory for me, I was a bit googled looking and I found this tutorial in the Eigen documentation.

#include <Eigen/Dense> #include <iostream> using namespace std; int main() { Eigen::ArrayXf v(6); v << 1, 2, 3, 4, 5, 6; cout << "v.head(3) =" << endl << v.head(3) << endl << endl; cout << "v.tail<3>() = " << endl << v.tail<3>() << endl << endl; v.segment(1,4) *= 2; cout << "after 'v.segment(1,4) *= 2', v =" << endl << v << endl; } 

It will display:

 v.head(3) = 1 2 3 v.tail<3>() = 4 5 6 after 'v.segment(1,4) *= 2', v = 1 4 6 8 10 6 

I have not tested it with vectors, but I think this is also possible.

+7
source

It seems like it would be easy to write yourself if it were just for vectors:

 #include "Eigen/Core" template <typename T, typename T2> T extract(const T2& full, const T& ind) { int num_indices = ind.innerSize(); T target(num_indices); for (int i = 0; i < num_indices; i++) { target[i] = full[ind[i]]; } return target; } int main() { Eigen::VectorXd full(8); full << 1, 2, 3, 4, 5, 6, 7, 8; Eigen::Vector4d ind_vec(4); ind_vec << 0, 2, 4, 5; std::cout << "full:" << full<< std::endl; std::cout << "ind_vec:" << ind_vec<< std::endl; std::cout << "extracted" << extract(full,ind_vec) << std::endl; } 

This should work in most cases.

edit: for cases where your scalar index type is different from your source and target scalar types, the following will work (for all built-in Eigen types).

 template <typename T, typename T2> Eigen::Matrix<typename T2::Scalar,T::RowsAtCompileTime,T::ColsAtCompileTime,T::Options> extract2(const Eigen::DenseBase<T2>& full, const Eigen::DenseBase<T>& ind) { using target_t = Eigen::Matrix < T2::Scalar, T::RowsAtCompileTime, T::ColsAtCompileTime, T::Options > ; int num_indices = ind.innerSize(); target_t target(num_indices); for (int i = 0; i < num_indices; i++) { target[i] = full[ind[i]]; } return target; } 

(this differs from the other in that you can use the ints vector as indices and the doubling vector as the source and get the doubling vector returned instead of the ints vector, as extract() )

+4
source

In C ++ 11 (and above) do the following:

  ind_vec.unaryExpr(x); 

You can use unaryExpr(Functor) , since we take an index array and apply a functor to each element of the array. The result type will have the same dimensions as the index array. For a functor, we need an object with an operator:

  Scalar operator() (Index index) const { return x[index]; } 

As it happens, Eigen::Matrix already has such an operator. Here is a complete example:

 Eigen::VectorXd x(8); x << 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8; Eigen::Array4i ind_vec(0,2,4,5); // result has dimensions as ind_vec matrix/array, and scalar type from x Eigen::Array4d result = ind_vec.unaryExpr(x); std::cout << "result^T = " << result.transpose() << std::endl; // Output: // result^T = 1.1 3.3 5.5 6.6 

The only caveat is that this requires at least C ++ 11. The problem is that eigen relies on std::result_of internally to get the type of scalar result. Without this, you can get errors by indicating that a throw is required.

0
source

Source: https://habr.com/ru/post/1204289/


All Articles