예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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
예제 #5
0
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
예제 #6
0
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