Пример #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 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)
Пример #3
0
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
Пример #4
0
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
Пример #5
0
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