I have a problem which requires taking product of two $10\times10$ matrices. I would like to do it by considering both matrices as $5\times5$ matrices such that each entry of both matrices is actually a $2\times2$ matrix; moreover, there are variables so this is a symbolic calculation. (Side remark: matrix multiplication is not a commutative operation, i.e. $AB\neq BA$ in general.) Does anyone know how to perform this block form multiplication in Mathematica, or using any other software?

  • $\begingroup$ Welcome! I added $\LaTeX$ markup to your question to make it read better. In the future, you can do the same by wrapping inline equations with $ and $$ to provide block style equations. If you have any questions about the operation of this site, please check out the FAQ, and the meta site. $\endgroup$
    – rcollyer
    Jul 5 '12 at 2:17
  • $\begingroup$ Got you! Thanks! $\endgroup$
    – Danny
    Jul 5 '12 at 2:54
  • 1
    $\begingroup$ Take a look at the (free) NCAlgebra package, see e.g. here: mathematica.stackexchange.com/questions/8/… You'll need it when doing more general operation on the block form of matrices. I'll post an answer if/when I have the time. $\endgroup$
    – Szabolcs
    Jul 5 '12 at 7:27
  • $\begingroup$ @Szabolcs: Thanks! I will bear this package in mind. Right now I am trying the function blockMultiply $\endgroup$
    – Danny
    Jul 5 '12 at 16:39

If I understand correctly, the main issue in your question is how to make a Dot product of two block matrices such that the result preserves the order of the factors in the resulting block matrix, because the entries are non-commuting matrices themselves.

The problem is that the result of Dot has multiplications of the matrix components in it, and this corresponds to the operation Times which is orderless. Dot preserves the order of its factors, but Times always sorts its factors lexicographically, i.e., in a standard sorting order so that z*b becomes b*z and m[2]*m[1] becomes m[1]*m[2], etc.

If one were to use the Dot function for the matrix multiplication, one would have to track in what way the order of the input factors is changed when brought into the lexicographical order of Times, and then undo that sorting.


As Mr. Wizard pointed out, it is best to us a generalization of Dot that doesn't apply Times to the components at all:

blockMultiply[mats__] := Inner[Dot, mats]

End edit

To show how this works, let's first define two $5\times 5$ matrices called smallMatrix[[1]] and smallMatrix[[2]]. I define them in one go, and show them afterwards:

smallMatrix = Table[Array[{"A", "B"}[[i]], {5, 5}], {i, 2}];


$\left( \begin{array}{ccccc} \text{A}(1,1) & \text{A}(1,2) & \text{A}(1,3) & \text{A}(1,4) & \text{A}(1,5) \\ \text{A}(2,1) & \text{A}(2,2) & \text{A}(2,3) & \text{A}(2,4) & \text{A}(2,5) \\ \text{A}(3,1) & \text{A}(3,2) & \text{A}(3,3) & \text{A}(3,4) & \text{A}(3,5) \\ \text{A}(4,1) & \text{A}(4,2) & \text{A}(4,3) & \text{A}(4,4) & \text{A}(4,5) \\ \text{A}(5,1) & \text{A}(5,2) & \text{A}(5,3) & \text{A}(5,4) & \text{A}(5,5) \\ \end{array} \right)$


$\left( \begin{array}{ccccc} \text{B}(1,1) & \text{B}(1,2) & \text{B}(1,3) & \text{B}(1,4) & \text{B}(1,5) \\ \text{B}(2,1) & \text{B}(2,2) & \text{B}(2,3) & \text{B}(2,4) & \text{B}(2,5) \\ \text{B}(3,1) & \text{B}(3,2) & \text{B}(3,3) & \text{B}(3,4) & \text{B}(3,5) \\ \text{B}(4,1) & \text{B}(4,2) & \text{B}(4,3) & \text{B}(4,4) & \text{B}(4,5) \\ \text{B}(5,1) & \text{B}(5,2) & \text{B}(5,3) & \text{B}(5,4) & \text{B}(5,5) \\ \end{array} \right)$

Now I multiply these matrices under the assumption that each of their entries is itself a (so far unspecified) matrix:

