From: Konrad H. <hi...@cn...> - 2002-03-08 11:37:51
|
> situation. My general point is that a _good_ solution is simple, > if a solution is not simple, then it is probably a bad solution. Agreed. So we just need to agree on what is "simple". > I find separating array and matrix instances (in a sense of raising > exception when doing <matrix> <op> <array>) not a very simple solution: > New concepts are introduced that actually do not solve the simplicity > problem of representing matrix operations. As I see it, they I disagree there, separating the concepts of matrix and array *does* solve the simplicity problem in my opinion. Matrices use operators for common matrix operations, and arrays use the same operators for common array operations. > only introduce restrictions and the main assumption behind the rationale > is that "users are dumb and they don't know what is best for them". No, not at all. On the contrary, the rationale is "users are smart and know that arrays and matrices are different" ;-) Unfortunately, I have the impression that there are two schools of thought in collision here (and not just when it comes to programming). There is the "mathematical" school that defines matrices and arrays as abstract entities with certain properties and associated operations. And there is the "engineering" school that sees arrays as a convenient data structure to express certain operations, of which "matrix operations" are a subset. As a student, I had a friend who studied mechanical engineering, and his math exercises made me go mad more than once. When I read "...the vector of the masses...", I just had to scream ;-) Many engineering textbooks have the same effect on me. Now obviously I belong to the "mathematical" school, but I don't expect to convert everyone else to it. So my arguments will remain pythonic and pragmatic: the "mathematical" approach solves the problem without asking for new operators, and thus has a better chance of getting realized. > This is how I interpret the raised exception as behind the scenes matrix > and array are the same (in the sense of data representation). But data representation and data semantics are two different things. Readibility of code depends on semantics, not on internal representations or even implementation. Using the same representation merely implies that conversion should be efficient, but not necessarily implicit. > The main objection to this proposal seems to be that it deviates from a > good pythonic style (ie don't mess with attributes in this way). > I'd say that if python does not provide a good solution to our problem, > then we are entitled to deviate from a general style. After all, in doing That's another point where I disagree. I use Python for many different uses, numerics is only one of them (though the most important one). Uniformity of style is an important value for me. Moreover, I claim that Python *does* provide a good solution, it is merely a very different one. > numerics the efficiency issue has a rather high weight. And a generally > good style of Python cannot always support that. Computational efficiency is not the issue here. If that's all you want, call a BLAS routine for matrix multiplication with two array arguments - doable today, without any modification of whatsoever. Even Fortran programmers do that, instead of suggesting that Fortran 2002 should add a "multiply-by-calling-BLAS" operator. > define > > T = TransposeOp() > H = TransposeOp(conjugate=1) Does that work? I'd expect that a**T would first call .__pow__(T) which quite probably crashes... (Not that it matters to me, I find this almost as abusive as the matrix attributes.) Konrad. -- ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hi...@cn... Centre de Biophysique Moleculaire (CNRS) | Tel.: +33-2.38.25.56.24 Rue Charles Sadron | Fax: +33-2.38.63.15.17 45071 Orleans Cedex 2 | Deutsch/Esperanto/English/ France | Nederlands/Francais ------------------------------------------------------------------------------- |
From: Pearu P. <pet...@ma...> - 2002-03-08 13:04:44
|
On Fri, 8 Mar 2002, Konrad Hinsen wrote: <snip> > Unfortunately, I have the impression that there are two schools of > thought in collision here (and not just when it comes to programming). > There is the "mathematical" school that defines matrices and arrays > as abstract entities with certain properties and associated operations. > And there is the "engineering" school that sees arrays as a convenient > data structure to express certain operations, of which "matrix operations" > are a subset. I see arrays as a convenient data structure (being implemented in computer programs) to hold matrices (being members of a mathematical concept). I guess that my views are narrow-minded (but willing to widen it) regarding to consider arrays as a mathematical concept too. Just in mathematics I never (need to) use arrays in that way (my fields are mathematical analysis, integrable systems, and not computer science nor engineering). So, I also belong to the school of "mathematics", but may be into a different one. <snip> > That's another point where I disagree. I use Python for many different > uses, numerics is only one of them (though the most important one). > Uniformity of style is an important value for me. Me too. Just I am not too crazy about the constant style but more of if something can be accomplished efficiently. To be honest, I don't like programming in Python because it has a nice style, but because I can accomplish a lot with it in a very efficient way (and not only by using efficient algorithms). Writing, for example, Numeric.transpose(a) instead of a**T, a.T, a`, or whatever just reduces this efficiency. I also realize and respect that for computer scientists (that I presume the developers of Python are) it is crucial to have consistent style for their reasons. Sometimes this style makes some site-specific simple tasks too verbose to follow. > Moreover, I claim that Python *does* provide a good solution, it is > merely a very different one. So, what is it? <snip> > Does that work? I'd expect that a**T would first call .__pow__(T) > which quite probably crashes... (Not that it matters to me, I find > this almost as abusive as the matrix attributes.) Yes, it works: >>> from Numeric import * >>> class T: __rpow__ = lambda s,o: transpose(o) ... >>> print array([[1,2],[3,4]]) ** T() [[1 3] [2 4]] And I don't understand why it is abusive (because it is a different approach?). It's just an idea. Pearu |
From: Konrad H. <hi...@cn...> - 2002-03-08 14:51:54
|
> regarding to consider arrays as a mathematical concept too. Just in > mathematics I never (need to) use arrays in that way (my fields are > mathematical analysis, integrable systems, and not computer science nor I meant "mathematical" as a school of thought (going from the abstract to the concrete), not as a domain of research. I don't know any area of mathematics either that uses the array concept, but it is definitely common in computer science (as a structured collection of similar data). Image data is a good example. > something can be accomplished efficiently. To be honest, I don't like > programming in Python because it has a nice style, but because I can > accomplish a lot with it in a very efficient way (and not only by using I want both :-) > > Moreover, I claim that Python *does* provide a good solution, it is > > merely a very different one. > > So, what is it? Separate matrix and array objects, with computationally efficient but explicit (verbose) interconversion. > Yes, it works: > >>> from Numeric import * > >>> class T: __rpow__ = lambda s,o: transpose(o) > ... > >>> print array([[1,2],[3,4]]) ** T() > [[1 3] > [2 4]] Right, it works as long as the left argument doesn't try to do the power operation itself. > And I don't understand why it is abusive (because it is a different > approach?). It's just an idea. For me, "power" is a shorthand for repeated multiplication, with certain properties attached to it. I have no problem with using the ** operator for something else, but then on different data types. The idea that a**b could be completely different operations for the same a as a function of b is not very appealing to me. In fact, the idea that an operand instead of the operator defines the operation is not very appealing to me. There's also a more pragmatic objection which is purely technical, I like to stay away from playing tricks with the binary operator type coercion system in Python. Sooner or later it always bites back. And the details have changed over Python releases, which is a compatibility nightmare. Konrad. -- ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hi...@cn... Centre de Biophysique Moleculaire (CNRS) | Tel.: +33-2.38.25.56.24 Rue Charles Sadron | Fax: +33-2.38.63.15.17 45071 Orleans Cedex 2 | Deutsch/Esperanto/English/ France | Nederlands/Francais ------------------------------------------------------------------------------- |
From: David B. <df...@mr...> - 2002-03-08 16:04:40
|
On Fri, 8 Mar 2002, Konrad Hinsen wrote: > > regarding to consider arrays as a mathematical concept too. Just in > > mathematics I never (need to) use arrays in that way (my fields are > > mathematical analysis, integrable systems, and not computer science nor > > I meant "mathematical" as a school of thought (going from the abstract > to the concrete), not as a domain of research. I don't know any area > of mathematics either that uses the array concept, but it is > definitely common in computer science (as a structured collection of > similar data). Image data is a good example. Just my 2c worth: I count myself in the "mathematical" school despite being a physicist. I look at matrices as having a specific algebra which, for instance, cannot be easily made to apply to higher-dimensional arrays. Therefore they are not just arrays looked at in a different way. For object-oriented thinkers this means they are different objects. They may "inherit" a lot of attributes from arrays but are not arrays. Another point to note is that a specific complaint earlier in the thread was the computational inefficiency of using numpy arrays for matrix-intensive operations. It seems to me that it would be far easier to write an optimised set of code for matrices if they were known to be a separate class. An example (which is probably not useful, but serves for illustration) is that one could "cache" or delay transposes etc, knowing that a matrix-multiply was likely to be about to come up. This sort of thing would be more difficult if the result of the transpose would have to be sensible when followed by a generic array operation. David |
From: Perry G. <pe...@st...> - 2002-03-08 15:11:49
|
Pearu Peterson writes: [...] > > I find separating array and matrix instances (in a sense of raising > exception when doing <matrix> <op> <array>) not a very simple solution: > New concepts are introduced that actually do not solve the simplicity > problem of representing matrix operations. As I see it, they > only introduce restrictions and the main assumption behind the rationale > is that "users are dumb and they don't know what is best for them". > This is how I interpret the raised exception as behind the scenes matrix > and array are the same (in the sense of data representation). > I don't think the issue is whether users are "dumb" but rather, will it be more or less transparent to them what is supposed to happen. Remember, this particular proposal affects in no way the notational convenience when operands are of the same type. It doesn't even affect the notational convenience of most of the examples presented (e.g., a.M * b.M) as long as the resulting operands are of the same type. It only affects cases involving mixed types. Do we really want <matrix> * <array> (yes, it would be possible to have one dominate over <array> * <matrix> the other always regardless of order) to mean two different things for example? Will a user always be aware that a module function returns arrays rather than matrices. Yes, users ought to check the documentation, but they often don't or they misremember. The more I think about it the more I come to think it really is better to be safer in this case. It will not be hard for users to explicitly convert, nor should it be notationally cumbersome. E.g. (just to use one the proposed options) matrix(a) * b a * array(b) I don't see this as a big burden. I would rather do it this way myself for my own code. [...] > (there have been two implementation approaches proposed for this: (i) a.M > returns a Matrix instance, (ii) a.M returns the same array with a > temporarily set bit saying that the following operation is somehow > special). > To me, this looks like a safe solution. Though it is a hack, at least it > is simple and understandable in anywhere where it is used (having a * b > where b can be either matrix or array, it is not predictable from just > looking the code what the result will be -- not very pythonic indeed). > It's safer, but it isn't safe. Besides, one could still do this and raise exceptions on mixed types. Is the issue that people strongly want to do (if both a an b are arrays) a.M * b (or matrix(a) * b) instead a.M * b.M (or matrix(a) * matrix(b)) to get matrix behavior? Perry |
From: Pearu P. <pe...@ce...> - 2002-03-08 15:37:29
|
On Fri, 8 Mar 2002, Perry Greenfield wrote: > It's safer, but it isn't safe. Besides, one could still do this and raise > exceptions on mixed types. Is the issue that people strongly want to do > (if both a an b are arrays) > > a.M * b (or matrix(a) * b) > > instead > > a.M * b.M (or matrix(a) * matrix(b)) > > to get matrix behavior? Just to be clear, my suggestion consisted on the following points: 1) not to introduce any new type or concept such as matrix 2) to forget the current Matrix class 3) all objects are arrays, including a.M 4) a.M has a temporary bit set only for the following operation So, with this setup there is no issue with mixed types at all and it is easy to implement. But if there will be introduced a new type, matrix, then this setup does not work. The reason why I proposed the above setup was exactly because I didn't like that a.M would return a different object type in the middle of an expresssion. Pearu |