计算机求解线性方程组python的ilu分解 python lu分解_python的ilu分解过程中,更多的是采用数值计算方法求解而取代数学意义上效率更高的求逆运算,其中一个重要的问题是数值的稳定性。

上述线性方程组中python的ilu分解 python lu分解_数值计算方法_02python的ilu分解 python lu分解_python_03阶方阵,其中实际求解问题中只针对非奇异矩阵的情况下,这里首先介绍一种较为常见的python的ilu分解 python lu分解_线性方程组_04分解方式求解方法。

python的ilu分解 python lu分解_线性方程组_04方法求解

原理为找出满足条件的三个python的ilu分解 python lu分解_python_03阶方阵python的ilu分解 python lu分解_线性方程组_04使得
python的ilu分解 python lu分解_数值计算方法_08
其中python的ilu分解 python lu分解_python_09为下三角矩阵,python的ilu分解 python lu分解_python的ilu分解_10为上三角矩阵,python的ilu分解 python lu分解_python_11为置换矩阵,在原方程python的ilu分解 python lu分解_python的ilu分解中会得到
python的ilu分解 python lu分解_python的ilu分解_13
其中定义python的ilu分解 python lu分解_python_14得到python的ilu分解 python lu分解_数学_15这时该位置向量python的ilu分解 python lu分解_数值计算方法_16会被更容易的求得,之后将python的ilu分解 python lu分解_python_14以类似方式求解,其中做回推:
python的ilu分解 python lu分解_python_18
上述两步python的ilu分解 python lu分解_数学_15python的ilu分解 python lu分解_python_14为三角矩阵求解未知数,用前者表示说明:
python的ilu分解 python lu分解_线性方程组_21
由于python的ilu分解 python lu分解_python_11为置换矩阵所以python的ilu分解 python lu分解_数值计算方法_23只是被替换顺序的原先列向量,而python的ilu分解 python lu分解_python_09是对角线元素为python的ilu分解 python lu分解_python_25的下三角矩阵,那么求解过程可以很容易的表示为:
python的ilu分解 python lu分解_线性方程组_26
可以看出方式为朴素的从上到下迭代求解,时间复杂度为python的ilu分解 python lu分解_数学_27,第二步的上三角矩阵反向推得可知:
python的ilu分解 python lu分解_数值计算方法_28
这里python的ilu分解 python lu分解_python的ilu分解_10为对角线不为1的上三角矩阵,那么求解过程不仅仅要自下而上并且需要有除法进行,其中计算机内进行过程中会涉及到数值精度问题。
python的ilu分解 python lu分解_数值计算方法_30
这里的置换矩阵python的ilu分解 python lu分解_python_11提高了解决问题的数值稳定性,主要解决的是分解矩阵时存在python的ilu分解 python lu分解_python_32趋近于零的情况,本文暂时讨论python的ilu分解 python lu分解_线性方程组_04分解计算方法,这里给出python的ilu分解 python lu分解_python的ilu分解_34上述对应的的求解方法:

import numpy as np
def LUPSolve(L, U, pi, b):
    n = L.shape[0]
    y = np.zeros((n, 1))
    x = np.zeros((n, 1))
    for i in range(n):
        y[i] = b[pi[i]] - np.dot(L[i], y)
    for i in range(n-1, -1, -1):
        x[i] = (y[i]-np.dot(U[i], x))/U[i, i]
    return x

其中各项数据及其输出为:

L = np.array([[1, 0, 0], [0.2, 1, 0], [0.6, 0.5, 1]])
U = np.array([[5, 6, 3], [0, 0.8, -0.6], [0, 0, 2.5]])
b = np.array([3, 7, 8])
pi = np.array([2, 0, 1])
print(LUPSolve(L, U, pi, b))
->[[-1.4] [ 2.2] [ 0.6]]

前三个变量以知,python的ilu分解 python lu分解_数值计算方法_35的角色扮演为索引数组取代了运算中置换矩阵的作用

计算python的ilu分解 python lu分解_线性方程组_36分解

首先考虑基础的不含python的ilu分解 python lu分解_python_11矩阵的python的ilu分解 python lu分解_线性方程组_36分解,那么可以由高斯消元法推得:
python的ilu分解 python lu分解_线性方程组_39
此处在方阵中采用的递推式消元,上述公式指明了消元的一个状态,而每个状态都能成功分解一层,由矩阵乘法验证可知:
python的ilu分解 python lu分解_python_40
其中上述式子推导类似高等代数中分块矩阵乘法所应用的情景,最终通过迭代python的ilu分解 python lu分解_python_03次求解python的ilu分解 python lu分解_线性方程组_36矩阵,可以看出并不用每一层处理后都进行分解,因为在递推的的状态下只需要将每层的数据保留继续计算下一层的python的ilu分解 python lu分解_数值计算方法_02直至结束即可,最终上三角部分即为矩阵python的ilu分解 python lu分解_python的ilu分解_10,下三角部分使用python的ilu分解 python lu分解_python_25填补对角线即为矩阵python的ilu分解 python lu分解_python_09

def LUDecomposition(A):
    n = A.shape[0]
    L, U = np.eye(n), np.zeros((n, n))
    for k in range(n):
        U[k, k] = A[k, k]
        for i in range(k+1, n):
            L[i, k] = A[i, k]/U[k, k]
            U[k, i] = A[k, i]
        for i in range(k + 1, n):
            for j in range(k+1, n):
                A[i, j] -= L[i, k]*U[k, j]
    return L, U

由于python的ilu分解 python lu分解_python_09对角线为python的ilu分解 python lu分解_python_25所以提前设置为单位矩阵,之后每行遍历对应第python的ilu分解 python lu分解_数值计算方法_49行:

  • 计算python的ilu分解 python lu分解_数学_50python的ilu分解 python lu分解_python的ilu分解_51的子矩阵;
  • 保留python的ilu分解 python lu分解_数学_50到矩阵python的ilu分解 python lu分解_数学_53
  • 维护子矩阵第python的ilu分解 python lu分解_数值计算方法_54列数据与第python的ilu分解 python lu分解_数值计算方法_54行数据;
  • 计算下一阶段子矩阵:
    python的ilu分解 python lu分解_线性方程组_56
计算python的ilu分解 python lu分解_线性方程组_04分解

为了解决上述python的ilu分解 python lu分解_python_32有可能为零的情况,python的ilu分解 python lu分解_线性方程组_04分解再分解过程中加入了选择步骤:

选择当前状态当前列的绝对值最大的行索引交换到当前行,并将过程中的交换内容保存在置换矩阵中,这里我们在数据实现部分将交换保存在了数组中,主要作用是减少占用空间且作为索引数组使用,记作python的ilu分解 python lu分解_线性方程组_60

其中推导过程下节结合舒尔补做进一步说明,这里给出实现程序:

def LUPDecomposition(A):
    n = A.shape[0]
    pi = np.zeros((n, 1))
    for i in range(n):
        pi[i] = i
    for k in range(n):
        p = 0
        for i in range(k, n):
            if np.abs(A[i, k]) > p:
                p = np.abs(A[i, k])
                k_ = i
        if p == 0:
            error("singular matrix")
        pi[k], pi[k_] = pi[k_], pi[k]
        A[[k, k_], :] = A[[k_, k], :]
        for i in range(k+1, n):
            A[i, k] /= A[k, k]
            for j in range(k+1, n):
                A[i, j] -= A[i, k]*A[k, j]
    return A