Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

This question already has an answer here:

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

share|improve this question

marked as duplicate by J. M. May 15 '13 at 13:00

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

    
    
@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 1

up vote 5 down vote accepted

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 \[CirclePlus] 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 \[CirclePlus] ZeroMatrix[3]\[CirclePlus]B 

enter image description here

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 \[CirclePlus] 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}] \[CirclePlus] Table[b[i, j], {i, 2}, {j, 2}];
mat2 = Table[c[i, j], {i, 3}, {j, 3}] \[CirclePlus] Table[d[i, j], {i, 2}, {j, 2}];
BlockMatrixRiffle[mat1, mat2]

enter image description here

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.

share|improve this answer
    
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. 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

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