数值分析——直接法解线性方程组

  数值分析中,直接法解线性方程组,python编写。具体代码见我的下载。

'''
    解线性方程组
    =====================================================
    =   直接法:(A为方阵)
    =       1. 高斯消去法/列主元消去法
    =       2. 三角分解法(A为方阵)
    =             直接分解法: A = L(DU)
    =             平方根法:   A = LDL.T
    =             追赶法:     A = (LD)U
    =====================================================
    =   创建日期: 2018/10/29 20:52
    =   修改日期: 2019/01/05 16:55
'''

# 引入numpy库
import numpy as np

# 测试矩阵

A1 = np.array([[ 5,  2,  1],
               [-1,  4,  2],
               [ 2, -3,  10]])
b1 = np.array([[-12],
               [ 20],
               [ 3]])

A2 = np.array([[ 0.001,  2.000,  3.000],
               [-1.000,  3.712,  4.622],
               [-2.000, 1.072,  5.643]])
b2 = np.array([[1.000],
               [2.000],
               [3.000]])

A3 = np.array([[1,2,3,4],\
               [1,2,3,4],\
               [1,2,3,4],\
               [1,2,3,4]])
b3 = np.array([[1],\
               [1],\
               [1],\
               [1]])

def gauss_eli(A, b):
    '''
    高斯消去法
    :param A:     系数矩阵
    :param b:
    :return:      解向量X
    '''

    # 将A和b组合成增广矩阵
    m,n = A.shape[0], A.shape[1]
    amat = np.zeros((m,n+1))
    amat[:, 0:n] = A
    amat[:, n] = b[:,0]
    # 获取待求解增广矩阵的系数矩阵的行数和列数
    (rmat_row, rmat_col) = np.shape(amat)  # rmat -- 系数矩阵(ratio matrix)
    rmat_col -= 1

    # 消元过程
    for k in range(rmat_row-1):  # n-1次消元
        # 计算Mik
        m_ik = np.array([0.0]*(rmat_row-k-1))  # 存放m_ik
        if amat[k, k] != 0:
            for c in range(rmat_row-k-1):
                m_ik[c] = amat[k+1+c, k] / amat[k, k]  # 公式
            # 计算消元K次后各元素的值
            for i in range(rmat_row-k-1):
                for j in range(rmat_col+1):  
                    amat[i+1+k, j] = amat[i+1+k, j] - m_ik[i]*amat[k, j]  # 公式
        else:
            print('主对角线元素为0!')
            break
        # 输出A
        print('第',k+1,'次:')
        print(amat)

    # 回代过程 -- 求解解向量
    x_arr = np.array([0.0]*rmat_row)  # 存放解向量
    x_arr[rmat_row-1] = amat[rmat_row-1, rmat_col] / amat[rmat_row-1, rmat_col-1]  # Xn
    for r in range(rmat_row-1):
        sum = 0.0
        for c in range(rmat_col-1-(rmat_row-r-2)):
            sum = sum + amat[rmat_row-r-2, (rmat_row-r-2)+c+1]*x_arr[rmat_row-r-1+c]
        x_arr[rmat_row-r-2] = (amat[rmat_row-r-2, rmat_col] - sum) / amat[rmat_row-r-2, rmat_row-r-2]
    # 返回解向量
    return x_arr.reshape(rmat_row, 1)

def gauss_col(A, b):
    '''
    :列主消元法
    :param A:
    :param b:
    :return:
    '''

    # 将A和b组合成增广矩阵
    m, n = A.shape[0], A.shape[1]
    amat = np.zeros((m, n + 1))
    amat[:, 0:n] = A
    amat[:, n] = b[:, 0]
    # 获取待求解增广矩阵的系数矩阵的行数和列数
    (rmat_row, rmat_col) = np.shape(amat)  # rmat -- 系数矩阵(ratio matrix)
    rmat_col -= 1
    # 消元过程
    for k in range(rmat_row-1):  # n-1次消元
        # 是否换行
        _max_index = np.abs(amat[:, k]).argmax()
        temp = np.array([0.0]*(rmat_col+1))
        for i in range((rmat_col+1)):
            temp[i] = amat[_max_index, i]
        amat[_max_index,:] = amat[k,:]
        for i in range((rmat_col+1)):
            amat[k,i] = temp[i]
        print('第',k+1,'换行:')
        print(amat)
        # 计算Mik
        m_ik = np.array([0.0]*(rmat_row-k-1))  # 存放m_ik
        if amat[k, k] != 0:
            for c in range(rmat_row - k - 1):
                m_ik[c] = amat[k+1+c, k] / amat[k, k]  # 公式
            # 计算消元K次后各元素的值
            for i in range(rmat_row-k-1):
                for j in range(rmat_col + 1):
                    amat[i+1+k, j] = amat[i+1+k, j] - m_ik[i]*amat[k,j]  # 公式
        else:
            print('主对角线元素为0!')
            break
        # 输出A
        print('第', k + 1, '次消元:')
        print(amat)

    # 回代过程 -- 求解解向量
    x_arr = np.array([0.0] * rmat_row)  # 存放解向量
    x_arr[rmat_row-1] = amat[rmat_row-1, rmat_col] / amat[rmat_row-1, rmat_col-1]  # Xn
    for r in range(rmat_row-1):
        sum = 0.0
        for c in range(rmat_col-1-(rmat_row-r-2)):
            sum = sum + amat[rmat_row-r-2, (rmat_row-r-2)+c+1] * x_arr[rmat_row-r-1+c]
        x_arr[rmat_row-r-2] = (amat[rmat_row-r-2, rmat_col]-sum) / amat[rmat_row-r-2, rmat_row-r-2]
    # 返回解向量
    return x_arr.reshape(rmat_row, 1)

