武汉理工大学-数值分析-(3)线性代数方程组的数值解法

文章目录

    • 实验目标
    • 编程语言与扩展库
      • 高斯消元法(Gauss)
      • 列主元高斯消元法(Gauss)
      • 列主元LU直接分解法
      • Jacobi迭代法
      • Gauss-Seidel迭代法
    • 写在最后

实验目标

用编程语言编程实现以下算法:
1.用 高斯(Gauss)消元法 求n阶线性方程组的解。
2.用 列主元高斯(Gauss)消元法 求n阶线性方程组的解。
3.用 列主元LU直接分解法 求n阶线性方程组的解。
4.用 Jacobi迭代法 求n阶线性方程组的解。
5.用 Gauss-Seidel迭代法 求n阶线性方程组的解。

编程语言与扩展库

语言:Python
扩展模块:numpy

高斯消元法(Gauss)

# 导入模块
from numpy import *

# 高斯消元法  求解Ax=b
def Gauss(A,b):

    # 获取A的行列
    row = A.shape[0]
    column = A.shape[1]
    # 非方阵情况
    if row != column:
        print('A不是方阵!')
        return

    n = row    # 未知数数量
    m = zeros((n,n))    # m矩阵存储乘数

    # 消元过程
    for k in range(0,n-1):
        for i in range(k+1,n):
            # 第i行除第k行得乘数
            m[i,k] = A[i,k]/A[k,k]
            # 方程消元
            A[i,:] = A[i,:] - m[i,k]*A[k,:]
            b[i] = b[i] - m[i,k]*b[k]

    # 回代过程
    x = transpose(zeros((1,n)))
    x[n-1] = b[n-1]/A[n-1,n-1]    # Xn的值

    # 计算Xn-1,Xn-2,...,X1的解
    for k in range(0,n-1)[::-1]:    # 第n-1行到第0行逆序
        sum = 0
        for j in range(k+1,n):
            sum += A[k,j]*x[j]
        x[k] = (b[k]-sum)/A[k,k]

    return x


if __name__ == '__main__':
    A = array([[1,1,1],[0,4,-1],[2,-2,1]], dtype = double)
    b = transpose(array([[6,5,1]], dtype = double))
    x = Gauss(A,b)
    print(x)

列主元高斯消元法(Gauss)

# 导入模块
from numpy import *

# 列主元高斯消元法  求解Ax=b
def Gauss_column_pivoting(A,b):

    # 获取A的行列
    row = A.shape[0]
    column = A.shape[1]
    # 非方阵情况
    if row != column:
        print('A不是方阵!')
        return

    n = row    # 未知数数量
    m = zeros((n, n))    # m矩阵存储乘数

    for k in range(0,n-1):
    # 寻找最大主元的行数
        h = argmax(abs(A[:,k]))
        # 交换行
        if k != h:
            temp1 = copy(A[k,:])    # copy产生该行的复制
            A[k,:] = A[h,:]
            A[h,:] = temp1
            temp2 = copy(b[k])
            b[k] = b[h]
            b[h] = temp2

        # 消元过程
        for i in range(k + 1, n):
            # 第i行除第k行得乘数
            m[i, k] = A[i, k] / A[k, k]
            # 方程消元
            A[i, :] = A[i, :] - m[i, k] * A[k, :]
            b[i] = b[i] - m[i, k] * b[k]

    # 回代过程
    x = transpose(zeros((1, n)))    # 构造x列向量
    x[n - 1] = b[n - 1] / A[n - 1, n - 1]    # Xn的值

    # 计算Xn-1,Xn-2,...,X1的解
    for k in range(0, n - 1)[::-1]:  # 第n-1行到第0行逆序
        sum = 0
        for j in range(k + 1, n):
            sum += A[k, j] * x[j]
        x[k] = (b[k] - sum) / A[k, k]

    return x

if __name__ == '__main__':
    A = array([[1, 1, 1], [0, 4, -1], [2, -2, 1]],  dtype = double)
    b = transpose(array([[6, 5, 1]], dtype = double))
    x = Gauss_column_pivoting(A,b)
    print(x)

列主元LU直接分解法

# 导入模块
from numpy import *

