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