# Add a sub-matrix of zeros in big matrix [duplicate]

I have a matrix of size $24\times24$ composed by 8 $3\times3$ submatrices in a diagonal way. I want to add a matrices of zeros ($3\times3$) between the sub-matrices, so the final matrix would be of size $48\times48$. I appreciate your help.

Real question:

Let's say that I have matrices in this way

\begin{equation} \begin{pmatrix} \mathbb{A} & \mathbb{0} & 0 \\ 0 & \mathbb{B} & 0 \\ 0 & 0 & \mathbb{C} \\ \end{pmatrix}, \hspace{0.5cm} \begin{pmatrix} \mathbb{D} & \mathbb{0} & 0 \\ 0 & \mathbb{E} & 0 \\ 0 & 0 & \mathbb{F} \\ \end{pmatrix} \end{equation} being $\mathbb{A}\ldots\mathbb{F}$ $3\times 3$ matrices. The zero's there also correspond to $3 \times 3$ matrices of zeros. The idea is to combine them in the following way:

\begin{equation} \begin{pmatrix} \mathbb{A} & 0 & 0 & 0 & 0 & 0 \\ 0 & \mathbb{D} & 0 & 0 & 0 & 0 \\ 0 & 0 & \mathbb{B} & 0 & 0 & 0 \\ 0 & 0 & 0 & \mathbb{E} & 0 & 0 \\ 0 & 0 & 0 & 0 &\mathbb{C} & 0 \\ 0 & 0 & 0 & 0 & 0 &\mathbb{F} \\ \end{pmatrix} \end{equation}

Thus the final size of the, let's say, "big matrix", would be twice as the original ones. When I use your answer, it give me a single matrix with some numbers, not block of numbers as I want

• Related/Duplicate: mathematica.stackexchange.com/q/761/5, mathematica.stackexchange.com/q/19778/5 – rm -rf May 14 '13 at 13:32
• @rm-rf I do find it amusing that if you follow that chain, I have the earliest answer. :) – rcollyer May 14 '13 at 14:25
• @Alejandro in that case, see (3558). I'm not going to vote to re-open just so that we can close as a duplicate of a different question, but do let us know if this still doesn't solve your problem. – Oleksandr R. May 15 '13 at 11:58
• Forgive me, but I don't understand the distinction you're making; matrices are just blocks of numbers, and an answer should give you an enlarged matrix. What am I missing? – rcollyer May 15 '13 at 12:23
• Sorry for confusing you @rcollyer, it seems the code is taking the first element, let's say $A[1,1]$, but not the whole matrix $\mathbb{A}$. I don't know if it clarifies the question. – Alejandro Guarnizo May 15 '13 at 12:48

## 1 Answer

If you already have you matrix in component form, i.e. you have it broken into submatrices, then it is straightforward to construct a block diagonal matrix of any size.

Clear[BlockDiagonal]
BlockDiagonal[a : {_?MatrixQ ..}] :=
ArrayFlatten[
DiagonalMatrix[Range[Length@a]] /. i_Integer?Positive :> a[[i]]]

(* Convenience notation *)
Unprotect[CirclePlus];
a_?MatrixQ ⊕ b__?MatrixQ := BlockDiagonal[{a, b}]
Protect[CirclePlus];


For convenience,

Clear[ZeroMatrix]
ZeroMatrix[dim_Integer?Positive] := ConstantArray[0, {dim, dim}]
ZeroMatrix[dims : {_Integer?Positive, _Integer?Positive}] :=
ConstantArray[0, dims]


Which is used as follows:

A = {{a, b}, {c, d}};
B = {{e, f}, {g, h}};
A ⊕ ZeroMatrix⊕B Edit:

Per the comments, if you want to interlace the blocks from two different matrices, you can either specify the blocks individually, as above, or you can make use of a feature of SparseArray to capture the blocks automatically.

Clear[BlockMatrixRiffle];
BlockMatrixRiffle[A_?MatrixQ, B_?MatrixQ]:=
Module[{nonzA, nonzB},
nonzA = FindClusters[SparseArray[A]["NonzeroPositions"], Method -> "Agglomerate"];
nonzB = FindClusters[SparseArray[B]["NonzeroPositions"], Method -> "Agglomerate"];
BlockDiagonal@Riffle[
A[[##]]&@@@Map[Span[Min[#], Max[#]]&, Transpose/@nonzA, {2}],
B[[##]]&@@@Map[Span[Min[#], Max[#]]&, Transpose/@nonzB, {2}]
]
]


(Edit 2: changed clustering method to Agglomerate which is hierarchical, and more appropriate for this case.)

SparseArray only stores elements that are different from a common base which is usually set to zero. So, when you turn a block diagonal matrix into a SparseArray you can retrieve the non-zero positions by

SparseArray[A ⊕ B]["NonzeroPositions"]
(* {{1, 1}, {1, 2}, {2, 1}, {2, 2}, {3, 3}, {3, 4}, {4, 3}, {4, 4}} *)


(Note: this will not find zero blocks, so if those exist, then some other method must be used.) Now, we use FindClusters to group them into blocks:

FindClusters[%, Method -> "Agglomerate"]
(* {{{1, 1}, {1, 2}, {2, 1}, {2, 2}}, {{3, 3}, {3, 4}, {4, 3}, {4, 4}}} *)


From there, I turn them into min/max ranges for use in Part:

Map[{Min[#], Max[#]}&, Transpose /@ %]
(* {{{1, 2}, {1, 2}}, {{3, 4}, {3, 4}}} *)


So, when I Apply A[[##]] to the above, I get the equivalent of

{A[[{1,2}, {1,2}]], A[[{3,4}, {3, 4}]]}


for both the matrices supplied to BlockMatrixRiffle which then interlaces the two matrices.

mat1 = Table[a[i, j], {i, 2}, {j, 2}] ⊕ Table[b[i, j], {i, 2}, {j, 2}];
mat2 = Table[c[i, j], {i, 3}, {j, 3}] ⊕ Table[d[i, j], {i, 2}, {j, 2}];
BlockMatrixRiffle[mat1, mat2] Note, if the number of blocks in B exceeds the number of blocks in A, those extra blocks will be ignored. But, if the reverse is true, multiple copies of the blocks from B will be included in the result. This can be prevented by a little extra processing, but I leave that as an exercise.

• Thanks rcollyer for your answer. I'm wondering in make something more "simple", but I'm not sure ho to do it: I have two matrices, same size (24x24), and they are build by submatrices again 3x3. I want to construct a new matrix from both such that first entry (a matrix 3x3) comes from the first matrix, the second entry for he second matrix, and so on. Basically construct a big array of size 48x48 and put both matrices in that way. Thanks again – Alejandro Guarnizo May 14 '13 at 13:21
• @Alejandro, You can use Riffle[] for that purpose. – J. M.'s ennui May 14 '13 at 14:18
• @AlejandroGuarnizo I added a method that auto-extracts the non-zero blocks and interlaces them together. – rcollyer May 14 '13 at 14:23
• @J.M. check out the edit. – rcollyer May 14 '13 at 14:24
• Thanks again rcollyer..I tried to use it, but it doesn't work!. It seems that I need to define somwhow that the matrices $A$ and $B$ are constructed block-wise – Alejandro Guarnizo May 14 '13 at 17:27