Python NumPy SciPy サンプルコード: QR 分解, コレスキー分解

今回は、線形方程式の数値計算法の QR 分解 , コレスキー分解 を紹介します。

Python で線形連立方程式を QR 分解, コレスキー分解で解く

QR 分解

QR 分解は LU 分解と同じで線形系の行列方程式を高速に解くための手法で、係数行列 \(\mathbf{A}\) を実直行行列 \(\mathbf{Q}\) と上三角行列 \(\mathbf{R}\) の積に分解して計算します。
LU 分解よりも計算量が多いですが数値計算の安定性がよりよいのが特徴です。
とはいえ一般的な行列では LU 分解で十分安定して解けるので、大規模な行列で特異性が心配になった場合に使ってみたらいいかと思います。

簡単に式の変形を示すと、

15060101.png

に \(\mathbf{A} = \mathbf{Q}\mathbf{R}\) を代入すると

15060102.png

となり、\(\mathbf{Q}\) を右辺に移動させて以下のようになります。

15060103.png

ここで、\(\mathbf{Q}\) は実直交行列なので \(\mathbf{Q}^{-1}=\mathbf{Q}^{T}\) です。

\(\mathbf{R}\) は上三角行列なので、ガウスの消去法の後退代入が使えて解が求まります(逆行列を計算する必要がない)。
やはり SciPy に QR 分解のメソッドがあるので、プログラムはそれを用いて以下のように書くことができます。

# coding: utf-8
import scipy.linalg as linalg
import numpy as np

A = np.array([[6, 4, 1],
	      [1, 8, -2],
	      [3, 2, 0]])
b = np.array([7, 6, 8])

Q, R = linalg.qr(A)
t = np.dot(Q.T, b)
x = linalg.solve(R, t)

print(x)
[ 4. -2. -9.]

コレスキー分解

コレスキー分解も線形系の方程式を高速に解くための手法です。

LU 分解よりも高速で、使用するメモリも少ない手法ですが、\(\mathbf{A}\) がエルミート行列(または実対称行列)で正定値である場合に使えます。

係数行列 \(\mathbf{A}\) を下三角行列 \(\mathbf{L}\) とその共役転置 \(\mathbf{L}^*\) の積に分解して計算します。

15060104.png

と分解され、方程式は以下となります。

15060105.png

NumPy にコレスキー分解のメソッドがあるので、プログラムはそれを用いて以下のように書くことができます。

import numpy as np

A = np.array([[7, -1, 0, 1],
	      [-1, 9, -2, 2],
	      [0, -2, 8, -3],
	      [1, 2, -3, 10]])
b = np.array([-5, 15, -10, 20])

L = np.linalg.cholesky(A)

t = np.linalg.solve(L, b)
x = np.linalg.solve(L.T.conj(), t)

print(x)
[-0.80693816  1.11613876 -0.3092006   1.76470588]

コメント

Comments powered by Disqus
書籍更新情報
2016-10-21
Pythonによる科学技術計算 基礎編
PDF版の販売を開始しました。
販売ページはこちら

2016-09-09
Pythonによる科学技術計算 基礎編
1.2版への更新が可能になりました。
サポートページはこちら
電子書籍
Pythonによる科学技術計算 基礎編
Kindle ストア、Leanpubで販売中です
Pythonによる科学技術計算 基礎編
PDF版の販売はこちら
同人誌
技術書典(2016/6/25)
Emacs/org-modeのPDF作成術
電子版をBOOTHで販売中です
Emacs/org-modeのPDF作成術
Share