Transcript
Page 1: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

1

数値解析

加古富志雄

令和元年 7月 8日

目 次12 行列の固有値 2

12.1 対称行列の固有値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

12.1.1 ヤコビ法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

12.1.2 ヤコビ法のプログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

12.1.3 実行結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

12.1.4 ヤコビ法のプログラム (行列の計算を効率的にしたもの) . . . . . . . . . . . . . . . . . . . 6

12.1.5 非対称行列の場合 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

12.1.6 ギブンス法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

12.1.7 ギブンス法のプログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

12.1.8 プログラムの実行結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

12.1.9 ギブンス法のプログラム (行列の計算を効率的にしたもの) . . . . . . . . . . . . . . . . . . 10

12.1.10ハウスホルダー法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

12.1.11ハウスホルダー法のプログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

12.1.12実行結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

12.1.13ハウスホルダー法のプログラム (行列の計算を効率的にしたもの) . . . . . . . . . . . . . . . 17

12.1.14三重対角行列の固有値 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

12.1.15三重対角行列から固有値を計算するプログラム . . . . . . . . . . . . . . . . . . . . . . . . . 19

12.2 ベキ乗法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

12.2.1 プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

12.3 グラム・シュミットの直交化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

12.3.1 グラム・シュミットの正規直交化プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . 23

12.4 QR分解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

12.5 ハウスホルダー変換による QR分解の計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

12.5.1 グラム・シュミットによる QR分解のプログラム . . . . . . . . . . . . . . . . . . . . . . . 25

12.5.2 プログラムの実行結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

12.5.3 ハウスホルダー法による QR分解のプログラム . . . . . . . . . . . . . . . . . . . . . . . . 27

12.5.4 プログラムの実行結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

12.5.5 QR分解を用いた固有値の計算 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

12.5.6 QR分解による固有値の計算プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

12.6 原点移動付き QR分解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

12.6.1 Wilkinsonシフトを行う QR分解プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . 32

12.7 非正方行列に対する QR分解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

12.7.1 非正方行列の QR分解プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

Page 2: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 2

12.8 課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

12 行列の固有値n× n行列 Aの固有値は、

Axn = λnxn

を満たす値 λn で、このときのベクトル xn を固有ベクトルという。n× n次の行列は重複を計算に入れて n個の固有値を持ち、互いに独立な n個の固有ベクトル x1, . . . , xn を持つ。この固有ベクトルから行列

X =

x1

...

xn

を作ると、

AX =

λ1 0 · · · 0

0 λ2. . . 0

.... . .

. . ....

0 0 · · · λn

X

固有値を λとすると、Ax = λxを満たすので、

(A− λI)x = 0

すなわち、行列 A− λI は特異行列(行列式が 0)となる。(I は n× nの単位行列を表す。)したがって、

det(A− λIn) = 0

が成り立つ。しかし行列式を直接計算することは非常に手間がかかるので、この式から固有値を計算することは難しい。特別な形の行列に対しては、固有値は簡単に求められる。例えば、対角行列あるいは上三角(下三角)行列

A =

a11 a12 . . . a1n

0 a22 . . . a2n...

. . ....

0 0 . . . ann

に対して、akk, k = 1, . . . , nが行列 Aの固有値になることがすぐ判る。また、対角線上およびその行隣以外の要素が全て零であるような行列(三重対角行列)については、その固有値を決定する方程式を簡単に求めることが出来る。数値計算で、行列の固有値を求めるには、固有値の値を変化させない行列の変形を行なって、上で述べたような行列の形に変形する方法がある。

12.1 対称行列の固有値aij = aji を満たす対称行列の固有値を求めるには、対角線上およびその行隣以外の要素が全て零であるような行列(三重対角行列)に変換し、得られた行列の固有値を求めるヤコビ法あるいはハウスホルダー法がある。

Page 3: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 3

12.1.1 ヤコビ法

ヤコビ法は、Aに B = P−1AP の変換を行う。ここで、P は、Ppp = Pqq = cosϕ, Ppq = −Pqp = sinϕでそれ以外は単位行列と同じ値である行列である。

P =

1 . . . . . .

1 . . . . . .

cosϕ sinϕ

− sinϕ cosϕ

1

1

この変換によって変化するのは、p行、q行および p列、q列だけで他の要素は不変である。

bij = aij , i, j ̸= p, q

bpk = bkp = apk cosϕ− aqk sinϕ, k ̸= p, q

bqk = bqk = apk sinϕ+ aqk cosϕ, k ̸= p, q

bpp =app+aqq

2 +app−aqq

2 cos 2ϕ− apq sin 2ϕ,

bqq =app+aqq

2 − app−aqq

2 cos 2ϕ+ apq sin 2ϕ,

bpq = bqp =app−aqq

2 sin 2ϕ+ apq cos 2ϕ,

これから、tan 2ϕ =

−2apqapp − aqq

を満たすように、ϕを選べば、変換した行列で bpq および bqp を 0に出来る。このような変換を逐次行なうことにより、行列の対角部分以外の要素を零に変形する方法がヤコビ法である。消去する成分 apq の選択方法には、いくつか考えられる。一つの方法は、|aij |が一番大きい要素を選び、それを零にするやり方である。

12.1.2 ヤコビ法のプログラム

ここで示すヤコビ法のプログラムは行列の積を使ってプログラミングしているので非常に効率が悪い。ここでは計算手順をわかりやすくプログラムを作成している。後に、その点を改良したプログラムを示す。

1

2 // jacobi method3

4 #include <stdio.h>5 #include <math.h>6

7 #define N 48

9 void householder(double a[N][N], int n);10 void show(char ∗s, double a[N][N], int n);11 void prod(double a[N][N], double b[N][N], double c[N][N],12 int n);13

14 int15 main(int ac, char ∗av[])16 {17 double a[N][N] = {18 {4.0, 3.0, 2.0, 1.0}, {3.0, 2.0, 1.0, 1.0},

Page 4: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 4

19 {2.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0} };20 double u[N][N], b[N][N];21 int n = N;22 int i, j, k, p, q;23 double t, e;24

25 for (k = 0;; k++) {26 e = 0;27 for (i = 0; i < n; i++) {28 for (j = i + 1; j < n; j++) {29 if (fabs(a[i][j]) > e) {30 e = fabs(a[i][j]);31 p = i;32 q = j;33 }34 }35 }36 if (e < 1.0e−10)37 break;38

39 for (i = 0; i < n; i++) {40 for (j = 0; j < n; j++)41 u[i][j] = 0;42 u[i][i] = 1;43 }44 t = atan2(−2 ∗ a[p][q], a[p][p] − a[q][q]) / 2;45 u[p][p] = u[q][q] = cos(t);46 u[p][q] = −sin(t);47 u[q][p] = +sin(t);48

49 printf("step %d\n", k);50 show("p=", u, n);51 prod(u, a, b, n);52 show("pa = ", b, n);53 u[p][q] = −u[p][q];54 u[q][p] = −u[q][p];55 prod(b, u, a, n);56 show("pap", a, n);57 }58 }59

60 void61 show(char ∗msg, double a[N][N], int n)62 {63 int i, j;64

65 printf("%s\n", msg);66 for (i = 0; i < n; i++) {67 for (j = 0; j < n; j++)68 printf("%15.10lf, ", a[i][j]);69 printf("\n");70 }71 }72

73 void74 prod(double a[N][N], double b[N][N], double c[N][N], int n)75 {76 int i, j, k;77 double s;78 for (i = 0; i < n; i++) {79 for (j = 0; j < n; j++) {

Page 5: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 5

80 s = 0;81 for (k = 0; k < n; k++)82 s = s + a[i][k] ∗ b[k][j];83 c[i][j] = s;84 }85 }86 }

12.1.3 実行結果

step 0

p=

0.8112421852, 0.5847102847, 0.0000000000, 0.0000000000,

-0.5847102847, 0.8112421852, 0.0000000000, 0.0000000000,

0.0000000000, 0.0000000000, 1.0000000000, 0.0000000000,

0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000,

pa =

4.9990995947, 3.6031471249, 2.2071946550, 1.3959524698,

0.0948854169, -0.1316464836, -0.3581783842, 0.2265319005,

2.0000000000, 1.0000000000, 1.0000000000, 1.0000000000,

1.0000000000, 1.0000000000, 1.0000000000, 1.0000000000,

pap

6.1622776602, 0.0000000000, 2.2071946550, 1.3959524698,

-0.0000000000, -0.1622776602, -0.3581783842, 0.2265319005,

2.2071946550, -0.3581783842, 1.0000000000, 1.0000000000,

1.3959524698, 0.2265319005, 1.0000000000, 1.0000000000,

最後は

step 15

