Home > Software design >  How can I generate a large ndarray with the structure of a smaller one in Numpy?
How can I generate a large ndarray with the structure of a smaller one in Numpy?

Time:03-05

I'm trying to construct a large matrix with the structure of a smaller one in python using numpy ndarrays, where the dimensions are dynamic variables within my problem.

For a simple test case, take the following code:

A = np.ones((2, 2))
B = np.zeros((2, 2))

matrix_structure = np.diag(np.ones(dimension-1), 1)   np.diag(np.ones(dimension-1), -1)

For a matrix dimension of 4, the matrix structure might look like the following:

[ 0 1 0 0 ]
[ 1 0 1 0 ]
[ 0 1 0 1 ]
[ 0 0 1 0 ]

with the desired final matrix being something like:

[ B A B B ]
[ A B A B ]
[ B A B A ]
[ B B A B ]

where A and B are the smaller submatrices.

I'm stuck on how to make that step - the function np.block() would do what I want, if I could figure out how to pass an appropriate array.

Is there a way to generate and then pass a multi-dimensional list of variable names, which then would pull the appropriate variable? Or am I just barking up the wrong tree here?

Edit:

Just for clarification, the final matrix (if A and B are 2x2) would look something like:

[ 0 0 1 1 0 0 0 0 ]
[ 0 0 1 1 0 0 0 0 ]
[ 1 1 0 0 1 1 0 0 ]
[ 1 1 0 0 1 1 0 0 ]
[ 0 0 1 1 0 0 1 1 ]
[ 0 0 1 1 0 0 1 1 ]
[ 0 0 0 0 1 1 0 0 ]
[ 0 0 0 0 1 1 0 0 ]

ie. the same structure, but composed of the smaller submatrices. The simple ones/zeros submatrices are just being used for illustration purposes.

CodePudding user response:

A naive approach would be to use np.block:

np.block([[B, A, B, B],
          [A, B, A, B],
          [B, A, B, A],
          [B, B, A, B]]).astype(int)

output:

array([[0, 0, 1, 1, 0, 0, 0, 0],
       [0, 0, 1, 1, 0, 0, 0, 0],
       [1, 1, 0, 0, 1, 1, 0, 0],
       [1, 1, 0, 0, 1, 1, 0, 0],
       [0, 0, 1, 1, 0, 0, 1, 1],
       [0, 0, 1, 1, 0, 0, 1, 1],
       [0, 0, 0, 0, 1, 1, 0, 0],
       [0, 0, 0, 0, 1, 1, 0, 0]])

Incorporating matrix_structure:

ms = str(np.where(matrix_structure.astype(bool), "A", "B").tolist()).replace("'A'", "A").replace("'B'", "B")
np.block(eval(ms)).astype(int)

output:

array([[0, 0, 1, 1, 0, 0, 0, 0],
       [0, 0, 1, 1, 0, 0, 0, 0],
       [1, 1, 0, 0, 1, 1, 0, 0],
       [1, 1, 0, 0, 1, 1, 0, 0],
       [0, 0, 1, 1, 0, 0, 1, 1],
       [0, 0, 1, 1, 0, 0, 1, 1],
       [0, 0, 0, 0, 1, 1, 0, 0],
       [0, 0, 0, 0, 1, 1, 0, 0]])

There is likely a better way than using eval, but it might give you an idea.

CodePudding user response:

Make a bigger matrix of zeros, Then add two smaller identity matrices in the correct position.

import numpy as np
dimension = 3
C = np.zeros((dimension 1, dimension 1))
C[:dimension,1:dimension 1]  = np.eye(dimension)
C[1:dimension 1,:dimension]  = np.eye(dimension)
print(C)

[[0. 1. 0. 0.]
 [1. 0. 1. 0.]
 [0. 1. 0. 1.]
 [0. 0. 1. 0.]]
  • Related