About weak-left. You need to define a priority of @ the matrix product regarding to * the elementwise product because (A*B)@C <> A*(B@C) : see the example above. I say that also from a mathematical point of view.

Using mathematical like notations, Matrix1 * Matrix2 * 3 can be written because (Matrix1 * Matrix2) * 3 = Matrix1 * (Matrix2 * 3).

That's why I think that the weak-left is the better choice.

About group implementation. I think the idea of calculating A@B@C as __atmul__([A,B,C]) is a very good idea because this allows efficient implementations.

---------------------
    [1 2]
A = [3 4]

    [5 6]
B = [7 8]

    [a d]
C = [b c]

---------------------
(A*B)@C
=
[5  12]   [a d]
[21 32] @ [b c]
=
[5a+12b  5d+12c ]
[21a+32b 21d+32c]

---------------------
A*(B@C)
=
[1 2]   [5a+6b 5d+6c]
[3 4] * [7a+8b 7d+8c]
=
[5a+6b   10d+12c]
[21a+24b 28d+32c]



2014-03-18 10:50 GMT+01:00 Eelco Hoogendoorn <hoogendoorn.eelco@gmail.com>:
To elaborate a little on such a more general and explicit method of specifying linear operations (perhaps 'expressions with named axes' is a good nomer to cover this topic).

I think indexing rather than calling is preferable. I worried at first about the performance overhead of checking for strings at every indexing op, but get ndarray__getitem__ is already quite a complex beast anyway, and adding (yet another) type test on its args isn't a significant difference. For those who disagree; we could also approach strings with a 'forgiveness is better then permission' attitude.

The general rules could be: if no string args, everything works as normal. In case of string args, we may think of the effect of __getitem__ as indexing with strings replaced by colons first, and then creating a NamedAxisIndexExpression (NAIE), associating the given string label with each corresponding axis. Thus, we can write things like A[0:3,'i']

As some additional rules; string arguments can be 'expanded', the string is split on commas if present, and otherwise split into characters, which are then the axis labels.

In expressions, all non-labeled axes are treated in sequential order, similar to the ... construct, and have standard numpy broadcasting semantics.

The only problem with [] notation is field name lookup; though I have always felt that tables with named columns should be an ndarray subtype, given their fundamentally different indexing semantics.

Realizing the full potential of such an approach would be a complex undertaking, but to start with, a more elegant interface to np.einsum would be rather easy to implement.


On Tue, Mar 18, 2014 at 9:46 AM, Sebastian Haase <seb.haase@gmail.com> wrote:
Just add one vote:  I am for
* right association *
because  1) I'm thinking of matrix multiplication more like operators,
which I also learned to work from right to left and because 2) I would
put a vector to the right, which would result in better performance.

I don't have an opinion on tight/same/ or weak.... (maybe that means
then 'same' because it's easier to remember !?)

My two cents,
Sebastian Haase


On Tue, Mar 18, 2014 at 7:13 AM, Eelco Hoogendoorn
<hoogendoorn.eelco@gmail.com> wrote:
>
>
> Perhaps this a bit of a thread hyjack; but this discussion got me thinking
> about how to arrive
>
> at a more vectorized/tensorified way of specifying linear algebra
> operations, in an elegant manner.
>
> I probably got a little carried away, but what about this syntax?
>
> indexing/calling an ndarray with a string returns a TensorExpression object
> these TensorExpression objects can be combined into a graph using operator
> overloads
> and these graphs are translated to calls to BLAS or einsum, as is
> appropriate
>
>
> #declare some symbols
> i,j,ij,k = 'i','j','ij','k'
> #we may force evaluation of a (sub) TensorExpression by calling it
> #this is trivial to translate to call to einsum
> #but such special cases could be dispatched to BLAS as well
> b = (A(ij) * x(j)) (i)
> #alternatively, we can predeclare a LHS which is automatically sized later
> #note that this translates into the same call as the above; just some
> syntactic sugar
> b = np.empty(())
> b[i] = A(ij) * x(j)
> #more complex TensorExpression graphs of this form are trivial to translate
> to a call to einsum as well
> a(i)*b(j)*c(k)
> #conceptually, there is no need to limit this scheme to multiplications
> only!
> #although such generalizations would require a more complex execution engine
> #however, the revamped nditer should make this quite managable to implement
> a(i)*b(j) + c(k)
> #if axes strings are omitted, standard numpy broadcasting rules are applied
> to the expressiongraph created
> #this is identical to a*b+c; except that we have the opportunity to
> eliminate temporaries
> a()*b()+c()
>
>
> Note that such an approach kills quite some birds with one stone
> it allows for the elimination of temporaries along the lines of numexpr
>
> But if i could write:
>
> b[i] = A[ij] * x[j]
> I would much prefer that over
> b = A @ x
> even though the latter is shorter
>
> Now if i had n input and output vectors, it would be easy what to do with
> them:
>
> b[ni] = A[ij] * x[nj]
>
> As i argued earlier, I much prefer this form of explicitness over
> conventions about what constitutes a row or column vector. And vectorization
> of linear algebra is a trivial extension in this manner, which in itself is
> just a subset of even more general multilinear products, which themselves
> are a subset of more general expression involving things other than products
>
> Its a somewhat ambitious idea, and there are probably reasons why it isnt a
> good idea as well, but it does not require python language modifications,
> and it does not clash with any other functionality or syntax of numpy, as
> far as i can tell. Calling of arrays is not yet defined, and alternatively
> array indexing could be overloaded on string type.
>
> Either way, something to chew on when deciding on the best way to go
> forward.
>
>
>
>
>
> On Tue, Mar 18, 2014 at 4:28 AM, Mark Daoust <daoust.mj@gmail.com> wrote:
>>
>> On Mon, Mar 17, 2014 at 8:54 PM, Nathaniel Smith <njs@pobox.com> wrote:
>>>
>>>
>>> But, this is actually a feature! Because obviously what *should* be
>>> returned in this case is *not* (Mat @ vec) @ Mat, *or* Mat @ (vec @
>>> Mat). Both of those answers are terrible; it's just, if you have an
>>> ordinary left-/right-associative operator, those are your only
>>> options. What *should* be returned is an error. And in this scheme we
>>> get to see the whole @ expression at once, so we actually can raise an
>>> error for such things.
>>
>>
>>
>> Sorry if this is a little off topic.
>>
>> But there's still something about the "vector" examples that bugs me,
>> "matrix@vector" and "vector@@2", keep popping up (this also applies to the
>> matrix@matrix examples to a lesser extent).
>>
>> I'm a little unconformable looking at the shape to to decide what's a
>> matrix and what's a vector. (Matlab has some problems like this)
>>
>> If it only has one or two dimensions it's easy, but I always find that if
>> I've written code that works for 1 matrix or vector, 5 minutes later I want
>> it to work for fields of matrices or vectors. If we're just going by shape
>> there's no way to distinguish between a 2d field of matrices and a 3d field
>> of vectors.
>>
>> I guess this is a repeat of part of what Eelco Hoogendoorn saying a few
>> posts back
>>
>> I was just wondering if anyone sees a place, to get @ a little closer to
>> Einsum, for some sort of array class that understands the difference between
>> a 4D array of scalars, a 3D array of vectors, and a 2D array of matrices...
>> The difference between the axes that broad-cast and the axes that can sum
>> when you hit them with an @ ... or something like that.
>>
>> Just a thought.
>>
>> Einsum is fantastic by the way, totally worth learning and using.
>>
>>
>>
>>
>> Mark Daoust
>>
>> _______________________________________________
>> 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
>
_______________________________________________
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