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.]]