当 A 是条带矩阵时,如何使用 scipy.linalg.solve_banded 来求解 Ax = b?

Y. *_*Ryu 5 python linear-algebra scipy

求解线性方程组

Ax=b
Run Code Online (Sandbox Code Playgroud)

其中 A 是一个条纹矩阵,如

图片

谁有 5 条非零对角线。

但与带状矩阵不同的是,A 具有三个偏移量分别为 0、-1 和 1 的非零对角线,以及两个偏移量分别为 -m 和 m 的非零对角线。

我尝试直接解决它

diagonals = [Ap, As, An, Aw, Ae]
A = diags(diagonals, [0, -1, 1, -m, m]).toarray()
x = linalg.solve(A, b)
Run Code Online (Sandbox Code Playgroud)

这种方法创建了整个 A。但是 A 是备用的,所以这种方法浪费了太多的内存来保存零元素。

所以我尝试使用solve_banded

A = np.zeros((2 * m + 1, len(initial)))
A[0] = Ae
A[m - 1] = An
A[m] = Ap
A[m + 1] = As
A[2 * m] = Aw
x = linalg.solve_banded((m, m), A, b)
Run Code Online (Sandbox Code Playgroud)

这种方法比以前的方法消耗更少的内存,但它仍然在(2m-4)个零向量上浪费了一些。有没有更聪明的方法只使用五个非零向量?

小智 4

嘿我可以部分回答这个问题。为了减少内存存储,您可以保持稀疏矩阵形式,而无需通过删除命令将其变成大矩阵to.array()

A = diags(diagonals, [0, -1, 1, -m, m])
Run Code Online (Sandbox Code Playgroud)

现在稀疏矩阵有它自己的spsolve方法,因此scipy.sparse.linalg.spsolve(A,b)可以工作。

为了进一步提高性能,您可以sparse.linalg.splu(A).solve(b)通过 LU 分解转换 A,然后 SuperLU 对象再次有一个solve方法。(正如我测试的,这种方法比直接方法稍快spsolve,后者也使用类似 LU 的分解。例如,请参见此处。)

这里唯一的问题是在 LU 分解过程中,由于分解,内存使用量也会很大。

我还想知道是否有任何方法可以将solve_banded稀疏矩阵的方法综合起来,因为没有固有的方法。