三角行列 
モジュールのインポート 
import numpy as np
import scipy as sp
from scipy.linalg import solve_triangular # 上三角あるいは下三角行列に対する連立方程式の計算
from scipy.linalg import lu # LU分解
from scipy.linalg import cholesky # コレスキー分解 
関数 solve_triangular 
 次のような行列表示の連立方程式を考える.
$$
\left( \begin{array}{cccc}
1 & 0 & 0 & 0\\
2 & 3 & 0 & 0\\
4 & 5 & 6 & 0\\
7 & 8 & 9 & 1\\
\end{array} \right)
\boldsymbol{x} =
\left( \begin{array}{c}
1 \\
8 \\
32 \\
54 \\
\end{array} \right)
$$
a = np.array([[1,0,0,0],[2,3,0,0],[4,5,6,0],[7,8,9,1]])
x = np.array([1,2,3,4])
a,x 
(array([[1, 0, 0, 0],
        [2, 3, 0, 0],
        [4, 5, 6, 0],
        [7, 8, 9, 1]]),
 array([1, 2, 3, 4])) 
b = a@x
b 
array([ 1,  8, 32, 54]) 
三角行列(Triangular matrices)の場合,
x_sol = solve_triangular(a, b, lower=True) # lower=Trueのとき,下三角行列を用いて計算する
x_sol 
array([1., 2., 3., 4.]) 
a.dot(x) # Check the result 
array([ 1,  8, 32, 54]) 
a.dot(x) == b 
array([ True,  True,  True,  True]) 
LU分解 
 行列$A$を
$$A=PLU$$
の形に分解する方法として,LU分解 (LU decomposition)がある.
ただし.$P$は順序置換行列(permutation matrix),$L$は下三角行列(lower triangular matrix),$U$は上三角行列(ppper triangular matrix)を示す.
a = np.array([[2,5,7,8],[5,2,2,8],[7,5,6,6],[5,4,4,8]])
p, l, u = lu(a) 
順序置換行列は,
p # 順序置換行列 
array([[0., 1., 0., 0.],
       [0., 0., 0., 1.],
       [1., 0., 0., 0.],
       [0., 0., 1., 0.]]) 
下三角行列は,
l # 下三角行列 
array([[ 1.        ,  0.        ,  0.        ,  0.        ],
       [ 0.28571429,  1.        ,  0.        ,  0.        ],
       [ 0.71428571,  0.12      ,  1.        ,  0.        ],
       [ 0.71428571, -0.44      , -0.04347826,  1.        ]]) 
上三角行列は,
u # 上三角行列 
array([[ 7.        ,  5.        ,  6.        ,  6.        ],
       [ 0.        ,  3.57142857,  5.28571429,  6.28571429],
       [ 0.        ,  0.        , -0.92      ,  2.96      ],
       [ 0.        ,  0.        ,  0.        ,  6.60869565]]) 
行列$A$は,
p@l@u 
array([[2., 5., 7., 8.],
       [5., 2., 2., 8.],
       [7., 5., 6., 6.],
       [5., 4., 4., 8.]]) 
a 
array([[2, 5, 7, 8],
       [5, 2, 2, 8],
       [7, 5, 6, 6],
       [5, 4, 4, 8]]) 
解の確認をして,
np.allclose(a - p@l@u, np.zeros((4, 4))) 
True 
x = np.array([1,2,3,4])
b = a@x
b 
array([65, 47, 59, 57]) 
lu = sp.linalg.lu_factor(a)
sp.linalg.lu_solve(lu, b) 
array([1., 2., 3., 4.]) 
コレスキー分解 
 行列$A$が正定値対称行列(固有値が全て正であるような対称行列)ならば,下三角行列とその複素・転置より
$$A = L L^{T*}$$
あるいは上三角行列とその複素・転置より
$$A = U^{T*} U$$
に分解できる.これをコレスキー分解( Choleski decomposition)という.
 ここでは,実数について簡単な計算例を示そう.
a = np.array([[1,0.2],[0.2,1]])
a 
array([[1. , 0.2],
       [0.2, 1. ]]) 
l = cholesky(a,lower=True) # Choleski decomposition
l 
array([[1.       , 0.       ],
       [0.2      , 0.9797959]]) 
l@l.T 
array([[1. , 0.2],
       [0.2, 1. ]]) 
l@l.T - a 
array([[ 0.00000000e+00,  0.00000000e+00],
       [ 0.00000000e+00, -1.11022302e-16]]) 
a 
array([[1. , 0.2],
       [0.2, 1. ]]) 
x = np.array([1,2])
b = a@x
b 
array([1.4, 2.2]) 
さて,
$$a x = b = L L^T x = L t$$
とおいて,
$$L t = b$$
をまず解く.
t =np.linalg.solve(l, b)
x =np.linalg.solve(l.T, t)
x 
array([1., 2.]) 
t2 = solve_triangular(l, b, lower=True) # lower=Trueのとき,下三角行列を用いて計算する
x2 = solve_triangular(l.T, t2) # lower=Trueのとき,上三角行列を用いて計算する
x2 
array([1., 2.]) 
a 
array([[1. , 0.2],
       [0.2, 1. ]]) 
u = cholesky(a) # Choleski decomposition
u 
array([[1.       , 0.2      ],
       [0.       , 0.9797959]]) 
u.T@u 
array([[1. , 0.2],
       [0.2, 1. ]]) 
u.T@u - a 
array([[ 0.00000000e+00,  0.00000000e+00],
       [ 0.00000000e+00, -1.11022302e-16]]) 
前のページに戻る 
「Python」の目次ページに戻る