一. 上三角
【问题描述】在一个上三角线性方程组基础上,进行线性方程组求解。
【输入形式】在屏幕上依次输入方阵阶数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()