I'm trying to sort an Eigen
VectorXf
x
in ascending order.
This sorts it in descending order:
std::sort(x.data(),x.data()+x.size());
and this doesn't work:
bool myfunction (int i,int j) { return (i<j); }
std::sort(x.data(),x.data()+x.size(),myfunction);
any ideas?
Preface
Since the original question turned out to be a misunderstanding, and the code in it is already the proper answer, I decided to write up and post a bit about using std::sort
in general.
std::sort
sorts range in ascending order defined by weak ordering of the elements. By default it uses <
operator defined on elements, but it can also take a function object or functor to provide the comparison. This functor needs to have properly overloaded function with signature of bool operator()(const T& lhs, const T& rhs) const
. An example of this follows:
struct FooSorter {
bool operator (const Foo& lhs, const Foo& rhs) const {
return lhs.ham_index < rhs.ham_index;
}
};
/* ... */
std::sort(begin(vec), end(vec), FooSorter());
This would sort the full range represented by vec, according to criteria defined in FooSorter
's operator()
.
Because writing custom functors for the simple things (sort in descending order, sort in ascending order) would quickly grow painful, STL provides many templated functors ready to use in functional header. The one relevant for sorting are:
std::equal_to
implementing x == y
std::not_equal_to
implementing x != y
std::greater
implementing x > y
std::less
implementing x < y
std::greater_equal
implementing x >= y
std::less_equal
implementing x <= y
All of these are templated and can be used for any type, that implements needed operators. Using these is easy:
std::sort(begin(vec), end(vec), std::greater<int>());
This would sort the range represented by vector in descending order.
But, since one of the biggest problems of STL algorithms was the pain of defining functors, C++11 brings a new trick: lambda functions. This lets you declare function object equivalent inline. Example follows:
std::sort(begin(vec), end(vec), [](int lhs, int rhs){return rhs > lhs});
This would also sort the range represented by vector in descending order, but we didn't have to explicitly declare a functor (or use already declared one). (This gets much better when implementing much more complex comparisons, or functors for different STL algorithms.)
If someone is looking for an answer, here how I did it. In this way, you can get eigenvalues and corresponding eigenvectors as well. Here covariance_matrix is the matrix in which eigenvalues and eigenvectors are to be solved.
std::vector<std::tuple<float, Eigen::VectorXf>> eigen_vectors_and_values;
Eigen::SelfAdjointEigenSolver<Eigen::MatrixXf> eigensolver(covariance_matrix);
if (eigensolver.info() != Eigen::Success) {
return;
}
Eigen::VectorXf eigen_values = eigensolver.eigenvalues();
Eigen::MatrixXf eigen_vectors = eigensolver.eigenvectors();
for(int i=0; i<eigen_values.size(); i++){
std::tuple<float, Eigen::VectorXf> vec_and_val(eigen_values[i], eigen_vectors.row(i));
eigen_vectors_and_values.push_back(vec_and_val);
}
std::sort(eigen_vectors_and_values.begin(), eigen_vectors_and_values.end(),
[&](const std::tuple<float, Eigen::VectorXf>& a, const std::tuple<float, Eigen::VectorXf>& b) -> bool{
return std::get<0>(a) < std::get<0>(b);
});
Note: Be careful when selecting which eigensolver is to be used. You may find here which one to be used: https://eigen.tuxfamily.org/dox/group__Eigenvalues__Module.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With