Re: [eigen] inconsistent cwise() support |

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]

*To*: eigen@xxxxxxxxxxxxxxxxxxx*Subject*: Re: [eigen] inconsistent cwise() support*From*: Benoit Jacob <jacob.benoit.1@xxxxxxxxx>*Date*: Tue, 17 Nov 2009 11:31:29 -0500*Dkim-signature*: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:in-reply-to:references :date:message-id:subject:from:to:content-type :content-transfer-encoding; bh=GJPrHypGcFItqBn73GgZ3fGja9ANDLYkv6pa+ZQZizg=; b=Wi6S+TrxTXmBInzeQpBYqZCRdFk2UNJPSsx/CNsvBBoQ6oqe9DAm9zhQgUjKEr0hkX JCESR1+sQtOLuLqKS4iqIja+AcNZ45qDGAOFuAEsPNMdODolhi1pVqX3EX1Q4u92xS+o WHbwoHresKgCYclNxC9fgTdYr8lS5KOZ5MYvU=*Domainkey-signature*: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type:content-transfer-encoding; b=GakZwgQlfnKmp6mUrOUY2mJUPFJdh7KXpEDvZ67e1S4sYr2UqVPMYwGrC+k4CTI332 NVMi4/hJqV3f3FSjCRIU10ocFa2kgYre133y8qXBfxUcckdwhroPzIMoiRFst3B4G4q7 dP2gH7epswnFXv/0att0fcwvCoitSNZW5SJjs=