p=

1.0000000000, 0.0000000000, 0.0000000000, -0.0000000001,

0.0000000000, 1.0000000000, 0.0000000000, 0.0000000000,

0.0000000000, 0.0000000000, 1.0000000000, 0.0000000000,

0.0000000001, 0.0000000000, 0.0000000000, 1.0000000000,

pa =

7.4078212378, -0.0000000000, -0.0000000000, -0.0000000010,

-0.0000000000, 0.8594285160, -0.0000000000, 0.0000000000,

-0.0000000000, 0.0000000000, 0.2846190229, 0.0000000000,

-0.0000000001, -0.0000000000, 0.0000000000, -0.5518687767,

pap

7.4078212378, -0.0000000000, -0.0000000000, 0.0000000000,

-0.0000000000, 0.8594285160, -0.0000000000, 0.0000000000,

-0.0000000000, 0.0000000000, 0.2846190229, 0.0000000000,

0.0000000000, -0.0000000000, 0.0000000000, -0.5518687767,

Page 6: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 6

12.1.4 ヤコビ法のプログラム (行列の計算を効率的にしたもの)

1 // jacobi method2

3 #include "pch.h"

4 #include <iostream.5 #include <math.h>6

7 #define N 48

9 void jacobi(double a[N][N], int n);10

11 int12 main(int ac, char ∗av[])13 {14 double a[N][N] = {15 {4.0, 3.0, 2.0, 1.0}, {3.0, 2.0, 1.0, 1.0},16 {2.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0}17 };18 int n = N;19 int i, j;20

21 jacobi(a, n);22 for (i = 0; i < n; i++) {23 for (j = 0; j < n; j++)24 printf("%8.5f, ", a[i][j]);25 printf("\n");26 }27 }28

29 void30 jacobi(double a[N][N], int n)31 {32 double P[N][N];33 int i, j, k;34 int p, q;35 double c, s;36 double t;37 double app, apq, aqq,38 bpp, bqq, bpq;39 double aqk, apk;40 double sm;41 int nrot;42

43 for (i = 0; i < n; i++) {44 for (j = 0; j < n; j++) {45 P[i][j] = 0;46 }47 P[i][i] = 1;48 }49

50 for (nrot = 0; nrot < 50; nrot++) {51 s = 0;52 p = 0;53 q = 0;54 sm = 0;55 for (i = 0; i < n; i++) {56 for (j = i + 1; j < n; j++) {57 sm = sm + a[i][j] ∗ a[i][j];

Page 7: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 7

58 if (fabs(a[i][j]) > s) {59 s = fabs(a[i][j]);60 p = i;61 q = j;62 }63 }64 }65 if (s == 0) {66 return;67 }68 if (p > q) {69 i = p;70 p = q;71 q = i;72 }73 t = −2 ∗ a[p][q] / (a[p][p] − a[q][q]);74 t = atan(t) / 2;75 s = sin(t);76 c = cos(t);77 app = a[p][p];78 apq = a[p][q];79 aqq = a[q][q];80 for (k = 0; k < n; k++) {81 if (k == p || k == q) continue;82 apk = a[p][k];83 aqk = a[q][k];84 a[p][k] = apk ∗ c − aqk ∗ s;85 a[q][k] = apk ∗ s + aqk ∗ c;86 a[k][p] = a[p][k];87 a[k][q] = a[q][k];88 }89 bpp = (app + aqq) / 2 + (app − aqq) / 2 ∗ (c ∗ c − s ∗ s) −90 apq ∗ 2 ∗ s ∗ c;91 bqq =92 (app + aqq) / 2 − (app − aqq) / 2 ∗ (c ∗ c − s ∗ s) +93 apq ∗ 2 ∗ s ∗ c;94 bpq = (app − aqq) ∗ s ∗ c + apq ∗ (c ∗ c − s ∗ s);95 a[p][p] = bpp;96 a[q][q] = bqq;97 a[p][q] = bpq;98 a[q][p] = bpq;99 }

100 }

12.1.5 非対称行列の場合

bij = aij , i, j ̸= p, q

bpk = apk cosϕ− aqk sinϕ, k ̸= p, q

bkp = akp cosϕ− akq sinϕ, k ̸= p, q

bqk = apk sinϕ+ aqk cosϕ, k ̸= p, q

bkq = akp sinϕ+ akq cosϕ, k ̸= p, q

bpp = (app cosϕ− aqp sinϕ) cosϕ− (apq cosϕ− aqq sinϕ) sinϕ,

bpq = (app cosϕ− aqp sinϕ) sinϕ+ (apq cosϕ− aqq sinϕ) cosϕ,

bqp = (app sinϕ+ aqp cosϕ) cosϕ− (apq sinϕ+ aqq cosϕ) sinϕ,

bqq = (app sinϕ+ aqp cosϕ) sinϕ+ (apq sinϕ+ aqq cosϕ) cosϕ,

Page 8: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 8

12.1.6 ギブンス法

ギブンス法は、ヤコビ法で零にする Aの要素の選び方を (1, 3), (1, 4), . . . , (1, n), (2, 4), . . . , (n − 2, n)の順番に消去を行なう。これを繰返すことにより、三重対角部分以外の要素を零に近づけて行く方法である。

12.1.7 ギブンス法のプログラム

1

2 // givens method3

4 #include <stdio.h>5 #include <math.h>6

7 #define N 48

9 void householder(double a[N][N], int n);10 void show(char ∗s, double a[N][N], int n);11 void prod(double a[N][N], double b[N][N], double c[N][N],12 int n);13

14 int15 main(int ac, char ∗av[])16 {17 double a[N][N] = {18 {4.0, 3.0, 2.0, 1.0}, {3.0, 2.0, 1.0, 1.0},19 {2.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0}20 };21 double u[N][N], b[N][N];22 int n = N;23 int i, j, k, p, q;24 double t, e;25

26 for (k = 0;; k++) {27 e = 0;28 for (i = 0; i < n; i++)29 for (j = i + 1; j < n; j++)30 if (fabs(a[i][j]) > e)31 e = fabs(a[i][j]);32 if (e < 1.0e−10)33 break;34 for (p = 0; p < n; p++) {35 for (q = p + 1; q < n; q++) {36 for (i = 0; i < n; i++) {37 for (j = 0; j < n; j++)38 u[i][j] = 0;39 u[i][i] = 1;40 }41 t = atan2(−2 ∗ a[p][q], a[p][p] − a[q][q]) / 2;42 u[p][p] = u[q][q] = cos(t);43 u[p][q] = −sin(t);44 u[q][p] = +sin(t);45

46 printf("step %d(%d, %d)\n", k, p, q);47 show("p=", u, n);48 prod(u, a, b, n);49 show("pa = ", b, n);50 u[p][q] = −u[p][q];

Page 9: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 9

51 u[q][p] = −u[q][p];52 prod(b, u, a, n);53 show("pap", a, n);54 }55 }56 }57 }58

59 void60 show(char ∗msg, double a[N][N], int n)61 {62 int i, j;63

64 printf("%s\n", msg);65 for (i = 0; i < n; i++) {66 for (j = 0; j < n; j++)67 printf("%15.10lf, ", a[i][j]);68 printf("\n");69 }70 }71

72 void73 prod(double a[N][N], double b[N][N], double c[N][N], int n)74 {75 int i, j, k;76 double s;77 for (i = 0; i < n; i++) {78 for (j = 0; j < n; j++) {79 s = 0;80 for (k = 0; k < n; k++)81 s = s + a[i][k] ∗ b[k][j];82 c[i][j] = s;83 }84 }85 }

12.1.8 プログラムの実行結果

step 0(0, 1)

p=

0.8112421852, 0.5847102847, 0.0000000000, 0.0000000000,

-0.5847102847, 0.8112421852, 0.0000000000, 0.0000000000,

0.0000000000, 0.0000000000, 1.0000000000, 0.0000000000,

0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000,

pa =

4.9990995947, 3.6031471249, 2.2071946550, 1.3959524698,

0.0948854169, -0.1316464836, -0.3581783842, 0.2265319005,

2.0000000000, 1.0000000000, 1.0000000000, 1.0000000000,

1.0000000000, 1.0000000000, 1.0000000000, 1.0000000000,

pap

6.1622776602, 0.0000000000, 2.2071946550, 1.3959524698,

-0.0000000000, -0.1622776602, -0.3581783842, 0.2265319005,

2.2071946550, -0.3581783842, 1.0000000000, 1.0000000000,

Page 10: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 10

1.3959524698, 0.2265319005, 1.0000000000, 1.0000000000,

....

step 3(2, 3)

p=

1.0000000000, 0.0000000000, 0.0000000000, 0.0000000000,

