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 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 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 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 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 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