更新:
在 NumPy 1.8 及更高版本中,函数numpy.linalg
是广义的通用函数。这意味着您现在可以执行以下操作:
import numpy as np
a = np.random.rand(12, 3, 3)
np.linalg.inv(a)
这将反转每个 3x3 数组并将结果作为 12x3x3 数组返回。请参阅numpy 1.8 发行说明。
原答案:
由于N
相对较小,我们如何一次手动计算所有矩阵的 LU 分解。这确保了所涉及的 for 循环相对较短。
以下是使用普通 NumPy 语法的方法:
import numpy as np
from numpy.random import rand
def pylu3d(A):
N = A.shape[1]
for j in xrange(N-1):
for i in xrange(j+1,N):
#change to L
A[:,i,j] /= A[:,j,j]
#change to U
A[:,i,j+1:] -= A[:,i,j:j+1] * A[:,j,j+1:]
def pylusolve(A, B):
N = A.shape[1]
for j in xrange(N-1):
for i in xrange(j+1,N):
B[:,i] -= A[:,i,j] * B[:,j]
for j in xrange(N-1,-1,-1):
B[:,j] /= A[:,j,j]
for i in xrange(j):
B[:,i] -= A[:,i,j] * B[:,j]
#usage
A = rand(1000000,3,3)
b = rand(3)
b = np.tile(b,(1000000,1))
pylu3d(A)
# A has been replaced with the LU decompositions
pylusolve(A, b)
# b has been replaced to the solutions of
# A[i] x = b[i] for each A[i] and b[i]
正如我所写,pylu3d
修改 A 以计算 LU 分解。用其 LU 分解替换每个N
x矩阵后,可用于求解表示矩阵系统右侧的x数组。它就地修改并进行适当的反向替换以解决系统问题。正如它所写的那样,这个实现不包括旋转,所以它在数值上不稳定,但在大多数情况下它应该工作得很好。N
pylusolve
M
N
b
b
根据您的数组在内存中的排列方式,使用 Cython 可能仍然要快一些。这里有两个 Cython 函数做同样的事情,但它们M
首先迭代。它不是矢量化的,但相对较快。
from numpy cimport ndarray as ar
cimport cython
@cython.boundscheck(False)
@cython.wraparound(False)
def lu3d(ar[double,ndim=3] A):
cdef int n, i, j, k, N=A.shape[0], h=A.shape[1], w=A.shape[2]
for n in xrange(N):
for j in xrange(h-1):
for i in xrange(j+1,h):
#change to L
A[n,i,j] /= A[n,j,j]
#change to U
for k in xrange(j+1,w):
A[n,i,k] -= A[n,i,j] * A[n,j,k]
@cython.boundscheck(False)
@cython.wraparound(False)
def lusolve(ar[double,ndim=3] A, ar[double,ndim=2] b):
cdef int n, i, j, N=A.shape[0], h=A.shape[1]
for n in xrange(N):
for j in xrange(h-1):
for i in xrange(j+1,h):
b[n,i] -= A[n,i,j] * b[n,j]
for j in xrange(h-1,-1,-1):
b[n,j] /= A[n,j,j]
for i in xrange(j):
b[n,i] -= A[n,i,j] * b[n,j]
您也可以尝试使用 Numba,但在这种情况下我无法让它像 Cython 一样快。