简体   繁体   中英

Python Numpy matrix multiplication using loop to multiply multiple matrices together

I have written code which creates matrices with name matrixi , where i is replaced with the current loop number:

for i in range(len(node2)):
    if sOrP[i] == 'S':
        #print('series connection')
        matrixTemplate = numpy.array([[1.0, 0.0], [0.0, 1.0]])  #Got to put 1.0 else it doesnt work
        matrixTemplate[0][1] = frequenciesList[0][i]
        globals()['matrix%s' % i] = matrixTemplate
        #print(matrixTemplate)
    elif sOrP[i] == 'P':
        #print('parallel connection')
        matrixTemplate = numpy.array([[1.0, 0.0], [0.0, 1.0]])
        matrixTemplate[1][0] = 1 / frequenciesList[0][i]
        globals()['matrix%s' % i] = matrixTemplate
        #print(matrixTemplate)

I then need to multiply the created matrices together:

Ty = matrix0 @ matrix1 @ matrix2 @ matrix3 @ matrix4 @ matrix5 @ matrix6 @ matrix7 @ matrix8 @ matrix9

This works but the code has to be able to take multiple inputs with potentially more or fewer matrices being created. In that case it wouldn't work.

Would it be possible to do the multiplication part using a loop or function?

You could use a list (or a dictionary) to hold your matrices:

matrices = []

for i in range(len(node2)):

    if (sOrP[i] == 'S'):
        #print('series connection')
        matrixTemplate = numpy.array([[1.0, 0.0],[0.0, 1.0]]) #Got to put 1.0 else it doesnt work

        matrixTemplate[0][1] = frequenciesList[0][i]

        matrices.append(matrixTemplate)

        #print(matrixTemplate)

    elif (sOrP[i] == 'P'):
        #print('parallel connection')
        matrixTemplate = numpy.array([[1.0, 0.0],[0.0, 1.0]])

        matrixTemplate[1][0] = 1/frequenciesList[0][i]

        matrices.append(matrixTemplate)

        #print(matrixTemplate)

And then use reduce and numpy.matmul to compute your total matrix product:

from functools import reduce

Ty = reduce(numpy.matmul, matrices)

You can use either a loop or a numpy function.

Loop implementation:

matrixes = [M1, M2, ..., Mn]
A = matrixes[0]
for i in range(1, len(matrixes)):
    B = matrixes[i]
    A = np.dot(A, B)

First iteration: A = M1, B = M2; M1.M2

Second iteration: A = M1.M2, B = M3; M1.M2.M3

...

Numpy function: numpy.linalg.multi_dot(matrixes)

Setting the variables you have done is a pretty terrible way if doing it, as you seem to realize already. If your matrices are all nice and square, you only need one variable to hold the entire stack, shaped (len(node2), 2, 2) .

Another point is your indexing. Numpy arrays are not lists. Your indices should look like [1, 0] , not [1][0] . Answers like the following shameless plug explain why: https://stackoverflow.com/a/60919478/2988730 .

Let's assume that sOrP and frequenciesList are numpy arrays. If they aren't, wrap them in a call to np.array . You can make the stack like this:

matrices = np.broadcast_to([[[1, 0], [0, 1]]], (len(node2), 2, 2)).copy()
maskS = (sOrP == 'S')
maskP = (sOrP == 'P')
matrices[maskS, 0, 1] = frequenciesList[maskS]
matrices[maskP, 1, 0] = 1 / frequenciesList[maskP]

You can verify that matrices[i] is equivalent to matrixi in your original construction.

The simple way to multiply all the matrices together would be using a loop:

Ty = np.eye(2)
for mat in matrices:
    Ty @= mat

But numpy is all about vectorization. As it happens, np.linalg.multidot was made to optimize this exact operation:

Ty = np.linalg.multidot(matrices)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM