индекс списка вне допустимого диапазона - проблема с использованием функции для разложения матрицы - PullRequest
0 голосов
/ 08 мая 2020

Я попытался использовать этот код для разложения LU матрицы nxn, но продолжаю получать «IndexError: индекс списка вне допустимого диапазона». Есть идеи, что здесь пошло не так и как это исправить?

import numpy as np
import pylab
from pprint import pprint

def matrixMul(A, B):
    TB = zip(*B)
    return [[sum(ea*eb for ea,eb in zip(a,b)) for b in TB] for a in A]

def permut(m):
    n = len(m)
    ID = [[float(i == j) for i in range(n)] for j in range(n)]
    for j in range(n):
        row = max(range(j, n), key=lambda i: abs(m[i][j]))
        if j != row:
            ID[j], ID[row] = ID[row], ID[j]
    return ID

def lu(A):
    n = len(A)
    L = [[0.0] * n for i in range(n)]
    U = [[0.0] * n for i in range(n)]
    P = permut(A)
    A2 = matrixMul(P, A)
    for j in range(n):
        L[j][j] = 1.0
        for i in range(j+1):
            s1 = sum(U[k][j] * L[i][k] for k in range(i))
            U[i][j] = A2[i][j] - s1
        for i in range(j, n):
            s2 = sum(U[k][j] * L[i][k] for k in range(j))
            L[i][j] = (A2[i][j] - s2) / U[j][j]
    return (L, U, P)

Я пытался использовать указанную выше функцию со следующим кодом:

a = np.array([[2, 1, 5], [4, 4, -4], [1, 3, 1]]);
for part in lu(a):
    pprint(part)
    print
print

Предполагается, что возвращать матрицы L , U, P, но все, что я получаю, это сообщение об ошибке:

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-52-da52bba817aa> in <module>()
      1 a = np.array([[2, 1, 5], [4, 4, -4], [1, 3, 1]]);
----> 2 for part in lu(a):
      3     pprint(part)
      4     print
      5 print

<ipython-input-51-e49d88430e36> in lu(A)
     27         for i in range(j, n):
     28             s2 = sum(U[k][j] * L[i][k] for k in range(j))
---> 29             L[i][j] = (A2[i][j] - s2) / U[j][j]
     30     return (L, U, P)
     31     print(L)

Ответы [ 3 ]

2 голосов
/ 08 мая 2020

Проблема возникает в этой строке в matrixMul:

    TB = zip(*B)

zip возвращает итератор, и вы можете выполнить итерацию по содержимому только один раз. Если вы посмотрите на значение A2, вы обнаружите, что это [[4.0, 4.0, -4.0], [], []].

Вы можете решить проблему, заменив строку выше на

    TB = list(zip(*B))

, который устанавливает TB в список, который можно повторять сколько угодно раз, или избавившись от этой строки и переписав строку ниже следующим образом:

    return [[sum(ea*eb for ea,eb in zip(a,b)) for b in zip(*B)] for a in A]

В этом случае zip(*B) оценивается один раз для каждой строки в A, поэтому вы получаете совершенно новый итератор для итерации для каждой строки.

1 голос
/ 08 мая 2020

Пробовал распечатать матрицу А2. Получил

A2 = 
[[4.0, 4.0, -4.0], [], []]

Похоже, функция matrixMul работает некорректно

Я заменил

A2 = matrixMul(P, A)

на это.

A2 = np.dot(P, A)

* 1017 Функция * .dot эквивалентна умножению матриц для 2D-массива (т.е. матрицы)

Ошибка исчезла.

Однако я не могу вам сказать о правильности разложения LU ответ.

1 голос
/ 08 мая 2020

Ваша функция matrixMul не выполняет то, что вы хотите, и форма A2 неверна.

Вы хотите это

return [[sum(a*b for a,b in zip(X_row,Y_col)) for Y_col in zip(*Y)] for X_row in X]
...