三角行列
モジュールのインポート
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)の場合,
https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.solve_triangular.html
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)を示す.
https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.lu.html
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)という.
https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.cholesky.html
ここでは,実数について簡単な計算例を示そう.
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」の目次ページに戻る