【发布时间】:2018-07-20 19:12:17
【问题描述】:
我正在我的大学学习数值分析课程。我们正在研究LU decomposition。在查看讲师的版本之前,我尝试实施我的版本。我认为我的速度相当快,但实际上比较它们,我的讲师版本更快,即使它使用循环!这是为什么呢?
讲师版
def LU_decomposition(A):
"""Perform LU decomposition using the Doolittle factorisation."""
L = np.zeros_like(A)
U = np.zeros_like(A)
N = np.size(A, 0)
for k in range(N):
L[k, k] = 1
U[k, k] = (A[k, k] - np.dot(L[k, :k], U[:k, k])) / L[k, k]
for j in range(k+1, N):
U[k, j] = (A[k, j] - np.dot(L[k, :k], U[:k, j])) / L[k, k]
for i in range(k+1, N):
L[i, k] = (A[i, k] - np.dot(L[i, :k], U[:k, k])) / U[k, k]
return L, U
我的版本
def lu(A, non_zero = 1):
'''
Given a matrix A, factorizes it into two matrices L and U, where L is
lower triangular and U is upper triangular. This method implements
Doolittle's method which sets l_ii = 1, i.e. L is a unit triangular
matrix.
:param A: Matrix to be factorized. NxN
:type A: numpy.array
:param non_zero: Value to which l_ii is assigned to. Must be non_zero.
:type non_zero: non-zero float.
:return: (L, U)
'''
# Check if the matrix is square
if A.shape[0] != A.shape[1]:
return 'Input argument is not a square matrix.'
# Store the size of the matrix
n = A.shape[0]
# Instantiate two zero matrices NxN (L, U)
L = np.zeros((n,n), dtype = float)
U = np.zeros((n,n), dtype = float)
# Start algorithm
for k in range(n):
# Specify non-zero value for l_kk (Doolittle's)
L[k, k] = non_zero
# Case k = 0 is trivial
if k == 0:
# Complete first row of U
U[0, :] = A[0, :] / L[0, 0]
# Complete first column of L
L[:, 0] = A[:, 0] / U[0, 0]
# Case k = n-1 is trivial
elif k == n-1:
# Obtain u_nn
U[-1, -1] = (A[-1, -1] - np.dot(L[-1, :], U[:, -1])) / L[-1, -1]
else:
# Obtain u_kk
U[k, k] = (A[k, k] - np.dot(L[k, :], U[:, k])) / L[k, k]
# Complete kth row of U
U[k, k+1:] = (A[k, k+1:] - [np.dot(L[k, :], U[:, i]) for i in \
range(k+1, n)]) / L[k, k]
# Complete kth column of L
L[k+1:, k] = (A[k+1:, k] - [np.dot(L[i, :], U[:, k]) for i in \
range(k+1, n)]) / U[k, k]
return L, U
基准测试
我使用了以下命令:
A = np.random.randint(1, 10, size = (4,4))
%timeit lu(A)
57.5 µs ± 2.67 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit LU_decomposition(A)
42.1 µs ± 776 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
还有,scipy 的版本怎么这么好?
scipy.linalg.lu(A)
6.47 µs ± 219 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
【问题讨论】:
标签: python arrays numpy matrix scipy