0.0000000000, 1.0000000000, 0.0000000000, 0.0000000000,

0.0000000000, 0.0000000000, 1.0000000000, 0.0000000000,

0.0000000000, 0.0000000000, -0.0000000000, 1.0000000000,

pa =

7.4078212378, -0.0000000000, -0.0000000000, 0.0000000000,

0.0000000000, 0.8594285160, -0.0000000000, -0.0000000000,

-0.0000000000, 0.0000000000, 0.2846190229, 0.0000000000,

0.0000000000, 0.0000000000, -0.0000000000, -0.5518687767,

pap

7.4078212378, -0.0000000000, -0.0000000000, 0.0000000000,

0.0000000000, 0.8594285160, -0.0000000000, -0.0000000000,

-0.0000000000, 0.0000000000, 0.2846190229, 0.0000000000,

0.0000000000, 0.0000000000, -0.0000000000, -0.5518687767,

12.1.9 ギブンス法のプログラム (行列の計算を効率的にしたもの)

1 // givens method2

3 #include "pch.h"

4 #include <iostream.5 #include <math.h>6

7 #define N 48

9 void givens(double a[N][N], int n);10

11 int12 main(int ac, char ∗av[])13 {14 double a[N][N] = {15 {4.0, 3.0, 2.0, 1.0}, {3.0, 2.0, 1.0, 1.0},16 {2.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0}17 };18 int n = N;19 int i,20 j;21

22 givens(a, n);23 for (i = 0; i < n; i++) {24 for (j = 0; j < n; j++)25 printf("%8.5f, ", a[i][j]);26 printf("\n");27 }28 }

Page 11: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 11

29

30 void31 givens(double a[N][N], int n)32 {33 double P[N][N];34 int i, j, k;35 int p, q;36 double c, s;37 double t;38 double app, apq, aqq,39 bpp, bqq, bpq;40 double aqk, apk;41 double sm;42 int nrot;43

44 for (i = 0; i < n; i++) {45 for (j = 0; j < n; j++) {46 P[i][j] = 0;47 }48 P[i][i] = 1;49 }50

51 for (nrot = 0; nrot < 30; nrot++) {52 s = 0;53 for (p = 0; p < n − 2; p++) {54 for (q = p + 2; q < n; q++) {55 t = −2 ∗ a[p][q] / (a[p][p] − a[q][q]);56 if (t == 0)57 continue;58 t = atan(t) / 2;59 s = sin(t);60 c = cos(t);61 app = a[p][p];62 apq = a[p][q];63 aqq = a[q][q];64 for (k = 0; k < n; k++) {65 if ( k == p || k == q) continue;66 apk = a[p][k];67 aqk = a[q][k];68 a[p][k] = apk ∗ c − aqk ∗ s;69 a[q][k] = apk ∗ s + aqk ∗ c;70 a[k][p] = a[p][k];71 a[k][q] = a[q][k];72 }73 apk = (app + aqq) / 2;74 aqk = (app − aqq) / 2 ∗ (c ∗ c − s ∗ s) − apq ∗ 2 ∗ s ∗ c;75 bpp = apk + aqk;76 bqq = apk − aqk;77 bpq = (app − aqq) ∗ s ∗ c + apq ∗ (c ∗ c − s ∗ s);78 a[p][p] = bpp;79 a[q][q] = bqq;80 a[p][q] = bpq;81 a[q][p] = bpq;82 }83 }84 }85 }

Page 12: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 12

12.1.10 ハウスホルダー法

ハウスホルダー法では、行列の相似変換を繰返して、Aを三重対角行列に変換する。

A′ = P−1AP

と変換して、

A′ =

∗ ∗ 0 · · · 0

∗ ∗ ∗ · · · ∗

0 ∗. . .

......

.... . .

...

0 ∗ · · · · · · ∗

(1)

の形にする。次に、aT = [a11, a21, . . . , an1]と、bT = [b1, b2, 0, . . . , 0] に対して、

(I − 2uuT )a = b

を満たし、[0, u2, . . . , un]の形のベクトル uを見つけることを考える。ただし、

||a|| = ||b||

を満たすとする。b1 = a11, b2 = ±

√∑nk=2 a

2k1 = s とすると、

u1 =a− b

||a− b||

とおいて、(I − 2u1uT1 )aを計算すると、

uT1 a =

(||a||2 − (b · a))||a− b||

=(||a||2 − a211 − b2a21)

||a− b||=

(s2 − sa21)

||a− b||

より、u1u

T1 a =

(s2 − sa21)

||a− b||2(a− b)

ここで、||a− b||2 = (a21 − s)2 +∑n

k=3 a2k1 = 2s2 − 2a21sより、u1u

T1 a = (a− b)/2。従って、

(I − 2u1uT1 )a = a− 2u1u

T1 a = b

を満たす。この結果から、

P1 = (I − 2u1uT1 )

と置くと、P−1AP は、式 (1)の形になる。ここで、

P 21 = (I − 2u1u

T1 )(I − 2u1u

T1 ) = I − 4u1u

T1 + 4u1u

T1 u1u

T1

となるが、uT1 u1 = ||u1||2 = 1より、

P 21 = I

従って、PT1 = P1 = P−1

1

Page 13: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 13

が成り立つ。s = ±

√∑nk=2 a

2k1 で、sの符号は正負のいずれをとっても構わないが、a− bの内積を計算するとき、sの符号

は a21の符号と反対の符号を選んだ方が計算誤差を少なくすることができる。結果の式には、a21 − sの計算が現れるが a21と sが同符号で同じぐらいの大きさの場合、a21 − sの計算で桁落ちが発生する。異符号に選べば、桁落ちは起こらない。P−11 AP1 = P1AP1 の計算は、P1A = (I − u1u

T1 )A = A− u1u

T1 A となるが

uT1 A =

( ∑nk=2 ukak1

∑nk=2 ukak2 . . .

∑nk=2 ukakn

)これから、sj =

∑nk=2 ukakj と置くと、

u1uT1 A =

0 0 · · · 0

u2s1 u2s2 . . . u2sn

u3s1 u3s2 . . . u3sn...

......

...

uns1 uns2 . . . unsn

と計算される。同じように、B = {bij}に対して

Bu1 =

∑nk=2 ukb1k∑nk=2 ukb2k∑nk=2 ukb3k

...∑nk=2 ukbnk

従って、tj =

∑nk=2 ukbjk と置くと、

Bu1uT1 =

0 u2t1 . . . unt1

0 u2t2 . . . unt2

0 u2t3 . . . unt3...

...

0 u2tn . . . untn

と計算される。次に、aT = [a′12, a

′22, . . . , a

′n2]および bT = [a′12, a

′22,±

√∑nk=3(a

′i2)

2, 0, . . . , 0]として、

u2 =a− b

||a− b||

から、P2 = (I − 2u2uT2 )の行列を作り、

A′′ = P−12 A′P2

を計算する。s = ±√∑n

k=3(a′i2)

2 と置いて、

uT2 = [0, 0, a′32 − s, a′42, . . . , a

′n2]

およびP2 = I − 2u2u

T2

と表される。uT2 a =

(||a||2 − (b · a))||a− b||

=||a||2 − (a′12)

2 − (a′22)2 − a′32s

||a− b||=

s2 − a′32s

||a− b||

Page 14: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 14

従って、u2u

T2 a =

s2 − a′32s

||a− b||2(a− b)

ここで、

||a− b||2 = (a′32 − s)2 +

n∑k=4

(a′k2)2 = 2s2 − 2a′32s

従って、P2a = (I − 2u2u

T2 )a = a− (a− b) = b

sの符号の取り方は、||a− b||2を計算するときに、sの符号と a′32の符号が反対になるように取った方が計算誤差を少なくすることができる。なお、A′′ の 1行目および 1列目の要素はこの変換で不変で A′ と同じである。従って、変換した行列 A′′ は

∗ ∗ 0 0 · · · 0

∗ ∗ ∗ 0 · · · 0

0 ∗ ∗ ∗ · · · ∗

0 0 ∗. . . ∗

......

. . ....

0 0 ∗ · · · · · · ∗

(2)

の形になる。これを繰返すことにより、対称な三重対角行列に変換できる。

12.1.11 ハウスホルダー法のプログラム

1

2 // householder method3

4 #include <stdio.h>5 #include <math.h>6

7 #define N 48

9 void householder(double a[N][N], int n);10 void show(char ∗s, double a[N][N], int n);11 void prod(double a[N][N], double b[N][N], double c[N][N], int n);12

