# Apply Outer to list of matrices and vectors

I have a list, M, of square $$n \times n$$ matrices, {M1, M2, M3, ...}, and a list, V, of $$n \times 1$$ vectors, {v1, v2, v3, ...}, and the corresponding transposes of those vectors {r1, r2, r3, ...}. I'm trying to form the matrix {{r1.M1.v1, r2.M1.v2, r3.M1.v3, ...}, {{r1.M2.v1, r2.M2.v2, r3.M2.v3, ...}, ...}. Note that M and V are not necessarily the same length (i.e. there may only be 5 matrices, but 100 vectors).

It seemed like a method using Outer would work, such as: Outer[Transpose[#2].#1.#2 &, M, V], which should then just be a 2-dimensional matrix of scalars.

However, I think that this runs into a problem because the lists M and V are themselves technically lists of lists (M being a list of matrices, V being a list of vectors), and so the outer gets distributed into the sublists, rather than doing the calculation I want and it ends up being a high dimensional object. I've tried playing around with various flattening schemes, but haven't quite figured it out - any assistance on how to implement this functionality (is Outer even the correct functional tool to use)?

• I believe what you want is Outer[#2.#1.#2 &, M, V, 1, 1]? – march Feb 15 '20 at 0:56

I believe what you want is

Outer[#2.#1.#2 &, M, V, 1]


First of all, you don't need to Transpose vectors in Mathematica. Dot knows what to do automatically. Second, you need to use the optional extra argument for Outer that tells it the level at which the "object" that you are feeding to the function lives. Otherwise, Outer seeks the lowest level by default. Since your "objects" are at level 1 in both lists (the elements of the lists which are either matrices or vectors), use the level-spec 1 as the extra argument to Outer.

• Ah ok. My problem is that my vectors V are defined as column vectors, i.e. v1={{1},{0},{0},{0}}. So I think that was screwing up the Outer. Flattening them does indeed work as you show. However, is there a way to work with the V as I had defined previously? It would be more convenient, as long as it would be much more complicated. – KHAAAAAAAAN Feb 15 '20 at 1:15
• @KHAAAAAAAAN In that case, I think do Flatten /@ Outer[Transpose[#2].#1.#2 &, M, V, 1]? – march Feb 16 '20 at 18:15

Just use Table

SeedRandom@12;
m = Table[RandomInteger[5, {2, 2}], 3];
MatrixForm /@ m


m=$$\{\left( \begin{array}{cc} 1 & 1 \\ 0 & 0 \\ \end{array} \right),\left( \begin{array}{cc} 5 & 4 \\ 1 & 4 \\ \end{array} \right),\left( \begin{array}{cc} 5 & 3 \\ 0 & 5 \\ \end{array} \right)\}$$

v = Table[RandomInteger[5, 2], 3]


v={{3, 4}, {1, 1}, {2, 5}}

Table[v[[j]].m[[i]].v[[j]], {i, Length@m}, {j, Length@m}]


{{21, 2, 14}, {169, 14, 170}, {161, 13, 175}}

Second Solution

#2.#1.#2 & @@@ Tuples[{m, v}] // Partition[#, 3] &

• Yeah this thought had occurred, but it seemed a less elegant solution than Outer, though of course still functional. That should be {j, Length@v} though I take it? – KHAAAAAAAAN Feb 15 '20 at 0:35
• Length@v=Length@m – OkkesDulgerci Feb 15 '20 at 0:37
• Well in general the list V and list M are not the same size for my use case, sorry that probably was not clear from my initial question. – KHAAAAAAAAN Feb 15 '20 at 0:48