ok, nevermind, your solution is better: just force more code to #include Array. (now replying to your other e-mail). Benoit 2009/11/17 Benoit Jacob <jacob.benoit.1@xxxxxxxxx>: > or you could just move the Array class to Core. This isn't quite like > merging the whole Array module into Core, e.g. the partial reductions > stay out; this is more about redefining what the Array module is. At > the moment it is a bit unfortunate that the word Array is used for 2 > different notions, the current Array module and the future Array > class. > > Benoit > > 2009/11/17 Gael Guennebaud <gael.guennebaud@xxxxxxxxx>: >> >> There is one little difficulty: currently a few methods of Cwise are defined >> in Core (abs, min/max) because they appeared to be really fundamental. With >> my proposal I don't see how this could be done because the class Array >> should really be declared in the Array module ! That means the Array module >> will have to be included more often. Again, there is a good counter part: >> this splitting of Cwise across two modules is really prone to annoying >> compilation errors which are really hard to understand for the users. >> >> gael. >> >> On Tue, Nov 17, 2009 at 12:48 PM, Gael Guennebaud >> <gael.guennebaud@xxxxxxxxx> wrote: >>> >>> I also agree with that proposal, but I'm thinking that once we'll have a >>> true array support, all this array/cwise stuff is going to be messy. Here >>> I'll assume that a true Array class supporting the standard global math >>> function (e.g., std::sin) is really needed. If that's not the case, then we >>> don't implement it => problem solved. So once we'll have this Array class, I >>> guess we'll also want an easy way to view a Matrix as an Array, so one will >>> be able to write: >>> >>> MatrixXf m; >>> abs(m.array()); >>> >>> that is redundant with the current: >>> >>> m.cwise().abs(); >>> >>> Since we are currently in favor of member functions rather than global >>> functions, we might also want to add, e.g., an abs() method to Array >>> yielding a third option for the user: >>> >>> m.array().abs(); >>> >>> For consistency reason, perhaps we would also support the cwise() API for >>> Array. After all it would be weird that this cwise() API works for Matrix >>> only. So now we would also have three options for Array objects: >>> >>> ArrayXf a; >>> abs(a); >>> a.abs(); >>> a.cwise().abs(); >>> >>> So the addition of such an Array class is perhaps the occasion to >>> reconsider coefficient wise operations. In order to make a decision, it is >>> also interesting to have a look at some binary operations: >>> >>> MatrixXf m1, m2; >>> ArrayXf a1, a2; >>> >>> m1.cwise() + m2; // current API >>> m1.array() + m2.array(); // more verbose, but symmetric >>> >>> a1 + a2; >>> a1.cwise() + a2; // very stupid >>> >>> m1.cwise().max(m2); // current API >>> max(m1.array(), m2.array()); // more verbose, but symmetric >>> m1.array().max(m2.array()); // more verbose, not really symmetric >>> >>> max(a1,a2); >>> a1.max(a2); // not really symmetric >>> a1.cwise().max(a2); // very stupid >>> >>> I think it is also important to acknowledge that the current cwise() API >>> is odd enough to make it hard to learn for new comers. They often have some >>> difficulties to determine where .cwise() is needed (e.g., m1.cwise() * >>> m2.cwise()), and how it propagates (though it does not, of course). For >>> instance, if you look at "m1.cwise() * m2" and you know, or did not >>> understand the prefix concept of .cwise(), then it seems that .cwise >>> propagate to m2. >>> >>> Ok I think you got me now. When we designed this cwise() API, I liked it a >>> lot because it was fun: it allows us to overload a couple of operators >>> (*,+,-,<,>,!=, etc.) but now, it looks more odd than fun, and this is >>> something that annoys me in Eigen. >>> >>> Said that, I still don't have an ideal solution to propose, but what about >>> removing the .cwise() prefix in favor of only the .array() style that is >>> illustrated above ? To help you make a decision here are the four main >>> consequences of such a change with their own pro and cons: >>> >>> 1 - It makes the API simpler once Array is implemented (+1) >>> >>> 2 - For binary operations you need to put Array on both sides, so it is, >>> at a first glance, a bit more verbose (-0.5). On the other hand it is >>> perhaps less cumbersome (+0.5). >>> >>> 3 - When you do: (m1.array() * m2.array()) you get an Array expression, >>> not a Matrix. So you might need to convert it back explicitly to a Matrix >>> (-0.5): >>> >>> (m1.array() * m2.array()).matrix() * m3; >>> >>> On the other hand this avoid the need to repeat .cwise() all the time when >>> all your operations are coefficient wise, e.g.: >>> >>> (m1.array() * m2.array()).abs().pow(alpha); >>> >>> // or: >>> >>> pow(abs(m1.array() * m2.array()), alpha); >>> >>> Since it seems to me that you very rarely have to mix pure Array >>> operations with pure Matrix ones in a single expression, this seems to be a >>> nice advantage (+1). >>> >>> 4 - Of course the last consequence is a significant API break, and here I >>> only see a strong drawback, I'm thinking hard, but I cannot find any >>> advantage for this consequence (-1). >>> >>> For the rest it is pretty much the same than for the current cwise() >>> solution (operator overloading, for unary ops it is just a text replacement, >>> etc.). >>> >>> At the end the sum of the scores is positive, +0.5, so that's a proof this >>> is a good proposal ;) Seriously, it seems to me that this proposal has some >>> real benefits for practical uses, but of course the major blocking point is >>> the API break. >>> >>> >>> >>> Finally, we can also discuss the choice to have both global functions and >>> member methods for Array. Here global functions are really useful, that's >>> why I'm in favor to provide both. >>> >>> >>> Cheers, >>> >>> Gael, who likes to put on the table tough API discussions, over and over >>> again ;) >>> >>> >>> On Mon, Nov 16, 2009 at 9:40 PM, Benoit Jacob <jacob.benoit.1@xxxxxxxxx> >>> wrote: >>>> >>>> 2009/11/16 Hauke Heibel <hauke.heibel@xxxxxxxxxxxxxx>: >>>> > On Mon, Nov 16, 2009 at 7:22 PM, Benoit Jacob >>>> > <jacob.benoit.1@xxxxxxxxx> >>>> > wrote: >>>> >> >>>> >> It seems like what you want is Gael's proposal for "true array >>>> >> support". >>>> > >>>> > Not really, since I am really required to work on matrices - actually I >>>> > was >>>> > working on spectral clustering involving eigenvalue decompositions (so >>>> > real >>>> > linear algebra stuff). >>>> > >>>> >> >>>> >> vector - scalar is not a standard operation; it doesn't have a >>>> >> geometric meaning. Actually matrix - scalar is sometimes used as >>>> >> matrix - scalar*Identity, so that's another reason not to let it mean >>>> >> coeff-wise substraction. >>>> > >>>> > I totally agree, I was just thinking about consistingly supporting (I >>>> > do >>>> > even volunteer to implement it) >>>> > >>>> > .cwise() += | -= | /= | *= >>>> >>>> oh, i see. >>>> >>>> Yes, I agree with your proposal, it would be cool if you implement it. >>>> It's true that there's no reason not to let .cwise syntax always work. >>>> >>>> Benoit >>>> >>>> >>>> > >>>> > and not in general >>>> > >>>> > MatrixBase::operator += etc. >>>> > >>>> > I just think that some problems (formulated in an algebraic framework) >>>> > do >>>> > sometimes need individual rescaling and sometimes even shifting when >>>> > you >>>> > need to work e.g. on zero-mean input data. >>>> > >>>> > - Hauke >>>> > >>>> >>>> >>> >> >> >> >> >

**References**:**[eigen] inconsistent cwise() support***From:*Hauke Heibel

**Re: [eigen] inconsistent cwise() support***From:*Benoit Jacob

**Re: [eigen] inconsistent cwise() support***From:*Hauke Heibel

**Re: [eigen] inconsistent cwise() support***From:*Benoit Jacob

**Re: [eigen] inconsistent cwise() support***From:*Gael Guennebaud

**Re: [eigen] inconsistent cwise() support***From:*Gael Guennebaud

**Re: [eigen] inconsistent cwise() support***From:*Benoit Jacob

**Messages sorted by:**[ date | thread ]- Prev by Date:
**Re: [eigen] inconsistent cwise() support** - Next by Date:
**Re: [eigen] inconsistent cwise() support** - Previous by thread:
**Re: [eigen] inconsistent cwise() support** - Next by thread:
**Re: [eigen] inconsistent cwise() support**

Mail converted by MHonArc 2.6.19+ | http://listengine.tuxfamily.org/ |