如何使用numpy为隐式方法快速编写循环

时间:2019-10-30 08:20:47

标签: python numpy numeric

Numpy非常适合通过矢量化来加速代码。但是,当进行诸如Gauss-Seidel method之类的隐式迭代方程求解方法时,则数组的元素n+1依赖于n的前几个元素,从而阻止了矢量化。

我已经像这样实现了高斯塞德尔:

def gaussSeidel(A, b, x0, tol = 1e-10):
    n = len(A)
    x = np.copy(x0)
    k = 0

        while (True):
        print(k)
        for i in range(n):
            x[i] = (b[i] - np.delete(A[i], i) @ np.delete(x, i)) / A[i, i]

        if max(abs(x - x0)) < tol:
            return x

        x0 = np.copy(x)
        k += 1

这种方式比像Jacobi方法那样的显式版本慢

def jacobi(A, b, x0, tol = 1e-10):
    n = len(A)
    M = np.copy(A)
    DInv = np.zeros((n, n))
    k = 0
    for i in range(n):
        DInv[i, i] = 1 / M[i, i]
        M[i, i] = 0

    while (True):
        x = DInv @ (b - M @ x0)
        if max(abs(x - x0))  < tol:
            return x
        x0 = x
        k += 1
        print(max(abs(x - x0)))

据我所知,这里不可能消除for循环,但这是加快速度的一种方法吗?

1 个答案:

答案 0 :(得分:0)

某些可能会有所帮助的方法是将if-test移到后续循环之外

        s = b[i]
        for j in range(n):
            if i == j:
                continue
            s -= A[i, j] * x[j]

相同
        s = b[i] + A[i, i] * x[i]
        for j in range(n):
            s -= A[i, j] * x[j]

这样就避免了n次if-tests。

另一种可以尝试的方法是numba软件包,该软件包可以即时编译您的代码,而无需外部编译步骤。