13 int14 main(int ac, char ∗av[])15 {16 double a[N][N] = {17 {4.0, 3.0, 2.0, 1.0}, {3.0, 2.0, 1.0, 1.0},18 {2.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0} };19 double p[N][N], q[N][N], b[N][N];20 double u[N], v[N];21 int n = N;22 int i, j, k;23 double s;24

25 for (i = 0; i < n − 2; i++) {26 for (k = 0; k <= i; k++)27 u[k] = 0;28 for (k = i + 1; k < n; k++)

Page 15: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 15

29 u[k] = a[k][i];30 s = 0;31 for (k = i + 1; k < n; k++)32 s = s + u[k] ∗ u[k];33 s = u[i + 1] > 0 ? −sqrt(s) : sqrt(s);34 u[i + 1] = u[i + 1] − s;35 s = 0;36 for (k = i + 1; k < n; k++)37 s = s + u[k] ∗ u[k];38 s = sqrt(s);39 for (k = i + 1; k < n; k++)40 u[k] = u[k] / s;41

42 for (k = 0; k < n; k++) {43 for (j = 0; j < n; j++) {44 p[k][j] = −2 ∗ u[k] ∗ u[j];45 }46 p[k][k] = p[k][k] + 1;47 }48 printf("step %d\n", i);49 printf("u = \n");50 for (k = 0; k < n; k++)51 printf("%10.5lf, ", u[k]);52 printf("\n");53 show("p=", p, n);54 prod(p, a, b, n);55 show("pa = ", b, n);56 prod(b, p, a, n);57 show("pap = ", b, n);58 }59 show("result", a, n);60 }61

62

63 void64 show(char ∗msg, double a[N][N], int n)65 {66 int i, j;67

68 printf("%s\n", msg);69 for (i = 0; i < n; i++) {70 for (j = 0; j < n; j++)71 printf("%15.10lf, ", a[i][j]);72 printf("\n");73 }74 }75

76 void77 prod(double a[N][N], double b[N][N], double c[N][N], int n)78 {79 int i, j, k;80 double s;81 for (i = 0; i < n; i++) {82 for (j = 0; j < n; j++) {83 s = 0;84 for (k = 0; k < n; k++)85 s = s + a[i][k] ∗ b[k][j];86 c[i][j] = s;87 }88 }89 }

Page 16: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 16

12.1.12 実行結果

step 0

u =

0.00000, 0.94915, 0.28158, 0.14079,

p=

1.0000000000, -0.0000000000, -0.0000000000, -0.0000000000,

-0.0000000000, -0.8017837257, -0.5345224838, -0.2672612419,

-0.0000000000, -0.5345224838, 0.8414269806, -0.0792865097,

-0.0000000000, -0.2672612419, -0.0792865097, 0.9603567451,

pa =

4.0000000000, 3.0000000000, 2.0000000000, 1.0000000000,

-3.7416573868, -2.4053511772, -1.6035674515, -1.6035674515,

-0.0000000000, -0.3069044968, 0.2276179871, 0.2276179871,

-0.0000000000, 0.3465477516, 0.6138089935, 0.6138089935,

pap =

4.0000000000, 3.0000000000, 2.0000000000, 1.0000000000,

-3.7416573868, -2.4053511772, -1.6035674515, -1.6035674515,

-0.0000000000, -0.3069044968, 0.2276179871, 0.2276179871,

-0.0000000000, 0.3465477516, 0.6138089935, 0.6138089935,

step 1

u =

0.00000, 0.00000, 0.73562, -0.67739,

p=

1.0000000000, -0.0000000000, -0.0000000000, 0.0000000000,

-0.0000000000, 1.0000000000, -0.0000000000, 0.0000000000,

-0.0000000000, -0.0000000000, -0.0822794996, 0.9966092935,

0.0000000000, 0.0000000000, 0.9966092935, 0.0822794996,

pa =

4.0000000000, -3.7416573868, -0.0000000000, -0.0000000000,

-3.7416573868, 3.2142857143, 0.0635706332, -0.7699984092,

-0.0000000000, -0.7726181305, 0.2538416697, 0.4234205615,

-0.0000000000, 0.0000000000, 0.3596295977, 0.3184898479,

pap =

4.0000000000, -3.7416573868, -0.0000000000, -0.0000000000,

-3.7416573868, 3.2142857143, 0.0635706332, -0.7699984092,

-0.0000000000, -0.7726181305, 0.2538416697, 0.4234205615,

-0.0000000000, 0.0000000000, 0.3596295977, 0.3184898479,

result

4.0000000000, -3.7416573868, -0.0000000000, -0.0000000000,

-3.7416573868, 3.2142857143, -0.7726181305, -0.0000000000,

-0.0000000000, -0.7726181305, 0.4010989011, 0.2878197990,

Page 17: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 17

-0.0000000000, 0.0000000000, 0.2878197990, 0.3846153846,

12.1.13 ハウスホルダー法のプログラム (行列の計算を効率的にしたもの)

1 // householder method2

3 #include "pch.h"

4 #include <iostream.5 #include <math.h>6

7 #define N 48

9 void householder(double a[N][N], int n);10

11 int12 main(int ac, char ∗av[])13 {14 double a[N][N] = {15 {4.0, 3.0, 2.0, 1.0}, {3.0, 2.0, 1.0, 1.0},16 {2.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0}17 };18 int n = N;19 int i,20 j, k;21

22 householder(a, n);23 printf("householder \n");24 for (i = 0; i < n; i++) {25 for (j = 0; j < n; j++)26 printf("%8.5f, ", a[i][j]);27 printf("\n");28 }29 }30

31 void32 householder(double a[N][N], int n)33 {34 double b[N][N];35 double v[N];36 int i, j, k, l;37 double s, t;38

39

40 for (i = 0; i < n−2; i++) {41 for(j = 0; j <=i; j++) v[j] = 0;42 s = 0;43 for(j = i+2; j < n; j++) {44 v[j] = a[i][j];45 s = s + v[j]∗v[j];46 }47 t = s;48 s = s + a[i][i+1]∗a[i][i+1];49 s = sqrt(s);50 if(a[i][i+1] < 0) s=−s;51 v[i+1] = a[i][i+1] + s;52 t = t + v[i+1]∗v[i+1];53 if(t < 1.0e−17) continue;54 t = sqrt(t);

Page 18: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 18

55 for(j = i+1; j < n; j++)56 v[j] = v[j]/t;57

58 for(j = 0; j <= i; j++) {59 for(k = 0; k < n; k++) {60 b[j][k] = a[j][k];61 }62 }63 for(j = i+1; j < n; j++) {64 for(k = 0; k < n; k++) {65 s = 0;66 for(l = i+1; l < n; l++) {67 s = s − 2∗v[j]∗v[l]∗a[l][k];68 }69 s = s + a[j][k];70 b[j][k] = s;71 }72 }73

74 for(j = 0; j < n; j++) {75 for(k = 0; k <= i; k++) {76 a[j][k] = b[j][k];77 }78 for(k = i+1; k < n; k++) {79 s = 0;80 for(l = i+1; l < n; l++) {81 s = s − 2∗v[l]∗v[k]∗b[j][l];82 }83 s = s + b[j][k];84 a[j][k] = s;85 }86 }87 }88 }

プログラム中、50行目で sの符号を決めている。このプログラムでは上の説明とはベクトル bの取り方が違って b = [a11,−s, 0, . . . , 0]としている。(51行目で v[i+ 1]に a[i][i+ 1] + sを代入している。) そのため、sの符号は a21 と同符号に取っている。

12.1.14 三重対角行列の固有値

A =

α1 β1 0 · · · 0

β1 α2 β2 · · · 0

0 β2 α3. . .

...

0 0. . .

. . . βn−1

0 0 · · · βn−1 αn

(3)

の固有値は、

det(A− λI) =

∣∣∣∣∣∣∣∣∣∣∣∣∣∣

α1 − λ β1 0 · · · 0

β1 α2 − λ β2 · · · 0

0 β2 α3 − λ. . .

...

0 0. . .

. . . βn−1

0 0 · · · βn−1 αn − λ

∣∣∣∣∣∣∣∣∣∣∣∣∣∣= 0 (4)

Page 19: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 19

を満たす λを求めれば良い。行列 (λI −A)の k番目の小行列式 pk(λ)は

pk(λ) =

∣∣∣∣∣∣∣∣∣∣∣∣∣∣

λ− α1 −β1 0 · · · 0

−β1 λ− α2 −β2 · · · 0

0 −β2 λ− α3. . .

...

0 0. . .

. . . −βk−1

0 0 · · · −βk−1 λ− αk

∣∣∣∣∣∣∣∣∣∣∣∣∣∣(5)

で与えられる。この行列式を最後の列について展開すると

pk(λ) = (λ− αk)pk−1(λ)− β2k−1pk−2(λ)

の漸化式が得られる。p1(λ) = λ− α1

