• 北航数值分析作业三


    from  math import *
    
    t_table = [0, 0.2, 0.4, 0.6, 0.8, 1.0]
    th = 0.2
    u_table = [0, 0.4, 0.8, 1.2, 1.6, 2]
    uh = 0.4
    z_table = [[-0.5, -0.34, 0.14, 0.94, 2.06, 3.5],
               [-0.42, -0.5, -0.26, 0.3, 1.18, 2.38],
               [-0.18, -0.5, -0.5, -0.18, 0.46, 1.42],
               [0.22, -0.34, -0.58, -0.5, -0.1, 0.62],
               [0.78, -0.02, -0.5, -0.66, -0.5, -0.02],
               [1.5, 0.46, -0.26, -0.66, -0.74, -0.5]
               ]
    table_x = [0.08 * i for i in range(11)]
    table_y = [0.5 + 0.05 * i for i in range(21)]
    table_z = [[0 for i in range(len(table_y))] for j in range(len(table_x))]
    epsilon = 1e-12
    sigma_limit = 1e-7
    
    # 向量的无穷范数
    vector_norm = lambda *x: max([abs(x[i]) for i in range(len(x))])
    
    # 列主元高斯消去法求解线性方程组
    def gauss(a, b):
       for i in range(len(b)):
          maxrow = i
          for j in range(i + 1, len(b)):
             if abs(a[j][i]) > abs(a[maxrow][i]):
                maxrow = j
          # 换行
          a[maxrow], a[i] = a[i], a[maxrow]
          b[maxrow], b[i] = b[i], b[maxrow]
          for j in range(i + 1, len(b)):
             k = a[j][i] / a[i][i]
             for col in range(i, len(a[0])):
                a[j][col] -= k * a[i][col]
             b[j] -= k * b[i]
       # 回代过程
       for i in range(len(b) - 1, -1, -1):
          for col in range(i + 1, len(a[0])):
             b[i] -= a[i][col] * b[col]
          b[i] /= a[i][i]
       return b
    
    
    # 矩阵转置
    def transform(x):
       row_cnt, col_cnt = len(x), len(x[0])
       y = [[0 for i in range(row_cnt)] for j in range(col_cnt)]
       for i in range(row_cnt):
          for j in range(col_cnt):
             y[j][i] = x[i][j]
       return y
    
    
    # 矩阵相乘
    def matrix_mul_matrix(x, y):
       row_cnt, col_cnt = len(x), len(y[0])
       z = [[0 for i in range(col_cnt)] for j in range(row_cnt)]
       for i in range(row_cnt):
          for j in range(col_cnt):
             for k in range(len(x[0])):
                z[i][j] += x[i][k] * y[k][j]
       return z
    
    #牛顿迭代法
    def newton_iterate(t, u, v, w, b):
       f = [0.5 * cos(t) + u + v + w - b[0],
            t + 0.5 * sin(u) + v + w - b[1],
            0.5 * t + u + cos(v) + w - b[2],
            t + 0.5 * u + v + sin(w) - b[3]]
       f = [-1 * i for i in f]
       ff = [[-0.5 * sin(t), 1, 1, 1],
             [1, 0.5 * cos(u), 1, 1],
             [0.5, 1, -sin(v), 1],
             [1, 0.5, 1, cos(w)]]
       delta = gauss(ff, f)
       t, u, v, w = t + delta[0], u + delta[1], v + delta[2], w + delta[3]
       return t, u, v, w
    
    
    # 迭代法求解非线性方程组
    def solve(x, y):
       t, u, v, w = 1, 2, 1, 2
       b = [2.67 + x, 1.07 + y, 3.74 + x, 0.79 + y]
       while 1:
          tt, uu, vv, ww = newton_iterate(t, u, v, w, b)
          if vector_norm(tt - t, uu - u, vv - v, ww - w) / vector_norm(tt, uu, vv, ww) < epsilon:
             return tt, uu, vv, ww
          t, u, v, w = tt, uu, vv, ww
    
    
    # 二次分片插值查表根据t,u插值求出z
    def interpolate(t, u):
       ti = round(t / th)
       ui = round(u / uh)
       ti = min(len(t_table) - 2, max(1, ti))
       ui = min(len(u_table) - 2, max(1, ui))
       ans = 0
       for i in range(ti - 1, ti + 2):
          for j in range(ui - 1, ui + 2):
             l = 1
             for k in range(ti - 1, ti + 2):
                if k != i:
                   l *= t - t_table[k]
                   l /= t_table[i] - t_table[k]
             for k in range(ui - 1, ui + 2):
                if k != j:
                   l *= u - u_table[k]
                   l /= u_table[j] - u_table[k]
             ans += z_table[i][j] * l
       return ans
    
    #根据x,y求z
    def getZ():
       for xi, x in enumerate(table_x):
          for yi, y in enumerate(table_y):
             t, u, v, w = solve(x, y)
             z = interpolate(t, u)
             table_z[xi][yi] = z
    
    
    # 列主元高斯消去法求逆矩阵
    def inverse(x):
       n = len(x)
       I = [[int(i == j) for i in range(n)] for j in range(n)]
       # 增广矩阵
       ex = [x[i] + I[i] for i in range(n)]
       for i in range(n):
          max_row = i
          for j in range(i + 1, n):
             if abs(ex[j][i]) > abs(ex[max_row][i]):
                max_row = j
          ex[i], ex[max_row] = ex[max_row], ex[i]
          for j in range(i + 1, n):
             k = ex[j][i] / ex[i][i]
             for col in range(n * 2):
                ex[j][col] -= k * ex[i][col]
          # 将当前行第一个数字变为1
          k = ex[i][i]
          for j in range(i, 2 * n):
             ex[i][j] /= k
       # 开始回溯
       for i in range(n - 1, -1, -1):
          for j in range(i + 1, n):  # 倍数ex[i][j]
             for k in range(n, 2 * n):
                ex[i][k] -= ex[i][j] * ex[j][k]
             ex[i][j] = 0
       # 后半部分变为逆矩阵
       ans = [[ex[i][j + n] for j in range(n)] for i in range(n)]
       return ans
    
    
    # 为了让矩阵乘法可读性更强
    class Matrix:
       def __init__(self, matrix):
          self.matrix = matrix
    
       def mul(self, x):
          return Matrix(matrix_mul_matrix(self.matrix, x))
    
    
    def get_sigma(k, C, cout=False):
       s = 0
       for xi, x in enumerate(table_x):
          for yi, y in enumerate(table_y):
             fxy = table_z[xi][yi]
             x_vector = [[table_x[xi] ** i for i in range(k + 1)]]  # 行向量
             y_vector = [[table_y[yi] ** i] for i in range(k + 1)]  # 列向量
             pxy = Matrix(x_vector).mul(C).mul(y_vector).matrix[0][0]
             s += (fxy - pxy) ** 2
             if cout:
                print(x, y, fxy, pxy)
       return s
    
    #最小二乘法曲面拟合
    def least_square():
       k = 1
       while 1:
          B = [[table_x[j] ** i for i in range(k + 1)] for j in range(len(table_x))]
          G = [[table_y[j] ** i for i in range(k + 1)] for j in range(len(table_y))]
          C = Matrix(inverse(matrix_mul_matrix(transform(B), B))) 
             .mul(transform(B)) 
             .mul(table_z) 
             .mul(G) 
             .mul(inverse(matrix_mul_matrix(transform(G), G))).matrix
          sigma = get_sigma(k, C)
          print(k, sigma)
          if sigma < sigma_limit:
             return k, sigma, C
          else:
             k += 1
    
    
    getZ()
    print("打印x,y,z")
    for xi, x in enumerate(table_x):
       for yi, y in enumerate(table_y):
          print(x, y, (table_z[xi][yi]))
    print("开始选择k并计算sigma")
    ans_k, ans_sigma, ans_C = least_square()
    print("最终选择的k,sigma,和系数矩阵为")
    print(ans_k, ans_sigma, ans_C)
    print("打印x,y,f(x,y),p(x,y)")
    get_sigma(ans_k, ans_C, cout=True)
    
  • 相关阅读:
    LeetCode 24. Swap Nodes in Pairs
    LeetCode 02.07. Intersection of Two Linked Lists LCCI
    LeetCode 707. Design Linked List
    centos7 mail
    centos7 安装postgresql10
    centos 7 安装 mail
    解决运行docker命令要用sudo的问题
    Linux 命令速记本
    iterm2配置lrzsz
    截取某段时间内的日志
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/6075921.html
Copyright © 2020-2023  润新知