Python LU分解中的零除警告-Doolittle算法工作

Python LU分解中的零除警告-Doolittle算法工作,python,numpy,linear-algebra,Python,Numpy,Linear Algebra,我通过以下链接实现了矩阵LU分解的标准方程/算法:()和() 这将返回如下所示的方形矩阵的LU分解。 然而,我的问题是-它也会给出一个除以零的警告 代码如下: import numpy as np def LUDecomposition (A): L = np.zeros(np.shape(A),np.float64) U = np.zeros(np.shape(A),np.float64) acc = 0 L[0,0]=1 for i in np.ar

我通过以下链接实现了矩阵LU分解的标准方程/算法:()和() 这将返回如下所示的方形矩阵的LU分解。 然而,我的问题是-它也会给出一个
除以零的警告

代码如下:

import numpy as np

def LUDecomposition (A):
    L = np.zeros(np.shape(A),np.float64)
    U = np.zeros(np.shape(A),np.float64)
    acc = 0
    L[0,0]=1
    for i in np.arange(len(A)):

        for k in range(i,len(A)):

            for j in range(0,i):
                acc += L[i,j]*U[j,k]
            U[i,k] = A[i,k]-acc


            for m in range(k+1,len(A)):
                if m==k:
                    L[m,k]=1
                else:

                    L[m,k] = (A[m,k]-acc)/U[k,k]
            acc=0
    return (L,U)

A = np.array([[-4, -1, -2],
              [-4, 12,  3],
              [-4, -2, 18]])

L, U = LUDecomposition (A)

我哪里出错了?

看来您可能对
循环的第一个内部级别
产生了一些缩进错误:
U
必须在
L
之前进行计算;您也没有正确计算求和项
acc
,也没有正确地将
L
的对角线项设置为1。在进行一些其他语法修改后,您可以按如下方式重写函数:

def LUDecomposition(A):

    n = A.shape[0]
    L = np.zeros((n,n), np.float64)
    U = np.zeros((n,n), np.float64)

    for i in range(n):
        # U
        for k in range(i,n):
            s1 = 0  # summation of L(i, j)*U(j, k) 
            for j in range(i):
                s1 += L[i,j]*U[j,k]
            U[i,k] = A[i,k] - s1

        # L
        for k in range(i,n):
            if i==k:
                # diagonal terms of L 
                L[i,i] = 1
            else:
                s2 = 0 # summation of L(k, j)*U(j, i) 
                for j in range(i):
                    s2 += L[k,j]*U[j,i]
                L[k,i] = (A[k,i] - s2)/U[i,i]

    return L, U
当与作为可靠参考进行比较时,这一次为矩阵
A
提供了正确的输出:

import numpy as np
from scipy.linalg import lu

A = np.array([[-4, -1, -2],
              [-4, 12,  3],
              [-4, -2, 18]])

L, U = LUDecomposition(A)
P, L_sp, U_sp = lu(A, permute_l=False)

P
>>> [[1., 0., 0.],
     [0., 1., 0.],
     [0., 0., 1.]])

L
>>> [[ 1.          0.          0.        ]
     [ 1.          1.          0.        ]
     [ 1.         -0.07692308  1.        ]]

np.allclose(L_sp, L))
>>>  True

U
>>> [[-4.         -1.         -2.        ]
     [ 0.         13.          5.        ]
     [ 0.          0.         20.38461538]]

np.allclose(U_sp, U))
>>>  True
注意:与scipy lapack getrf算法不同,此Doolittle实现不包括旋转,只有当scipy.linalg.lu
返回的置换矩阵
p
是单位矩阵时,这两个比较才是真的,即scipy没有执行任何置换,对于矩阵
A
,情况确实如此。scipy算法中确定的置换矩阵旨在优化生成矩阵的条件数,以减少舍入误差。最后,您只需验证
A=LU
,如果因子分解正确,则始终如此:

