1

I want to create a square matrix like this one where its element is a square matrix either the B square matrix or the negative identity matrix or zeros. I have created the B matrix as well as the -I and also I have created a Z matrix of zeros. B, I and Z squares matrices with same n1*n1 (or n2 * n2) dimensions and the final matrix I want to have n*n dimensions where n = n1 * n2

If for example B, I and Z are 4*4 the final will be 16*16

I know how to concatenate and stack matrices but I don't know how to implement this better since need to make the below process 64! times.

for iter in range(64):
if iter == 0:
    temp = B
    temp = np.hstack((temp, I))
    temp = np.hstack((temp, Z))
    temp = np.hstack((temp, Z))
if iter == 1:
    temp2 = I
    temp2 = np.hstack((temp2, B))
    temp2 = np.hstack((temp2, I))
    temp2 = np.hstack((temp2, Z))
if iter == 2:
    temp3 = Z
    temp3 = np.hstack((temp3, I))
    temp3 = np.hstack((temp3, B))
    temp3 = np.hstack((temp3, I))
if iter == 3:
    temp4 = Z
    temp4 = np.hstack((temp4, Z))
    temp4 = np.hstack((temp4, I))
    temp4 = np.hstack((temp4, B)) 
    .......
    ........
    ........

st1 = np.vstack((temp, temp2))
st2 = np.vstack((st1, temp3))
.......

Can I save n*n matrices into array elements and then concatenate or stack them?

Er1Hall
  • 147
  • 2
  • 11
  • 2
    What you're looking for is a block toeplitz matrix, take a look at [Toeplitz matrix of toeplitz matrix](https://stackoverflow.com/questions/36464191/toeplitz-matrix-of-toeplitz-matrix) – user2699 Mar 14 '19 at 12:41

2 Answers2

0

Depending on whether you are dealing with numpy arrays or lists, you can use the following example to append arrays:

import numpy as np
x = np.array([[11.1, 12.1, 13.1], [21.1, 22.1, 23.1]])
print(x.shape)
y = np.array([[11.2, 12.2],[21.2, 22.2]])
print(y.shape)
z = np.append(x,y, axis=1)
print(z.shape)
print(z)

Please note that as mentioned by @user2699, the numpy append could get slow for large array sizes (Fastest way to grow a numpy numeric array).

With lists, you can use the append command:

x = [1, 2, 3]
x.append([4, 5])
print (x) #

This example is taken from: Difference between append vs. extend list methods in Python

U3.1415926
  • 812
  • 12
  • 30
  • 1
    Just a note, `np.append` should not be used in situations like this one where multiple arrays are being joined sequentially, for example see https://stackoverflow.com/questions/7133885/fastest-way-to-grow-a-numpy-numeric-array – user2699 Mar 14 '19 at 12:23
  • `np.append` is a poorly named cover function for `np.concatenate`. In this case the arrays already have the right number of dimensions: `np.concatenate((x,y),axis=1)`. – hpaulj Mar 14 '19 at 16:53
0

np.block helps you create an array like this:

In [109]: B =np.arange(1,5).reshape(2,2)                                        
In [110]: I =np.eye(2).astype(int)                                              
In [111]: Z = np.zeros((2,2),int)                                               
In [112]: np.block?                                                             
In [113]: np.block([[B,I,Z,Z],[I,B,I,Z],[Z,I,B,I],[Z,Z,I,B]])                   
Out[113]: 
array([[1, 2, 1, 0, 0, 0, 0, 0],
       [3, 4, 0, 1, 0, 0, 0, 0],
       [1, 0, 1, 2, 1, 0, 0, 0],
       [0, 1, 3, 4, 0, 1, 0, 0],
       [0, 0, 1, 0, 1, 2, 1, 0],
       [0, 0, 0, 1, 3, 4, 0, 1],
       [0, 0, 0, 0, 1, 0, 1, 2],
       [0, 0, 0, 0, 0, 1, 3, 4]])

block does a nested sequence of concatenate starting with the innermost lists. Previous versions used hstack on the inner lists, and vstack of those results.

In [118]: np.vstack((np.hstack([B,I,Z,Z]),np.hstack([I,B,I,Z])))                
Out[118]: 
array([[1, 2, 1, 0, 0, 0, 0, 0],
       [3, 4, 0, 1, 0, 0, 0, 0],
       [1, 0, 1, 2, 1, 0, 0, 0],
       [0, 1, 3, 4, 0, 1, 0, 0]])

The lists of lists in [113] could be constructed with code, using the desired sizes, but I won't go into those details.

Another approach is to create a np.zeros((8,8)) target array, and fill in the desired blocks. Maybe even better to make a np.zeros((4,2,4,2)), fill that, and reshape later.

In [119]: res = np.zeros((4,2,4,2),int)                                         
In [120]: res[np.arange(4),:,np.arange(4),:] = B                                
In [121]: res[np.arange(3),:,np.arange(1,4),:] = I                              
In [122]: res[np.arange(1,4),:,np.arange(3),:] = I  
In [124]: res.reshape(8,8)                                                      
Out[124]: 
array([[1, 2, 1, 0, 0, 0, 0, 0],
       [3, 4, 0, 1, 0, 0, 0, 0],
       [1, 0, 1, 2, 1, 0, 0, 0],
       [0, 1, 3, 4, 0, 1, 0, 0],
       [0, 0, 1, 0, 1, 2, 1, 0],
       [0, 0, 0, 1, 3, 4, 0, 1],
       [0, 0, 0, 0, 1, 0, 1, 2],
       [0, 0, 0, 0, 0, 1, 3, 4]])
hpaulj
  • 221,503
  • 14
  • 230
  • 353