# 列主元LU分解法  求解Ax=b
def LU_column_pivoting(A,b):

    # 获取A的行列
    row = A.shape[0]
    column = A.shape[1]
    # 非方阵情况
    if row != column:
        print('A不是方阵!')
        return

    n = row
    Ip = list(range(n))    # 标记主元交换次序

    for k in range(0,n):

        # 寻找最大主元的行数
        h = argmax(abs(A[:,k]))

        # 只能选择未交换的行进行交换
        if Ip[h] == h:
             temp = copy(A[k, :])
             A[k, :] = A[h, :]
             A[h, :] = temp
             Ip[k] = h

        # 对角线减去对应行列乘积和
        A[k,k] = A[k,k] - dot(A[k,0:k], A[0:k,k])
        if A[k,k] == 0:
            print('第{}个主元为0!'.format(k+1))
            return

        # 直接在A上保存L和U
        for j in range(k+1,n):    # j>k
            A[k,j] = A[k,j] - dot(A[k,0:k], A[0:k,j])
            A[j,k] = (A[j,k] - dot(A[j,0:k], A[0:k,k])) / A[k,k]

    # 单位下三角L和上三角U
    L = tril(A,-1) + identity((n))
    U = triu(A,0)
    L.dtype = double
    U.dtype = double

    # 交换b对应行
    for i in range(0,n):
        t = Ip[i]
        if t != i:
            temp = copy(b[i])
            b[i] = b[t]
            b[t] = temp

    # 求解Ly=b
    y = transpose(array([arange(n)], dtype = double))
    y[0] = b[0]
    for i in range(1,n):
        sum = 0
        for t in range(0,i):
            sum += L[i,t]*y[t]
        y[i] = b[i] - sum

    # 求解Ux=y
    x = transpose(array([arange(n)],dtype = double))
    x[n-1] = y[n-1]/U[n-1,n-1]
    for i in range(0,n-1)[::-1]:
        sum = 0
        for t in range(i+1,n):
            sum +=  U[i,t]*x[t]
        x[i] = (y[i]-sum)/U[i,i]

    return x

if __name__ == '__main__':
    A = array([[1,2,3],[2,5,2],[3,1,5]], dtype = double)
    b = transpose(array([[14,18,20]], dtype = double))
    x = LU_column_pivoting(A,b)
    print(x)

Jacobi迭代法

# 导入模块
from numpy import *

# 初始解向量,迭代上限,误差范围
x_start = array([[0],[0],[0]])
N = 100
tol = 1e-7

# Jacobi迭代
def Jacobi(A,b):

    # 获取A的行列
    row = A.shape[0]
    column = A.shape[1]
    # 非方阵情况
    if row != column:
        print('A不是方阵!')
        return

    n = row
    x_k = x_start

    # 删去A的对角线
    A_ = copy(A)
    for i in range(n):
        A_[i,i] = 0

    # 迭代求解
    for i in range(N):

        t = transpose([diag(A)])
        x_k_plus = (b - dot(A_, x_k))/t

        # 达到足够小的误差
        if (max(abs((x_k - x_k_plus)[:,0])) < tol):
            print('迭代次数: {}'.format(i+1))
            print('方程组解: ')
            print(x_k_plus)
            break
        x_k = x_k_plus

    if  i == N:
        print('错误!不收敛!')

if __name__ == '__main__':
    A = array([[8,-3,2],[4,11,-1],[6,3,12]], dtype = double)
    b = transpose(array([[20,33,36]], dtype = double))
    Jacobi(A,b)

Gauss-Seidel迭代法

# 导入模块
from numpy import *

# 初始解向量,迭代上限,误差范围
x_start = array([[1],[2],[3]])
N = 1000
tol = 1e-10

# GS迭代法  求解Ax=b
def Gauss_Seidel(A,b):

    # 获取A的行列
    row = A.shape[0]
    column = A.shape[1]
    # 非方阵情况
    if row != column:
        print('A不是方阵!')
        return

    # 初值
    n = row
    x_k = x_start

    # 构造DLU
    U = copy(A)     # U
    DL = copy(A)    # D-L
    for i in range(n):
        for j in range(n):
            if j<=i:
                U[i,j] = 0
            else:
                DL[i,j] = 0
    U = 0-U

    # DL逆与U, b相乘
    DL_U = dot(linalg.inv(DL),U)
    DL_b = dot(linalg.inv(DL),b)

    # 迭代求解
    for i in range(N):
        x_k_plus = dot(DL_U,x_k) + DL_b

        # 达到误差要求
        if max(abs((x_k_plus - x_k)[:,0])) < tol:
            print('方程组解: ')
            print(x_k_plus)
            break
        x_k = x_k_plus

    if i == N:
        print('错误!不收敛!')

if __name__ == '__main__':
    A = array([[8, -3, 2], [4, 11, -1], [6, 3, 12]], dtype=double)
    b = transpose(array([[20, 33, 36]], dtype=double))
    Gauss_Seidel(A,b)

写在最后

声明:本文内容来源于武汉理工大学2019-2020学年数值分析方法课程实验,仅供学习参考
如有不足地方,还请指出。祝愿读者能够在编程之路上不断进步!

你可能感兴趣的:(数值分析)