Python LU分解中的零除警告-Doolittle算法工作
我通过以下链接实现了矩阵LU分解的标准方程/算法:()和() 这将返回如下所示的方形矩阵的LU分解。 然而,我的问题是-它也会给出一个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
除以零的警告
代码如下:
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)的编码错了