Re: [Numpy-discussion] [RFC] should we argue for a matrix power operator, @@?
Hello. Maybe a solution would be to not see @ and @@ only from the matrix point of view. Why ? The philosophy of Python is to give total control of the infix operators +, * and ** for example via the magic methods. So it can be also the case for @ and @@ that could be use for something else that matrix@@int. So what we can expect from A@@B@@C. I will say that is the same as a**b**c because a human goes from top to down (but this is not a general convention in CAS). Ok guy but what can we do for matrix@@matrix@@matrix. Just raises an error. The programmer has the possibility to use @@ as ** but it has to take care of the meaning regarding to the types of the objects. This is for example what we expect for matrix@@pi even if we mathematically can give a meaning to that for some matrices. Do not forget also that a direct computation of the inverse of a matrice is a complicated things, and that integer power of matrices have to be cleverly build, but I'm sure that everyones here know that. *So standard Python can...* - only proposes multiplication of matrices, - and for the power of matrices, just indicates that there is a magic method associated to @@ and explains that regarding to the complexity of this problem, it will be the job of the programmer to implement it. I think the problem from Guido's point of view is the asymmetrical type domain for operations. All the numeric operators are from number*number to number. Hoping that my frenchy english is clear enough. Chrisopthe BAL PS: maybe a good question for Python would be to see if other operators could be useful. For CAS, I would like to have the possibility to use f°g for composition, even if it is more for pedagogical reason, and f°°n for dynamical systems. But this is just a dream... 2014-03-15 6:39 GMT+01:00 Jaime Fernández del Río jaime.f...@gmail.com: On Fri, Mar 14, 2014 at 9:32 PM, Nathaniel Smith n...@pobox.com wrote: Here are the interesting use cases for @@ that I can think of: - 'vector @@ 2' gives the squared Euclidean length (because it's the same as vector @ vector). Kind of handy. - 'matrix @@ n' of course gives the matrix power, which is of marginal use but does come in handy sometimes, e.g., when looking at graph connectivity. - 'matrix @@ -1' provides a very transparent notation for translating textbook formulas (with all their inverses) into code. It's a bit unhelpful in practice, because (a) usually you should use solve(), and (b) 'matrix @@ -1' is actually more characters than 'inv(matrix)'. But sometimes transparent notation may be important. (And in some cases, like using numba or theano or whatever, 'matrix @@ -1 @ foo' could be compiled into a call to solve() anyway.) (Did I miss any?) I'm not really arguing for it, and I am not sure how, or even if, it fits in the general scheme. But for completeness sake, 'e @@ Matrix' is used in some treatments of linear systems of differential equations, where: dvector/dt = matrix @ vector would have solution vector = e @@ (matrix * t) @ vector_0 I don't think it makes any sense to use it as such in the context of numpy, as I think it would make broadcasting undecidable. But there may be parallel universes where having n @@ matrix and matrix @@ n both with well defined, yet different meanings may make sense. It is my impression that in this entirely made up scenario you would want e @@ A @@ 3 to be evaluated as (e @@ A) @@ 3. Which probably has more to do with the fact that the two @@ mean different things, than with the associativity that repeated calls to the same @@ should have. Personally I couldn't care less, and if I had a vote I would let @@ rest for now, until we see how @ plays out. Jaime ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
I tend to favor tight-right. The general scheme of precedence more or less puts heavier operations higher than lighter operations (+ * **) and @ is heavier than * in my mind. I think tight (either -right or -left) has a good correspondence with current dot() expressions, so it will make translation a bit more straightforward, IMO. s * dot(A, b) == s * A @ b dot(s * A, b) == (s * A) @ b On Sat, Mar 15, 2014 at 3:41 AM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the main blocker for adding a matrix multiply operator '@' to Python: we need to decide what we think its precedence and associativity should be. I'll explain what that means so we're on the same page, and what the choices are, and then we can all argue about it. But even better would be if we could get some data to guide our decision, and this would be a lot easier if some of you all can help; I'll suggest some ways you might be able to do that. So! Precedence and left- versus right-associativity. If you already know what these are you can skim down until you see CAPITAL LETTERS. We all know what precedence is. Code like this: a + b * c gets evaluated as: a + (b * c) because * has higher precedence than +. It binds more tightly, as they say. Python's complete precedence able is here: http://docs.python.org/3/reference/expressions.html#operator-precedence Associativity, in the parsing sense, is less well known, though it's just as important. It's about deciding how to evaluate code like this: a * b * c Do we use a * (b * c)# * is right associative or (a * b) * c# * is left associative ? Here all the operators have the same precedence (because, uh... they're the same operator), so precedence doesn't help. And mostly we can ignore this in day-to-day life, because both versions give the same answer, so who cares. But a programming language has to pick one (consider what happens if one of those objects has a non-default __mul__ implementation). And of course it matters a lot for non-associative operations like a - b - c or a / b / c So when figuring out order of evaluations, what you do first is check the precedence, and then if you have multiple operators next to each other with the same precedence, you check their associativity. Notice that this means that if you have different operators that share the same precedence level (like + and -, or * and /), then they have to all have the same associativity. All else being equal, it's generally considered nice to have fewer precedence levels, because these have to be memorized by users. Right now in Python, every precedence level is left-associative, except for '**'. If you write these formulas without any parentheses, then what the interpreter will actually execute is: (a * b) * c (a - b) - c (a / b) / c but a ** (b ** c) Okay, that's the background. Here's the question. We need to decide on precedence and associativity for '@'. In particular, there are three different options that are interesting: OPTION 1 FOR @: Precedence: same as * Associativity: left My shorthand name for it: same-left (yes, very creative) This means that if you don't use parentheses, you get: a @ b @ c - (a @ b) @ c a * b @ c - (a * b) @ c a @ b * c - (a @ b) * c OPTION 2 FOR @: Precedence: more-weakly-binding than * Associativity: right My shorthand name for it: weak-right This means that if you don't use parentheses, you get: a @ b @ c - a @ (b @ c) a * b @ c - (a * b) @ c a @ b * c - a @ (b * c) OPTION 3 FOR @: Precedence: more-tightly-binding than * Associativity: right My shorthand name for it: tight-right This means that if you don't use parentheses, you get: a @ b @ c - a @ (b @ c) a * b @ c - a * (b @ c) a @ b * c - (a @ b) * c We need to pick which of which options we think is best, based on whatever reasons we can think of, ideally more than hmm, weak-right gives me warm fuzzy feelings ;-). (In principle the other 2 possible options are tight-left and weak-left, but there doesn't seem to be any argument in favor of either, so we'll leave them out of the discussion.) Some things to consider: * and @ are actually not associative (in the math sense) with respect to each other, i.e., (a * b) @ c and a * (b @ c) in general give different results when 'a' is not a scalar. So considering the two expressions 'a * b @ c' and 'a @ b * c', we can see that each of these three options gives produces different results in some cases. Same-left is the easiest to explain and remember, because it's just, @ acts like * and /. So we already have to know the rule in order to understand other non-associative expressions like a / b / c or a - b - c, and it'd be nice if the same rule applied to things like a * b @ c so we only had to memorize *one* rule. (Of course there's ** which uses the opposite rule, but I guess everyone internalized that one
[Numpy-discussion] [ANN] OpenOpt Suite release 0.53: Stochastic programming addon now is BSD-licensed
hi all, I'm glad to inform you about new OpenOpt Suite release 0.53: Stochastic programming addon now is available for free Some minor changes -- Regards, D. http://openopt.org/Dmitrey ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [RFC] should we argue for a matrix power operator, @@?
On 3/15/2014 12:32 AM, Nathaniel Smith wrote: I know you were worried about losing the .I attribute on matrices if switching to ndarrays for teaching -- given that ndarray will probably not get a .I attribute, how much would the existence of @@ -1 affect you? Not much. Positive integer powers would be useful (for illustrating e.g. graph theory and difference equations), but not enough to delay the PEP. I think NumPy should take the money and run. Getting `@` is great. Let's get experience with it before deciding whether it's worth asking for `@@`. Questions for `@@`: - would it just be `matrix_power`, with all the restrictions? - or would `a(10,2,2)@@-1` return an array of matrix inverses? - etc In the end, I'd like to see a functional implementation before deciding on `@@`, but I would not like to see `@` delayed at all. Congratulations, Alan ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
I favor the weak right option. 1) Giving '*' higher precedence than `@` makes it easier, to my mind, to parse out what is going to happen: all the element-wise multiplications, followed by the matrix operations. I'd probably still use parenthesis for clarity. 2) Right associative has the advantage of efficiency in many common use cases, plus I tend to read matrix expressions from right to left. Chuck ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] It looks like Py 3.5 will include a dedicated infix matrix multiply operator
On Fri, Mar 14, 2014 at 6:51 PM, Nathaniel Smith n...@pobox.com wrote: Well, that was fast. Guido says he'll accept the addition of '@' as an infix operator for matrix multiplication, once some details are ironed out: https://mail.python.org/pipermail/python-ideas/2014-March/027109.html http://legacy.python.org/dev/peps/pep-0465/ Specifically, we need to figure out whether we want to make an argument for a matrix power operator (@@), and what precedence/associativity we want '@' to have. I'll post two separate threads to get feedback on those in an organized way -- this is just a heads-up. Surprisingly little discussion on python-ideas, or so it seemed to me. Guido came out in favor less than halfway through. Congratulations on putting together a successful proposal, many of us had given up on ever seeing a matrix multiplication operator. Chuck ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [RFC] should we argue for a matrix power operator, @@?
On Fri, Mar 14, 2014 at 10:32 PM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the second thread for discussion about Guido's concerns about PEP 465. The issue here is that PEP 465 as currently written proposes two new operators, @ for matrix multiplication and @@ for matrix power (analogous to * and **): http://legacy.python.org/dev/peps/pep-0465/ The main thing we care about of course is @; I pushed for including @@ because I thought it was nicer to have than not, and I thought the analogy between * and ** might make the overall package more appealing to Guido's aesthetic sense. It turns out I was wrong :-). Guido is -0 on @@, but willing to be swayed if we think it's worth the trouble to make a solid case. Note that question now is *not*, how will @@ affect the reception of @. @ itself is AFAICT a done deal, regardless of what happens with @@. For this discussion let's assume @ can be taken for granted, and that we can freely choose to either add @@ or not add @@ to the language. The question is: which do we think makes Python a better language (for us and in general)? Some thoughts to start us off: Here are the interesting use cases for @@ that I can think of: - 'vector @@ 2' gives the squared Euclidean length (because it's the same as vector @ vector). Kind of handy. - 'matrix @@ n' of course gives the matrix power, which is of marginal use but does come in handy sometimes, e.g., when looking at graph connectivity. - 'matrix @@ -1' provides a very transparent notation for translating textbook formulas (with all their inverses) into code. It's a bit unhelpful in practice, because (a) usually you should use solve(), and (b) 'matrix @@ -1' is actually more characters than 'inv(matrix)'. But sometimes transparent notation may be important. (And in some cases, like using numba or theano or whatever, 'matrix @@ -1 @ foo' could be compiled into a call to solve() anyway.) (Did I miss any?) In practice it seems to me that the last use case is the one that's might matter a lot practice, but then again, it might not -- I'm not sure. For example, does anyone who teaches programming with numpy have a feeling about whether the existence of '@@ -1' would make a big difference to you and your students? (Alan? I know you were worried about losing the .I attribute on matrices if switching to ndarrays for teaching -- given that ndarray will probably not get a .I attribute, how much would the existence of @@ -1 affect you?) On a more technical level, Guido is worried about how @@'s precedence should work (and this is somewhat related to the other thread about @'s precedence and associativity, because he feels that if we end up giving @ and * different precedence, then that makes it much less clear what to do with @@, and reduces the strength of the */**/@/@@ analogy). In particular, if we want to argue for @@ then we'll need to figure out what expressions like a @@ b @@ c and a ** b @@ c and a @@ b ** c should do. A related question is what @@ should do if given an array as its right argument. In the current PEP, only integers are accepted, which rules out a bunch of the more complicated cases like a @@ b @@ c (at least assuming @@ is right-associative, like **, and I can't see why you'd want anything else). OTOH, in the brave new gufunc world, it technically would make sense to define @@ as being a gufunc with signature (m,m),()-(m,m), and the way gufuncs work this *would* allow the power to be an array -- for example, we'd have: mat = randn(m, m) pow = range(n) result = gufunc_matrix_power(mat, pow) assert result.shape == (n, m, m) for i in xrange(n): assert np.all(result[i, :, :] == mat ** i) In this case, a @@ b @@ c would at least be a meaningful expression to write. OTOH it would be incredibly bizarre and useless, so probably no-one would ever write it. As far as these technical issues go, my guess is that the correct rule is that @@ should just have the same precedence and the same (right) associativity as **, and in practice no-one will ever write stuff like a @@ b @@ c. But if we want to argue for @@ we need to come to some consensus or another here. It's also possible the answer is ugh, these issues are too complicated, we should defer this until later when we have more experience with @ and gufuncs and stuff. After all, I doubt anyone else will swoop in and steal @@ to mean something else! OTOH, if e.g. there's a strong feeling that '@@ -1' will make a big difference in pedagogical contexts, then putting that off for years might be a mistake. I don't have a strong feeling either way on '@@' . Matrix inverses are pretty common in matrix expressions, but I don't know that the new operator offers much advantage over a function call. The positive integer powers might be useful in some domains, as others have pointed out, but computational practice one would tend to factor
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 2:49 PM, Charles R Harris charlesr.har...@gmail.com wrote: I favor the weak right option. 1) Giving '*' higher precedence than `@` makes it easier, to my mind, to parse out what is going to happen: all the element-wise multiplications, followed by the matrix operations. I'd probably still use parenthesis for clarity. It seems to me that 'tight' gives the same benefit. Any reasoning for the preference of 'weak' over 'tight'? -- Robert Kern ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [RFC] should we argue for a matrix power operator, @@?
2014-03-15 11:18 GMT-04:00 Charles R Harris charlesr.har...@gmail.com: On Fri, Mar 14, 2014 at 10:32 PM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the second thread for discussion about Guido's concerns about PEP 465. The issue here is that PEP 465 as currently written proposes two new operators, @ for matrix multiplication and @@ for matrix power (analogous to * and **): http://legacy.python.org/dev/peps/pep-0465/ The main thing we care about of course is @; I pushed for including @@ because I thought it was nicer to have than not, and I thought the analogy between * and ** might make the overall package more appealing to Guido's aesthetic sense. It turns out I was wrong :-). Guido is -0 on @@, but willing to be swayed if we think it's worth the trouble to make a solid case. Note that question now is *not*, how will @@ affect the reception of @. @ itself is AFAICT a done deal, regardless of what happens with @@. For this discussion let's assume @ can be taken for granted, and that we can freely choose to either add @@ or not add @@ to the language. The question is: which do we think makes Python a better language (for us and in general)? Some thoughts to start us off: Here are the interesting use cases for @@ that I can think of: - 'vector @@ 2' gives the squared Euclidean length (because it's the same as vector @ vector). Kind of handy. - 'matrix @@ n' of course gives the matrix power, which is of marginal use but does come in handy sometimes, e.g., when looking at graph connectivity. - 'matrix @@ -1' provides a very transparent notation for translating textbook formulas (with all their inverses) into code. It's a bit unhelpful in practice, because (a) usually you should use solve(), and (b) 'matrix @@ -1' is actually more characters than 'inv(matrix)'. But sometimes transparent notation may be important. (And in some cases, like using numba or theano or whatever, 'matrix @@ -1 @ foo' could be compiled into a call to solve() anyway.) (Did I miss any?) In practice it seems to me that the last use case is the one that's might matter a lot practice, but then again, it might not -- I'm not sure. For example, does anyone who teaches programming with numpy have a feeling about whether the existence of '@@ -1' would make a big difference to you and your students? (Alan? I know you were worried about losing the .I attribute on matrices if switching to ndarrays for teaching -- given that ndarray will probably not get a .I attribute, how much would the existence of @@ -1 affect you?) On a more technical level, Guido is worried about how @@'s precedence should work (and this is somewhat related to the other thread about @'s precedence and associativity, because he feels that if we end up giving @ and * different precedence, then that makes it much less clear what to do with @@, and reduces the strength of the */**/@/@@ analogy). In particular, if we want to argue for @@ then we'll need to figure out what expressions like a @@ b @@ c and a ** b @@ c and a @@ b ** c should do. A related question is what @@ should do if given an array as its right argument. In the current PEP, only integers are accepted, which rules out a bunch of the more complicated cases like a @@ b @@ c (at least assuming @@ is right-associative, like **, and I can't see why you'd want anything else). OTOH, in the brave new gufunc world, it technically would make sense to define @@ as being a gufunc with signature (m,m),()-(m,m), and the way gufuncs work this *would* allow the power to be an array -- for example, we'd have: mat = randn(m, m) pow = range(n) result = gufunc_matrix_power(mat, pow) assert result.shape == (n, m, m) for i in xrange(n): assert np.all(result[i, :, :] == mat ** i) In this case, a @@ b @@ c would at least be a meaningful expression to write. OTOH it would be incredibly bizarre and useless, so probably no-one would ever write it. As far as these technical issues go, my guess is that the correct rule is that @@ should just have the same precedence and the same (right) associativity as **, and in practice no-one will ever write stuff like a @@ b @@ c. But if we want to argue for @@ we need to come to some consensus or another here. It's also possible the answer is ugh, these issues are too complicated, we should defer this until later when we have more experience with @ and gufuncs and stuff. After all, I doubt anyone else will swoop in and steal @@ to mean something else! OTOH, if e.g. there's a strong feeling that '@@ -1' will make a big difference in pedagogical contexts, then putting that off for years might be a mistake. I don't have a strong feeling either way on '@@' . Matrix inverses are pretty common in matrix expressions, but I don't know that the new operator offers much advantage over a function call. The positive integer powers might be useful in some domains, as
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 11:44 AM, Robert Kern robert.k...@gmail.com wrote: I tend to favor tight-right. The general scheme of precedence more or less puts heavier operations higher than lighter operations (+ * **) and @ is heavier than * in my mind. I think tight (either -right or -left) has a good correspondence with current dot() expressions, so it will make translation a bit more straightforward, IMO. s * dot(A, b) == s * A @ b dot(s * A, b) == (s * A) @ b I'm not sure if this is a convincing argument, but I'll throw it out there: in most of my programming fonts, @ is a bigger, more visually salient character than *, so in any expression that mixes the two, my visual system is going to end up grouping the @-connected terms anyways. -- Robert Kern ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] GSoC project: draft of proposal
Because of the license problem, I think I will choose Yeppp as a default backend. And if time allows, maybe I can implement other bindings. (Vc library) Also I found that sleef library is in public domain. But it seems that it only provides fast math function, not vectorized math function. So I am not sure if it can be used in this project. Finally, if there are any suggestions for my proposal, please point out. I will appreciate your suggestions. Thanks. Regards, Leo Mao ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 9:58 AM, Robert Kern robert.k...@gmail.com wrote: On Sat, Mar 15, 2014 at 2:49 PM, Charles R Harris charlesr.har...@gmail.com wrote: I favor the weak right option. 1) Giving '*' higher precedence than `@` makes it easier, to my mind, to parse out what is going to happen: all the element-wise multiplications, followed by the matrix operations. I'd probably still use parenthesis for clarity. It seems to me that 'tight' gives the same benefit. Any reasoning for the preference of 'weak' over 'tight'? Two other reasons come to mind. First, '*' is right associative, so I think it is nicer to first view the expression as parsed into blocks separated by '@', which act somewhat like parenthesis at that point, and then evaluate the blocks. Second, and somewhat weaker, it might make it easier to track how arrays are broadcast. Chuck ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
Oops, make that '*' is *left* associative. snip Chuck ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 4:40 PM, Charles R Harris charlesr.har...@gmail.com wrote: On Sat, Mar 15, 2014 at 9:58 AM, Robert Kern robert.k...@gmail.com wrote: On Sat, Mar 15, 2014 at 2:49 PM, Charles R Harris charlesr.har...@gmail.com wrote: I favor the weak right option. 1) Giving '*' higher precedence than `@` makes it easier, to my mind, to parse out what is going to happen: all the element-wise multiplications, followed by the matrix operations. I'd probably still use parenthesis for clarity. It seems to me that 'tight' gives the same benefit. Any reasoning for the preference of 'weak' over 'tight'? Two other reasons come to mind. First, '*' is right associative, so I think it is nicer to first view the expression as parsed into blocks separated by '@', which act somewhat like parenthesis at that point, and then evaluate the blocks. Again, I think tight does the same amount of separation, just with blocks of matrix multiplication broken up by elementwise multiplication; this is just an argument against 'same', not for 'weak' over 'tight'. As I mentioned elsewhere, my visual system seems to break things up with @-tight anyways. Does it not for you? Second, and somewhat weaker, it might make it easier to track how arrays are broadcast. I think this point is going to ultimately determine this, if we can break down all the cases and if they actually do favor one choice over another. -- Robert Kern ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Fri, Mar 14, 2014 at 11:41 PM, Nathaniel Smith n...@pobox.com wrote: Here's the main blocker for adding a matrix multiply operator '@' to Python: we need to decide what we think its precedence and associativity should be. I am not ready to form my own opinion, but I hope the following will help shaping the discussion. Currently, [1], Python operator precedence is +, -Addition and subtraction*, /, //, %Multiplication, division, remainder [5] http://docs.python.org/3/reference/expressions.html#id20+x, -x, ~xPositive, negative, bitwise NOT**Exponentiation [6]http://docs.python.org/3/reference/expressions.html#id21 x[index], x[index:index], x(arguments...), x.attributeSubscription, slicing, call, attribute reference We need to decide whether @ belongs to one of the existing row or deserves one of its own. The associativity debate is one of those debates [2] where there is no right answer. Guido has very wisely left it for the numeric community to decide. I would start with surveying the prior art of using right associativity and the reasons it was chosen and see if those reasons apply. (An example of a choice made for wrong reasons is our decimal system. We write our numbers backwards - from high to low place value - only because we took them from people who write text from right to left. As a result, computer parsers have to skip to the last or count the number of digits before they can start evaluating the number.) Here is the start: 1. APL uses right to left associativity for all operators and all operators have the same precedence. 2. Exponentiation operator is right associative in most languages with MATLAB being a notable exception. [1] http://docs.python.org/3/reference/expressions.html#evaluation-order [2] http://en.wikipedia.org/wiki/Lilliput_and_Blefuscu [3] http://www.tcl.tk/cgi-bin/tct/tip/274.html ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 3:41 AM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the main blocker for adding a matrix multiply operator '@' to Python: we need to decide what we think its precedence and associativity should be. Another data point that might be useful: Matlab: same-left R: tight-left IDL: same-left GAUSS: same-left (IIUC -- any GAUSS experts please correct me if I misunderstood the fine manual) Mathematica: instead of having an associativity, a @ b @ c gets converted into mdot([a, b, c]) -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 1:28 PM, Nathaniel Smith n...@pobox.com wrote: On Sat, Mar 15, 2014 at 3:41 AM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the main blocker for adding a matrix multiply operator '@' to Python: we need to decide what we think its precedence and associativity should be. Another data point that might be useful: Matlab: same-left R: tight-left I was going to ask this earlier, but I was worried I was missing something major. Why was tight-left not an option? This means that if you don't use parentheses, you get: a @ b @ c - (a @ b) @ c a * b @ c - a * (b @ c) a @ b * c - (a @ b) * c In my (very inexperienced) opinion, it seems like the most intuitive option. Cheers, -Joe IDL: same-left GAUSS: same-left (IIUC -- any GAUSS experts please correct me if I misunderstood the fine manual) Mathematica: instead of having an associativity, a @ b @ c gets converted into mdot([a, b, c]) -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
Hi Chris, On Sat, Mar 15, 2014 at 4:15 AM, Chris Laumann chris.laum...@gmail.com wrote: Hi all, Let me preface my two cents by saying that I think the best part of @ being accepted is the potential for deprecating the matrix class — the syntactic beauty of infix for matrix multiply is a nice side effect IMHO :) This may be why my basic attitude is: I don’t think it matters very much but I would vote (weakly) for weak-right. Where there is ambiguity, I suspect most practitioners will just put in parentheses anyway — especially with combinations of * and @, where I don’t think there is a natural intuitive precedence relationship. At least, element-wise multiplication is very rare in math/physics texts as an explicitly defined elementary operation so I’d be surprised if anybody had a strong intuition about the precedence of the ‘*’ operator. And the binding order doesn’t matter if it is scalar multiplication. It doesn't matter and no-one has strong intuitions are generally arguments for same-left, since that allows everyone to reason about @ in the same way they reason about all of Python's operators. I have quite a bit of code with large matrices where the order of matrix-vector multiplies is an important optimization and I would certainly have a few simpler looking expressions for op @ op @ vec, hence the weak preference for right-associativity. That said, I routinely come across situations where the optimal matrix multiplication order is more complicated than can be expressed as left-right or right-left (because some matrices might be diagonal, CSR or CSC), which is why the preference is only weak. I don’t see a down-side in the use-case that it is actually associative (as in matrix-matrix-vector). Would you mind taking a more systematic look through this code, or sharing some examples so the rest of us can look? Certainly have a few simpler looking expressions is a good start, but when we're talking about changing the grammar of one of the most popular programming languages in the world it seems worth the effort to gather some more careful data :-). -n -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 6:33 PM, Joe Kington joferking...@gmail.com wrote: On Sat, Mar 15, 2014 at 1:28 PM, Nathaniel Smith n...@pobox.com wrote: On Sat, Mar 15, 2014 at 3:41 AM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the main blocker for adding a matrix multiply operator '@' to Python: we need to decide what we think its precedence and associativity should be. Another data point that might be useful: Matlab: same-left R: tight-left I was going to ask this earlier, but I was worried I was missing something major. Why was tight-left not an option? This means that if you don't use parentheses, you get: a @ b @ c - (a @ b) @ c a * b @ c - a * (b @ c) a @ b * c - (a @ b) * c In my (very inexperienced) opinion, it seems like the most intuitive option. Because tight-left doesn't seem to have much to recommend it over same-left, and all else being equal having fewer levels of precedence is usually considered a good thing. Unless I'm missing something. If we do decide that tight-left is best then we could certainly advocate for it. I wouldn't read too much into R's choice; they don't actually define a separate precedence level for matrix multiplication specifically. They have a single precedence level for all special (user-defined) operators, and matrix multiplication happens to be one of these. (Their versions of // and % are also special, but I don't think anyone would expect // to bind more tightly than / if one were choosing precedences on a case-by-case basis.) -n -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 2:25 PM, Alexander Belopolsky ndar...@mac.comwrote: On Fri, Mar 14, 2014 at 11:41 PM, Nathaniel Smith n...@pobox.com wrote: Here's the main blocker for adding a matrix multiply operator '@' to Python: we need to decide what we think its precedence and associativity should be. I am not ready to form my own opinion, but I hope the following will help shaping the discussion. One more question that I think should be answered by the PEP and may influence the associativity decision is what happens if in an A @ B @ C expression, each operand has its own type that defines __matmul__ and __rmatmul__? For example, A can be an ndarray, B a sympy expression and C a pyoperator. ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 12:40 PM, Nathaniel Smith n...@pobox.com wrote: On Sat, Mar 15, 2014 at 6:33 PM, Joe Kington joferking...@gmail.com wrote: On Sat, Mar 15, 2014 at 1:28 PM, Nathaniel Smith n...@pobox.com wrote: On Sat, Mar 15, 2014 at 3:41 AM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the main blocker for adding a matrix multiply operator '@' to Python: we need to decide what we think its precedence and associativity should be. Another data point that might be useful: Matlab: same-left R: tight-left I was going to ask this earlier, but I was worried I was missing something major. Why was tight-left not an option? This means that if you don't use parentheses, you get: a @ b @ c - (a @ b) @ c a * b @ c - a * (b @ c) a @ b * c - (a @ b) * c In my (very inexperienced) opinion, it seems like the most intuitive option. Because tight-left doesn't seem to have much to recommend it over same-left, and all else being equal having fewer levels of precedence is usually considered a good thing. Unless I'm missing something. If we do decide that tight-left is best then we could certainly advocate for it. I wouldn't read too much into R's choice; they don't actually define a separate precedence level for matrix multiplication specifically. They have a single precedence level for all special (user-defined) operators, and matrix multiplication happens to be one of these. (Their versions of // and % are also special, but I don't think anyone would expect // to bind more tightly than / if one were choosing precedences on a case-by-case basis.) Just to throw something new into the mix u@v@w = u@(v@w) -- u@v is a dyadic matrix u@v -- is a scalar It would be nice if u@v@None, or some such, would evaluate as a dyad. Or else we will still need the concept of row and column 1-D matrices. I still think v.T should set a flag so that one can distinguish u@v.T (dyad) from u.T@v (inner product), where 1-D arrays are normally treated as column vectors. Chuck ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 1:01 PM, Alexander Belopolsky ndar...@mac.comwrote: On Sat, Mar 15, 2014 at 2:25 PM, Alexander Belopolsky ndar...@mac.comwrote: On Fri, Mar 14, 2014 at 11:41 PM, Nathaniel Smith n...@pobox.com wrote: Here's the main blocker for adding a matrix multiply operator '@' to Python: we need to decide what we think its precedence and associativity should be. I am not ready to form my own opinion, but I hope the following will help shaping the discussion. One more question that I think should be answered by the PEP and may influence the associativity decision is what happens if in an A @ B @ C expression, each operand has its own type that defines __matmul__ and __rmatmul__? For example, A can be an ndarray, B a sympy expression and C a pyoperator. My impression is that the pyoperator folks would prefer right associativity as it corresponds to function composition, which also proceeds right to left. I don't think the sympy folks have expressed and opinion, except perhaps that they are more in the sage camp where matrices are symbolic, and not to be confused with arrays. That is, they don't depend on having two operators, one for the Hadamard product and another for the matrix product. Chuck ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On 15 Mar 2014 19:02, Charles R Harris charlesr.har...@gmail.com wrote: Just to throw something new into the mix u@v@w = u@(v@w) -- u@v is a dyadic matrix u@v -- is a scalar It would be nice if u@v@None, or some such, would evaluate as a dyad. Or else we will still need the concept of row and column 1-D matrices. I still think v.T should set a flag so that one can distinguish u@v.T (dyad) from u.T@v (inner product), where 1-D arrays are normally treated as column vectors. This sounds important but I have no idea what any of it means :-) (What's a dyadic matrix?) Can you elaborate? -n ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 3:29 PM, Nathaniel Smith n...@pobox.com wrote: It would be nice if u@v@None, or some such, would evaluate as a dyad. Or else we will still need the concept of row and column 1-D matrices. I still think v.T should set a flag so that one can distinguish u@v.T(dyad) from u.T@v(inner product), where 1-D arrays are normally treated as column vectors. This sounds important but I have no idea what any of it means :-) (What's a dyadic matrix?) Can you elaborate? I assume dyadic means 2d. This discussion gave me an idea that is only tangentially relevant to the discussion at hand. It looks like numpy operators commonly need to make a choice whether to treat an Nd array as a unit (atom) or as a list to broadcast itself over. APL-derived languages solve this problem by using operator modifiers. Applied to our case, given a dot-product operator @, each[@] operator works on 2d arrays by dotting them pair-wise and returning a 1d array. Similarly, eachleft[@] would operate on 2d, 1d operands by broadcasting itself over the left operand (incidentally reproducing the mat @ vec behavior) and eachright[@] would treat its left operand atomically and broadcast over the right operand. My idea is inspired by Guido's use facade suggestion. We can define ndarray.each(axes=(0,)) method that would return a light-weigh proxy object so that a each[@] b is spelled a.each() @ b.each() a eachleft[@] b is spelled a.each() @ b a eachright[@] b is spelled a @ b.each() ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 1:29 PM, Nathaniel Smith n...@pobox.com wrote: On 15 Mar 2014 19:02, Charles R Harris charlesr.har...@gmail.com wrote: Just to throw something new into the mix u@v@w = u@(v@w) -- u@v is a dyadic matrix u@v -- is a scalar It would be nice if u@v@None, or some such, would evaluate as a dyad. Or else we will still need the concept of row and column 1-D matrices. I still think v.T should set a flag so that one can distinguish u@v.T(dyad) from u.T@v(inner product), where 1-D arrays are normally treated as column vectors. This sounds important but I have no idea what any of it means :-) (What's a dyadic matrix?) Can you elaborate? Dyadic matrices date back to the beginning of vector calculus and J. W. Gibbs. These days they are usually written as v*w.T, i.e., the outer product of two vectors and are a fairly common occurrence in matrix expressions. For instance, covariance matrices are defined as E(v * v.T) Chuck ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 4:00 PM, Charles R Harris charlesr.har...@gmail.com wrote: These days they are usually written as v*w.T, i.e., the outer product of two vectors and are a fairly common occurrence in matrix expressions. For instance, covariance matrices are defined as E(v * v.T) With the current numpy, we can do x = arange(1, 5) x[:,None].dot(x[None,:]) array([[ 1, 2, 3, 4], [ 2, 4, 6, 8], [ 3, 6, 9, 12], [ 4, 8, 12, 16]]) I assume once @ becomes available, we will have x[:,None] @ x[None,:] array([[ 1, 2, 3, 4], [ 2, 4, 6, 8], [ 3, 6, 9, 12], [ 4, 8, 12, 16]]) ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 2:12 PM, Alexander Belopolsky ndar...@mac.comwrote: On Sat, Mar 15, 2014 at 4:00 PM, Charles R Harris charlesr.har...@gmail.com wrote: These days they are usually written as v*w.T, i.e., the outer product of two vectors and are a fairly common occurrence in matrix expressions. For instance, covariance matrices are defined as E(v * v.T) With the current numpy, we can do x = arange(1, 5) x[:,None].dot(x[None,:]) array([[ 1, 2, 3, 4], [ 2, 4, 6, 8], [ 3, 6, 9, 12], [ 4, 8, 12, 16]]) I assume once @ becomes available, we will have x[:,None] @ x[None,:] array([[ 1, 2, 3, 4], [ 2, 4, 6, 8], [ 3, 6, 9, 12], [ 4, 8, 12, 16]]) Yes, that works. I was thinking more of easy translation of the forms found in textbooks. Householder reflection, for instance, is usually written as I - 2 * v * v.T Where the `v` are unit vectors. Chuck ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [RFC] should we argue for a matrix power operator, @@?
Speaking only for myself (and as someone who has regularly used matrix powers), I would not expect matrix power as @@ to follow from matrix multiplication as @. I do agree that matrix power is the only reasonable use for @@ (given @), but it's still not something I would be confident enough to know without looking up. We should keep in mind that each new operator imposes some (small) cognitive burden on everyone who encounters them for the first time, and, in this case, this will include a large fraction of all Python users, whether they do numerical computation or not. Guido has given us a tremendous gift in the form of @. Let's not insist on @@, when it is unclear if the burden of figuring out what @@ means it would be worth using, even for heavily numeric code. I would certainly prefer to encounter norm(A), inv(A), matrix_power(A, n), fractional_matrix_power(A, n) and expm(A) rather than their infix equivalents. It will certainly not be obvious which of these @@ will support for objects from any given library. One useful data point might be to consider whether matrix power is available as an infix operator in other languages commonly used for numerical work. AFAICT from some quick searches: MATLAB: Yes R: No IDL: No All of these languages do, of course, implement infix matrix multiplication, but it is apparently not clear at all whether the matrix power is useful. Best, Stephan On Sat, Mar 15, 2014 at 9:03 AM, Olivier Delalleau sh...@keba.be wrote: 2014-03-15 11:18 GMT-04:00 Charles R Harris charlesr.har...@gmail.com: On Fri, Mar 14, 2014 at 10:32 PM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the second thread for discussion about Guido's concerns about PEP 465. The issue here is that PEP 465 as currently written proposes two new operators, @ for matrix multiplication and @@ for matrix power (analogous to * and **): http://legacy.python.org/dev/peps/pep-0465/ The main thing we care about of course is @; I pushed for including @@ because I thought it was nicer to have than not, and I thought the analogy between * and ** might make the overall package more appealing to Guido's aesthetic sense. It turns out I was wrong :-). Guido is -0 on @@, but willing to be swayed if we think it's worth the trouble to make a solid case. Note that question now is *not*, how will @@ affect the reception of @. @ itself is AFAICT a done deal, regardless of what happens with @@. For this discussion let's assume @ can be taken for granted, and that we can freely choose to either add @@ or not add @@ to the language. The question is: which do we think makes Python a better language (for us and in general)? Some thoughts to start us off: Here are the interesting use cases for @@ that I can think of: - 'vector @@ 2' gives the squared Euclidean length (because it's the same as vector @ vector). Kind of handy. - 'matrix @@ n' of course gives the matrix power, which is of marginal use but does come in handy sometimes, e.g., when looking at graph connectivity. - 'matrix @@ -1' provides a very transparent notation for translating textbook formulas (with all their inverses) into code. It's a bit unhelpful in practice, because (a) usually you should use solve(), and (b) 'matrix @@ -1' is actually more characters than 'inv(matrix)'. But sometimes transparent notation may be important. (And in some cases, like using numba or theano or whatever, 'matrix @@ -1 @ foo' could be compiled into a call to solve() anyway.) (Did I miss any?) In practice it seems to me that the last use case is the one that's might matter a lot practice, but then again, it might not -- I'm not sure. For example, does anyone who teaches programming with numpy have a feeling about whether the existence of '@@ -1' would make a big difference to you and your students? (Alan? I know you were worried about losing the .I attribute on matrices if switching to ndarrays for teaching -- given that ndarray will probably not get a .I attribute, how much would the existence of @@ -1 affect you?) On a more technical level, Guido is worried about how @@'s precedence should work (and this is somewhat related to the other thread about @'s precedence and associativity, because he feels that if we end up giving @ and * different precedence, then that makes it much less clear what to do with @@, and reduces the strength of the */**/@/@@ analogy). In particular, if we want to argue for @@ then we'll need to figure out what expressions like a @@ b @@ c and a ** b @@ c and a @@ b ** c should do. A related question is what @@ should do if given an array as its right argument. In the current PEP, only integers are accepted, which rules out a bunch of the more complicated cases like a @@ b @@ c (at least assuming @@ is right-associative, like **, and I can't see why you'd want anything else). OTOH, in the brave new gufunc world, it technically would make sense to define @@ as being a
Re: [Numpy-discussion] [RFC] should we argue for a matrix power operator, @@?
I think I wouldn't use anything like @@ often enough to remember it's meaning. I'd rather see english names for anything that is not **very** common. I find A@@-1 pretty ugly compared to inv(A) A@@(-0.5) might be nice (do we have matrix_sqrt ?) Josef On Sat, Mar 15, 2014 at 5:11 PM, Stephan Hoyer sho...@gmail.com wrote: Speaking only for myself (and as someone who has regularly used matrix powers), I would not expect matrix power as @@ to follow from matrix multiplication as @. I do agree that matrix power is the only reasonable use for @@ (given @), but it's still not something I would be confident enough to know without looking up. We should keep in mind that each new operator imposes some (small) cognitive burden on everyone who encounters them for the first time, and, in this case, this will include a large fraction of all Python users, whether they do numerical computation or not. Guido has given us a tremendous gift in the form of @. Let's not insist on @@, when it is unclear if the burden of figuring out what @@ means it would be worth using, even for heavily numeric code. I would certainly prefer to encounter norm(A), inv(A), matrix_power(A, n), fractional_matrix_power(A, n) and expm(A) rather than their infix equivalents. It will certainly not be obvious which of these @@ will support for objects from any given library. One useful data point might be to consider whether matrix power is available as an infix operator in other languages commonly used for numerical work. AFAICT from some quick searches: MATLAB: Yes R: No IDL: No All of these languages do, of course, implement infix matrix multiplication, but it is apparently not clear at all whether the matrix power is useful. Best, Stephan On Sat, Mar 15, 2014 at 9:03 AM, Olivier Delalleau sh...@keba.be wrote: 2014-03-15 11:18 GMT-04:00 Charles R Harris charlesr.har...@gmail.com: On Fri, Mar 14, 2014 at 10:32 PM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the second thread for discussion about Guido's concerns about PEP 465. The issue here is that PEP 465 as currently written proposes two new operators, @ for matrix multiplication and @@ for matrix power (analogous to * and **): http://legacy.python.org/dev/peps/pep-0465/ The main thing we care about of course is @; I pushed for including @@ because I thought it was nicer to have than not, and I thought the analogy between * and ** might make the overall package more appealing to Guido's aesthetic sense. It turns out I was wrong :-). Guido is -0 on @@, but willing to be swayed if we think it's worth the trouble to make a solid case. Note that question now is *not*, how will @@ affect the reception of @. @ itself is AFAICT a done deal, regardless of what happens with @@. For this discussion let's assume @ can be taken for granted, and that we can freely choose to either add @@ or not add @@ to the language. The question is: which do we think makes Python a better language (for us and in general)? Some thoughts to start us off: Here are the interesting use cases for @@ that I can think of: - 'vector @@ 2' gives the squared Euclidean length (because it's the same as vector @ vector). Kind of handy. - 'matrix @@ n' of course gives the matrix power, which is of marginal use but does come in handy sometimes, e.g., when looking at graph connectivity. - 'matrix @@ -1' provides a very transparent notation for translating textbook formulas (with all their inverses) into code. It's a bit unhelpful in practice, because (a) usually you should use solve(), and (b) 'matrix @@ -1' is actually more characters than 'inv(matrix)'. But sometimes transparent notation may be important. (And in some cases, like using numba or theano or whatever, 'matrix @@ -1 @ foo' could be compiled into a call to solve() anyway.) (Did I miss any?) In practice it seems to me that the last use case is the one that's might matter a lot practice, but then again, it might not -- I'm not sure. For example, does anyone who teaches programming with numpy have a feeling about whether the existence of '@@ -1' would make a big difference to you and your students? (Alan? I know you were worried about losing the .I attribute on matrices if switching to ndarrays for teaching -- given that ndarray will probably not get a .I attribute, how much would the existence of @@ -1 affect you?) On a more technical level, Guido is worried about how @@'s precedence should work (and this is somewhat related to the other thread about @'s precedence and associativity, because he feels that if we end up giving @ and * different precedence, then that makes it much less clear what to do with @@, and reduces the strength of the */**/@/@@ analogy). In particular, if we want to argue for @@ then we'll need to figure out what expressions like a @@ b @@ c and a ** b @@ c and a @@ b ** c should do. A related question is what @@ should do
Re: [Numpy-discussion] [RFC] should we argue for a matrix power operator, @@?
On Sat, Mar 15, 2014 at 8:38 PM, josef.p...@gmail.com wrote: I think I wouldn't use anything like @@ often enough to remember it's meaning. I'd rather see english names for anything that is not **very** common. I find A@@-1 pretty ugly compared to inv(A) A@@(-0.5) might be nice (do we have matrix_sqrt ?) scipy.linalg.sqrtm: http://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.sqrtm.html Warren Josef On Sat, Mar 15, 2014 at 5:11 PM, Stephan Hoyer sho...@gmail.com wrote: Speaking only for myself (and as someone who has regularly used matrix powers), I would not expect matrix power as @@ to follow from matrix multiplication as @. I do agree that matrix power is the only reasonable use for @@ (given @), but it's still not something I would be confident enough to know without looking up. We should keep in mind that each new operator imposes some (small) cognitive burden on everyone who encounters them for the first time, and, in this case, this will include a large fraction of all Python users, whether they do numerical computation or not. Guido has given us a tremendous gift in the form of @. Let's not insist on @@, when it is unclear if the burden of figuring out what @@ means it would be worth using, even for heavily numeric code. I would certainly prefer to encounter norm(A), inv(A), matrix_power(A, n), fractional_matrix_power(A, n) and expm(A) rather than their infix equivalents. It will certainly not be obvious which of these @@ will support for objects from any given library. One useful data point might be to consider whether matrix power is available as an infix operator in other languages commonly used for numerical work. AFAICT from some quick searches: MATLAB: Yes R: No IDL: No All of these languages do, of course, implement infix matrix multiplication, but it is apparently not clear at all whether the matrix power is useful. Best, Stephan On Sat, Mar 15, 2014 at 9:03 AM, Olivier Delalleau sh...@keba.be wrote: 2014-03-15 11:18 GMT-04:00 Charles R Harris charlesr.har...@gmail.com: On Fri, Mar 14, 2014 at 10:32 PM, Nathaniel Smith n...@pobox.comwrote: Hi all, Here's the second thread for discussion about Guido's concerns about PEP 465. The issue here is that PEP 465 as currently written proposes two new operators, @ for matrix multiplication and @@ for matrix power (analogous to * and **): http://legacy.python.org/dev/peps/pep-0465/ The main thing we care about of course is @; I pushed for including @@ because I thought it was nicer to have than not, and I thought the analogy between * and ** might make the overall package more appealing to Guido's aesthetic sense. It turns out I was wrong :-). Guido is -0 on @@, but willing to be swayed if we think it's worth the trouble to make a solid case. Note that question now is *not*, how will @@ affect the reception of @. @ itself is AFAICT a done deal, regardless of what happens with @@. For this discussion let's assume @ can be taken for granted, and that we can freely choose to either add @@ or not add @@ to the language. The question is: which do we think makes Python a better language (for us and in general)? Some thoughts to start us off: Here are the interesting use cases for @@ that I can think of: - 'vector @@ 2' gives the squared Euclidean length (because it's the same as vector @ vector). Kind of handy. - 'matrix @@ n' of course gives the matrix power, which is of marginal use but does come in handy sometimes, e.g., when looking at graph connectivity. - 'matrix @@ -1' provides a very transparent notation for translating textbook formulas (with all their inverses) into code. It's a bit unhelpful in practice, because (a) usually you should use solve(), and (b) 'matrix @@ -1' is actually more characters than 'inv(matrix)'. But sometimes transparent notation may be important. (And in some cases, like using numba or theano or whatever, 'matrix @@ -1 @ foo' could be compiled into a call to solve() anyway.) (Did I miss any?) In practice it seems to me that the last use case is the one that's might matter a lot practice, but then again, it might not -- I'm not sure. For example, does anyone who teaches programming with numpy have a feeling about whether the existence of '@@ -1' would make a big difference to you and your students? (Alan? I know you were worried about losing the .I attribute on matrices if switching to ndarrays for teaching -- given that ndarray will probably not get a .I attribute, how much would the existence of @@ -1 affect you?) On a more technical level, Guido is worried about how @@'s precedence should work (and this is somewhat related to the other thread about @'s precedence and associativity, because he feels that if we end up giving @ and * different precedence, then that makes it much less clear what to do with @@, and reduces the strength of the */**/@/@@ analogy). In particular, if we want to
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Fri, Mar 14, 2014 at 11:41 PM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the main blocker for adding a matrix multiply operator '@' to Python: we need to decide what we think its precedence and associativity should be. I'll explain what that means so we're on the same page, and what the choices are, and then we can all argue about it. But even better would be if we could get some data to guide our decision, and this would be a lot easier if some of you all can help; I'll suggest some ways you might be able to do that. So! Precedence and left- versus right-associativity. If you already know what these are you can skim down until you see CAPITAL LETTERS. We all know what precedence is. Code like this: a + b * c gets evaluated as: a + (b * c) because * has higher precedence than +. It binds more tightly, as they say. Python's complete precedence able is here: http://docs.python.org/3/reference/expressions.html#operator-precedence Associativity, in the parsing sense, is less well known, though it's just as important. It's about deciding how to evaluate code like this: a * b * c Do we use a * (b * c)# * is right associative or (a * b) * c# * is left associative ? Here all the operators have the same precedence (because, uh... they're the same operator), so precedence doesn't help. And mostly we can ignore this in day-to-day life, because both versions give the same answer, so who cares. But a programming language has to pick one (consider what happens if one of those objects has a non-default __mul__ implementation). And of course it matters a lot for non-associative operations like a - b - c or a / b / c So when figuring out order of evaluations, what you do first is check the precedence, and then if you have multiple operators next to each other with the same precedence, you check their associativity. Notice that this means that if you have different operators that share the same precedence level (like + and -, or * and /), then they have to all have the same associativity. All else being equal, it's generally considered nice to have fewer precedence levels, because these have to be memorized by users. Right now in Python, every precedence level is left-associative, except for '**'. If you write these formulas without any parentheses, then what the interpreter will actually execute is: (a * b) * c (a - b) - c (a / b) / c but a ** (b ** c) Okay, that's the background. Here's the question. We need to decide on precedence and associativity for '@'. In particular, there are three different options that are interesting: OPTION 1 FOR @: Precedence: same as * Associativity: left My shorthand name for it: same-left (yes, very creative) This means that if you don't use parentheses, you get: a @ b @ c - (a @ b) @ c a * b @ c - (a * b) @ c a @ b * c - (a @ b) * c OPTION 2 FOR @: Precedence: more-weakly-binding than * Associativity: right My shorthand name for it: weak-right This means that if you don't use parentheses, you get: a @ b @ c - a @ (b @ c) a * b @ c - (a * b) @ c a @ b * c - a @ (b * c) OPTION 3 FOR @: Precedence: more-tightly-binding than * Associativity: right My shorthand name for it: tight-right This means that if you don't use parentheses, you get: a @ b @ c - a @ (b @ c) a * b @ c - a * (b @ c) a @ b * c - (a @ b) * c We need to pick which of which options we think is best, based on whatever reasons we can think of, ideally more than hmm, weak-right gives me warm fuzzy feelings ;-). (In principle the other 2 possible options are tight-left and weak-left, but there doesn't seem to be any argument in favor of either, so we'll leave them out of the discussion.) Some things to consider: * and @ are actually not associative (in the math sense) with respect to each other, i.e., (a * b) @ c and a * (b @ c) in general give different results when 'a' is not a scalar. So considering the two expressions 'a * b @ c' and 'a @ b * c', we can see that each of these three options gives produces different results in some cases. Same-left is the easiest to explain and remember, because it's just, @ acts like * and /. So we already have to know the rule in order to understand other non-associative expressions like a / b / c or a - b - c, and it'd be nice if the same rule applied to things like a * b @ c so we only had to memorize *one* rule. (Of course there's ** which uses the opposite rule, but I guess everyone internalized that one in secondary school; that's not true for * versus @.) This is definitely the default we should choose unless we have a good reason to do otherwise. BUT: there might indeed be a good reason to do otherwise, which is the whole reason this has come up. Consider: Mat1 @ Mat2 @ vec Obviously this will execute much more quickly if we do Mat1 @ (Mat2 @ vec) because that results in
Re: [Numpy-discussion] [RFC] should we argue for a matrix power operator, @@?
On Sat, Mar 15, 2014 at 8:47 PM, Warren Weckesser warren.weckes...@gmail.com wrote: On Sat, Mar 15, 2014 at 8:38 PM, josef.p...@gmail.com wrote: I think I wouldn't use anything like @@ often enough to remember it's meaning. I'd rather see english names for anything that is not **very** common. I find A@@-1 pretty ugly compared to inv(A) A@@(-0.5) might be nice (do we have matrix_sqrt ?) scipy.linalg.sqrtm: http://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.sqrtm.html maybe a good example: I could never figured that one out M = sqrtm(A) A = M @ M but what we use in stats is A = R.T @ R (eigenvectors dot diag(sqrt of eigenvalues) which sqrt is A@@(0.5) ? Josef Warren Josef On Sat, Mar 15, 2014 at 5:11 PM, Stephan Hoyer sho...@gmail.com wrote: Speaking only for myself (and as someone who has regularly used matrix powers), I would not expect matrix power as @@ to follow from matrix multiplication as @. I do agree that matrix power is the only reasonable use for @@ (given @), but it's still not something I would be confident enough to know without looking up. We should keep in mind that each new operator imposes some (small) cognitive burden on everyone who encounters them for the first time, and, in this case, this will include a large fraction of all Python users, whether they do numerical computation or not. Guido has given us a tremendous gift in the form of @. Let's not insist on @@, when it is unclear if the burden of figuring out what @@ means it would be worth using, even for heavily numeric code. I would certainly prefer to encounter norm(A), inv(A), matrix_power(A, n), fractional_matrix_power(A, n) and expm(A) rather than their infix equivalents. It will certainly not be obvious which of these @@ will support for objects from any given library. One useful data point might be to consider whether matrix power is available as an infix operator in other languages commonly used for numerical work. AFAICT from some quick searches: MATLAB: Yes R: No IDL: No All of these languages do, of course, implement infix matrix multiplication, but it is apparently not clear at all whether the matrix power is useful. Best, Stephan On Sat, Mar 15, 2014 at 9:03 AM, Olivier Delalleau sh...@keba.bewrote: 2014-03-15 11:18 GMT-04:00 Charles R Harris charlesr.har...@gmail.com : On Fri, Mar 14, 2014 at 10:32 PM, Nathaniel Smith n...@pobox.comwrote: Hi all, Here's the second thread for discussion about Guido's concerns about PEP 465. The issue here is that PEP 465 as currently written proposes two new operators, @ for matrix multiplication and @@ for matrix power (analogous to * and **): http://legacy.python.org/dev/peps/pep-0465/ The main thing we care about of course is @; I pushed for including @@ because I thought it was nicer to have than not, and I thought the analogy between * and ** might make the overall package more appealing to Guido's aesthetic sense. It turns out I was wrong :-). Guido is -0 on @@, but willing to be swayed if we think it's worth the trouble to make a solid case. Note that question now is *not*, how will @@ affect the reception of @. @ itself is AFAICT a done deal, regardless of what happens with @@. For this discussion let's assume @ can be taken for granted, and that we can freely choose to either add @@ or not add @@ to the language. The question is: which do we think makes Python a better language (for us and in general)? Some thoughts to start us off: Here are the interesting use cases for @@ that I can think of: - 'vector @@ 2' gives the squared Euclidean length (because it's the same as vector @ vector). Kind of handy. - 'matrix @@ n' of course gives the matrix power, which is of marginal use but does come in handy sometimes, e.g., when looking at graph connectivity. - 'matrix @@ -1' provides a very transparent notation for translating textbook formulas (with all their inverses) into code. It's a bit unhelpful in practice, because (a) usually you should use solve(), and (b) 'matrix @@ -1' is actually more characters than 'inv(matrix)'. But sometimes transparent notation may be important. (And in some cases, like using numba or theano or whatever, 'matrix @@ -1 @ foo' could be compiled into a call to solve() anyway.) (Did I miss any?) In practice it seems to me that the last use case is the one that's might matter a lot practice, but then again, it might not -- I'm not sure. For example, does anyone who teaches programming with numpy have a feeling about whether the existence of '@@ -1' would make a big difference to you and your students? (Alan? I know you were worried about losing the .I attribute on matrices if switching to ndarrays for teaching -- given that ndarray will probably not get a .I attribute, how much would the existence of @@ -1 affect you?) On a more technical level, Guido is worried about how @@'s precedence should work
Re: [Numpy-discussion] [RFC] should we argue for a matrix power operator, @@?
On Sat, Mar 15, 2014 at 1:13 PM, Alan G Isaac alan.is...@gmail.com wrote: On 3/15/2014 12:32 AM, Nathaniel Smith wrote: I know you were worried about losing the .I attribute on matrices if switching to ndarrays for teaching -- given that ndarray will probably not get a .I attribute, how much would the existence of @@ -1 affect you? Not much. Positive integer powers would be useful (for illustrating e.g. graph theory and difference equations), but not enough to delay the PEP. So to be clear, even if numpy.matrix is going away, and even if ndarray isn't getting a .I attribute, then you're just as happy typing/teaching inv(X) as X @@ -1? I think NumPy should take the money and run. Getting `@` is great. Let's get experience with it before deciding whether it's worth asking for `@@`. Questions for `@@`: - would it just be `matrix_power`, with all the restrictions? - or would `a(10,2,2)@@-1` return an array of matrix inverses? - etc The version in the PEP does do gufunc-style broadcasting for 2d arrays, yes. So will np.linalg.matrix_power as soon as someone bothers to send a patch ;-) In the end, I'd like to see a functional implementation before deciding on `@@`, but I would not like to see `@` delayed at all. Oh, well, not much is going to affect `@`'s timing, unless we're *dreadfully* slow. Py 3.5 isn't even scheduled yet b/c 3.4 isn't out, and IIUC Python's standard release cycle is 18 months. So we've got a year+ before feature freeze, regardless. -n -- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 7:20 PM, josef.p...@gmail.com wrote: On Fri, Mar 14, 2014 at 11:41 PM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the main blocker for adding a matrix multiply operator '@' to Python: we need to decide what we think its precedence and associativity should be. I'll explain what that means so we're on the same page, and what the choices are, and then we can all argue about it. But even better would be if we could get some data to guide our decision, and this would be a lot easier if some of you all can help; I'll suggest some ways you might be able to do that. So! Precedence and left- versus right-associativity. If you already know what these are you can skim down until you see CAPITAL LETTERS. We all know what precedence is. Code like this: a + b * c gets evaluated as: a + (b * c) because * has higher precedence than +. It binds more tightly, as they say. Python's complete precedence able is here: http://docs.python.org/3/reference/expressions.html#operator-precedence Associativity, in the parsing sense, is less well known, though it's just as important. It's about deciding how to evaluate code like this: a * b * c Do we use a * (b * c)# * is right associative or (a * b) * c# * is left associative ? Here all the operators have the same precedence (because, uh... they're the same operator), so precedence doesn't help. And mostly we can ignore this in day-to-day life, because both versions give the same answer, so who cares. But a programming language has to pick one (consider what happens if one of those objects has a non-default __mul__ implementation). And of course it matters a lot for non-associative operations like a - b - c or a / b / c So when figuring out order of evaluations, what you do first is check the precedence, and then if you have multiple operators next to each other with the same precedence, you check their associativity. Notice that this means that if you have different operators that share the same precedence level (like + and -, or * and /), then they have to all have the same associativity. All else being equal, it's generally considered nice to have fewer precedence levels, because these have to be memorized by users. Right now in Python, every precedence level is left-associative, except for '**'. If you write these formulas without any parentheses, then what the interpreter will actually execute is: (a * b) * c (a - b) - c (a / b) / c but a ** (b ** c) Okay, that's the background. Here's the question. We need to decide on precedence and associativity for '@'. In particular, there are three different options that are interesting: OPTION 1 FOR @: Precedence: same as * Associativity: left My shorthand name for it: same-left (yes, very creative) This means that if you don't use parentheses, you get: a @ b @ c - (a @ b) @ c a * b @ c - (a * b) @ c a @ b * c - (a @ b) * c OPTION 2 FOR @: Precedence: more-weakly-binding than * Associativity: right My shorthand name for it: weak-right This means that if you don't use parentheses, you get: a @ b @ c - a @ (b @ c) a * b @ c - (a * b) @ c a @ b * c - a @ (b * c) OPTION 3 FOR @: Precedence: more-tightly-binding than * Associativity: right My shorthand name for it: tight-right This means that if you don't use parentheses, you get: a @ b @ c - a @ (b @ c) a * b @ c - a * (b @ c) a @ b * c - (a @ b) * c We need to pick which of which options we think is best, based on whatever reasons we can think of, ideally more than hmm, weak-right gives me warm fuzzy feelings ;-). (In principle the other 2 possible options are tight-left and weak-left, but there doesn't seem to be any argument in favor of either, so we'll leave them out of the discussion.) Some things to consider: * and @ are actually not associative (in the math sense) with respect to each other, i.e., (a * b) @ c and a * (b @ c) in general give different results when 'a' is not a scalar. So considering the two expressions 'a * b @ c' and 'a @ b * c', we can see that each of these three options gives produces different results in some cases. Same-left is the easiest to explain and remember, because it's just, @ acts like * and /. So we already have to know the rule in order to understand other non-associative expressions like a / b / c or a - b - c, and it'd be nice if the same rule applied to things like a * b @ c so we only had to memorize *one* rule. (Of course there's ** which uses the opposite rule, but I guess everyone internalized that one in secondary school; that's not true for * versus @.) This is definitely the default we should choose unless we have a good reason to do otherwise. BUT: there might indeed be a good reason to do otherwise, which is the whole reason this has come up. Consider: Mat1 @ Mat2 @ vec Obviously this will execute much more
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 11:30 PM, Charles R Harris charlesr.har...@gmail.com wrote: On Sat, Mar 15, 2014 at 7:20 PM, josef.p...@gmail.com wrote: On Fri, Mar 14, 2014 at 11:41 PM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the main blocker for adding a matrix multiply operator '@' to Python: we need to decide what we think its precedence and associativity should be. I'll explain what that means so we're on the same page, and what the choices are, and then we can all argue about it. But even better would be if we could get some data to guide our decision, and this would be a lot easier if some of you all can help; I'll suggest some ways you might be able to do that. So! Precedence and left- versus right-associativity. If you already know what these are you can skim down until you see CAPITAL LETTERS. We all know what precedence is. Code like this: a + b * c gets evaluated as: a + (b * c) because * has higher precedence than +. It binds more tightly, as they say. Python's complete precedence able is here: http://docs.python.org/3/reference/expressions.html#operator-precedence Associativity, in the parsing sense, is less well known, though it's just as important. It's about deciding how to evaluate code like this: a * b * c Do we use a * (b * c)# * is right associative or (a * b) * c# * is left associative ? Here all the operators have the same precedence (because, uh... they're the same operator), so precedence doesn't help. And mostly we can ignore this in day-to-day life, because both versions give the same answer, so who cares. But a programming language has to pick one (consider what happens if one of those objects has a non-default __mul__ implementation). And of course it matters a lot for non-associative operations like a - b - c or a / b / c So when figuring out order of evaluations, what you do first is check the precedence, and then if you have multiple operators next to each other with the same precedence, you check their associativity. Notice that this means that if you have different operators that share the same precedence level (like + and -, or * and /), then they have to all have the same associativity. All else being equal, it's generally considered nice to have fewer precedence levels, because these have to be memorized by users. Right now in Python, every precedence level is left-associative, except for '**'. If you write these formulas without any parentheses, then what the interpreter will actually execute is: (a * b) * c (a - b) - c (a / b) / c but a ** (b ** c) Okay, that's the background. Here's the question. We need to decide on precedence and associativity for '@'. In particular, there are three different options that are interesting: OPTION 1 FOR @: Precedence: same as * Associativity: left My shorthand name for it: same-left (yes, very creative) This means that if you don't use parentheses, you get: a @ b @ c - (a @ b) @ c a * b @ c - (a * b) @ c a @ b * c - (a @ b) * c OPTION 2 FOR @: Precedence: more-weakly-binding than * Associativity: right My shorthand name for it: weak-right This means that if you don't use parentheses, you get: a @ b @ c - a @ (b @ c) a * b @ c - (a * b) @ c a @ b * c - a @ (b * c) OPTION 3 FOR @: Precedence: more-tightly-binding than * Associativity: right My shorthand name for it: tight-right This means that if you don't use parentheses, you get: a @ b @ c - a @ (b @ c) a * b @ c - a * (b @ c) a @ b * c - (a @ b) * c We need to pick which of which options we think is best, based on whatever reasons we can think of, ideally more than hmm, weak-right gives me warm fuzzy feelings ;-). (In principle the other 2 possible options are tight-left and weak-left, but there doesn't seem to be any argument in favor of either, so we'll leave them out of the discussion.) Some things to consider: * and @ are actually not associative (in the math sense) with respect to each other, i.e., (a * b) @ c and a * (b @ c) in general give different results when 'a' is not a scalar. So considering the two expressions 'a * b @ c' and 'a @ b * c', we can see that each of these three options gives produces different results in some cases. Same-left is the easiest to explain and remember, because it's just, @ acts like * and /. So we already have to know the rule in order to understand other non-associative expressions like a / b / c or a - b - c, and it'd be nice if the same rule applied to things like a * b @ c so we only had to memorize *one* rule. (Of course there's ** which uses the opposite rule, but I guess everyone internalized that one in secondary school; that's not true for * versus @.) This is definitely the default we should choose unless we have a good reason to do otherwise. BUT: there might indeed be a good reason to do otherwise, which is the whole reason this
Re: [Numpy-discussion] [help needed] associativity and precedence of '@'
On Sat, Mar 15, 2014 at 10:53 PM, josef.p...@gmail.com wrote: On Sat, Mar 15, 2014 at 11:30 PM, Charles R Harris charlesr.har...@gmail.com wrote: On Sat, Mar 15, 2014 at 7:20 PM, josef.p...@gmail.com wrote: On Fri, Mar 14, 2014 at 11:41 PM, Nathaniel Smith n...@pobox.com wrote: Hi all, Here's the main blocker for adding a matrix multiply operator '@' to Python: we need to decide what we think its precedence and associativity should be. I'll explain what that means so we're on the same page, and what the choices are, and then we can all argue about it. But even better would be if we could get some data to guide our decision, and this would be a lot easier if some of you all can help; I'll suggest some ways you might be able to do that. So! Precedence and left- versus right-associativity. If you already know what these are you can skim down until you see CAPITAL LETTERS. We all know what precedence is. Code like this: a + b * c gets evaluated as: a + (b * c) because * has higher precedence than +. It binds more tightly, as they say. Python's complete precedence able is here: http://docs.python.org/3/reference/expressions.html#operator-precedence Associativity, in the parsing sense, is less well known, though it's just as important. It's about deciding how to evaluate code like this: a * b * c Do we use a * (b * c)# * is right associative or (a * b) * c# * is left associative ? Here all the operators have the same precedence (because, uh... they're the same operator), so precedence doesn't help. And mostly we can ignore this in day-to-day life, because both versions give the same answer, so who cares. But a programming language has to pick one (consider what happens if one of those objects has a non-default __mul__ implementation). And of course it matters a lot for non-associative operations like a - b - c or a / b / c So when figuring out order of evaluations, what you do first is check the precedence, and then if you have multiple operators next to each other with the same precedence, you check their associativity. Notice that this means that if you have different operators that share the same precedence level (like + and -, or * and /), then they have to all have the same associativity. All else being equal, it's generally considered nice to have fewer precedence levels, because these have to be memorized by users. Right now in Python, every precedence level is left-associative, except for '**'. If you write these formulas without any parentheses, then what the interpreter will actually execute is: (a * b) * c (a - b) - c (a / b) / c but a ** (b ** c) Okay, that's the background. Here's the question. We need to decide on precedence and associativity for '@'. In particular, there are three different options that are interesting: OPTION 1 FOR @: Precedence: same as * Associativity: left My shorthand name for it: same-left (yes, very creative) This means that if you don't use parentheses, you get: a @ b @ c - (a @ b) @ c a * b @ c - (a * b) @ c a @ b * c - (a @ b) * c OPTION 2 FOR @: Precedence: more-weakly-binding than * Associativity: right My shorthand name for it: weak-right This means that if you don't use parentheses, you get: a @ b @ c - a @ (b @ c) a * b @ c - (a * b) @ c a @ b * c - a @ (b * c) OPTION 3 FOR @: Precedence: more-tightly-binding than * Associativity: right My shorthand name for it: tight-right This means that if you don't use parentheses, you get: a @ b @ c - a @ (b @ c) a * b @ c - a * (b @ c) a @ b * c - (a @ b) * c We need to pick which of which options we think is best, based on whatever reasons we can think of, ideally more than hmm, weak-right gives me warm fuzzy feelings ;-). (In principle the other 2 possible options are tight-left and weak-left, but there doesn't seem to be any argument in favor of either, so we'll leave them out of the discussion.) Some things to consider: * and @ are actually not associative (in the math sense) with respect to each other, i.e., (a * b) @ c and a * (b @ c) in general give different results when 'a' is not a scalar. So considering the two expressions 'a * b @ c' and 'a @ b * c', we can see that each of these three options gives produces different results in some cases. Same-left is the easiest to explain and remember, because it's just, @ acts like * and /. So we already have to know the rule in order to understand other non-associative expressions like a / b / c or a - b - c, and it'd be nice if the same rule applied to things like a * b @ c so we only had to memorize *one* rule. (Of course there's ** which uses the opposite rule, but I guess everyone internalized that one in secondary school; that's not true for * versus @.) This is definitely the default we should choose unless we have a good reason to do otherwise. BUT: there might