# Matrix multiplication in Block Form symbolic calculation by Mathematica

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?

-
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. – rcollyer Jul 5 '12 at 2:17 Got you! Thanks! – Danny Jul 5 '12 at 2:54 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. – Szabolcs Jul 5 '12 at 7:27 @Szabolcs: Thanks! I will bear this package in mind. Right now I am trying the function blockMultiply – Danny Jul 5 '12 at 16:39 ## 2 Answers 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. Edit 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}]; MatrixForm[smallMatrix[[1]]] $\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)$MatrixForm[smallMatrix[[2]]] $\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}]; MatrixForm[blockMatrix[[1]]]  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. - Jens, why not {a, b} = Table[Array[{"A", "B"}[[i]], {5, 5}], {i, 2}]; Inner[Dot, a, b] ? – Mr.Wizard Jul 5 '12 at 7:02 @Mr.Wizard Because of the lateness of the hour, I guess. Thanks for the simplificiation! – Jens Jul 5 '12 at 7:19 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. – Mr.Wizard Jul 5 '12 at 7:34 @Mr.Wizard You're right - all those fireworks messed with my brain. – Jens Jul 5 '12 at 14:33 the Pyrotechnic Mitigation Plea -- granted. ;^) – Mr.Wizard Jul 5 '12 at 14:44 You are talking about tensors, right? Such a tensor can be created with e.g. example=Array[e,{5,5,2,2}]; example//MatrixForm  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. - 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. –  Danny Jul 5 '12 at 16:48
No problem! Thanks for the feedback! –  partial81 Jul 5 '12 at 18:49