Registered Member
|
Hi all,
is there a performant way in Eigen to perform the following Matlab operation:
What the command does is: Looking for matrix entries that satisfy a certain condition (>40 in this case) and replacing all those entries by their median value leaving the other matrix entries untouched. There will be a chain of operations (e.g., >10, >20, >30, ...) performed. Unlike this example, the sets that fulfil the conditions are usually disjoint and every matrix element belongs to one of the sets. How are manipulations like this done best in Eigen? Best regards vernal |
Registered Member
|
Didn't I make myself clear?
Is it possible to do this line
efficiently with Eigen? |
Moderator
|
In Eigen we don't have any median operator, and can only do things like:
Array a; a = (a>40).select(value,a); to mimic a(a>40) = ...; Regarding your specific use case, I would recommend you to sort all your entries into a vector of pair of value,index (e.g., std::pair<scalar,int>), where the index is the index of the respective coefficient in the original vector a. Then your chain of operation is a O(n) process! |
Registered Member
|
Thank you! I didn't look here for a while. I have to try the select feature of Eigen. Sounds like what I need here.
That's an interesting idea. If I understand correctly you mean sorting with bucketsort in O(n). And then perform an operation (e. g., Median) on the buckets. Is that correct? |
Registered Member
|
It's only now that I come to test the suggestion.
The expression in your example works but if I'm doing it a bit differently I can't assign the result of (myEigenArray < somevalue) to another array to save that "binary mask" for later re-use. I read in the docs that the return type of the expression is a CwiseBinaryOp but I know too little of the inner Eigen workings to figure out how I can save that into an array. Cheers vernal |
Moderator
|
you can store it in a boolean matrix:
Matrix<bool,Dynamic,Dynamic> foo = a>40; or convert it to int MatrixXi foo = (a>40).cast<int>() You could also store it as an expression which would simply be an alias for (a>40), but then writing the type is quite painful unless you are ok to use a C++1x feature: auto foo = a>40; The auto keyword is supported by recent versions of GCC and MSVC. |
Registered Member
|
How would you use that matrix to index the original matrix afterward? Can you do something like this?
|
Registered Member
|
Hi, are there any changes w.r.t. this feature? Right now the above seems to be failing (using Eigen 3.0.0), but perhaps I'm doing it wrong. I'm currently trying to "clean" some data, where by "cleaning" I mean keeping selected rows based on a defined criterion (storing the columns of a big "dirty" ArrayXXd into a bunch of clean VectorXd's). Here's how I currently do it (just a workaround):
I would love to get this shorter and more optimized, if possible. I'd rather do it this way (much more elegant and concise than manual resizing with a hand-crafted for-loop):
However, then compilation fails: WARNING!
error C2664: 'const double &Eigen::DenseCoeffsBase<Derived,Level>::operator ()(__w64 int) const' : cannot convert parameter 1 from 'Eigen::CwiseBinaryOp<BinaryOp,Lhs,Rhs>' to '__w64 int' with [ Derived=Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>, Level=0 ] and [ BinaryOp=Eigen::internal::scalar_product_op<bool,bool>, Lhs=const Eigen::CwiseBinaryOp<Eigen::internal::scalar_product_op<bool,bool>,const Eigen::CwiseUnaryOp<std::binder2nd<std::greater<double>>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>>,const Eigen::CwiseUnaryOp<std::binder2nd<std::greater<double>>,const Eigen::CwiseBinaryOp<Eigen::internal::scalar_quotient_op<double>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>>>>, Rhs=const Eigen::CwiseUnaryOp<std::binder2nd<std::less<double>>,const Eigen::CwiseBinaryOp<Eigen::internal::scalar_quotient_op<double>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>>> ] No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called In addition, when applying the above-mentioned workaround, compiler treats me with the following performance warning (pointing exactly at the line where I "multiply" the boolean subexpressions in order to simulate the AND operator -- that is the location marked below as "***filename.cpp(123)***"): WARNING!
>c:\eigen\eigen\src/Core/Functors.h(67): warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) c:\eigen\eigen\src/Core/Functors.h(67) : while compiling class template member function 'const bool Eigen::internal::scalar_product_op<LhsScalar,RhsScalar>::operator ()(const LhsScalar &,const RhsScalar &) const' with [ LhsScalar=bool, RhsScalar=bool ] c:\eigen\eigen\src/Core/util/Meta.h(161) : see reference to class template instantiation 'Eigen::internal::scalar_product_op<LhsScalar,RhsScalar>' being compiled with [ LhsScalar=bool, RhsScalar=bool ] c:\eigen\eigen\src/Core/CwiseBinaryOp.h(71) : see reference to class template instantiation 'Eigen::internal::result_of<T>' being compiled with [ T=Eigen::internal::scalar_product_op<bool,bool> (bool,bool) ] c:\eigen\eigen\src/Core/CwiseBinaryOp.h(177) : see reference to class template instantiation 'Eigen::internal::traits<T>' being compiled with [ T=Eigen::CwiseBinaryOp<Eigen::internal::scalar_product_op<bool,bool>,const Eigen::CwiseUnaryOp<std::binder2nd<std::greater<double>>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>>,const Eigen::CwiseUnaryOp<std::binder2nd<std::greater<double>>,const Eigen::CwiseBinaryOp<Eigen::internal::scalar_quotient_op<double>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>>>> ] c:\eigen\eigen\src/Core/CwiseBinaryOp.h(124) : see reference to class template instantiation 'Eigen::CwiseBinaryOpImpl<BinaryOp,Lhs,Rhs,StorageKind>' being compiled with [ BinaryOp=Eigen::internal::scalar_product_op<bool,bool>, Lhs=const Eigen::CwiseUnaryOp<std::binder2nd<std::greater<double>>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>>, Rhs=const Eigen::CwiseUnaryOp<std::binder2nd<std::greater<double>>,const Eigen::CwiseBinaryOp<Eigen::internal::scalar_quotient_op<double>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>>>, StorageKind=Eigen::Dense ] ***filename.cpp(123)*** : see reference to class template instantiation 'Eigen::CwiseBinaryOp<BinaryOp,Lhs,Rhs>' being compiled with [ BinaryOp=Eigen::internal::scalar_product_op<bool,bool>, Lhs=const Eigen::CwiseUnaryOp<std::binder2nd<std::greater<double>>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>>, Rhs=const Eigen::CwiseUnaryOp<std::binder2nd<std::greater<double>>,const Eigen::CwiseBinaryOp<Eigen::internal::scalar_quotient_op<double>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>,const Eigen::Block<Eigen::Array<double,-1,-1>,-1,1,true>>> ] So, even if the current workaround is the way to do this, I'm worried about the long warning (and performance). Any advice/suggestions/comments/help? |
Moderator
|
Hi, nope this feature has not been implemented yet. Regarding, the use of operator* on bool, we should implement proper boolean operators && and ||. This later is very easy to do and patch welcome.
If you don't want us to forget about these features, you can fill bug reports in our bugzilla: http://eigen.tuxfamily.org/bz/ |
Registered Member
|
OK, just need a classification clarification:
1. &&, || bool operators -- does this belong in core-expression templates or core-general? 2. Element selection based on bool expressions -- core-expression templates? |
Moderator
|
Don't worry, that's not very important.I saw you already filled an entry for, 1, and for 2 yes core-expression sounds fine.
|
Registered Member
|
Hi!
I just stumbled upon this thread. Is the use of bool for indexing like described in the above already possible? Like mattd is saying, it would give much more elegant lines for the code that I am writing! Cheers |
Registered users: bartoloni, Bing [Bot], Google [Bot], Yahoo [Bot]