def gauss_seidel(a: Dmatrix, b: Dvector, x0: Dvector, N: int = N): k = 0 x = x0.copy() xo = Dvector(1, N) # xo[1...N] while True: # xo <- x_k, x <- x_{k+1} for i in range(1, N + 1): xo[i] = x[i] # x_k に x_(k+1) を代入 # i=1 の処理 x[1] = (b[1] - sum( (a[1][j] * xo[j] for j in range(2, N + 1)))) / a[1][1] # i=2,3,...N の処理 for i in range(2, N + 1): s = sum((a[i][j] * x[j] for j in range(1, i))) # i-1列までの和 t = sum((a[i][j] * xo[j] for j in range(i + 1, N + 1))) # i+1列以降の和 x[i] = (b[i] - s - t) / a[i][i] for i in range(1, N + 1): xo[i] = xo[i] - x[i] eps = vector_norm_max(xo) k += 1 if eps <= EPS or k >= KMAX: break if k == KMAX: print("答えが見つかりませんでした") exit(1) else: print(f"反復回数は{k}回です") return x
def inverse_iteration(a: Dmatrix, a_qr: Dmatrix, eps: float) -> Dmatrix: mu = 0.0 y = Dvector(1, N) a_ii = a_qr.copy() for i in range(1, N + 1): lambda_ = a_ii[i][i] # 近似固有値の代入 y[i] = 1.0 # 初期値設定 # 行列の作成およびLU分解 lu = a.copy() for k in range(1, N + 1): lu[k][k] -= lambda_ lu, p = lu_decomp(lu, N) # LU分解 # 逆反復法 while True: muo = mu v = y.copy() v = lu_solve(lu, v, p, N) # 固有ベクトルの計算 mu = inner_product(v, y) # 補正 v2s = sqrt(inner_product(v, v)) for j in range(1, N + 1): y[j] = v[j] / v2s if abs((mu - muo) / mu) < eps: break # 結果の代入(固有ベクトルはaのi列に) for j in range(1, N + 1): a_ii[j][i] = y[j] return a_ii
def main(): print("データの個数を入力してください--->") n = int(input()) n -= 1 # データ数が n なので, n <- n-1 として添字を0,1,...,n とする print("補間点を入力してください--->") xi = float(input()) x = Dvector(0, n) # x[0...n] y = Dvector(0, n) # y[0...n] # ファイルのオープン with open("input_lag.dat", "r") as fin: with open("output_lag.dat", "w") as fout: input_vector(x, "x", fin, fout) # ベクトル x の入出力 input_vector(y, "y", fin, fout) # ベクトル y の入出力 print("補間の結果は, P({:.6f})={:.6f}".format(xi, lagrange(x, y, 0, n, xi))) # グラフを描くために結果をファイルに出力 xi = x[0] while xi <= x[n]: fout.write("{:.6f} \t {:.6f}\n".format( xi, lagrange(x, y, 0, n, xi))) xi += 0.01
def adams(y0: float, y: Dvector, a: float, b: float, n: int, N: int, eps: float, f) -> Dvector: y = Dvector(0, n) # y[0,1,...n] の確保 F = Dvector(0, 4) # F[0,1,...4] の確保 h = (b - a) / n # 刻み幅の設定 # スタータ y = rk4(y0, y, a, b, n, f) x = a for i in range(4): F[i] = f(x, y[i]) x += h # 反復計算 for i in range(3, n): # アダムス・バッシュフォース法 F[3] = f(x - h, y[i]) yp = y[i] + h * (55.0 * F[3] - 59.0 * F[2] + 37.0 * F[1] - 9.0 * F[0]) / 24.0 for j in range(1, N + 1): # アダムス・ムルトン法 F[4] = f(x, yp) y[i + 1] = y[i] + h * (9.0 * F[4] + 19.0 * F[3] - 5.0 * F[2] + F[1]) / 24.0 if abs(y[i + 1] - yp) < eps: break yp = y[i + 1] for j in range(1, 5): F[j - 1] = F[j] # F[i] の更新 x += h return y
def __init__(self, row_head_idx: int, row_last_idx: int, col_head_idx: int, col_last_idx: int): matrix = Dvector(row_head_idx, row_last_idx) for i in range(row_head_idx, row_last_idx+1): matrix[i] = Dvector(col_head_idx, col_last_idx) self.matrix = matrix self.row_head_idx = row_head_idx self.row_last_idx = row_last_idx self.col_head_idx = col_head_idx self.col_last_idx = col_last_idx
def main(): global N # ベクトルの定義, 配列 a,b の添字は 1~N a, b = Dvector(1, N), Dvector(1, N) for i in range(1, N + 1): a[i] = i / 20.0 b[i] = i / 10.0 print(f"a と b の内積は{inner_product(a, b)} です")
def householder(a: Dmatrix, n: int) -> Dmatrix: u = Dvector(1, n) f = Dvector(1, n) g = Dvector(1, n) a_hh = a.copy() for k in range(1, n - 1): # v の計算 for i in range(1, k + 1): u[i] = 0.0 for i in range(k + 1, n + 1): u[i] = a_hh[i][k] # s の計算 ss = 0.0 for i in range(k + 2, n + 1): ss += u[i] * u[i] if abs(ss) <= 0.0: # 消去が必要ない場合の処理 continue s = sqrt(ss + u[k + 1] * u[k + 1]) if u[k + 1] > 0.0: s = -s # uの計算 u[k + 1] -= s uu = sqrt(ss + u[k + 1] * u[k + 1]) for i in range(k + 1, n + 1): u[i] /= uu # f, gの計算 for i in range(1, n + 1): f[i], g[i] = 0.0, 0.0 for j in range(k + 1, n + 1): f[i] += a_hh[i][j] * u[j] g[i] += a_hh[j][i] * u[j] # gammaの計算 gamma = 0.0 for j in range(1, n + 1): gamma += u[j] * g[j] # f, gの計算 for i in range(1, n + 1): f[i] -= gamma * u[i] g[i] -= gamma * u[i] # A の計算 for i in range(1, n + 1): for j in range(1, n + 1): a_hh[i][j] -= 2.0 * u[i] * g[j] + 2.0 * f[i] * u[j] return a_hh
def main(): global M, N x = Dvector(1, M) # x[1...M] y = Dvector(1, M) # y[1...M] # ファイルのオープン with open("input_func.dat", "r") as fin: with open("output_func.dat", "w") as fout: input_vector(x, 'x', fin, fout) # ベクトル x の入出力 input_vector(y, 'y', fin, fout) # ベクトル y の入出力 least_square(x, y, fout) # 最小2乗近似
def main(): a = 0.0 b = 3.1415926535897932 N = 2 # N変数 y = Dvector(1, N) f = Dvector(1, N) y[1], y[2] = 1.0, 0.0 # 初期値の設定 print("分割数を入力してください--->", end="") n = int(input()) rk4_m(y, f, N, a, b, n, FUNC) # ルンゲ・クッタ法
def jacobi_lin(a: Dmatrix, b: Dvector, x: Dvector) -> Dvector: k = 0 xn = Dvector(1, N) # xn[1...N] # x <- x_k, xn <- x_{k+1} while True: for i in range(1, N+1): xn[i] = b[i] for j in range(1, N+1): xn[i] -= a[i][j] * x[j] xn[i] += a[i][i] * x[i] # 余分に引いた分を加える xn[i] /= a[i][i] for i in range(1, N+1): x[i] = xn[i] - x[i] eps = vector_norm_max(x) # 最大値ノルムの計算 for i in range(1, N+1): x[i] = xn[i] # 値を更新 k += 1 if eps <= EPS or k >= KMAX: break if k == KMAX: print("答えが見つかりませんでした") else: print(f"反復回数は{k}回です") return x
def least_square(x: Dvector, y: Dvector, fout): global M, N p = Dmatrix(1, N + 1, 1, N + 1) # p[1...N+1][1...N+1] a = Dvector(1, N + 1) # a[1...N-1] # 右辺ベクトルの作成 for i in range(1, N + 2): a[i] = 0.0 for j in range(1, M + 1): a[i] += y[j] * (x[j]**(i - 1)) # 係数行列の作成 for i in range(1, N + 2): for j in range(1, i + 1): p[i][j] = 0.0 for k in range(1, M + 1): p[i][j] += x[k]**(i + j - 2) p[j][i] = p[i][j] # 連立一次方程式を解く. 結果は a に上書き a = gauss2(p, a, N + 1) # 結果の出力 fout.write("最小2乗近似式は y=\n") for i in range(N + 1, 0, -1): fout.write("+ {:5.2f} x^{} ".format(a[i], i - 1)) fout.write("\n")
def main(): a = Dmatrix(1, N, 1, N) # 行列 a[1...N][1...N] b = Dvector(1, N) # b[1...N] x = Dvector(1, N) # x[1...N] # ファイルのオープン with open("input_sp.dat", "r") as fin: with open("output_sp.dat", "w") as fout: input_matrix( a, 'A', fin, fout ) # 行列 A の入出力 input_vector( b, 'b', fin, fout ) # ベクトル b の入出力 input_vector( x, 'x', fin, fout ) # 初期ベクトル x0 の入出力 x = jacobi_lin( a, b, x ) # ヤコビ法 # 結果の出力 fout.write("Ax=b の解は次の通りです\n") for i in range(1, N+1): fout.write("{:.6f}\n".format(x[i]))
def main(): global N a = Dmatrix(1, N, 1, N) # 行列 a[1...N][1...N] b = Dvector(1, N) # b[1...N] with open("input.dat", "r") as fin: with open("output.dat", "w") as fout: input_matrix(a, 'A', fin, fout) input_vector(b, 'b', fin, fout)
def matrix_vector_product(a: Dmatrix, b: Dvector): N = b.last_idx - b.head_idx + 1 c = Dvector(1, N) for i in range(1, N + 1): c[i] = sum((a[i][j] * b[j] for j in range(1, N + 1))) return c
def main(): a = Dmatrix(1, N, 1, N) # 行列 a[1...N][1...N] b = Dvector(1, N) # b[1...N] x0 = Dvector(1, N) # x[1...N] # ファイルのオープン with open("input_sp.dat", "r") as fin: with open("output_sp.dat", "w") as fout: input_matrix(a, 'A', fin, fout) # 行列 A の入出力 input_vector(b, 'b', fin, fout) # ベクトル b の入出力 input_vector(x0, 'x0', fin, fout) # 初期ベクトル x0 の入出力 x = gauss_seidel(a, b, x0) # ガウス・ザイデル法 # 結果の出力 fout.write("Ax=b の解は次の通りです\n") for i in range(1, N + 1): fout.write("{:.6f}\n".format(x[i]))
def cg(a: Dmatrix, b: Dvector, x0: Dvector): k = 0 r = Dvector(1, N) # r[1...N] p = Dvector(1, N) # p[1...N] x = x0.copy() tmp = matrix_vector_product(a, x) # tmp <- A b for i in range(1, N + 1): p[i] = b[i] - tmp[i] r[i] = p[i] while True: # alpha の計算 tmp = matrix_vector_product(a, p) # tmp <- A p_k work = inner_product(p, tmp) # work <- (p, Ap_k) alpha = inner_product(p, r) / work # x_{k+1} と r_{k+1} の計算 for i in range(1, N + 1): x[i] += alpha * p[i] for i in range(1, N + 1): r[i] -= alpha * tmp[i] # 収束判定 eps = vector_norm1(r) k += 1 # 反復回数の更新 if eps < EPS: break # beta と p_{k+1} の計算 beta = -inner_product(r, tmp) / work for i in range(1, N + 1): p[i] = r[i] + beta * p[i] if k >= KMAX: break if k == KMAX: print("答えが見つかりませんでした") exit(1) else: print(f"反復回数は{k}回です") # 反復回数を画面に表示 return x
def qr(a: Dmatrix, eps: float, n: int) -> Dmatrix: # 領域の確保 q = Dmatrix(1, n, 1, n) work = Dvector(1, n) a_qr = a.copy() m = n while m > 1: # 収束判定 if abs(a_qr[m][m-1]) < eps: m = m - 1 continue # 原点移動 s = a_qr[n][n] if m == n: # m=n のときは原点移動なし s = 0.0 for i in range(1, m+1): a_qr[i][i] -= s # QR法 for i in range(1, m+1): for j in range(1, m+1): q[i][j] = 0.0 # Q を m x m 単位行列で初期化 q[i][i] = 1.0 # R と Q の計算 for i in range(1, m): r = sqrt( a_qr[i][i]*a_qr[i][i] + a_qr[i+1][i]*a_qr[i+1][i] ) if r == 0.0: sint = 0.0 cost = 0.0 else: sint = a_qr[i+1][i] / r cost = a_qr[i][i] / r for j in range(i+1, m+1): tmp = a_qr[i][j]*cost + a_qr[i+1][j]*sint a_qr[i+1][j] = -a_qr[i][j]*sint + a_qr[i+1][j]*cost a_qr[i][j] = tmp a_qr[i+1][i] = 0.0 a_qr[i][i] = r for j in range(1, m+1): # Q は P の転置 tmp = q[j][i]*cost + q[j][i+1]*sint q[j][i+1] = -q[j][i]*sint + q[j][i+1]*cost q[j][i] = tmp # RQ の計算 for i in range(1, m+1): for j in range(i, m+1): work[j] = a_qr[i][j] for j in range(1, m+1): a_qr[i][j] = sum( ( work[k] * q[k][j] for k in range(i, m+1) ) ) # 原点移動後の処理 for i in range(1, m+1): a_qr[i][i] += s return a_qr
def main(): a = Dmatrix(1, N, 1, N) # 行列領域の確保 x = Dvector(1, N) # ベクトル領域の確保 # ファイルのオープン with open("input_eigen.dat", "r") as fin: with open("result_eigen.dat", "w") as fout: input_matrix( a, 'A', fin, fout ) # 行列 A の入出力 input_vector( x, 'x', fin, fout ) # ベクトル x の入出力 power_method( a, x, fout ) # べき乗法
def matrix_norm1(a: Dmatrix): m1, m2 = a.row_head_idx, a.row_last_idx n1, n2 = a.col_head_idx, a.col_last_idx work = Dvector(n1, n2) # ベクトルwork[n1...n2] # 列和の計算 for j in range(n1, n2 + 1): work[j] = 0.0 for i in range(m1, m2 + 1): work[j] += abs(a[i][j]) return max(work)
def matrix_norm_max(a: Dmatrix): m1, m2 = a.row_head_idx, a.row_last_idx n1, n2 = a.col_head_idx, a.col_last_idx work = Dvector(m1, m2) # 行和の計算 for i in range(m1, m2 + 1): work[i] = 0.0 for j in range(n1, n2 + 1): work[i] += abs(a[i][j]) return max(work)
def rk4_m(y: Dvector, f: Dvector, N: int, a: float, b: float, n: int, F): k1 = Dvector(1, N) k2 = Dvector(1, N) k3 = Dvector(1, N) k4 = Dvector(1, N) tmp = Dvector(1, N) # 初期値の設定・表示 h = (b - a) / n # 刻み幅 x = a print("x={:.6f} \t y1={:6f} \t y2={:.6f} ".format(x, y[1], y[2])) # ルンゲ・クッタ法(N 変数版) for i in range(n): # k1 の計算 FUNC(x, y, f) for j in range(1, N + 1): k1[j] = f[j] for j in range(1, N + 1): tmp[j] = y[j] + h * k1[j] / 2.0 # k2 の計算 FUNC(x + h / 2.0, tmp, f) for j in range(1, N + 1): k2[j] = f[j] for j in range(1, N + 1): tmp[j] = y[j] + h * k2[j] / 2.0 # k3 の計算 FUNC(x + h / 2.0, tmp, f) for j in range(1, N + 1): k3[j] = f[j] for j in range(1, N + 1): tmp[j] = y[j] + h * k3[j] # k4 の計算 FUNC(x + h, tmp, f) for j in range(1, N + 1): k4[j] = f[j] for j in range(1, N + 1): y[j] = y[j] + h / 6.0 * (k1[j] + 2.0 * k2[j] + 2.0 * k3[j] + k4[j]) x += h print("x={:.6f} \t y1={:.6f} \t y2={:.6f} ".format(x, y[1], y[2]))
def sor(a: Dmatrix, b: Dvector, x0: Dvector, omega: float, N: int = N): k = 0 x = x0.copy() xo = Dvector(1, N) # xo[1...N] while True: # xo <- x_k, x <- x_{k+1} for i in range(1, N + 1): xo[i] = x[i] # x_k に x_(k+1) を代入 # i=1 の処理 x[1] = (b[1] - sum( (a[1][j] * xo[j] for j in range(2, N + 1)))) / a[1][1] # i=2,3,...N の処理 for i in range(2, N + 1): s = sum((a[i][j] * x[j] for j in range(1, i))) # i-1列までの和 t = sum((a[i][j] * xo[j] for j in range(i + 1, N + 1))) # i+1列以降の和 x[i] = (b[i] - s - t) / a[i][i] # ここまではガウス・ザイデル法と同じ # SOR法 for i in range(1, N + 1): x[i] = xo[i] + omega * (x[i] - xo[i]) # 補正 for i in range(1, N + 1): xo[i] = xo[i] - x[i] eps = vector_norm_max(xo) k += 1 if eps <= EPS or k >= KMAX: break if k == KMAX: print("答えが見つかりませんでした") exit(1) else: print(f"反復回数は{k}回です") # 反復回数を画面に表示 return x
def cholesky_solve(a_cd: Dmatrix, b: Dvector, N: int = N): b_cs = b.copy() # LDy = b b_cs[1] = b[1] / a_cd[1][1] for i in range(2, N + 1): b_cs[i] = (b_cs[i] - sum((a_cd[j][j] * a_cd[i][j] * b_cs[j] for j in range(1, i)))) / a_cd[i][i] # L^t x = y for i in range(N - 1, 0, -1): b_cs[i] -= sum((a_cd[j][i] * b_cs[j] for j in range(i + 1, N + 1))) return b_cs
def newton2(x: float, y: float, z: float): global N k = 0 d = Dvector(1, N) # d[1...N] xk = Dvector(1, N) # xk[1...N] J = Dmatrix(1, N, 1, N) # 行列 J[1...N][1...N] xk[1] = x xk[2] = y xk[3] = z while True: # 右辺ベクトルの作成 d[1] = -f(xk[1], xk[2], xk[3]) d[2] = -g(xk[1], xk[2], xk[3]) d[3] = -h(xk[1], xk[2], xk[3]) # ヤコビ行列の作成 J[1][1] = f_x(xk[1], xk[2], xk[3]) J[1][2] = f_y(xk[1], xk[2], xk[3]) J[1][3] = f_z(xk[1], xk[2], xk[3]) J[2][1] = g_x(xk[1], xk[2], xk[3]) J[2][2] = g_y(xk[1], xk[2], xk[3]) J[2][3] = g_z(xk[1], xk[2], xk[3]) J[3][1] = h_x(xk[1], xk[2], xk[3]) J[3][2] = h_y(xk[1], xk[2], xk[3]) J[3][3] = h_z(xk[1], xk[2], xk[3]) d = gauss(J, d, N) # 連立一次方程式を解く for i in range(1, N + 1): xk[i] += d[i] k += 1 if vector_norm1(d) <= EPS or k >= KMAX: break if k == KMAX: print("答えが見つかりませんでした") else: print(f"答えは x={xk[1]}, y={xk[2]}, z={xk[3]} です")
def main(): a, b, y0 = 0.0, 1.0, 1.0 print("分割数を入力してください--->", end="") n = int(input()) y = Dvector(0, n) y = rk4(y0, y, a, b, n, func) # ルンゲクッタ法 # 結果の表示 h = (b - a) / n for i in range(n + 1): print("x={:.6f} \t y={:.6f} ".format(a + i * h, y[i]))
def main(): print("分割数を入力してください--->", end="") n = int(input()) u = Dvector(1,n-1) u_bvp = bvp( u, 0.0, 1.0, 0.0, 0.0, n, func ) h = 1.0 / n print("求める答え u と誤差の最大値 e は次の通りです.") for i in range(1,n): print("u[{}]={:.6f}".format(i, u_bvp[i])) for i in range(1,n): u_bvp[i] -= exact(i*h) print("e={:.6f}".format(vector_norm_max(u_bvp)))
def lu_solve(a: Dmatrix, b: Dvector, p: List[int], N:int=N) -> Dvector: b_lu = b.copy() # 値渡し # 右辺の行交換 for k in range(1, N): b_lu[k], b_lu[p[k]] = b_lu[p[k]], b_lu[k] # 前進代入 for i in range(k+1, N+1): b_lu[i] += a[i][k] * b_lu[k] # 後退代入 b_lu[N] /= a[N][N] for k in range(N-1, 0, -1): b_lu[k] = ( b_lu[k] - sum( (a[k][j] * b_lu[j] for j in range(k+1, N+1)) ) ) / a[k][k] return b_lu
def main(): global N a = Dmatrix(1, N, 1, N) # 行列 a[1...N][1...N] b = Dvector(1, N) # b[1...N] # ファイルのオープン with open("input.dat", "r") as fin: with open("output.dat", "w") as fout: input_matrix( a, 'A', fin, fout ) # 行列 A の入出力 input_vector( b, 'b', fin, fout ) # ベクトル b の入出力 b = simple_gauss( a, b ) # ガウス消去法 # 結果の出力 fout.write("Ax=b の解は次の通りです\n") for i in range(1, N+1): fout.write("{:.6f}\n".format(b[i]))
def main(): a, b, y0 = 0.0, 1.0, 1.0 eps = 10.0**-8.0 N = 10 # 最大反復回数N print("分割数を入力してください--->", end="") n = int(input()) y = Dvector(0, n) # アダムス法 y = adams(y0, y, a, b, n, N, eps, func) # 結果の表示 h = (b - a) / n # 刻み幅 for i in range(n + 1): print("x={:.6f} \t y={:.6f} ".format(a + i * h, y[i]))
def main(): global N a = Dmatrix(1, N, 1, N) b = Dvector(1, N) # ファイルのオープン with open("input.dat", "r") as fin: with open("output.dat", "w") as fout: input_matrix(a, 'A', fin, fout) # 行列 A の入出力 input_vector(b, 'b', fin, fout) # ベクトル b の入出力 b = gauss(a, b) # ガウス消去法 # 結果の出力 fout.write("Ax=b の解は次の通りです\n") for i in range(1, N + 1): fout.write(f"{b[i]}\n")