Search code examples
pythonarraysmatrixblockdiag

How to pack matrices into cells and then form a diagonal matrix with python


I need to create a diagonal matrix in python from an X matrix which is repeated 3 times. In matlab I do it in the following way:

  X=[1 2 3;
     4 5 6;
     7 8 9]

for i=1:1:3
  Brep{i}=X;      
end    
Mdiag=blkdiag(Brep{:})

Mdiag =

 1     2     3     0     0     0     0     0     0
 4     5     6     0     0     0     0     0     0
 7     8     9     0     0     0     0     0     0
 0     0     0     1     2     3     0     0     0
 0     0     0     4     5     6     0     0     0
 0     0     0     7     8     9     0     0     0
 0     0     0     0     0     0     1     2     3
 0     0     0     0     0     0     4     5     6
 0     0     0     0     0     0     7     8     9

But I don't know how to do this in Pyhton.

I would appreciate any help.

--------------------------------- ANSWER:--------------------------------------

Taking into account the answer provided by Fabrizio Bernini, I modified his code in order to do it more general. The code can now repeat the matrix X (any dimension), n times on the diagonal. For example:

import numpy as np

n=5

x = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])

Mdiag = np.zeros((n*x.shape[0], n*x.shape[1]))

for i in range(n):

Mdiag[x.shape[0]*i:x.shape[0]*i+x.shape[0],x.shape[1]*i:x.shape[1]*i+x.shape[1]]= x

Mdiag =[1., 2., 3., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [4., 5., 6., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [7., 8., 9., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 1., 2., 3., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 4., 5., 6., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 7., 8., 9., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 1., 2., 3., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 4., 5., 6., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 7., 8., 9., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 2., 3., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 4., 5., 6., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 7., 8., 9., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 2., 3.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 4., 5., 6.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 7., 8., 9.]

Thanks you all for the answers provided.


Solution

  • you can do something like this using numpy:

    import numpy
    x = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
    Mdiag = np.zeros((9, 9))
    for i in range(3):
        Mdiag[3*i:3*i+3, 3*i:3*i+3] = x
    

    you can also generate your initial matrix using np.reshape:

    x = np.arange(1, 10)
    x = x.reshape((3, 3))
    

    More in general, if you have a nxn submatrix and want to create a MxM diagonal block matrix, where M = c*n, you can do:

    import numpy
    x = ... define here your nxn matrix
    Mdiag = np.zeros((M, M))
    for i in range(n):
        Mdiag[n*i:n*i+n, n*i:n*i+n] = x
    

    There are numpy in-built functions to copy block matrices and generate block matrices, but I am not aware of one generating a diagonal block matrix with just one command. See also this for reference:

    [1]: https://numpy.org/doc/stable/reference/generated/numpy.matlib.repmat.html#numpy.matlib.repmat and [2]: https://numpy.org/doc/stable/reference/generated/numpy.block.html?highlight=block%20matrix