This forum has been archived. All content is frozen. Please use KDE Discuss instead.

[SOLVED] Arithmetic col/rowwise - broadcasting

Tags: None
(comma "," separated)
rschulz
Registered Member
Posts
1
Karma
0
Hi,

is it in Eigen possible to somehow do arithmetic operations on matrices with different shape as in Numpy (there called broadcasting)?

I would like to do
x-y
with x(3,8) and y(3,1) and would like Eigen to substract y for each row of x. So basicly a rowwise/colwise arithmetic opration.

BTW: Nice library!

Thanks
Roland

Last edited by ggael on Wed Jun 10, 2009 9:11 am, edited 1 time in total.
User avatar
bjacob
Registered Member
Posts
658
Karma
3
Fun coincidence, this is exactly the subject of one of the most recent threads,
question-on-cwiseb ... 47094.html
the answer is to use replicate() that is available in the development version (trunk). No good solution is available in 2.0.

i'm starting to wonder -- perhaps it's worth adding also operators +,-,+=,-= to PartialRedux, allowing m.rowwise()+v ....?


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
bjacob wrote:i'm starting to wonder -- perhaps it's worth adding also operators +,-,+=,-= to PartialRedux, allowing m.rowwise()+v ....?


yes this is something I wanted to do after implementing Replicate, but 1) I wanted to have some feedbacks on Replicate before using it more seriously, 2) lack of time !
User avatar
marton
Registered Member
Posts
10
Karma
0
OS
To have numpy-like broadcasting would be fantastic, indeed, as it enables to write operations such as A = A-mean(A) easily. (Btw, isn't mean missing from PartialRedux?)

However, wouldn't it be more logical to add it to .cwise() rather than row/colwise? In an example such as:
Code: Select all
A.cwise() *= w;

from the dimensions of w (1xN or Nx1) it should clear whether the operation is meant row- or columnwise.

In numpy, dimensions of length 1 are implicitly broadcast up to match, i.e., if A is 5x1x6 and B is 5x3x1, A+B is 5x3x6. With this semantics, an outer product (i.e., x*x^T) could be performed simply by writing
Code: Select all
MatrixXf P = u.cwise() * v.transpose();
User avatar
bjacob
Registered Member
Posts
658
Karma
3
Well, cwise means coefficient-wise, it wasn't intended as a generic prefix for all array operations, and I think that asking the user to write explicitly rowwise or colwise can actually make the code more explicit.


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
User avatar
marton
Registered Member
Posts
10
Karma
0
OS
Dear Benoit,

I see your point. Would with rowwise/colwise an outer product still be possible? Such as:
Code: Select all
A = u.rowwise() * v.transpose().colwise();
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
why would you need a special product for that ? simply do:
Code: Select all
A = u * v.transpose();
User avatar
marton
Registered Member
Posts
10
Karma
0
OS
OK, that was a bad example :) What about an outer sum:
Code: Select all
A = u.rowwise() + v.transpose().colwise();


I don't remember exactly what outer sums are used for, but A has always rank 2 with some special properties.
User avatar
bjacob
Registered Member
Posts
658
Karma
3
marton wrote:OK, that was a bad example :) What about an outer sum:
Code: Select all
A = u.rowwise() + v.transpose().colwise();


I don't remember exactly what outer sums are used for, but A has always rank 2 with some special properties.


With the proposed change (not yet implemented), if A is a matrix and v is a vector, so that v.transpose() is a row-vector, then you could just do

Code: Select all
A = u.rowwise() + v.transpose();


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
bjacob wrote:
marton wrote:OK, that was a bad example :) What about an outer sum:
Code: Select all
A = u.rowwise() + v.transpose().colwise();


I don't remember exactly what outer sums are used for, but A has always rank 2 with some special properties.


With the proposed change (not yet implemented), if A is a matrix and v is a vector, so that v.transpose() is a row-vector, then you could just do

Code: Select all
A = u.rowwise() + v.transpose();



This will work only if u is a matrix. If u is a column vector, then you either have to explicitly "replicate" one of the vector, or extend eigen to add a outerSum() function doing the proper calls to replicate.

If we want to handle that example more nicely we would have to add the notion of "automatic size" (via an enum like Dynamic) so that an expression could have no specific size. This would also allows to define size-less constants (Identity, Ones, Zero, etc.). However, this would require deep changes in Eigen, and I don't see any pertinent use cases for that, so it's not worth it.
User avatar
bjacob
Registered Member
Posts
658
Karma
3
ggael wrote:
bjacob wrote:
Code: Select all
A = u.rowwise() + v.transpose();



This will work only if u is a matrix. If u is a column vector, then you either have to explicitly "replicate" one of the vector, or extend eigen to add a outerSum() function doing the proper calls to replicate.


Ah right, i had misunderstood what he wanted -- i mixed up u and A.


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
equark
Registered Member
Posts
3
Karma
0
I mentioned this a month ago, but I think Stata's mata matrix language has a very elegant and consistent set of rules for what they they call colon operators. They are like elementwise operators, but allow other obviously conformable operations. They call it C-conformability. The help files gives lots of nice examples:

http://www.stata.com/help.cgi?m2_op_colon

The basic idea is to do elementwise operations, but match on one dimension of the matrix. So a 1x2 row vector can be added to a 10x2 matrix.

I think it is a good idea to enforce some standards. For instance, not allow 1x3 to be added to a 3x1. It makes sense to force a transpose here. This ensures there is no ambiguity for something like a 2x1 and a 2x2 matrix. 2x1+2x2 should add column wise, whereas 1x2 +2x2 should add row wise.

I understand replicate is another option, but its definitely doesn't seem as elegant.

Thoughts?
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
I've just added a few rowwise/colwise operators: +, -, +=, and -= so that you can write:

Code: Select all
Vector3f v;
Matrix3f a, b;
a = b.colwise() + v;
User avatar
bjacob
Registered Member
Posts
658
Karma
3
ggael wrote:I've just added a few rowwise/colwise operators: +, -, +=, and -= so that you can write:

Code: Select all
Vector3f v;
Matrix3f a, b;
a = b.colwise() + v;



Thank you !!


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
User avatar
marton
Registered Member
Posts
10
Karma
0
OS
ggael wrote:I've just added a few rowwise/colwise operators: +, -, +=, and -= so that you can write:

Code: Select all
Vector3f v;
Matrix3f a, b;
a = b.colwise() + v;



Wow, great! What about *, /, *= and /=? Wouldn't they make sense, too? To normalize a list of vectors to unit length, for example...


Bookmarks



Who is online

Registered users: Bing [Bot], Google [Bot], Sogou [Bot]