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$
2
$\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$
  • $\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 Aug 3 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 Aug 5 at 0:06
  • $\begingroup$ This is exactly what I meant. Thanks!! $\endgroup$ – xabdax Aug 5 at 22:40
2
$\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$
  • $\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 Jul 31 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 Jul 31 at 5:02
  • $\begingroup$ @xabdax, please see the new version. $\endgroup$ – kglr Jul 31 at 5:22
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, privacy policy and cookie policy

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