である。また、p0(λ) = 1と定義しておく。この漸化式から、pn(λ)を求めてその解を計算すれば良い。ここで定義した多項式列 {pk(λ)}は、スツルム列になっている。

12.1.15 三重対角行列から固有値を計算するプログラム

1

2 // tridiagonal matrix3

4 #include "pch.h"

5 #include <iostream.6 #include <math.h>7

8 #define N 49

10 void tridiagonal(double a[N][N], int n);11 void householder(double a[N][N], int n);12 double newton(double x);13 double f(double x);14 double df(double x);15

16 double C[N + 1];17 int Deg;18

19 int20 main(int ac, char ∗av[])21 {22 double a[N][N] = {23 {4.0, 3.0, 2.0, 1.0}, {3.0, 2.0, 1.0, 1.0},24 {2.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0}25 };26

27 int n = N;28 int i, j;29 double r;30

31

32 householder(a, n);33 printf("tridiagonal matrix = \n");

Page 20: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 20

34 for (i = 0; i < n; i++) {35 for (j = 0; j < n; j++)36 printf("%8.5f, ", a[i][j]);37 printf("\n");38 }39 tridiagonal(a, n);40 r = newton(7.0);41 }42

43 void44 tridiagonal(double a[N][N], int n)45 {46 double c[3][N + 1];47 int i, j;48 int k, k1, k2;49 for (i = 0; i <= n; i++)50 c[0][i] = c[1][i] = c[2][i] = 0;51 c[0][0] = 1;52 c[1][0] = −a[0][0];53 c[1][1] = 1;54 for (i = 2; i <= n; i++) {55 k = i % 3;56 k1 = (i − 1) % 3;57 k2 = (i − 2) % 3;58

59 for (j = 1; j < i; j++) {60 c[k][j] = −a[i − 1][i − 1] ∗ c[k1][j] + c[k1][j − 1]61 − a[i − 1][i − 2] ∗ a[i − 1][i − 2] ∗ c[k2][j];62 }63 c[k][0] = −a[i − 1][i − 1] ∗ c[k1][0]64 − a[i − 1][i − 2] ∗ a[i − 1][i − 2] ∗ c[k2][0];65 c[k][i] = c[k1][i − 1] ∗ c[k1][i − 1];66 }67 printf("eq = ");68 for (i = 0; i <= n; i++)69 printf("%8.5f, ", c[k][i]);70 printf("\n");71 for (i = 0; i <= n; i++) {72 C[i] = c[k][i];73 }74 Deg = n;75 }76

77 void78 householder(double a[N][N], int n)79 {80 .81 .82 .83 }84

85 // newton method86

87 double88 newton(double x0)89 {90 .91 .92 .93 }94

Page 21: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 21

95 double96 f(double x)97 {98 double r;99 double xn;

100 int i;101 r = 0;102 xn = 1;103 for (i = 0; i <= Deg; i++) {104 r = r + C[i] ∗ xn;105 xn = xn ∗ x;106 }107 return r;108 }109

110 double111 df(double x)112 {113 double r;114 double xn;115 int i;116 r = 0;117 xn = 1;118 for (i = 0; i < Deg; i++) {119 r = r + C[i + 1] ∗ (i + 1) ∗ xn;120 xn = xn ∗ x;121 }122 return r;123 }

12.2 ベキ乗法n× n行列 Aに対して、適当な初期ベクトル x(0) を取り、

x(k) = Ax(k−1)

を順に計算する。このとき、x(k) は Aの絶対値が最大の固有ベクトル u1 に収束する。これから、∑nj=1(x

(k)j )2∑n

j=1 x(k)j x

(k−1)j

= λ1

から固有値が求められる。求めた、固有ベクトル u1を使って、初期ベクトル x(0) から u1 成分を差し引いたベクトルを初期値に選んで同じ計算を行なえば、2番目に大きな固有値に対する固有ベクトルが得られるはずである。実際には、計算誤差のため、u1成分のベクトルが x(k)に現れてくるので、2番目あるいは 3番目以降の固有値に対する計算を行なうのはちょっと難しい。

12.2.1 プログラム

1 // power method2

3 #include "pch.h"

4 #include <iostream.

Page 22: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 22

5 #include <math.h>6

7 #define N 48

9 int10 main(int ac, char ∗av[])11 {12 double a[N][N] = {13 {4.0, 3.0, 2.0, 1.0}, {3.0, 2.0, 1.0, 1.0},14 {2.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0}15 };16 double x[N] = { 1.0, 1.0, 1.0, 1.0 };17 double y[N];18

19 double e, s, t;20 int n = N;21 int loop, i, j;22

23

24 e = 0;25 for (loop = 0; loop < 15; loop++) {26 for (i = 0; i < n; i++) {27 s = 0;28 for (j = 0; j < n; j++)29 s = s + a[i][j] ∗ x[j];30 y[i] = s;31 }32 s = 0;33 t = 0;34 for (i = 0; i < n; i++) {35 s = s + x[i] ∗ x[i];36 t = t + x[i] ∗ y[i];37 }38 if (fabs(e − t / s) < 1.0e−5)39 break;40 e = t / s;41 for (i = 0; i < n; i++)42 x[i] = y[i];43 }44 printf("eigenvalue = %8.5f\n", e);45 }

12.3 グラム・シュミットの直交化n次元の一次独立なベクトルの組 {q1, q2, . . . , qn}において、

(qi, qj) =

