6
$\begingroup$

How to multiply two matrices, which elements themselves are matrices? The following works but is there a more elegant way?

(A = Array[Subscript[a, ##] &, {3, 3, 2, 2}]) // MatrixForm

Matrix A

(B = Array[Subscript[b, ##] &, {3, 1, 2}]) // MatrixForm

Matrix B

dotdot[A_, B_] := Table[Sum[A[[i, l]].B[[l, j]], {l, Dimensions[A][[2]]}], {i, Dimensions[A][[1]]}, {j, Dimensions[B][[2]]}];
dotdot[A, B] // MatrixForm

Matrix AB

$\endgroup$
9
$\begingroup$

One way is to turn them into ordinary matrices, take the dot product, and then ArrayReshape them into the form you want.

Af = ArrayFlatten[A];
Bf = Flatten[B];

ArrayReshape[Af.Bf, {3, 1, 2}] // MatrixForm

enter image description here

Just to check:

ArrayReshape[Af.Bf, {3, 1, 2}] == dotdot[A, B]

(* True *)
$\endgroup$
5
$\begingroup$

You could use TensorContract instead:

r1 = dotdot[A, B];
r2 = TensorTranspose[
    TensorContract[TensorProduct[A, B], {{2, 5}, {4, 7}}],
    {1, 3, 2}
];

r1 === r2

True

Comparison

One advantage of the TensorContract approach is that if A and B are sparse arrays, then the result is also a sparse array. This is not true for the other answers. For example:

A=SparseArray @ RandomChoice[{.9,.1}->{0,1}, {5, 6, 7, 8}];
B=SparseArray @ RandomChoice[{.9,.1}->{0,1}, {6, 9, 8}];

r1 = dotdot[A, B];
r2 = TensorTranspose[
    TensorContract[TensorProduct[A, B], {{2, 5}, {4, 7}}],
    {1, 3, 2}
];

Normal[r1] === Normal[r2]
Head /@ {r1, r2}

True

{List, SparseArray}

I didn't include @aardvark2012's answer because ArrayReshape apparently doesn't work with sparse arrays anyway

$\endgroup$
  • $\begingroup$ great, you guessed my next question: how to do the same with SparseArray.. $\endgroup$ – tukan Oct 29 '17 at 10:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.