I'm not saying that Python choices are wrong, I'm just saying that if * is elementwise product, then (A*B)@C <> A*(B@C) should imply to choose different levels fro * and @.

By choosing A*B@C = (A*B)@C, that is a convention, we just say that a human who want to calculate something like A*B@C*D@E@G*H*K will have to start first with the elementwise products and then finish by the matrix product that is to say this human will evaluate (A*B)@(C*D)@E@(G*H*K).

Maybe you should argue to calculate first the @-products but this will not be a good choice if * is the product of a scalar with a matrix like in 2*A@3*B.

On the other hand, if you calculate from left to right, there will be a lot of isolate @-products to do instead of doing a single one. This will not allow to use the very good group technic you have proposed.

1) If A*B@C*D@E@G*H*K = (A*B)@(C*D)@E@(G*H*K), you quickly evaluate first X = A*B, Y = C*D and Z = G*H*K, and then you can do an efficient @-product of X, Y and Z.

2) If you calculate from left to right, you will do three @-products on couple without having the possibility to choose the more efficient way to evaluate the @-products.

Christophe BAL

PS1: // is an approximate calculation of the exact mathematical inversion, so it is not really a counter example.

PS2: here is a second time my example showing that (A*B)@C <> A*(B@C).

[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]