productAB = blockMultiply[smallMatrix[[1]], smallMatrix[[2]]];
productBA = blockMultiply[smallMatrix[[2]], smallMatrix[[1]]];

If you inspect these result matrices you'll see that the order of the factors is correct, and each element is a sum of (matrix) Dot products. The results are too large to display here.

Another way to check that this works is to insert an actual pair of $10\times 10$ matrices by writing them as block matrices. I first define the big two-dimensional matrices and then use Partition to subdivide them into blocks of size $2\times 2$:

bigMatrix = Table[Array[{"a", "b"}[[i]], {10, 10}], {i, 2}];
blockMatrix = Table[Partition[bigMatrix[[i]], {2, 2}], {i, 2}];


block matrix

and similarly for MatrixForm[blockMatrix[[2]]].

Now we use these big matrices in the results obtained above with blockMultiply:

AB = Flatten[
   productAB /. Thread[
     Flatten[smallMatrix] -> Flatten[blockMatrix, {{1, 2, 3}}]
   {{1, 3}, {2, 4}}];

BA = Flatten[
   productBA /. Thread[
     Flatten[smallMatrix] -> Flatten[blockMatrix, {{1, 2, 3}}]
   {{1, 3}, {2, 4}}];

FullSimplify[AB == bigMatrix[[1]].bigMatrix[[2]]]

(* ==> True *)

FullSimplify[BA == bigMatrix[[2]].bigMatrix[[1]]]

(* ==> True *)

This says that the block multiplications yield the same result as doing the matrix products directly (as in bigMatrix[[1]].bigMatrix[[2]]). And the order of the multiplications is correctly captured.

The Flatten commands appearing in the definition of AB and BA (for the two different orders of the factors) are perhaps a little hard to see through. With a command like Flatten[blockMatrix, {{1, 2, 3}}] one gets a list in which the sub-blocks of the blockMatrix appear flattened, so that they can be used in the Thread of the -> which replaces the small symbolic block matrices by the blocks of the big matrix. The Flatten[ ..., {{1, 3}, {2, 4}}] removes the block matrix level and creates a $10\times 10$ matrix from the $2\times 2$ blocks.

The function blockMultiply is intended to work for any number of arguments in a matrix multiplication, and also for any dimension as long as all adjacent factor share a common dimension as required by Dot. So you could also repeat the above tests by splitting up the two matrices in bigMatrix into $5\times 5$ blocks, for example.

  • $\begingroup$ Jens, why not {a, b} = Table[Array[{"A", "B"}[[i]], {5, 5}], {i, 2}]; Inner[Dot, a, b] ? $\endgroup$
    – Mr.Wizard
    Jul 5 '12 at 7:02
  • $\begingroup$ @Mr.Wizard Because of the lateness of the hour, I guess. Thanks for the simplificiation! $\endgroup$
    – Jens
    Jul 5 '12 at 7:19
  • 1
    $\begingroup$ Thanks for the credit in the edit. IMHO it would be better to leave out the long blockMultiply code as I don't think it is instructive. $\endgroup$
    – Mr.Wizard
    Jul 5 '12 at 7:34
  • 1
    $\begingroup$ @Mr.Wizard You're right - all those fireworks messed with my brain. $\endgroup$
    – Jens
    Jul 5 '12 at 14:33
  • 1
    $\begingroup$ the Pyrotechnic Mitigation Plea -- granted. ;^) $\endgroup$
    – Mr.Wizard
    Jul 5 '12 at 14:44

You are talking about tensors, right? Such a tensor can be created with e.g.


All you have to do now, is to take from the example e[1,1,1,1] etc. and replace it with the variables you want to use. The same can be done with a second exampleTensor, so that you can work with both of them (multiply etc.).

I hope this helps.

  • $\begingroup$ Sorry that my post is ambiguous. This is not about tensor - tensor of two $10\times 10$ matrices would be a $100\times 100$ matrix. What I meant was as Jens pointed out in his first two paragraphs. $\endgroup$
    – Danny
    Jul 5 '12 at 16:48
  • $\begingroup$ No problem! Thanks for the feedback! $\endgroup$
    – partial81
    Jul 5 '12 at 18:49

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.