I have a problem where I want to multiply many 2x2 square matrices. The elements in the matrix are of the from a+ib (complex number)
Here's how the code looks like:
Final_list=[]
for x in list_x:
Matrix=np.array([[1,0],[0,1]])
for y in list_y:
Matrix_y=[....] #create a 2x2 matrix from values x and y
Matrix= Matrix.dot(Matrix_y)
value= 5/(Matrix[0,0] + Matrix[1,0]....) #something like this
Final_list.append(abs(value))
Final_list is what I need.
My code works but it takes a while and I feel like there must be a better way to write this. If length of list_x=30000 and list_y=300 it takes a while to compute ~ a minute or so.
I was able to create a large matrix of shape (300,30000,2,2). I did that by array broadcasting and using np.shape. I hoped to multiply all matrices in a column to get an array of matrices of shape (30000,2,2). I am thinking that might help in the computation but havent figured out a way to do it.
Is there a better way to write this instead of using multiple for loops?
Thanks
I don't know a fully vectorized solution. Initially I thought that np.matmul.reduce
might work, but reduce
seems to be unsupported for non-commutative operations according to the old docs. There is also np.linalg.multi_dot
, but it seems like an overkill for 2 by 2 matrices.
Here is a answer that runs in 1.5 seconds on my machine; it is similar to the approach here.
arr = np.random.rand(300, 30_000, 2, 2)
def my_mul(mats):
if len(mats) == 1:
return mats[0,...]
elif len(mats) == 2:
return mats[0,...] @ mats[1,...]
else:
mid = len(mats) // 2
return my_mul(mats[:mid,...]) @ my_mul(mats[mid:,...])
result = my_mul(arr) # 1.53 s