2
$\begingroup$

I would like to construct a diagonal matrix that is defined as a function and put it multiple times in a block-diagonal matrix each block evaluated at a consecutive integer.

Let's say my matrix looks like this:

$$\mathtt{mat}[x\_]=\begin{pmatrix} x & 1 \\ 1 & x^2 \end{pmatrix}$$

and I would like to stack it up such that it looks something like this:

$$\mathtt{matnew}[x\_]=\begin{pmatrix} x|_1 & 1 & 0& 0&0\\ 1 & x^2|_1 & 0& 0&0\\ 0& 0&x|_2 & 1 &0\\ 0& 0&1 & x^2|_2 &0\\ 0& 0&0 & 0&\ddots\\ \end{pmatrix}$$

where each block in this block-diagonal matrix is evaluated at a different consecutive number. An interesting approach came up here. Particularly, the function

mats[p_, n_] := ArrayFlatten[DiagonalMatrix[Array[1 &, n]] /. {1 -> p, 0 -> 0 p}];

seems to be very helpful, but unfortunately each block will not be evaluated at different x. How should I change the function Array[] in this definition to get the above matrix matnew[x_] with x = 1, x = 2, ...?

$\endgroup$

3 Answers 3

3
$\begingroup$
mat[x_] := {{x, 1}, {1, x^2}}

matnew[n_] := Block[{f}, 
  ArrayFlatten@(DiagonalMatrix[Array[f, n]] /. Table[f[i] -> mat[i], {i, n}])]

matnew[3]

(* {{1, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 0, 0}, {0, 0, 2, 1, 0, 0}, 
   {0, 0, 1, 4, 0, 0}, {0, 0, 0, 0, 3, 1}, {0, 0, 0, 0, 1, 9}} *)

% // TeXForm

$ \left( \begin{array}{cccccc} 1 & 1 & 0 & 0 & 0 & 0 \\ 1 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 2 & 1 & 0 & 0 \\ 0 & 0 & 1 & 4 & 0 & 0 \\ 0 & 0 & 0 & 0 & 3 & 1 \\ 0 & 0 & 0 & 0 & 1 & 9 \\ \end{array} \right) $

Here is a more general version that allows fractional numbers

matnew2[imin_, imax_, di_] := 
 Block[{f}, 
  ArrayFlatten@(DiagonalMatrix[Table[f[i], {i, imin, imax, di}]] /. 
     Table[f[i] -> mat[i], {i, imin, imax, di}])]

matnew2[1, 3, 1] gives the same result as before:

$ \left( \begin{array}{cccccc} 1 & 1 & 0 & 0 & 0 & 0 \\ 1 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 2 & 1 & 0 & 0 \\ 0 & 0 & 1 & 4 & 0 & 0 \\ 0 & 0 & 0 & 0 & 3 & 1 \\ 0 & 0 & 0 & 0 & 1 & 9 \\ \end{array} \right) $

And, for example, with intervals of 1/2 instead of 1:

matnew2[1, 3, 1/2]

$ \left( \begin{array}{cccccccccc} 1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & \frac{3}{2} & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & \frac{9}{4} & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 2 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 4 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & \frac{5}{2} & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & \frac{25}{4} & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 3 & 1 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 9 \\ \end{array} \right) $

$\endgroup$
3
  • $\begingroup$ This answer worked perfectly. How would I have to change it if I wanted fractions numbers instead of integers? More precisely, the Array[f, n] above should include a range like Array[f, n, {min,max}]. $\endgroup$
    – xabdax
    Commented Aug 3, 2019 at 23:12
  • 1
    $\begingroup$ @xabdax I updated the function so it takes three values: min, max, and interval. Let me know if that's not what you meant. $\endgroup$
    – MelaGo
    Commented Aug 5, 2019 at 0:06
  • $\begingroup$ This is exactly what I meant. Thanks!! $\endgroup$
    – xabdax
    Commented Aug 5, 2019 at 22:40
3
$\begingroup$
mat = Array[x^(# Boole[# == #2]) &, {2, 2}];

n = 3;

mats = mat /. {x -> #} & /@ Range[n];

sa  = SparseArray[{Band[{1, 1}] -> mats}]

TeXForm @ MatrixForm @ sa

$\left( \begin{array}{cccccc} 1 & 1 & 0 & 0 & 0 & 0 \\ 1 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 2 & 1 & 0 & 0 \\ 0 & 0 & 1 & 4 & 0 & 0 \\ 0 & 0 & 0 & 0 & 3 & 1 \\ 0 & 0 & 0 & 0 & 1 & 9 \\ \end{array} \right)$

Also

Control`BlockDiagonalMatrix @@ mats // MatrixForm // TeXForm 

same picture

Module[{i = 1}, ArrayFlatten[IdentityMatrix[n] /. {1 :> mats[[i++]]}]] // 
  MatrixForm // TeXForm 

same picture

$\endgroup$
4
  • $\begingroup$ How would this look like if 𝑚𝑎𝑡[𝑥_] was an arbitrary function/matrix? I wrote x and x^2 to make the question look simpler but in reality my initial matrix is more complicated (and also bigger) than that. $\endgroup$
    – xabdax
    Commented Jul 31, 2019 at 4:52
  • $\begingroup$ will each block be evaluated at different integers? I updated the question to make this a little clearer. Basically I do not only need them to be on the diagonal but also each block should be evaluated at a different number. $\endgroup$
    – xabdax
    Commented Jul 31, 2019 at 5:02
  • $\begingroup$ @xabdax, please see the new version. $\endgroup$
    – kglr
    Commented Jul 31, 2019 at 5:22
  • $\begingroup$ Control`BlockDiagonalMatrix @@ mats // MatrixForm // TeXForm should be LinearAlgebra`BlockDiagonalMatrix[mats] // MatrixForm . $\endgroup$
    – lotus2019
    Commented Oct 24, 2022 at 12:36
2
$\begingroup$

Using an undocumented function:

With[{n = 3}, SparseArray`SparseBlockMatrix[Table[{x, x} -> {{x, 1}, {1, x^2}}, {x, 1, n}]]]

generates a block diagonal matrix as a SparseArray[]; use Normal[] if you wish to have an actual list instead.


In general, SparseArray`SparseBlockMatrix[] takes a list of rules corresponding to the positions of a specified block; e.g. {1, 1} -> {{1, 1}, {1, 1}} corresponds to block $(1,1)$ of the block matrix.

As another example, here is how to construct a block triangular matrix:

SparseArray`SparseBlockMatrix[{{1, 1} -> HilbertMatrix[2], {1, 2} -> IdentityMatrix[2],
                               {2, 2} -> Array[Min, {2, 2}]}] // Normal
   {{1, 1/2, 1, 0}, {1/2, 1/3, 0, 1}, {0, 0, 1, 1}, {0, 0, 1, 2}}
$\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.