Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sort eigen vectorXf in ascending order

Tags:

c++

eigen

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?

like image 987
user189035 Avatar asked Feb 17 '14 17:02

user189035


2 Answers

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

like image 67
Xarn Avatar answered Nov 21 '22 00:11

Xarn


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

like image 29
GPrathap Avatar answered Nov 21 '22 01:11

GPrathap