北航数值分析作业三

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)

你可能感兴趣的:(c/c++,ui,数据结构与算法)