5
$\begingroup$

I am trying to generate a matrix from square blocks. Effectively, I have three blocks, call them $A_{diag}$, $A_{up}$, $A_{down}$, and a block of zeroes, which I'll just call $0$. I have some integer $L$ such that if $L=1$ then I am generating the matrix

$$M = \begin{pmatrix} A_{diag} \end{pmatrix}$$

If $L=2$ then I should generate

$$M = \begin{pmatrix} A_{diag} & A_{up} \\ A_{down} & A_{diag} \end{pmatrix}$$

If $L=3$ then

$$M = \begin{pmatrix} A_{diag} & A_{up} & 0 \\ A_{down} & A_{diag} & A_{up} \\ 0 & A_{down} & A_{diag} \end{pmatrix}$$

If $L=4$ then

$$M = \begin{pmatrix} A_{diag} & A_{up} & 0 & 0\\ A_{down} & A_{diag} & A_{up} & 0 \\ 0 & A_{down} & A_{diag} & A_{up} \\ 0 & 0 & A_{down} & A_{diag}\end{pmatrix}$$

and so forth. I suspect this is relatively simple, I found other questions which were similar but more complicated and specific. Any help appreciated, thank you.

$\endgroup$
2
  • 1
    $\begingroup$ Something like SparseArray with Band? (See 1st example in the Basic Examples section.) $\endgroup$
    – corey979
    Jan 31, 2018 at 18:03
  • $\begingroup$ Ah that would also work, thanks, I didn't know about Band $\endgroup$
    – Kai
    Jan 31, 2018 at 20:22

4 Answers 4

4
$\begingroup$

You can use ArrayFlatten and DiagonalMatrix:

mat[diag_, up_, down_, n_] := ArrayFlatten @ Block[{Identity},
    DiagonalMatrix[ConstantArray[Identity[diag], n]]+
    DiagonalMatrix[ConstantArray[Identity[up], n-1], 1]+
    DiagonalMatrix[ConstantArray[Identity[down], n-1], -1]
]

I used a blocked Identity head so that DiagonalMatrix didn't complain.

Example:

mat[Array[a, {2,2}], Array[b, {2,2}], Array[c, {2,2}], 3] //TeXForm

$\left( \begin{array}{cccccc} a(1,1) & a(1,2) & b(1,1) & b(1,2) & 0 & 0 \\ a(2,1) & a(2,2) & b(2,1) & b(2,2) & 0 & 0 \\ c(1,1) & c(1,2) & a(1,1) & a(1,2) & b(1,1) & b(1,2) \\ c(2,1) & c(2,2) & a(2,1) & a(2,2) & b(2,1) & b(2,2) \\ 0 & 0 & c(1,1) & c(1,2) & a(1,1) & a(1,2) \\ 0 & 0 & c(2,1) & c(2,2) & a(2,1) & a(2,2) \\ \end{array} \right)$

$\endgroup$
2
  • $\begingroup$ Thanks, the only downside to this is it doesn't work when n=1 $\endgroup$
    – Kai
    Feb 1, 2018 at 1:16
  • $\begingroup$ I simply added If[n>1, (your code) , Adiag] which works perfectly it seems $\endgroup$
    – Kai
    Feb 1, 2018 at 1:31
4
$\begingroup$

While the other posted methods work, this is the one I wound up using, based on corey979's suggestion:

If[L == 1,
  A[r_] := Adiag[r],
  mup   = SparseArray[Band[{1, 2}] -> 1, {L, L}];
  mdown = SparseArray[Band[{2, 1}] -> 1, {L, L}];
  mdiag = SparseArray[Band[{1, 1}] -> 1, {L, L}];
  A[r_] :=
    KroneckerProduct[mup  ,   Aup[r]] + 
    KroneckerProduct[mdown, Adown[r]] + 
    KroneckerProduct[mdiag, Adiag[r]];
  ];

It has the advantage of using SparseArray's, which is desirable if L is large. One can always use Normal to convert the SparseArray's into regular matrices for small L. For my application for example I found that using normal matrices was faster for L < 3 but using SparseArray's was faster for L > 3, with both being equally fast for L = 3.

$\endgroup$
3
  • $\begingroup$ Wow, this one is really fast. Respect. $\endgroup$ Mar 11, 2018 at 22:46
  • 1
    $\begingroup$ For your mdiag, I would instead use IdentityMatrix[L, SparseArray]. $\endgroup$ Mar 17, 2018 at 11:34
  • $\begingroup$ Thanks, I don't notice much change in speed but it certainly makes more sense. $\endgroup$
    – Kai
    Mar 18, 2018 at 5:38
4
$\begingroup$

The "SparseArray`" context contains many hidden gems, for example this one:

SparseArray`SparseBlockMatrix[{
   Band[{1, 1}] -> SparseArray@Array[a, {2, 2}],
   Band[{1, 2}] -> SparseArray@Array[b, {2, 2}],
   Band[{2, 1}] -> SparseArray@Array[c, {2, 2}]
   }, {3, 3}] // MatrixForm

$$\left( \begin{array}{cccccc} a(1,1) & a(1,2) & b(1,1) & b(1,2) & 0 & 0 \\ a(2,1) & a(2,2) & b(2,1) & b(2,2) & 0 & 0 \\ c(1,1) & c(1,2) & a(1,1) & a(1,2) & b(1,1) & b(1,2) \\ c(2,1) & c(2,2) & a(2,1) & a(2,2) & b(2,1) & b(2,2) \\ 0 & 0 & c(1,1) & c(1,2) & a(1,1) & a(1,2) \\ 0 & 0 & c(2,1) & c(2,2) & a(2,1) & a(2,2) \\ \end{array} \right)$$

It's not very efficient, though...

$\endgroup$
2
$\begingroup$

There it is,

M[n_] := Adiag IdentityMatrix[n] + 
Table[Aup KroneckerDelta[i + 1, j], {i, 1, n}, {j, 1, n}] + 
Table[Adown KroneckerDelta[i - 1, j], {i, 1, n}, {j, 1, n}];

MatrixForm[M[3]]

to elaborate more, you can have Aup[i, j] and Adown[i, j] and Adiag[i, i].

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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