线性方程组的解 python

一. 上三角

【问题描述】在一个上三角线性方程组基础上,进行线性方程组求解。

【输入形式】在屏幕上依次输入方阵阶数n,系数矩阵A和常数矩阵B。

【输出形式】每一行输出一个根

【样例1输入】

4

4 -1 2 3

0 -2 7 -4

0 0 6 5

0 0 0 3

20

-7

4

6

【样例1输出】

[[ 3.]

[-4.]

[-1.]

[ 2.]]

【样例1说明】输入:第1行为方阵阶数4,第2行至5行为系数矩阵A,第6行至9行为常数矩阵B。输出:每行依次输出方程解:x1, x2, x3, x4。

【评分标准】根据输入得到的输出准确

# 回代法解上三角矩阵
import numpy as np

def backsub(A, B):
    n = B.size
    X = np.zeros([n,1], dtype = np.double)
    X[n-1] = B[n-1] / A[n-1, n-1]
    for k in range (n-2, -1, -1):
        X[k] = (B[k] - A[k, k+1:] @ X[k+1:]) / A[k, k] 
    return X

def main():
    n = int(input())
    A = np.zeros([n,n],dtype=np.double)
    for r in range(n):
        A[r:] = np.array(input().split(),dtype = np.double)
    B = np.zeros((n,1),dtype=np.double)
    for r in range(n):
        B[r] = np.array(input(),dtype = np.double)
    X = backsub(A,B)
    print(X)

if __name__ == '__main__':
    main()

二. 选主元的高斯消去

【问题描述】为求解一个线性方程组,首先构造增广矩阵[A|B],采用偏序选主元策略的高斯消去法变换成上三角矩阵,再执行回代过程得到解。

【输入形式】在屏幕上依次输入方阵阶数n,系数矩阵A和常数矩阵B。

【输出形式】首先输出上三角矩阵(变换后的增广矩阵),然后每一行输出一个根

【样例1输入】

4

1 2 1 4

2 0 4 3

4 2 2 1

-3 1 3 2

13

28

20

6

【样例1输出】

[[ 4. 2. 2. 1. 20. ]

[ 0. 2.5 4.5 2.75 21. ]

[ 0. 0. 4.8 3.6 26.4 ]

[ 0. 0. 0. 3.75 7.5 ]]

[[ 3.]

[-1.]

[ 4.]

[ 2.]]

【样例1说明】输入:第1行为方阵阶数4,第2行至5行为系数矩阵A,第6行至9行为常数矩阵B。

输出:首先输出上三角矩阵(变换后的增广矩阵),然后每行依次输出方程解:x1, x2, x3, x4。

【评分标准】根据输入得到的输出准确

10.0
import numpy as np
import math
def Elimination(n, A):
    # 机器精度
    epslion = np.finfo(np.float32).eps
    # i是指列号, i列搜过之后,i行也确定下来,i有时也可指行号
    for i in range(n):
        # np.argmax(a, axis=0)按列方向搜索最大值, 默认按列搜索
        # np.argmax(a, axis=1)行方向搜索最大值,
        # np.abs()取绝对值
        # A[i:n, i] 行从i开始,不包含n
        max_index = np.argmax(np.abs(A[i:n, i])) # 返回第i列(搜过的就不要搜了)最大绝对值的“相对列”的行号
        max_row = max_index + i # 真实列的行号
        # 交换i, max_row行,python的特殊语法,记住
        A[[i, max_row], :] = A[[max_row, i], :]
        # (if A[i, i] != 0:) 主元不可为零,太小也不行
        if abs(A[i, i]) < epslion:
            # 从下一行开始处理
            for j in range(i+1, n):
                m = A[j, i]/A[i, i]
                """
                for k in range(i,n+1):
                    if k == i:
                        A[j, k] = 0
                    else:
                        A[j, k] = A[j, k]-m*A[i, k]
                """
                A[j, i:n+1] = A[j, i:n+1] - m*A[i, i:n+1]
    return A

def backsub(n, A, B):
    X = np.zeros([n,1], dtype = np.double)
    X[n-1] = B[n-1] / A[n-1, n-1]
    for k in range (n-2, -1, -1):
        X[k] = (B[k] - A[k, k+1:] @ X[k+1:]) / A[k, k]
    return X

def main():
    n = int(input())
    A = np.zeros([n, n], dtype=np.double)
    for r in range(n):
        A[r:] = np.array(input().split(), dtype=np.double)
    B = np.zeros((n, 1), dtype=np.double)
    for r in range(n):
        B[r] = np.array(input(),dtype = np.double)
    # np.hstack 将A,B以列合并,U为增广矩阵
    U = np.hstack((A, B))
    # 高斯消元,构造上三角矩阵
    U = Elimination(n, U)
    # 输出构造好的上三角矩阵
    print(U)
    crr = backsub(n, U[:, 0:n], U[:, n:])
    print(crr)
if __name__ == '__main__':
    main()

关于矩阵切片,参考冒号在矩阵中的使用

三. 三角分解

【问题描述】为求解一个线性方程组,首先采用偏序选主元策略的三角分解法构造矩阵L,U和P,再用前向替换法对方程组LY=PB求解Y,最后用回代法对方程组UX=Y求解X。

【输入形式】在屏幕上依次输入方阵阶数n,系数矩阵A和常数矩阵B。

【输出形式】先输出LU分解结果,再输出方程解。

【样例1输入】

4

1 2 4 1

2 8 6 4

3 10 8 8

4 12 10 6

21

52

79

82

【样例1输出】