def LU(A, b):
    '''
    :直接三角形分解法 -- 使用的是杜利特尔分解
    :param A:   系数矩阵
    :param b:
    :return:    解向量X、L、U
    '''

    m = A.shape[0]   # 行数
    n = A.shape[1]   # 列数

    A = np.array(A, dtype=float)  # 如果A的所有元素为整数,必须变换A的类型!!!

    # 矩阵LU分解
    L = np.eye(m)   # 单位下三角矩阵
    for k in range(m-1):
        # 计算Mik
        m_ik = np.array([0.0]*(m-1-k))  # 存放m_ik
        if A[k, k] != 0:
            for c in range(len(m_ik)):
                m_ik[c] = A[k+1+c, k] / A[k, k]  # 公式
                A[c+1+k,:] = A[c+1+k,:] + (-m_ik[c]*A[k,:])
        for i in range(m-k-1):
            L[i+1+k, k] = m_ik[i]    # L矩阵
    U = A  # 上三角矩阵

    # Ly = b
    y = np.dot(np.linalg.inv(L), b)
    # Ux = y 等价于 (DU)x = y
    x = np.dot(np.linalg.inv(U), y)
    # 返回x, L, U
    return x, L, U

def purchase(A, b):
    '''
    :追赶法 -- 使用的是crout分解
    :param A:  系数矩阵
    :param b:
    :return:   返回x、L、D、U
    '''

    m = A.shape[0]  # 行数
    n = A.shape[1]  # 列数

    A = np.array(A, dtype=float)

    # 矩阵LU分解
    L = np.eye(m)  # 单位下三角矩阵
    for k in range(m - 1):
        # 计算Mik
        m_ik = np.array([0.0] * (m - 1 - k))  # 存放m_ik
        if A[k, k] != 0:
            for c in range(len(m_ik)):
                m_ik[c] = A[k + 1 + c, k] / A[k, k]  # 公式
                A[c + 1 + k, :] = A[c + 1 + k, :] + (-m_ik[c] * A[k, :])
        for i in range(m - k - 1):
            L[i + 1 + k, k] = m_ik[i]  # L矩阵
    U = A  # 上三角矩阵
    D = np.zeros((m,n))  # 对角矩阵
    for i in range(m):
        if U[i,i] != 0:
            D[i,i] = U[i,i]
            U[i,:] = U[i,:] / D[i,i]  # 把U变为单位下三角矩阵

    # (LD)y = b
    y = np.dot(np.linalg.inv(np.dot(L,D)), b)
    # Ux = y
    x = np.dot(np.linalg.inv(U), y)
    # 返回x, L, U
    return x, L, D, U

def sqrt2(A, b):
    '''
    :改进的平方根法
    :param A:  A为正定实对称矩阵
    :param b:
    :return:
    '''

    m = A.shape[0]  # 行数
    n = A.shape[1]  # 列数

    A = np.array(A, dtype=float)

    # 矩阵LU分解
    L = np.eye(m)  # 单位下三角矩阵
    for k in range(m - 1):
        # 计算Mik
        m_ik = np.array([0.0] * (m - 1 - k))  # 存放m_ik
        if A[k, k] != 0:
            for c in range(len(m_ik)):
                m_ik[c] = A[k + 1 + c, k] / A[k, k]  # 公式
                A[c + 1 + k, :] = A[c + 1 + k, :] + (-m_ik[c] * A[k, :])
        for i in range(m - k - 1):
            L[i + 1 + k, k] = m_ik[i]  # L矩阵
    # 在该方法中,L.T = U
    U = A  # 上三角矩阵
    D = np.zeros((m, n))  # 对角矩阵
    for i in range(m):
        if U[i, i] != 0:
            D[i, i] = U[i, i]
            U[i, :] = U[i, :] / D[i, i]  # 把U变为单位下三角矩阵

    # Ly = b
    y = np.dot(np.linalg.inv(np.dot(L, D)), b)
    # (DL.T)x = y
    x = np.dot(np.linalg.inv(U), y)
    # 返回x, L, U
    return x, L, D, U

def main():

    print('=' * 25, '高斯消去法', '=' * 25)
    x = gauss_eli(A2, b2)
    print('解:')
    print(x)

    print('=' * 25, '列主消去法', '=' * 25)
    x1 = gauss_col(A2, b2)
    print('解:')
    print(x1)

    xlu,L1,U1 = LU(A2, b2)
    print('='*25,'直接三角形分解法','='*25)
    print('单位下三角矩阵-L:')
    print(L1)
    print('上三角矩阵-U:')
    print(U1)
    print('解:')
    print(xlu)

    xpur, L2, D2, U2 = purchase(A2, b2)
    print('=' * 25, '追赶法', '=' * 25)
    print('单位下三角矩阵-L:')
    print(L2)
    print('对角矩阵-D:')
    print(D2)
    print('单位上三角矩阵-U:')
    print(U2)
    print('解:')
    print(xpur)
    print('=' * 25, '平方根法', '=' * 25)
    print('对于平方根法,由于A为正定实堆成矩阵,所以求的L的转置=U')
    print('只要将追赶法中的U写成L的转置即可,其余的同追赶法!')

    input('')

if __name__ == "__main__":
    main()

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值