MATLAB find() / Numpy nonzero idioms for Eigen

前端 未结 3 441
盖世英雄少女心
盖世英雄少女心 2021-02-06 16:36

Chances are this is a very stupid question but I spent a pretty absurd amount of time looking for it on the documentation, to no avail.

in MATLAB, the find() function gi

相关标签:
3条回答
  • 2021-02-06 17:08

    Not sure if this is part of your question, but to construct the appropriate element-wise inequality result you must first cast your matrices to arrays:

    MatrixXd A,B;
    ...
    Matrix<bool,Dynamic,Dynamic> C = A.array()<B.array();
    

    Now C is the same size as A and B and C(i,j) = A(i,j) < B(i,j).

    To find all of the indices (assuming column-major order) of the true entries, you can use this compact c++11 routine---as described by libigl's conversion table:

    VectorXi I = VectorXi::LinSpaced(C.size(),0,C.size()-1);
    I.conservativeResize(std::stable_partition(
      I.data(), I.data()+I.size(), [&C](int i){return C(i);})-I.data());
    

    Now I is C.nonZeros() long and contains indices of the true entries in C. These two lines essentially implement find.

    0 讨论(0)
  • 2021-02-06 17:12

    It is reasonable to expect Eigen to have a find() function. Unfortunately, Eigen doesn't have one, or even a less than operator for matrices. Fortunately, the problem isn't too difficult. Here is one solution to the problem. I am using vector to store the Column Major indices of elements > 0. You could use VectorXf if you prefer that. Use this on B - A (B-A > 0 is the same as evaluating B>A). I'm using the stl for_each() function.

    #include<algorithm>
    #include<vector>
    #include <Eigen/Dense>
    using namespace Eigen;
    using namespace std;
    
    class isGreater{
        public:
        vector<int>* GT;
        isGreater(vector<int> *g){GT = g;}
        void operator()(float i){static int it = 0; if(i>0)GT->push_back(it); it++;}
    };
    int main(int argc,char **argv){
        MatrixXf P = MatrixXf::Random(4,5);
        vector<int> GT;
        for_each(P.data(),P.data()+P.rows()*P.cols(),isGreater(&GT));
        cout<<P<<endl;
        for(int i=0;i<GT.size();++i)cout<<GT[i]<<" ";
        cout<<GT.size()<<endl;
        return 0;
    }
    
    0 讨论(0)
  • 2021-02-06 17:28

    This might work for you and others who check this out. In order to set elements of a matrix m based on the condition on another matrix A, you can use this notation:

    m = (A.array() != 0).select(1, m);
    

    This command replaces those elements in matrix m that have non-zero corresponding elements in A, with one.

    0 讨论(0)
提交回复
热议问题