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 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 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 lu_decomp(a: Dmatrix, N: int=N) -> Tuple[Dmatrix, List[int]]: eps = 2.0 ** -50.0 # eps = 2^{-50}とする p = [0] * (a.row_last_idx - a.row_head_idx + 1) # p[1...N-1] を利用, p[0] は未使用 a_lu = a.copy() # 値渡し for k in range(1, N): # ピボットの選択 amax = abs(a_lu[k][k]) ip = k for i in range(k+1, N+1): if abs(a_lu[i][k]) > amax: amax = abs(a_lu[i][k]) ip = i # 正則性の判定 if amax < eps: print("入力した行列は正則ではない!!") # ipを配列pに保存 p[k] = ip # 行交換 if ip != k: for j in range(k, N+1): a_lu[k][j], a_lu[ip][j] = a_lu[ip][j], a_lu[k][j] # 前進消去 for i in range(k+1, N+1): alpha = - a_lu[i][k] / a_lu[k][k] a_lu[i][k] = alpha for j in range(k+1, N+1): a_lu[i][j] += alpha * a_lu[k][j] return (a_lu, p)
def produce_matrix(nr1: int, nr2: int, nl1: int, nl2: int): a = Dmatrix(nr1, nr2, nl1, nl2) seed() # シードを与える for i in range(nr1, nr2 + 1): for j in range(nl1, nl2 + 1): a[i][j] = rand() / RAND_MAX return a
def bvp(b: Dvector, a1: float, a2: float, u0: float, un: float, n: float, f) -> Dvector: h = (a2 - a1) / n # 刻み幅 h2 = h * h a = Dmatrix(1, n-1, 1, n-1) # 係数行列 # 行列の作成 for i in range(2, n-1): a[i][i] = 2.0 a[i][i+1] = -1.0 a[i][i-1] = -1.0 for j in range(3, n): a[1][j] = 0.0 a[1][1] = 2.0 a[1][2] = -1.0 for j in range(1, n-2): a[n-1][j] = 0.0 a[n-1][n-2] = -1.0 a[n-1][n-1] = 2.0 # 右辺ベクトルの作成 for i in range(1, n): b[i] = h2 * func( a1 + h*i ) b[1] += u0 b[n-1] += un # 修正コレスキー分解 a_cd = cholesky_decomp(a, n-1) # 修正コレスキー分解を利用して連立一次方程式を解く b_cs = cholesky_solve( a_cd, b, n-1) return b_cs
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 cholesky_decomp(a: Dmatrix, N: int = N): a_cd = a.copy() for i in range(2, N + 1): for j in range(1, i): a_cd[i][j] = (a_cd[i][j] - sum( (a_cd[i][k] * a_cd[k][k] * a_cd[j][k] for k in range(1, j)))) / a_cd[j][j] a_cd[i][i] -= sum( (a_cd[i][k] * a_cd[i][k] * a_cd[k][k] for k in range(1, j + 1))) return a_cd
def matrix_sum(a: Dmatrix, b: Dmatrix): m1, m2 = a.row_head_idx, a.row_last_idx n1, n2 = a.col_head_idx, a.col_last_idx c = Dmatrix(m1, m2, n1, n2) for i in range(m1, m2 + 1): for j in range(n1, n2 + 1): c[i][j] = a[i][j] + b[i][j] return c
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 main(): global ROW, COLUMN a = Dmatrix(1, ROW, 1, COLUMN) # 行列 a[1...ROW][1...COLUMN] b = Dmatrix(1, ROW, 1, COLUMN) # 行列 b[1...ROW][1...COLUMN] # 行列の定義 for i in range(1, ROW + 1): for j in range(1, COLUMN + 1): a[i][j] = 2.0 * (i + j) b[i][j] = 3.0 * (i + j) # 行列の和の計算 c = matrix_sum(a, b) # 結果の表示 print("行列 A と行列 B の和は次の通りです") for i in range(1, ROW + 1): for j in range(1, COLUMN + 1): print(c[i][j], end=" ") print()
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 matrix_product(a: Dmatrix, b: Dmatrix) -> Dmatrix: l1, l2 = a.row_head_idx, a.row_last_idx m1, m2 = a.col_head_idx, a.col_last_idx n1, n2 = b.col_head_idx, b.col_last_idx c = Dmatrix(l1, l2, n1, n2) for i in range(l1, l2 + 1): # 行の添字 for j in range(n1, n2 + 1): c[i][j] = 0.0 # 変数の初期化 for k in range(m1, m2 + 1): # 列の添字 c[i][j] += a[i][k] * b[k][j] return c
def main(): global ROW, COLUMN a = Dmatrix(1, ROW, 1, COLUMN) # 行列 a[1...ROW][1...COLUMN] # 行列の定義 print("A=") for i in range(1, ROW + 1): for j in range(1, COLUMN + 1): a[i][j] = 2.0 * (i + j) * (-1.0)**j print(a[i][j], end="\t") print() print(f"Aの1ノルムは{matrix_norm1(a)}") print(f"Aの最大値ノルムは{matrix_norm_max(a)}")
def main(): a = Dmatrix(1, N, 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 の入出力 a_hh = householder(a, N) # ハウスホルダー法 # 結果の出力 print("Hessenberg 行列は") for i in range(1, N + 1): for j in range(1, N + 1): print("{:10.7f}\t".format(a_hh[i][j]), end="") print()
def main(): global L, M, N a = Dmatrix(1, L, 1, M) # 行列 a[1...L][1...M] b = Dmatrix(1, M, 1, N) # 行列 b[1...M][1...N] # 行列 A の定義 for i in range(1, L + 1): for j in range(1, M + 1): a[i][j] = 2.0 * (i + j) # 行列 B の定義 for i in range(1, M + 1): for j in range(1, N + 1): b[i][j] = 2.0 * (i + j) # 行列の積の計算 c = matrix_product(a, b) # 結果の表示 print("A x B の結果は次の通りです") for i in range(1, L + 1): for j in range(1, N + 1): print(c[i][j], end=" ") print()
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(): 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")
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 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_cho.dat", "r") as fin: with open("output_cho.dat", "w") as fout: input_matrix(a, 'A', fin, fout) # 行列 A の入出力 input_vector(b, 'b', fin, fout) # ベクトル b の入出力 a_cd = cholesky_decomp(a) # 修正コレスキー分解 b_cs = cholesky_solve(a_cd, b) # 前進代入・後退代入 # 結果の出力 fout.write("Ax=bの解は次の通りです\n") for i in range(1, N + 1): fout.write("{:.6f}\t\n".format(b_cs[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_lu.dat", "r") as fin: with open("output_lu.dat", "w") as fout: input_matrix( a, 'A', fin, fout ) # 行列 A の入力 input_vector( b, 'B', fin, fout ) # ベクトル b の入出力 a_lu, p = lu_decomp( a ) # LU分解 b_lu = lu_solve( a_lu, b, p ) # 前進代入・後退代入 # 結果の出力 fout.write("Ax=b の解は次の通りです\n") for i in b_lu: fout.write(f"{i}\n")
def newton_ip(x: Dvector, y: Dvector, n: int, xi: float) -> float: pn = 0.0 a = Dmatrix(0, n, 0, n) for i in range(n+1): a[i][0] = y[i] # 差商の計算 for j in range(1, n+1): for i in range(n-j+1): a[i][j] = ( a[i+1][j-1] - a[i][j-1] ) / ( x[i+j] - x[i] ) # 補間の計算 pn, li = y[0], 1.0 for j in range(1, n+1): li *= ( xi - x[j-1] ) pn += a[0][j] * li return pn
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(): eps = 10.0 ** -8.0 a = Dmatrix(1, N, 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 の入出力 a_hh = householder( a, N ) # ハウスホルダー法 a_qr = qr( a_hh, eps, N ) # QR法 # 結果の出力 print("QR法の結果は") for i in range(1, N+1): for j in range(1, N+1): print("{:10.7f}\t".format(a_qr[i][j]), end="") print() print("固有値は") for i in range(1, N+1): print("{:10.7f}\t".format(a_qr[i][i]), end="") print()
def main(): eps = 10.0**-8.0 a = Dmatrix(1, N, 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の入出力 a_hh = householder(a, N) # ハウスホルダー法 a_qr = qr(a_hh, eps, N) # QR 法 print("固有値は") for i in range(1, N + 1): print("{:10.7f}".format(a_qr[i][i]), end="\t") print() a_ii = inverse_iteration(a, a_qr, eps) # 逆反復法 print("固有ベクトルは") for i in range(1, N + 1): print("[", end="") for j in range(1, N + 1): print("{:10.7f}".format(a_ii[j][i]), end="\t") print("]")