[[ 4. 12. 10. 6. ]

[ 0.5 2. 1. 1. ]

[ 0.25 -0.5 2. 0. ]

[ 0.75 0.5 0. 3. ]]

[[1.]

[2.]

[3.]

[4.]]

【样例1说明】输入:第1行为方阵阶数4,第2行至5行为系数矩阵A,第6行至9行为常数矩阵B。输出:第1至第4行输出LU分解结果,第5行至第8行依次输出方程解:x1, x2, x3, x4。

【评分标准】根据输入得到的输出准确

import numpy as np
import math
def sanjiao(n, A, B ):
    # R记录行的交换
    R = np.zeros((n, 1), dtype=int)
    for r in range(n):
        R[r] = r
    for i in range(n-1):
        # np.argmax(a, axis=0)按列方向搜索最大值, 默认按列搜索
        # np.argmax(a, axis=1)行方向搜索最大值,
        # np.abs()取绝对值
        # A[i:n, i] 行从i开始,不包含n
        max_index = np.argmax(np.abs(A[i:n, i]))  # 返回第i列(搜过的就不要搜了)最大绝对值的“相对列”的行号
        max_row = max_index + i  # 真实列的行号
        # 交换i, max_row行,python的特殊语法,记住
        A[[i, max_row], :] = A[[max_row, i], :]
        # 在R上做标记
        #R[[i, max_row], :] = R[[max_row, i], :]
        R[i], R[max_row]= R[max_row], R[i]
        #print(i, max_row)print(R)
        if A[i, i] != 0:
            # 从下一行开始,一行一行处理
            for j in range(i+1, n):
                m = A[j, i]/A[i, i]
                # A是LU的结合体
                A[j, i] = m
                A[j, i+1:n] = A[j, i+1:n]-m*A[i, i+1:n]
    print(A)
    # 向前替换求Y
    Y = np.zeros([n, 1], dtype=np.double)
    # L的对角线上全为1
    Y[0] = B[R[0]]
    for i in range(1,n):
        k = i
        Y[i] = B[R[i]]
        while (k>0):
            Y[i] = Y[i] - A[i,k-1]*Y[k-1]
            k = k - 1
    #print(Y)
    X = backsub(n, A, Y)
    print(X)

def backsub(n, A, B):
    X = np.zeros([n,1], dtype = np.double)
    X[n-1] = B[n-1] / A[n-1, n-1]
    for k in range (n-2, -1, -1):
        X[k] = (B[k] - A[k, k+1:] @ X[k+1:]) / A[k, k]
    return X

def main():
    n = int(input())
    A = np.zeros([n, n], dtype=np.double)
    for r in range(n):
        A[r:] = np.array(input().split(), dtype=np.double)
    B = np.zeros((n, 1), dtype=np.double)
    for r in range(n):
        B[r] = np.array(input(), dtype=np.double)
    sanjiao(n, A, B)

if __name__ == '__main__':
    main()

四. 高斯赛德尔迭代法

【问题描述】为求解一个线性方程组,使用高斯赛德尔迭代法,采用欧几里得距离判定是否收敛。精度delta为1E-9,最大迭代次数为20。

【输入形式】在屏幕上依次输入方阵阶数n,系数矩阵A,常数矩阵B和起始点P。

【输出形式】输出实际迭代次数,然后每一行输出一个根。

【样例1输入】

3
4 -1 1
4 -8 1
-2 1 5
7
-21
15
1
2
2

【样例1输出】

10

[[2.]

[4.]

[3.]]

【样例1说明】输入:第1行为方阵阶数3,第2行至4行为系数矩阵A,第5行至7行为常数矩阵B,第8行至10行为起始点。输出:实际迭代次数为10,然后每行依次输出方程解:x1, x2, x3。

【评分标准】根据输入得到的输出准确

import numpy as np
import math
# 高斯赛德尔迭代法
def gaos(n, A = None,B = None,P=None):
    # delta = 1e-9为精度
    delta = 1e-9
    eps = 1e-6
    # 最大迭代次数
    max1 = 20
    # X(k+1)的集,将更新P
    X = np.zeros([n, 1], dtype=np.double)
    for i in range(max1):
        for j in range(n):
            if j == 0:
                X[0] = (B[0]-A[0,1:]@P[1:])/A[0, 0]
            else:
                # j!==n-1时,P未更新,应用X(k+1),即为X
                if j == n-1:
                    X[n-1] = (B[n-1]-A[n-1, :n-1] @ X[:n-1])/A[n-1,n-1]
                # j!=0,j!==n-1时,P未更新,X为更新完,应用X(k+1)和P的部分
                else:
                    X[j] = (B[j]-A[j, :j] @ X[:j]-A[j,j+1:] @ P[j+1:])/A[j,j]
        # np.linalg.norm()求范数 np.inf无穷大
        err = np.linalg.norm(X-P, np.inf)
        # 精度
        relerr = err/(np.linalg.norm(X, np.inf)+eps)
        # 更新P
        P = X.copy()
        if err < delta or relerr < delta:
            # 输出迭代次数
            print(i)
            break
    print(X)
def main():
    n = int(input())
    A = np.zeros([n, n], dtype=np.double)
    for r in range(n):
        A[r:] = np.array(input().split(), dtype=np.double)
    B = np.zeros((n, 1), dtype=np.double)
    for r in range(n):
        B[r] = np.array(input(), dtype=np.double)
    # 起始点
    P = np.zeros((n, 1), dtype=np.double)
    for r in range(n):
        P[r] = np.array(input(), dtype=np.double)
    gaos(n, A, B, P)
if __name__ == '__main__':
    main()

你可能感兴趣的:(python,numpy,python)