<?php /****************************************/ /* 最大固有値と固有ベクトル(べき乗法) */ /* coded by Y.Suganuma */ /****************************************/ // データの設定 $ct = 200; $eps = 1.0e-10; $n = 3; $m = 15; $A = array($n); $B = array($n); $C = array($n); $v = array($n); for ($i1 = 0; $i1 < $n; $i1++) { $A[$i1] = array($n); $B[$i1] = array($n); $C[$i1] = array($n); $v[$i1] = array($n); } $r = array($n); $v0 = array($n); $v1 = array($n); $v2 = array($n); $A[0][0] = 11.0; $A[0][1] = 6.0; $A[0][2] = -2.0; $A[1][0] = -2.0; $A[1][1] = 18.0; $A[1][2] = 1.0; $A[2][0] = -12.0; $A[2][1] = 24.0; $A[2][2] = 13.0; for ($i1 = 0; $i1 < $n; $i1++) { for ($i2 = 0; $i2 < $n; $i2++) $B[$i1][$i2] = 0.0; $B[$i1][$i1] = 1.0; $v0[$i1] = 1.0; } // 計算 $ind = power(0, $n, $m, $ct, $eps, $A, $B, $C, $r, $v, $v0, $v1, $v2); // 出力 if ($ind == 0) printf("固有値が求まりませんでした!\n"); else { for ($i1 = 0; $i1 < $ind; $i1++) { printf("固有値 %f", $r[$i1]); printf(" 固有ベクトル "); for ($i2 = 0; $i2 < $n; $i2++) printf(" %f", $v[$i1][$i2]); printf("\n"); } } /****************************************/ /* 最大固有値と固有ベクトル(べき乗法) */ /* i : 何番目の固有値かを示す */ /* n : 次数 */ /* m : 丸め誤差の修正回数 */ /* ct : 最大繰り返し回数 */ /* eps : 収束判定条件 */ /* A : 対象とする行列 */ /* B : nxnの行列,最初は,単位行列 */ /* C : 作業域,nxnの行列 */ /* r : 固有値 */ /* v : 各行が固有ベクトル(nxn) */ /* v0 : 固有ベクトルの初期値 */ /* v1,v2 : 作業域(n次元ベクトル) */ /* return : 求まった固有値の数 */ /* coded by Y.Suganuma */ /****************************************/ function power($i, $n, $m, $ct, $eps, $A, $B, $C, &$r, &$v, $v0, $v1, $v2) { // 初期設定 $ind = $i; $k = 0; $l1 = 0.0; for ($i1 = 0; $i1 < $n; $i1++) { $l1 += $v0[$i1] * $v0[$i1]; $v1[$i1] = $v0[$i1]; } $l1 = sqrt($l1); // 繰り返し計算 while ($k < $ct) { // 丸め誤差の修正 if ($k%$m == 0) { $l2 = 0.0; for ($i1 = 0; $i1 < $n; $i1++) { $v2[$i1] = 0.0; for ($i2 = 0; $i2 < $n; $i2++) $v2[$i1] += $B[$i1][$i2] * $v1[$i2]; $l2 += $v2[$i1] * $v2[$i1]; } $l2 = sqrt($l2); for ($i1 = 0; $i1 < $n; $i1++) $v1[$i1] = $v2[$i1] / $l2; } // 次の近似 $l2 = 0.0; for ($i1 = 0; $i1 < $n; $i1++) { $v2[$i1] = 0.0; for ($i2 = 0; $i2 < $n; $i2++) $v2[$i1] += $A[$i1][$i2] * $v1[$i2]; $l2 += $v2[$i1] * $v2[$i1]; } $l2 = sqrt($l2); for ($i1 = 0; $i1 < $n; $i1++) $v2[$i1] /= $l2; // 収束判定 // 収束した場合 if (abs(($l2-$l1)/$l1) < $eps) { $k1 = -1; for ($i1 = 0; $i1 < $n && $k1 < 0; $i1++) { if (abs($v2[$i1]) > 0.001) { $k1 = $i1; if ($v2[$k1]*$v1[$k1] < 0.0) $l2 = -$l2; } } $k = $ct; $r[$i] = $l2; for ($i1 = 0; $i1 < $n; $i1++) $v[$i][$i1] = $v2[$i1]; if ($i == $n-1) $ind = $i + 1; else { for ($i1 = 0; $i1 < $n; $i1++) { for ($i2 = 0; $i2 < $n; $i2++) { $C[$i1][$i2] = 0.0; for ($i3 = 0; $i3 < $n; $i3++) { $x = ($i1 == $i3) ? $A[$i1][$i3] - $l2 : $A[$i1][$i3]; $C[$i1][$i2] += $x * $B[$i3][$i2]; } } } for ($i1 = 0; $i1 < $n; $i1++) { for ($i2 = 0; $i2 < $n; $i2++) $B[$i1][$i2] = $C[$i1][$i2]; } for ($i1 = 0; $i1 < $n; $i1++) { $v1[$i1] = 0.0; for ($i2 = 0; $i2 < $n; $i2++) $v1[$i1] += $B[$i1][$i2] * $v0[$i2]; } for ($i1 = 0; $i1 < $n; $i1++) $v0[$i1] = $v1[$i1]; $ind = power($i+1, $n, $m, $ct, $eps, $A, $B, $C, $r, $v, $v0, $v1, $v2); } } // 収束しない場合 else { for ($i1 = 0; $i1 < $n; $i1++) $v1[$i1] = $v2[$i1]; $l1 = $l2; $k++; } } return $ind; } ?>