{1, i = j

0, i ̸= j

を満たすとき、これを正規直交系という。ここで、(x, y)はベクトルの内積である。あるベクトル f が与えられたとき、

(f, qk)qk

は f の qk 成分、あるいは f の qk 方向への正射影という。f から qk 成分を取り除いたベクトルは、qk と直交する(内積が零になる)。今、一次独立なベクトル

a1, a2, . . . , an

Page 23: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 23

が与えられているものとして、これから正規直交系を構成する。まず、a1 から、

q1 =a1

||a1||=

a1(a1, a1)

を計算して、q1 とする。次に a2 から q1 成分を取り除いて、

u2 = a2 − (a2, q1)q1

を求め、これを正規化して、q2 =

u2

||u2||

から q2を求める。これを順に繰返して行くことにより、正規直交系 {q1, q2, . . . , qn}を求めることが出来る。これをグラム・シュミットの直交化という。ここで、qk を計算するときに、元々のグラム・シュミットの方法では、

uk = ak − (ak, q1)q1 − (ak, q2)q2 − · · · − (ak, qk−1)qk−1

で uk を求め、qk =

uk

||uk||

と計算する。これに対して、修正グラム・シュミットの方法では、

u(1)k = ak − (ak, q1)q1

u(l)k = u

(l−1)k − (u

(l−1)k , ql)ql, l = 2, . . . , k − 1

qk =u(k−1)k

||u(k−1)k ||

として計算する。ベクトル ak からベクトル qj 成分を取り除くのだが、取り除く成分の大きさを全く取り除いていない元の ak を使って (ak, qj)で計算するか、q1 から qj−1 成分までを取り除いた u

(l−1)k を使って計算するかが違っている。

修正グラム・シュミットの方法で計算した方が誤差が少ない。

12.3.1 グラム・シュミットの正規直交化プログラム

1 #define N 42 void gramm schmidt(double a[N][N], int n) // 修正バージョン3 {4 int i, j, k;5 double s;6 for (i=0; i < n; i++) {7 s=0;8 for(j = 0; j < n; j++)9 s = s + a[i][j] ∗ a[i][j]; // (a[i], a[i])の計算

10 s = 1/sqrt(s);11 for(j=0; j < n; j++)12 a[i][j] = a[i][j]∗s; // a[i]の正規化13 for(k = i+1; k < n; k++) {14 s = 0;15 for(j=0; j < n; j++)16 s = s + a[k][j] ∗ a[i][j]; // (a[i], a[k])の計算17 for(j=0; j<n; j++)

Page 24: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 24

18 a [k][j] = a[k][j] − s∗a[i][j]; // a[i]成分の消去19 }20 }21 }

上記のプログラムは修正グラム・シュミットの方法で計算している。ちなみに、元々の方法で計算するプログラムは次のようになる。

1 void gramm schmidt(double a[N][N], int n) // オリジナルバージョン2 {3 int i, j, k;4 double s,u[N];5 for (i=0; i < n; i++) {6 for(j = 0; j < n;j++)7 u[j] = a[i][j]; // u = a[i]8 for(k = 0; k < i; k++) {9 s = 0;

10 for(j = 0; j < n; j++)11 s = s + a[k][j]∗a[i][j]; // (a[i],a[k])の計算12 for(j = 0; j < n; j++)13 u[j] = u[j] − s∗a[k][j]; // a[k] 成分の消去14 }15 s=0;16 for(j = 0; j < n; j++)17 s = s + u[j]∗u[j]; // (u,u)の計算18 s = 1/sqrt(s);19 for(j=0; j < n; j++)20 a[i][j] = u[j]∗s; // a[i]の正規化21 }22 }

12.4 QR分解グラム・シュミットの直交化により求めた、q1, q2, . . . , qn を列ベクトルにもつ行列 Qを作ると、

QTQ = I

を満たす。Qはユニタリー行列である。Q と Aから、次のようにして行列 Rを構築する。

rjk =

(ak, qj), j < k

||ak −∑k−1

l=1 (ak, ql)ql|| = ||ak −∑k−1

l=1 rlkql||, j = k

0, j > k

このとき、A = QR

となる。これを、行列 Aの QR分解という。【注意】上に示したグラム・シュミットのプログラムで返される行列は正規直行ベクトル q1, q2, . . .を行ベクトルに持つ行列である。すなわち QT が返されることに注意せよ。

12.5 ハウスホルダー変換によるQR分解の計算基本はハウスホルダー変換による行列の三重対角化と同じ。

A0 = A

Page 25: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 25

Ak+1 = UkAk, Uk = I − 2ukuTk , (k = 0, . . . , n− 2)

A =

6 7 5 5 3

7 3 4 7 6

5 4 7 6 2

5 8 6 7 3

3 6 2 3 5

12.5.1 グラム・シュミットによるQR分解のプログラム

1 // qr decomposition by gramm−schmidt2

3

4 #include <stdio.h>5 #include <math.h>6

7 #define N 58

9 void gramm schmidt(double a[N][N], int n, double q[N][N]);10 void qr decomposition(double a[N][N], int n, double q[N][N], double r[N][N]);11 void show(char ∗msg, double a[N][N], int n);12

13 int14 main(int ac, char ∗av[])15 {16 double a[N][N] = {17 {5.0, 4.0, 3.0, 3.0, 2.0},18 {4.0, 3.0, 2.0, 1.0, 1.0}, {3.0, 2.0, 1.0, 1.0, 1.0},19 {2.0, 1.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0, 1.0} };20 double q[N][N], r[N][N];21 int n = N;22

23 qr decomposition(a, n, q, r);24 show("a=", a, n);25 show("q=", q, n);26 show("r=", r, n);27 }28

29 void show(char ∗msg, double a[N][N], int n)30 {31 int i, j;32 printf("%s\n", msg);33 for(i =0; i < n; i++) {34 for(j = 0; j < n; j++)35 printf("%10.7lf, ", a[i][j]);36 printf("\n");37 }38 }39

40 void41 qr decomposition(double a[N][N], int n, double q[N][N], double r[N][N])42 {43 int i, j, k, l;44 double s, p;45

Page 26: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 26

46 gramm schmidt(a, n, q);47 for(k = 0; k < n; k++) {48 for(j = 0; j < k; j++) {49 s = 0;50 for(i = 0; i < n; i++)51 s = s + a[i][k] ∗ q[i][j]; // (a[i], q[i])52 r[j][k] = s;53 }54 s = 0;55 for(i = 0; i < n; i++) { // a[i] − r[l][k] q[l]56 p = a[i][k];57 for(l = 0; l < k; l++) {58 p = p − r[l][k] ∗ q[i][l];59 }60 s = s + p∗p;61 }62 s = sqrt(s);63 r[k][k] = s;64 for(j = k+1; j < n; j++)65 r[j][k] = 0;66 }67 }68

69 void70 gramm schmidt(double a[N][N], int n, double q[N][N])71 {72 int i, j, k;73 double s, b[N][N];74 for (i= 0; i < n; i++)75 for (j = 0; j < n; j++)76 b[j][i] = a[i][j];77 for (i=0; i < n; i++) {78 s=0;79 for(j = 0; j < n; j++)80 s = s + b[i][j] ∗ b[i][j]; // calculate (a[i], a[i])81 if(s != 0.0) {82 s = 1/sqrt(s);83 for(j=0; j < n; j++)84 b[i][j] = b[i][j]∗s; // normalize a[i]85 }86 for(k = i+1; k < n; k++) {87 s = 0;88 for(j=0; j < n; j++)89 s = s + b[k][j] ∗ b[i][j]; // calculate (a[i], a[k])90 for(j=0; j<n; j++)91 b[k][j] = b[k][j] − s∗b[i][j]; // remove a[i] component92 }93 }94 for (i= 0; i < n; i++)95 for (j = 0; j < n; j++)96 q[j][i] = b[i][j];97 }

12.5.2 プログラムの実行結果

a=

5.0000000, 4.0000000, 3.0000000, 3.0000000, 2.0000000,

4.0000000, 3.0000000, 2.0000000, 1.0000000, 1.0000000,

Page 27: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 27

3.0000000, 2.0000000, 1.0000000, 1.0000000, 1.0000000,

2.0000000, 1.0000000, 1.0000000, 1.0000000, 1.0000000,

1.0000000, 1.0000000, 1.0000000, 1.0000000, 1.0000000,

q=

0.6741999, 0.4128614, 0.2041241, 0.4082483, -0.4082483,

0.5393599, 0.0275241, -0.2041241, -0.8164966, -0.0000000,

0.4045199, -0.3578132, -0.6123724, 0.4082483, 0.4082483,

0.2696799, -0.7431505, 0.6123724, 0.0000000, -0.0000000,

0.1348400, 0.3853373, 0.4082483, 0.0000000, 0.8164966,

r=

7.4161985, 5.5284389, 3.9103592, 3.3709993, 2.6967994,

0.0000000, 0.6605783, 0.5780060, 0.5504819, 0.1376205,

0.0000000, 0.0000000, 0.6123724, 0.8164966, 0.6123724,

0.0000000, 0.0000000, 0.0000000, 0.8164966, 0.4082483,

0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.4082483,

qr=

5.0000000, 4.0000000, 3.0000000, 3.0000000, 2.0000000,

4.0000000, 3.0000000, 2.0000000, 1.0000000, 1.0000000,

3.0000000, 2.0000000, 1.0000000, 1.0000000, 1.0000000,

2.0000000, 1.0000000, 1.0000000, 1.0000000, 1.0000000,

1.0000000, 1.0000000, 1.0000000, 1.0000000, 1.0000000,

q^t q =

1.0000000, -0.0000000, 0.0000000, -0.0000000, -0.0000000,

-0.0000000, 1.0000000, 0.0000000, 0.0000000, -0.0000000,

0.0000000, 0.0000000, 1.0000000, -0.0000000, 0.0000000,

-0.0000000, 0.0000000, -0.0000000, 1.0000000, -0.0000000,

-0.0000000, -0.0000000, 0.0000000, -0.0000000, 1.0000000,

12.5.3 ハウスホルダー法によるQR分解のプログラム

1

2 // qr decomposition by householder transformation3

4 #include <stdio.h>5 #include <math.h>6

7 #define N 58

9 void show(char ∗s, double a[N][N], int n);10 void makeu(double p[N][N], double a[N][N], int i, int n);11 void prod(double a[N][N], double p[N][N], double b[N][N], int n);12 void copy(double a[N][N], double b[N][N], int n);13 void unit(double a[N][N], int n);14

15 int16 main(int ac, char ∗av[])17 {18 double a[N][N] = {

Page 28: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 28

19 {5.0, 4.0, 3.0, 3.0, 2.0},20 {4.0, 3.0, 2.0, 1.0, 1.0}, {3.0, 2.0, 1.0, 1.0, 1.0},21 {2.0, 1.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0, 1.0} };22 double p[N][N], q[N][N], b[N][N];23 int n = N, i;24

25 unit(q, n);26 show("r = ", a, n);27 for (i = 0; i < n − 1; i++) {28 makep(p, a, i, n);29 prod(p, a, b, n);30 copy(b, a, n);31 prod(q, p, b, n);32 copy(b, q, n);33 }34 show("r = ", a, n);35 show("q = ", q, n);36 }37

38 void39 makep(double p[N][N], double a[N][N], int i, int n)40 {41 int j, k;42 double s, u[N];43

44 for (k = 0; k < i; k++)45 u[k] = 0;46 for (k = i; k < n; k++)47 u[k] = a[k][i];48 s = 0;49 for (k = i; k < n; k++)50 s = s + u[k] ∗ u[k];51 u[i] = u[i] − sqrt(s);52 s = 0;53 for (k = i; k < n; k++)54 s = s + u[k] ∗ u[k];55 s = sqrt(s);56 for (k = i; k < n; k++)57 u[k] = u[k] / s;58

59 for (k = 0; k < n; k++) {60 for (j = 0; j < n; j++) {61 p[k][j] = −2 ∗ u[k] ∗ u[j];62 }63 p[k][k] = p[k][k] + 1;64 }65 }66

67 void68 show(char ∗msg, double p[N][N], int n)69 {70 int i, j;71

72 printf("%s\n", msg);73 for (i = 0; i < n; i++) {74 for (j = 0; j < n; j++)75 printf("%15.10lf, ", p[i][j]);76 printf("\n");77 }78 }79

Page 29: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 29

80 void81 prod(double a[N][N], double v[N][N], double b[N][N], int n)82 {83 int i, j, k;84 double s;85

86 for (i = 0; i < n; i++) {87 for (j = 0; j < n; j++) {88 s = 0;89 for (k = 0; k < n; k++)90 s = s + a[i][k] ∗ v[k][j];91 b[i][j] = s;92 }93 }94 }95

96 void97 copy(double a[N][N], double b[N][N], int n)98 {99 int i, j;

100

101 for (i = 0; i < n; i++) {102 for (j = 0; j < n; j++) {103 b[i][j] = a[i][j];104 }105 }106 }107

108 void109 unit(double a[N][N], int n)110 {111 int i, j;112

113 for (i = 0; i < n; i++) {114 for (j = 0; j < n; j++) {115 a[i][j] = 0;116 }117 a[i][i] = 1;118 }119 }

12.5.4 プログラムの実行結果

a =

5.0000000000, 4.0000000000, 3.0000000000, 3.0000000000, 2.0000000000,

4.0000000000, 3.0000000000, 2.0000000000, 1.0000000000, 1.0000000000,

3.0000000000, 2.0000000000, 1.0000000000, 1.0000000000, 1.0000000000,

2.0000000000, 1.0000000000, 1.0000000000, 1.0000000000, 1.0000000000,

1.0000000000, 1.0000000000, 1.0000000000, 1.0000000000, 1.0000000000,

r =

7.4161984871, 5.5284388722, 3.9103592023, 3.3709993123, 2.6967994499,

0.0000000000, 0.6605782591, 0.5780059767, 0.5504818826, 0.1376204706,

0.0000000000, -0.0000000000, 0.6123724357, 0.8164965809, 0.6123724357,

0.0000000000, 0.0000000000, 0.0000000000, 0.8164965809, 0.4082482905,

-0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.4082482905,

Page 30: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 30

q =

0.6741998625, 0.4128614119, 0.2041241452, 0.4082482905, -0.4082482905,

0.5393598900, 0.0275240941, -0.2041241452, -0.8164965809, -0.0000000000,

0.4045199175, -0.3578132237, -0.6123724357, 0.4082482905, 0.4082482905,

0.2696799450, -0.7431505415, 0.6123724357, -0.0000000000, -0.0000000000,

0.1348399725, 0.3853373178, 0.4082482905, -0.0000000000, 0.8164965809,

12.5.5 QR分解を用いた固有値の計算

A = Q0R0

と分解する。A1 = R0Q0

を求める。これは、Q−10 AQ0 = Q−1

0 Q0R0Q0 = R0Q0 = A1 より Aのユニタリー変換である。

Ak = QkRk

Ak+1 = RkQk

の変換を繰返し行なうことにより, Ak, k = 1, 2, . . . を求める。Ak は上三角行列に収束し、対角線上には Aの固有値が並ぶ。

12.5.6 QR分解による固有値の計算プログラム

先に示したQR分解のプログラムにより、固有値を計算するプログラム (main関数のみ)と実行結果を次に示す。

1 // eigenvalue caluculation by qr decomposition2 int3 main(int ac, char ∗av[])4 {5 double a[N][N] = {6 {5.0, 4.0, 3.0, 3.0, 2.0},7 {4.0, 3.0, 2.0, 1.0, 1.0}, {3.0, 2.0, 1.0, 1.0, 1.0},8 {2.0, 1.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0, 1.0} };9 double q[N][N], r[N][N], e;

10 int i, j, k, n = N;11

12 k = 0;13 do {14 k++;15 qr decomposition(a, n, q, r);16 prod(r, q, a, n);17 e = 0;18 for(i = 0; i < n; i++)19 for(j = 0; j < i; j++)20 if(fabs(a[i][j]) > e)21 e = fabs(a[i][j]);22 printf("loop %d, err = %le\n", k, e);23 show("rq=", a, n);24 } while (e > 1.0e−5);25 show("a=", a, n);26 }

Page 31: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 31

loop 1, err = 7.571150e-01

rq=

10.8363636, 0.3488667, 1.1560120, 0.1100964, 0.7706746,

0.7571150, -0.5446970, -0.0955116, -0.3033899, 0.3483366,

0.5504819, -0.5899249, 0.3750000, 0.2500000, 0.7500000,

0.2752409, -0.4494666, 0.6666667, 0.0000000, 0.3333333,

0.0550482, 0.1573133, 0.1666667, 0.0000000, 0.3333333,

loop 2, err = 4.736193e-01

rq=

10.9216710, 0.1037304, 0.5199569, 0.5781936, 0.8168132,

0.0450758, -0.4598973, -0.8521643, -0.5760737, -0.5485527,

0.0396787, -0.4736193, 0.3170725, 0.3164595, 0.3220265,

0.0090967, -0.1314472, 0.2843330, -0.1788462, 0.0392232,

0.0022626, 0.0726832, 0.1519125, -0.1078639, 0.4000000,

loop 3, err = 6.671272e-01

...

loop 1264, err = 9.974844e-06

rq=

10.9246606, -0.5310316, 0.3223013, 0.6052355, 0.6810933,

0.0000000, 0.8708253, -0.4539212, -0.4057649, -0.5119381,

0.0000000, -0.0000000, -0.7925936, -0.2710775, -0.2714800,

0.0000000, 0.0000000, 0.0000000, -0.3656208, 0.0630359,

0.0000000, 0.0000000, 0.0000000, -0.0000100, 0.3627285,

a=

10.9246606, -0.5310316, 0.3223013, 0.6052355, 0.6810933,

0.0000000, 0.8708253, -0.4539212, -0.4057649, -0.5119381,

0.0000000, -0.0000000, -0.7925936, -0.2710775, -0.2714800,

0.0000000, 0.0000000, 0.0000000, -0.3656208, 0.0630359,

0.0000000, 0.0000000, 0.0000000, -0.0000100, 0.3627285,

12.6 原点移動付きQR分解QR分解によって固有値の計算を行った結果では、収束が非常に遅い。上の例では、1264回の繰り返し後にようやく下三角行列部分の要素の値が 10−5 以下になっている。Ak の収束を早くするためは次のような修正を加える。行列 Aを、A− µI とシフトして、これを分解する。すなわち、各ステップにおいて

Ak − µkI = QkRk

と分解し、Ak+1 = RkQk + µkI

とする。これを繰り返す。ここで µkの選択方法として、Wilkinsonによる方法やRayleigh 商を用いる方法がある。Wilkinsonによる方法では、Ak の右下の 2× 2小行列の固有値のうち ann の値に近い方を選ぶ。

Page 32: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 32

(an−1,n−1 an−1,n

an,n−1 an.n

)の固有値は

(an−1,n−1 − x)(an,n − x)− an−1,nan,n−1 = 0

の解であるから

x =(an−1,n−1 + an,n)±

√(an−1,n−1 + an,n)2 − 4(an−1,n−1an,n − an−1,nan,n−1)

2

=(an−1,n−1 + an,n)±

√(an−1,n−1 − an,n)2 + 4an−1,nan,n−1

2

となる。ここで、符号は δの符号に合わせる。

x = an,n − sign(δ)an,n−1an−1,n

|δ|+√

δ2 + an,n−1an−1,n

ただし、δ = (an−1,n−1 − an,n)/2。

12.6.1 Wilkinsonシフトを行うQR分解プログラム

原点移動を行う QR分解のプログラム ( main関数の部分のみ)を示す。

1 int2 main(int ac, char ∗av[])3 {4 double a[N][N] = {{4.0, 3.0, 2.0, 1.0}, {3.0, 2.0, 1.0, 1.0},5 {2.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0}};6 double q[N][N], r[N][N];7 int n = N;8 int i, j, k;9 double mu, s, e;

10

11 k = 0;12 do {13 s = (a[n − 2][n − 2] − a[n − 1][n − 1])/2;14 mu = s ∗ s + a[n − 2][n − 1] ∗ a[n − 1][n − 2];15 if (mu < 0) {16 mu = a[n − 1][n − 1];17 } else {18 mu = a[n−2][n−1]∗a[n−2][n−1]/(fabs(s) + sqrt(mu));19 if(s < 0) mu = −mu;20 mu = a[n−1][n−1] − mu;21 }22 for (i = 0; i < n; i++)23 a[i][i] = a[i][i] − mu;24 qr decomposition(a, n, q, r);25 prod(r, q, a, n);26 for (i = 0; i < n; i++)27 a[i][i] = a[i][i] + mu;28 e = 0;29 for(i = 0; i < n; i++)30 for(j = 0; j < i; j++)31 if(fabs(a[i][j]) > e)32 e = fabs(a[i][j]);33 printf("loop %d, err = %le\n", k, e);34 show("rq=", a, n);

Page 33: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 33

35 } while (e > 1.0e−5);36 printf("qr decomposition\n");37 show("a=\n", a, n);38 }

loop 1, err = 3.031695e+00

rq=

10.0000000, 2.6678919, 1.3970766, 0.0529842, -0.3981104,

3.0316953, 0.3566176, 0.2200312, -0.8636233, -0.6434067,

1.4168093, 0.0356150, -0.3046034, -0.1604376, -0.1472308,

0.4579692, -0.2578347, 0.0777120, 0.3204936, 0.3479467,

0.2308193, 0.1959367, 0.2171070, 0.2350370, 0.6274921,

loop 2, err = 5.465360e-01

rq=

10.8830652, 0.9322317, -0.1318840, -0.1730229, -1.0102879,

0.5465360, -0.7183932, -0.0061082, -0.1330317, 0.7226384,

0.1716986, -0.2524560, -0.3768060, 0.0958944, 0.1060137,

-0.0001764, -0.1231217, -0.0223046, 0.3005298, -0.2584495,

0.0033663, 0.0148401, 0.0156932, 0.0847893, 0.9116042,

loop 3, err = 1.888353e-01

...

loop 36, err = 7.786662e-06

rq=

10.9246606, 0.1711415, -0.4362681, -0.0545166, 0.1711427,

0.0000000, -0.7925980, 0.2428167, -0.0366966, -1.6634240,

0.0000000, -0.0000078, -0.3656155, 0.1708967, -0.0000044,

0.0000000, -0.0000000, -0.0000000, 0.3627276, 0.0000000,

0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.8708253,

a=

10.9246606, 0.1711415, -0.4362681, -0.0545166, 0.1711427,

0.0000000, -0.7925980, 0.2428167, -0.0366966, -1.6634240,

0.0000000, -0.0000078, -0.3656155, 0.1708967, -0.0000044,

0.0000000, -0.0000000, -0.0000000, 0.3627276, 0.0000000,

0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.8708253,

12.7 非正方行列に対するQR分解n×m次行列 A(n ≥ mとする)に対して、

A = QR

ただし、QはQTQ = I

Page 34: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 34

を満たすn×m次行列であり、Rはm×m次の上三角行列 (対角線より下の三角部分の要素は 0である行列)とする。これをAのQR分解という。正方行列に対してはQR分解で得られる行列Qはユニタリー行列でQTQ = QQT = I

を満たすが、非正方行列の場合は QQT は必ずしも単位行列になるとは限らない。計算方法は、グラム・シュミットの直交化により求めた、q1, q2, . . . , qn を列ベクトルにもつ行列 Qを作ると、

QTQ = I

を満たす。これから QTAを計算すると、

QTA = QTQR = R (6)

となり、Rが求められる。あるいは、Q と Aから、次のようにして行列 Rを構築する。

rjk =

(ak, qj), j < k

||ak −∑k−1

l=1 (ak, ql)ql|| = ||ak −∑k−1

l=1 rlkql||, j = k

0, j > k

(7)

で Rを計算する。

12.7.1 非正方行列のQR分解プログラム

1

2 // qr decomposition of rectangular matrix3 // assume n > m4

5

6 #include <stdio.h>7 #include <math.h>8

9 #define N 510 #define M 411

12 void gramm schmidt(double a[N][M], int n, int m, double q[N][M]);13 void qr decomposition(double a[N][M], int n, int m, double q[N][M], double r[M][M]);14 void show(char ∗msg, double ∗a, int n, int m);15

16 int17 main(int ac, char ∗av[])18 {19 double a[N][M] = {20 {5.0, 4.0, 3.0, 2.0},21 {4.0, 3.0, 2.0, 1.0}, {3.0, 2.0, 1.0, 1.0},22 {2.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0} };23 double q[N][M], r[M][M];24 int n = N, m = M;25

26 qr decomposition(a, n, m, q, r);27 show("a=", (double ∗) a, n, m);28 show("q=", (double ∗) q, n, m);29 show("r=", (double ∗) r, m, m);30 }31

32 void

Page 35: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 35

33 show(char ∗msg, double ∗a, int n, int m)34 {35 int i, j;36 printf("%s\n", msg);37 for (i = 0; i < n; i++) {38 for (j = 0; j < m; j++)39 printf("%10.7lf, ", ∗a++);40 printf("\n");41 }42 }43

44 void45 qr decomposition(double a[N][M], int n, int m, double q[N][M], double r[M][M])46 {47 int i, j, k, l;48 double s, p;49

50 gramm schmidt(a, n, m, q);51 for (k = 0; k < m; k++) {52 for (j = 0; j < k; j++) {53 s = 0;54 for (i = 0; i < n; i++)55 s = s + a[i][k] ∗ q[i][j]; // (a[k], q[j])56 r[j][k] = s;57 }58 s = 0;59 for (i = 0; i < n; i++) { // a[i] − r[l][k] q[l]60 p = a[i][k];61 for (l = 0; l < k; l++) {62 p = p − r[l][k] ∗ q[i][l];63 }64 s = s + p ∗ p;65 }66 s = sqrt(s);67 r[k][k] = s;68 for (j = k + 1; j < m; j++)69 r[j][k] = 0;70 }71 }72

73 void74 gramm schmidt(double a[N][M], int n, int m, double q[N][M])75 {76 int i, j, k;77 double s, b[M][N];78 for (i = 0; i < n; i++)79 for (j = 0; j < m; j++)80 b[j][i] = a[i][j];81 for (i = 0; i < m; i++) {82 s = 0;83 for (j = 0; j < n; j++)84 s = s + b[i][j] ∗ b[i][j]; // calculate (a[i], a[i])85 if (s != 0.0) {86 s = 1 / sqrt(s);87 for (j = 0; j < n; j++)88 b[i][j] = b[i][j] ∗ s; // normalize a[i]89 }90 for (k = i + 1; k < m; k++) {91 s = 0;92 for (j = 0; j < n; j++)93 s = s + b[k][j] ∗ b[i][j]; // calculate (a[i], a[k])

Page 36: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 36

94 for (j = 0; j < n; j++)95 b[k][j] = b[k][j] − s ∗ b[i][j]; // remove a[i]96 // component97 }98 }99 for (i = 0; i < n; i++)

100 for (j = 0; j < m; j++)101 q[i][j] = b[j][i];102 }

このプログラムで、

A =

3 −6

4 −8

0 1

の分解を計算した結果は次のようになる。

a=

3.00000, -6.00000,

4.00000, -8.00000,

0.00000, 1.00000,

qr decomposition

q=

0.60000, 0.00000,

0.80000, 0.00000,

0.00000, 1.00000,

r=

5.00000, -10.00000,

0.00000, 1.00000,

すなわち、

A =

3 −6

4 −8

0 1

=

0.6 0

0.8 0

0 1

( 5 −10

0 1

)

12.8 課題問題 12.1 次の対称行列

4 3 2 1

3 2 1 1

2 1 1 1

1 1 1 1

の固有値を求めよ。この行列の固有値は、p(λ) = λ4 − 8λ3 + 4λ2 + 3λ − 1 = 0 の解、で、λ1 = 7.40782, λ2 = 0.859429, λ3 =

0.284619, λ4 = −0.551869 となる。

1. ハウスホルダー法により、与えられた(対称)行列を三重対角行列に変換する。

2. 三重対角行列から固有値を決める特性方程式を計算する。

3. 特性方程式の解を全て求める。(対称行列なので、固有値は全て実数である。)

Page 37: 数値解析kako/teaching/na/chap12.pdf12. 行列の固有値 3 12.1.1 ヤコビ法 ヤコビ法は、A にB = P 1AP の変換を行う。 ここで、P は、Ppp = Pqq = cosϕP pq

12. 行列の固有値 37

方程式の解を全て求めるには、例えばニュートン法を使って一つの解 xiを求め、方程式を x− xiで割った方程式を組立除法等を使って計算し、得られた方程式の解を同じくニュートン法で求める。このようにして、方程式の次数を下げながら、解を求めて行くことにより、全解を求めることが出来る。

問題 12.2

A =

6 7 5 5 3

7 3 4 7 6

5 4 7 6 2

5 8 6 7 3

3 6 2 3 5

の QR分解を計算せよ。


Top Related