A = np.random.rand(10,10)
L, U = LUDecomposition(A)

np.allclose(A, np.dot(L, U))
>>>  True

然而,就数值效率和精度而言,我不建议您使用自己的函数来计算LU分解。希望这能有所帮助。

似乎您在
循环的第一个内部级别
上出现了一些缩进错误:
U
必须在
L
之前进行计算;您也没有正确计算求和项
acc
,也没有正确地将
L
的对角线项设置为1。在进行一些其他语法修改后,您可以按如下方式重写函数:

def LUDecomposition(A):

    n = A.shape[0]
    L = np.zeros((n,n), np.float64)
    U = np.zeros((n,n), np.float64)

    for i in range(n):
        # U
        for k in range(i,n):
            s1 = 0  # summation of L(i, j)*U(j, k) 
            for j in range(i):
                s1 += L[i,j]*U[j,k]
            U[i,k] = A[i,k] - s1

        # L
        for k in range(i,n):
            if i==k:
                # diagonal terms of L 
                L[i,i] = 1
            else:
                s2 = 0 # summation of L(k, j)*U(j, i) 
                for j in range(i):
                    s2 += L[k,j]*U[j,i]
                L[k,i] = (A[k,i] - s2)/U[i,i]

    return L, U
当与作为可靠参考进行比较时,这一次为矩阵
A
提供了正确的输出:

import numpy as np
from scipy.linalg import lu

A = np.array([[-4, -1, -2],
              [-4, 12,  3],
              [-4, -2, 18]])

L, U = LUDecomposition(A)
P, L_sp, U_sp = lu(A, permute_l=False)

P
>>> [[1., 0., 0.],
     [0., 1., 0.],
     [0., 0., 1.]])

L
>>> [[ 1.          0.          0.        ]
     [ 1.          1.          0.        ]
     [ 1.         -0.07692308  1.        ]]

np.allclose(L_sp, L))
>>>  True

U
>>> [[-4.         -1.         -2.        ]
     [ 0.         13.          5.        ]
     [ 0.          0.         20.38461538]]

np.allclose(U_sp, U))
>>>  True
注意:与scipy lapack getrf算法不同,此Doolittle实现不包括旋转,只有当scipy.linalg.lu
返回的置换矩阵
p
是单位矩阵时,这两个比较才是真的,即scipy没有执行任何置换,对于矩阵
A
,情况确实如此。scipy算法中确定的置换矩阵旨在优化生成矩阵的条件数,以减少舍入误差。最后,您只需验证
A=LU
,如果因子分解正确,则始终如此:

A = np.random.rand(10,10)
L, U = LUDecomposition(A)

np.allclose(A, np.dot(L, U))
>>>  True

然而,就数值效率和精度而言,我不建议您使用自己的函数来计算LU分解。希望这会有所帮助。

首先,请不要发布这样的图片,这意味着人们必须手动键入示例代码,并且它与屏幕阅读器不兼容,等等。其次,如果您将代码粘贴到文件中,并将其作为普通python脚本运行(即不在jupyter中),它将准确地告诉您问题所在。毫不奇怪,它发生在唯一一行上带有
/
。如果您使用调试器,您可以在该行上设置断点并检查其原因。首先,请不要发布这样的图片,这意味着人们必须手动键入示例代码,并且它与屏幕阅读器不兼容,等等。其次,如果您将代码粘贴到文件中,并将其作为普通python脚本运行(即不在jupyter中)它将准确地告诉您问题所在。毫不奇怪,它发生在唯一一行上带有
/
。如果使用调试器,您可以在该行上设置断点并检查其原因。我明白了,这是我的“创新”问题。我认为两个范围循环(I,n)是做同样的事情,为什么不合并呢。而且很明显我对L(I,j)的编码错了。我知道,这是我的“创新”问题。我认为两个范围循环(I,n)在做同样的事情,所以为什么不合并呢。而且很明显我对L(I,j)的编码错了