# On elegant use of Inner and Outer on tensors

I have a collection of 5-element vectors each of which corresponds to an {x,y} location from a (20 x 21) grid. Because of that I represent that data as a (5 x 20 x 21)-sized tensor called W.

I also have a set of 128 (5 x 5)-sized matrices which I've packed as a (128 x 5 x 5) tensor called R.

I then want to compute for each vector in W and each matrix in R the product Transpose[w].r.w (which is a scalar) and obtain a (128 x 20 x 21)-sized tensor. Finally, I only care about the sum over the 128 matrices, which will be a (20 x 21)-sized matrix.

I can compute that operation with the following command which leaves me very unsatisfied since it seems somewhat inelegant:

Total[Outer[#1.#2.#1 &, TensorTranspose[W, {3, 2, 1}], R, 2, 1], {3}]


It seems to me that there should be a way to not use TensorTranspose, and that the Total should be redundant if I were to use Inner. However I don't see a clean way to use level specifications to get the answer I want. Any ideas? (preferably ones that are efficient too!).

If you have to know, this implements a 5-sensor broadband delay-and-sum beamscanner. W holds the steering vectors for each location to scan, and R are the covariance matrices for each frequency band.

Thanks!

Perhaps I'm missing something, but can't you sum the covariance matrices at the start?

result =  With[{r = Total @ R}, Map[#.r.# &, Transpose[W, {3, 2, 1}], {2}]]


This is several hundred times faster than the original.

Take care!! With the instruction:

Total[Outer[#1.#2.#1 &, TensorTranspose[W, {3, 2, 1}], R, 2, 1], {3}]


you are effectively doing:

Transpose[w].r.Transpose[w]


If you really want to do:

Transpose[w].r.w


Then you should:

Total[Outer[TensorTranspose[#1, {3, 2, 1}].#2.#1 &, W, R, 2, 1], {3}]