Welcome to the KDE Community Forums, the official forum board for KDE.
You are currently viewing the forums as an unregistered user. Registration allows you to post and discuss topics, receive private messages, vote on ideas, subscribe to topics and many such great features. Registration is a simple process and completely free. So register now and be a part of the community!

blitz++ or matlab find()



n2k

Registered Member

Posts: 13

Karma: 0

blitz++ or matlab find()

Post Mon Aug 24, 2009 9:52 pm

Hi there,

I was wondering if there is a quick way to reproduce the Matlab/blitz++ function find() for vectors and matrixes. I wrote my own function but it looks a bit cumbersome. Any help is appreciated.

Btw, Eigen is by far the best library I've ever used, thank you!

Code: Select all
#include <Eigen/Core>
#include <Eigen/Array>

void find(Eigen::MatrixXi A, Eigen::MatrixXi & F){
   F.resize(A.sum(),2);
   int k=0;
   for (int r=0; r<A.rows();++r){
   for (int c=0; c<A.cols();++c){
      if (A(r,c)==1){
         F.row(k)<<r,c;
         k+=1;
      }
   }}
}

int main (){

   
   Eigen::MatrixXd A;
   Eigen::MatrixXi F;
   A.setRandom(4,4);
   find((A.cwise()>0.5).cast<int>(),F);
   std::cout<< "A="<<std::endl<<A<<std::endl;
   std::cout<< "F="<<std::endl<<F<<std::endl;
}

Moderator User avatar

ggael

Moderator

Posts: 205

Karma: 0

Gender:  Male

France

Re: blitz++ or matlab find()

Post Tue Aug 25, 2009 7:51 am

hi,

I guess this function could fit in the Array module, find() being a member function of MatrixBase returning the coordinates, so that you would write:

F = (A.cwise()>0.5).find();

Note that you can already do that using EIGEN_MATRIXBASE_PLUGIN (see http://eigen.tuxfamily.org/api/Customiz ... MatrixBase).

At the same time this will remove the creation of an unnecessary temporary.

Also it should return a Matrix<int,Dynamic,2> instead of a MatrixXi. If we include it in Eigen this way we'll add a convenient:

typedef Matrix<int,Dynamic,2> MatricX2i;

Another problem is that the boolean matrix is evaluated twice, so 2 options:
- you return a std::vector<Vector2i> instead of a MatrixX2i and use std::vector::push(),
- you wait we add a conservativeResize() function in Matrix which will preserve the data while resizing.

Another option would be to allocate a big MatrixX2i of the same size than the input and return a VectorBlock expression of the meaningful part, but unfortunately this cannot be done easily because we cannot return an expression of a temporary object.
ggael, proud to be a member of KDE forums since 2008-Dec.



n2k

Registered Member

Posts: 13

Karma: 0

Re: blitz++ or matlab find()

Post Thu Oct 22, 2009 8:12 pm

Hi, I'm trying to use my find() functionality with EIGEN_MATRIXBASE_PLUGIN but I'm having a problem. The problem is with "cast" and, I suppose, M being template (?). I'm aware of the following topics:
viewtopic.php?f=74&t=62606&hilit=cast
viewtopic.php?f=74&t=57882&hilit=cast
but I think that doesn't apply to my case. I tried using the template keyword in many combinations but still receive ...

Code: Select all
expected primary-expression before 'int'

expected `)' before 'int'

expected `)' before ';' token

... at the "F.resize( (M.cast<int>()).sum() );" line. Can anybody please tell me what I'm doing wrong? The following is the function-form of the implementation that is giving me troubles.


Code: Select all

namespace Eigen {
   typedef Eigen::Matrix<int,Eigen::Dynamic,2> MatrixX2i;
}

   template<typename Derived>
   void find(const Eigen::MatrixBase<Derived>& M, Eigen::MatrixX2i & F){      
      F.resize( (M.cast<int>()).sum() ,2);
      int k=0;
      for (int r=0; r<M.rows();++r){
         for (int c=0; c<M.cols();++c){
            if (M(r,c)==true){
               F.row(k)<<r,c;
               k+=1;}}}
      
   }

Last edited by n2k on Thu Oct 22, 2009 8:20 pm, edited 1 time in total.

Moderator User avatar

bjacob

Moderator

Posts: 293

Karma: 0

France

Re: blitz++ or matlab find()

Post Thu Oct 22, 2009 8:20 pm

Have you tried:
Code: Select all
F.resize( (M.template cast<int>()).sum() )
Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!



n2k

Registered Member

Posts: 13

Karma: 0

Re: blitz++ or matlab find()

Post Thu Oct 22, 2009 8:27 pm

Well... I thought I did, but apparently I didn't :)
Now it's working, thank you!

Btw, the correct line is:
F.resize( (M.template cast<int>()).sum(), 2 );
otherwise the compiler says:
YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX' is not a member of 'Eigen::ei_static_assert<false>'

Can the "2" in M.resize(*,2) be understood from the definition of MatrixX2i?

Moderator User avatar

bjacob

Moderator

Posts: 293

Karma: 0

France

Re: blitz++ or matlab find()

Post Thu Oct 22, 2009 8:29 pm

Can the "2" in M.resize(*,2) be understood from the definition of MatrixX2i?


Ah, with the development branch you can do:

resize(newsize, NoChange);

not sure about the 2.0 branch.
Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!


Who is online

Users browsing this forum: No registered users and 4 guests