3

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?

3 Answers 3

3

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)
Sign up to request clarification or add additional context in comments.

Comments

0

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)

1 Comment

By the way, np.linalg.multi_dot does exactly the same think as described by dzang, but with np.dot instead of np.matmul. If you want to know the differences between dot and matmul, you can look at this post.
0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.