情報学部 | 菅沼ホーム | 目次 | 索引 |
/************************************************/ /* 実対称行列の固有値・固有ベクトル(ヤコビ法) */ /* coded by Y.Suganuma */ /************************************************/ #include <stdio.h> int Jacobi(int, int, double, double **, double **, double **, double **, double **); int main() { double **A, **A1, **A2, **X1, **X2, eps; int i1, i2, ind, ct, n; // データの設定 ct = 1000; eps = 1.0e-10; n = 3; A = new double * [n]; A1 = new double * [n]; A2 = new double * [n]; X1 = new double * [n]; X2 = new double * [n]; for (i1 = 0; i1 < n; i1++) { A[i1] = new double [n]; A1[i1] = new double [n]; A2[i1] = new double [n]; X1[i1] = new double [n]; X2[i1] = new double [n]; } A[0][0] = 1.0; A[0][1] = 0.0; A[0][2] = -1.0; A[1][0] = 0.0; A[1][1] = 1.0; A[1][2] = -1.0; A[2][0] = -1.0; A[2][1] = -1.0; A[2][2] = 2.0; // 計算 ind = Jacobi(n, ct, eps, A, A1, A2, X1, X2); // 出力 if (ind > 0) printf("収束しませんでした!\n"); else { printf("固有値\n"); for (i1 = 0; i1 < n; i1++) printf(" %f", A1[i1][i1]); printf("\n固有ベクトル(各列が固有ベクトル)\n"); for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) printf(" %f", X1[i1][i2]); printf("\n"); } } for (i1 = 0; i1 < n; i1++) { delete [] A[i1]; delete [] A1[i1]; delete [] A2[i1]; delete [] X1[i1]; delete [] X2[i1]; } delete [] A; delete [] A1; delete [] A2; delete [] X1; delete [] X2; return 0; } /*************************************************************/ /* 実対称行列の固有値・固有ベクトル(ヤコビ法) */ /* n : 次数 */ /* ct : 最大繰り返し回数 */ /* eps : 収束判定条件 */ /* A : 対象とする行列 */ /* A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値 */ /* X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル */ /* return : =0 : 正常 */ /* =1 : 収束せず */ /* coded by Y.Suganuma */ /*************************************************************/ #include <math.h> int Jacobi(int n, int ct, double eps, double **A, double **A1, double **A2, double **X1, double **X2) { double max, s, t, v, sn, cs; int i1, i2, k = 0, ind = 1, p = 0, q = 0; // 初期設定 for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { A1[i1][i2] = A[i1][i2]; X1[i1][i2] = 0.0; } X1[i1][i1] = 1.0; } // 計算 while (ind > 0 && k < ct) { // 最大要素の探索 max = 0.0; for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { if (i2 != i1) { if (fabs(A1[i1][i2]) > max) { max = fabs(A1[i1][i2]); p = i1; q = i2; } } } } // 収束判定 // 収束した if (max < eps) ind = 0; // 収束しない else { // 準備 s = -A1[p][q]; t = 0.5 * (A1[p][p] - A1[q][q]); v = fabs(t) / sqrt(s * s + t * t); sn = sqrt(0.5 * (1.0 - v)); if (s*t < 0.0) sn = -sn; cs = sqrt(1.0 - sn * sn); // Akの計算 for (i1 = 0; i1 < n; i1++) { if (i1 == p) { for (i2 = 0; i2 < n; i2++) { if (i2 == p) A2[p][p] = A1[p][p] * cs * cs + A1[q][q] * sn * sn - 2.0 * A1[p][q] * sn * cs; else if (i2 == q) A2[p][q] = 0.0; else A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn; } } else if (i1 == q) { for (i2 = 0; i2 < n; i2++) { if (i2 == q) A2[q][q] = A1[p][p] * sn * sn + A1[q][q] * cs * cs + 2.0 * A1[p][q] * sn * cs; else if (i2 == p) A2[q][p] = 0.0; else A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn; } } else { for (i2 = 0; i2 < n; i2++) { if (i2 == p) A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn; else if (i2 == q) A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn; else A2[i1][i2] = A1[i1][i2]; } } } // Xkの計算 for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { if (i2 == p) X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn; else if (i2 == q) X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn; else X2[i1][i2] = X1[i1][i2]; } } // 次のステップへ k++; for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { A1[i1][i2] = A2[i1][i2]; X1[i1][i2] = X2[i1][i2]; } } } } return ind; }
/************************************************/ /* 実対称行列の固有値・固有ベクトル(ヤコビ法) */ /* coded by Y.Suganuma */ /************************************************/ import java.io.*; public class Test { public static void main(String args[]) throws IOException { double A[][], A1[][], A2[][], X1[][], X2[][], eps; int i1, i2, ind, ct, n; // データの設定 ct = 1000; eps = 1.0e-10; n = 3; A = new double [n][n]; A1 = new double [n][n]; A2 = new double [n][n]; X1 = new double [n][n]; X2 = new double [n][n]; A[0][0] = 1.0; A[0][1] = 0.0; A[0][2] = -1.0; A[1][0] = 0.0; A[1][1] = 1.0; A[1][2] = -1.0; A[2][0] = -1.0; A[2][1] = -1.0; A[2][2] = 2.0; // 計算 ind = Jacobi(n, ct, eps, A, A1, A2, X1, X2); // 出力 if (ind > 0) System.out.println("収束しませんでした!"); else { System.out.println("固有値"); for (i1 = 0; i1 < n; i1++) System.out.print(" " + A1[i1][i1]); System.out.println("\n固有ベクトル(各列が固有ベクトル)"); for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) System.out.print(" " + X1[i1][i2]); System.out.println(); } } } /*************************************************************/ /* 実対称行列の固有値・固有ベクトル(ヤコビ法) */ /* n : 次数 */ /* ct : 最大繰り返し回数 */ /* eps : 収束判定条件 */ /* A : 対象とする行列 */ /* A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値 */ /* X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル */ /* return : =0 : 正常 */ /* =1 : 収束せず */ /* coded by Y.Suganuma */ /*************************************************************/ static int Jacobi(int n, int ct, double eps, double A[][], double A1[][], double A2[][], double X1[][], double X2[][]) { double max, s, t, v, sn, cs; int i1, i2, k = 0, ind = 1, p = 0, q = 0; // 初期設定 for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { A1[i1][i2] = A[i1][i2]; X1[i1][i2] = 0.0; } X1[i1][i1] = 1.0; } // 計算 while (ind > 0 && k < ct) { // 最大要素の探索 max = 0.0; for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { if (i2 != i1) { if (Math.abs(A1[i1][i2]) > max) { max = Math.abs(A1[i1][i2]); p = i1; q = i2; } } } } // 収束判定 // 収束した if (max < eps) ind = 0; // 収束しない else { // 準備 s = -A1[p][q]; t = 0.5 * (A1[p][p] - A1[q][q]); v = Math.abs(t) / Math.sqrt(s * s + t * t); sn = Math.sqrt(0.5 * (1.0 - v)); if (s*t < 0.0) sn = -sn; cs = Math.sqrt(1.0 - sn * sn); // Akの計算 for (i1 = 0; i1 < n; i1++) { if (i1 == p) { for (i2 = 0; i2 < n; i2++) { if (i2 == p) A2[p][p] = A1[p][p] * cs * cs + A1[q][q] * sn * sn - 2.0 * A1[p][q] * sn * cs; else if (i2 == q) A2[p][q] = 0.0; else A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn; } } else if (i1 == q) { for (i2 = 0; i2 < n; i2++) { if (i2 == q) A2[q][q] = A1[p][p] * sn * sn + A1[q][q] * cs * cs + 2.0 * A1[p][q] * sn * cs; else if (i2 == p) A2[q][p] = 0.0; else A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn; } } else { for (i2 = 0; i2 < n; i2++) { if (i2 == p) A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn; else if (i2 == q) A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn; else A2[i1][i2] = A1[i1][i2]; } } } // Xkの計算 for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { if (i2 == p) X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn; else if (i2 == q) X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn; else X2[i1][i2] = X1[i1][i2]; } } // 次のステップへ k++; for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { A1[i1][i2] = A2[i1][i2]; X1[i1][i2] = X2[i1][i2]; } } } } return ind; } }
<!DOCTYPE HTML> <HTML> <HEAD> <TITLE>実対称行列の固有値・固有ベクトル(ヤコビ法)</TITLE> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8"> <SCRIPT TYPE="text/javascript"> function main() { // データの設定 let eps = 1.0e-10; let ct = parseInt(document.getElementById("trial").value); let n = parseInt(document.getElementById("order").value); let A = new Array(); for (let i1 = 0; i1 < n; i1++) A[i1] = new Array(); let s = (document.getElementById("ar").value).split(/ {1,}|\n{1,}/); let k = 0; for (let i1 = 0; i1 < n; i1++) { for (let i2 = 0; i2 < n; i2++) { A[i1][i2] = parseFloat(s[k]); k++; } } let A1 = new Array(); for (let i1 = 0; i1 < n; i1++) A1[i1] = new Array(); let A2 = new Array(); for (let i1 = 0; i1 < n; i1++) A2[i1] = new Array(); let X1 = new Array(); for (let i1 = 0; i1 < n; i1++) X1[i1] = new Array(); let X2 = new Array(); for (let i1 = 0; i1 < n; i1++) X2[i1] = new Array(); ind = jacobi(n, ct, eps, A, A1, A2, X1, X2); // 出力 if (ind > 0) document.getElementById("ans").value = "解を求めることができません!"; else { let str = "固有値:\n"; for (let i1 = 0; i1 < n; i1++) { if (i1 == n-1) str = str + A1[i1][i1] + "\n"; else str = str + A1[i1][i1] + " "; } str = str + "固有ベクトル:\n"; for (let i1 = 0; i1 < n; i1++) { str = str + " "; for (let i2 = 0; i2 < n; i2++) { if (i2 == n-1) str = str + X1[i1][i2] + "\n"; else str = str + X1[i1][i2] + " "; } } document.getElementById("ans").value = str; } } /*************************************************************/ /* 実対称行列の固有値・固有ベクトル(ヤコビ法) */ /* n : 次数 */ /* ct : 最大繰り返し回数 */ /* eps : 収束判定条件 */ /* A : 対象とする行列 */ /* A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値 */ /* X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル */ /* return : =0 : 正常 */ /* =1 : 収束せず */ /* coded by Y.Suganuma */ /*************************************************************/ function jacobi(n, ct, eps, A, A1, A2, X1, X2) { let max; let s; let t; let v; let sn; let cs; let i1; let i2; let k = 0; let ind = 1; let p = 0; let q = 0; // 初期設定 for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { A1[i1][i2] = A[i1][i2]; X1[i1][i2] = 0.0; } X1[i1][i1] = 1.0; } // 計算 while (ind > 0 && k < ct) { // 最大要素の探索 max = 0.0; for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { if (i2 != i1) { if (Math.abs(A1[i1][i2]) > max) { max = Math.abs(A1[i1][i2]); p = i1; q = i2; } } } } // 収束判定 // 収束した if (max < eps) ind = 0; // 収束しない else { // 準備 s = -A1[p][q]; t = 0.5 * (A1[p][p] - A1[q][q]); v = Math.abs(t) / Math.sqrt(s * s + t * t); sn = Math.sqrt(0.5 * (1.0 - v)); if (s*t < 0.0) sn = -sn; cs = Math.sqrt(1.0 - sn * sn); // Akの計算 for (i1 = 0; i1 < n; i1++) { if (i1 == p) { for (i2 = 0; i2 < n; i2++) { if (i2 == p) A2[p][p] = A1[p][p] * cs * cs + A1[q][q] * sn * sn - 2.0 * A1[p][q] * sn * cs; else if (i2 == q) A2[p][q] = 0.0; else A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn; } } else if (i1 == q) { for (i2 = 0; i2 < n; i2++) { if (i2 == q) A2[q][q] = A1[p][p] * sn * sn + A1[q][q] * cs * cs + 2.0 * A1[p][q] * sn * cs; else if (i2 == p) A2[q][p] = 0.0; else A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn; } } else { for (i2 = 0; i2 < n; i2++) { if (i2 == p) A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn; else if (i2 == q) A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn; else A2[i1][i2] = A1[i1][i2]; } } } // Xkの計算 for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { if (i2 == p) X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn; else if (i2 == q) X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn; else X2[i1][i2] = X1[i1][i2]; } } // 次のステップへ k++; for (i1 = 0; i1 < n; i1++) { for (i2 = 0; i2 < n; i2++) { A1[i1][i2] = A2[i1][i2]; X1[i1][i2] = X2[i1][i2]; } } } } return ind; } </SCRIPT> </HEAD> <BODY STYLE="font-size: 130%; background-color: #eeffee;"> <H2 STYLE="text-align:center"><B>実対称行列の固有値・固有ベクトル(ヤコビ法)</B></H2> <DL> <DT> テキストフィールドおよびテキストエリアには,例として,以下に示す行列の固有値及び固有ベクトル(固有ベクトルは,正規化された列ベクトルとして表示)を求める場合に対する値が設定されています.他の問題を実行する場合は,それらを適切に修正してください. <P STYLE="text-align:center"><IMG SRC="jacobi.gif"></P> </DL> <DIV STYLE="text-align:center"> 次数:<INPUT ID="order" STYLE="font-size: 100%" TYPE="text" SIZE="2" VALUE="3"> 最大繰り返し回数:<INPUT ID="trial" STYLE="font-size: 100%;" TYPE="text" SIZE="4" VALUE="1000"> <BUTTON STYLE="font-size: 100%; background-color: pink" onClick="main()">OK</BUTTON><BR><BR> <TEXTAREA ID="ar" COLS="50" ROWS="15" STYLE="font-size: 100%">1 0 -1 0 1 -1 -1 -1 2</TEXTAREA><BR><BR> <TEXTAREA ID="ans" COLS="60" ROWS="15" STYLE="font-size: 100%"></TEXTAREA> </DIV> </BODY> </HTML>
<?php /************************************************/ /* 実対称行列の固有値・固有ベクトル(ヤコビ法) */ /* coded by Y.Suganuma */ /************************************************/ // データの設定 $ct = 1000; $eps = 1.0e-10; $n = 3; $A = array($n); $A1 = array($n); $A2 = array($n); $X1 = array($n); $X2 = array($n); for ($i1 = 0; $i1 < $n; $i1++) { $A[$i1] = array($n); $A1[$i1] = array($n); $A2[$i1] = array($n); $X1[$i1] = array($n); $X2[$i1] = array($n); } $A[0][0] = 1.0; $A[0][1] = 0.0; $A[0][2] = -1.0; $A[1][0] = 0.0; $A[1][1] = 1.0; $A[1][2] = -1.0; $A[2][0] = -1.0; $A[2][1] = -1.0; $A[2][2] = 2.0; // 計算 $ind = Jacobi($n, $ct, $eps, $A, $A1, $A2, $X1, $X2); // 出力 if ($ind > 0) printf("収束しませんでした!\n"); else { printf("固有値\n"); for ($i1 = 0; $i1 < $n; $i1++) printf(" %f", $A1[$i1][$i1]); printf("\n固有ベクトル(各列が固有ベクトル)\n"); for ($i1 = 0; $i1 < $n; $i1++) { for ($i2 = 0; $i2 < $n; $i2++) printf(" %f", $X1[$i1][$i2]); printf("\n"); } } /*************************************************************/ /* 実対称行列の固有値・固有ベクトル(ヤコビ法) */ /* n : 次数 */ /* ct : 最大繰り返し回数 */ /* eps : 収束判定条件 */ /* A : 対象とする行列 */ /* A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値 */ /* X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル */ /* return : =0 : 正常 */ /* =1 : 収束せず */ /* coded by Y.Suganuma */ /*************************************************************/ function Jacobi($n, $ct, $eps, $A, &$A1, $A2, &$X1, $X2) { // 初期設定 $k = 0; $ind = 1; $p = 0; $q = 0; for ($i1 = 0; $i1 < $n; $i1++) { for ($i2 = 0; $i2 < $n; $i2++) { $A1[$i1][$i2] = $A[$i1][$i2]; $X1[$i1][$i2] = 0.0; } $X1[$i1][$i1] = 1.0; } // 計算 while ($ind > 0 && $k < $ct) { // 最大要素の探索 $max = 0.0; for ($i1 = 0; $i1 < $n; $i1++) { for ($i2 = 0; $i2 < $n; $i2++) { if ($i2 != $i1) { if (abs($A1[$i1][$i2]) > $max) { $max = abs($A1[$i1][$i2]); $p = $i1; $q = $i2; } } } } // 収束判定 // 収束した if ($max < $eps) $ind = 0; // 収束しない else { // 準備 $s = -$A1[$p][$q]; $t = 0.5 * ($A1[$p][$p] - $A1[$q][$q]); $v = abs($t) / sqrt($s * $s + $t * $t); $sn = sqrt(0.5 * (1.0 - $v)); if ($s*$t < 0.0) $sn = -$sn; $cs = sqrt(1.0 - $sn * $sn); // Akの計算 for ($i1 = 0; $i1 < $n; $i1++) { if ($i1 == $p) { for ($i2 = 0; $i2 < $n; $i2++) { if ($i2 == $p) $A2[$p][$p] = $A1[$p][$p] * $cs * $cs + $A1[$q][$q] * $sn * $sn - 2.0 * $A1[$p][$q] * $sn * $cs; else if ($i2 == $q) $A2[$p][$q] = 0.0; else $A2[$p][$i2] = $A1[$p][$i2] * $cs - $A1[$q][$i2] * $sn; } } else if ($i1 == $q) { for ($i2 = 0; $i2 < $n; $i2++) { if ($i2 == $q) $A2[$q][$q] = $A1[$p][$p] * $sn * $sn + $A1[$q][$q] * $cs * $cs + 2.0 * $A1[$p][$q] * $sn * $cs; else if ($i2 == $p) $A2[$q][$p] = 0.0; else $A2[$q][$i2] = $A1[$q][$i2] * $cs + $A1[$p][$i2] * $sn; } } else { for ($i2 = 0; $i2 < $n; $i2++) { if ($i2 == $p) $A2[$i1][$p] = $A1[$i1][$p] * $cs - $A1[$i1][$q] * $sn; else if ($i2 == $q) $A2[$i1][$q] = $A1[$i1][$q] * $cs + $A1[$i1][$p] * $sn; else $A2[$i1][$i2] = $A1[$i1][$i2]; } } } // Xkの計算 for ($i1 = 0; $i1 < $n; $i1++) { for ($i2 = 0; $i2 < $n; $i2++) { if ($i2 == $p) $X2[$i1][$p] = $X1[$i1][$p] * $cs - $X1[$i1][$q] * $sn; else if ($i2 == $q) $X2[$i1][$q] = $X1[$i1][$q] * $cs + $X1[$i1][$p] * $sn; else $X2[$i1][$i2] = $X1[$i1][$i2]; } } // 次のステップへ $k++; for ($i1 = 0; $i1 < $n; $i1++) { for ($i2 = 0; $i2 < $n; $i2++) { $A1[$i1][$i2] = $A2[$i1][$i2]; $X1[$i1][$i2] = $X2[$i1][$i2]; } } } } return $ind; } ?>
#***********************************************/ # 実対称行列の固有値・固有ベクトル(ヤコビ法) */ # coded by Y.Suganuma */ #***********************************************/ #************************************************************/ # 実対称行列の固有値・固有ベクトル(ヤコビ法) */ # n : 次数 */ # ct : 最大繰り返し回数 */ # eps : 収束判定条件 */ # a : 対象とする行列 */ # a1, a2 : 作業域(nxnの行列),a1の対角要素が固有値 */ # x1, x2 : 作業域(nxnの行列),x1の各列が固有ベクトル */ # return : =0 : 正常 */ # =1 : 収束せず */ # coded by Y.Suganuma */ #************************************************************/ def Jacobi(n, ct, eps, a, a1, a2, x1, x2) # 初期設定 k = 0 ind = 1 p = 0 q = 0 for i1 in 0 ... n for i2 in 0 ... n a1[i1][i2] = a[i1][i2] x1[i1][i2] = 0.0 end x1[i1][i1] = 1.0 end # 計算 while ind > 0 && k < ct # 最大要素の探索 max = 0.0 for i1 in 0 ... n for i2 in 0 ... n if i2 != i1 if a1[i1][i2].abs() > max max = a1[i1][i2].abs() p = i1 q = i2 end end end end # 収束判定 # 収束した if max < eps ind = 0 # 収束しない else # 準備 s = -a1[p][q] t = 0.5 * (a1[p][p] - a1[q][q]) v = t.abs() / Math.sqrt(s * s + t * t) sn = Math.sqrt(0.5 * (1.0 - v)) if s*t < 0.0 sn = -sn end cs = Math.sqrt(1.0 - sn * sn) # akの計算 for i1 in 0 ... n if i1 == p for i2 in 0 ... n if i2 == p a2[p][p] = a1[p][p] * cs * cs + a1[q][q] * sn * sn - 2.0 * a1[p][q] * sn * cs elsif i2 == q a2[p][q] = 0.0 else a2[p][i2] = a1[p][i2] * cs - a1[q][i2] * sn end end elsif i1 == q for i2 in 0 ... n if (i2 == q) a2[q][q] = a1[p][p] * sn * sn + a1[q][q] * cs * cs + 2.0 * a1[p][q] * sn * cs elsif i2 == p a2[q][p] = 0.0 else a2[q][i2] = a1[q][i2] * cs + a1[p][i2] * sn end end else for i2 in 0 ... n if i2 == p a2[i1][p] = a1[i1][p] * cs - a1[i1][q] * sn elsif i2 == q a2[i1][q] = a1[i1][q] * cs + a1[i1][p] * sn else a2[i1][i2] = a1[i1][i2] end end end end # xkの計算 for i1 in 0 ... n for i2 in 0 ... n if i2 == p x2[i1][p] = x1[i1][p] * cs - x1[i1][q] * sn elsif i2 == q x2[i1][q] = x1[i1][q] * cs + x1[i1][p] * sn else x2[i1][i2] = x1[i1][i2] end end end # 次のステップへ k += 1 for i1 in 0 ... n for i2 in 0 ... n a1[i1][i2] = a2[i1][i2] x1[i1][i2] = x2[i1][i2] end end end end return ind end # データの設定 ct = 1000 eps = 1.0e-10 n = 3 a = Array.new(n) a1 = Array.new(n) a2 = Array.new(n) x1 = Array.new(n) x2 = Array.new(n) for i1 in 0 ... n a[i1] = Array.new(n) a1[i1] = Array.new(n) a2[i1] = Array.new(n) x1[i1] = Array.new(n) x2[i1] = Array.new(n) end a[0][0] = 1.0 a[0][1] = 0.0 a[0][2] = -1.0 a[1][0] = 0.0 a[1][1] = 1.0 a[1][2] = -1.0 a[2][0] = -1.0 a[2][1] = -1.0 a[2][2] = 2.0 # 計算 ind = Jacobi(n, ct, eps, a, a1, a2, x1, x2) # 出力 if ind > 0 printf("収束しませんでした!\n") else printf("固有値\n") for i1 in 0 ... n printf(" %f", a1[i1][i1]) end printf("\n固有ベクトル(各列が固有ベクトル)\n") for i1 in 0 ... n for i2 in 0 ... n printf(" %f", x1[i1][i2]) end printf("\n") end end
# -*- coding: UTF-8 -*- import numpy as np from math import * ############################################ # 実対称行列の固有値・固有ベクトル(ヤコビ法) # n : 次数 # ct : 最大繰り返し回数 # eps : 収束判定条件 # A : 対象とする行列 # A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値 # X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル # return : =0 : 正常 # =1 : 収束せず # coded by Y.Suganuma ############################################ def Jacobi(n, ct, eps, A, A1, A2, X1, X2) : # 初期設定 k = 0 ind = 1 p = 0 q = 0 for i1 in range(0, n) : for i2 in range(0, n) : A1[i1][i2] = A[i1][i2] X1[i1][i2] = 0.0 X1[i1][i1] = 1.0 # 計算 while ind > 0 and k < ct : # 最大要素の探索 max = 0.0 for i1 in range(0, n) : for i2 in range(0, n) : if i2 != i1 : if abs(A1[i1][i2]) > max : max = fabs(A1[i1][i2]) p = i1 q = i2 # 収束判定 # 収束した if max < eps : ind = 0 # 収束しない else : # 準備 s = -A1[p][q] t = 0.5 * (A1[p][p] - A1[q][q]) v = fabs(t) / sqrt(s * s + t * t) sn = sqrt(0.5 * (1.0 - v)) if s*t < 0.0 : sn = -sn cs = sqrt(1.0 - sn * sn) # Akの計算 for i1 in range(0, n) : if i1 == p : for i2 in range(0, n) : if i2 == p : A2[p][p] = A1[p][p] * cs * cs + A1[q][q] * sn * sn - 2.0 * A1[p][q] * sn * cs elif i2 == q : A2[p][q] = 0.0 else : A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn elif i1 == q : for i2 in range(0, n) : if i2 == q : A2[q][q] = A1[p][p] * sn * sn + A1[q][q] * cs * cs + 2.0 * A1[p][q] * sn * cs elif i2 == p : A2[q][p] = 0.0 else : A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn else : for i2 in range(0, n) : if i2 == p : A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn elif i2 == q : A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn else : A2[i1][i2] = A1[i1][i2] # Xkの計算 for i1 in range(0, n) : for i2 in range(0, n) : if i2 == p : X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn elif i2 == q : X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn else : X2[i1][i2] = X1[i1][i2] # 次のステップへ k += 1 for i1 in range(0, n) : for i2 in range(0, n) : A1[i1][i2] = A2[i1][i2] X1[i1][i2] = X2[i1][i2] return ind ############################################ # 実対称行列の固有値・固有ベクトル(ヤコビ法) # coded by Y.Suganuma ############################################ # データの設定 ct = 1000 eps = 1.0e-10 n = 3 A = np.array([[1, 0, -1],[0, 1, -1],[-1, -1, 2]], np.float) A1 = np.empty((n, n), np.float) A2 = np.empty((n, n), np.float) X1 = np.empty((n, n), np.float) X2 = np.empty((n, n), np.float) # 計算 ind = Jacobi(n, ct, eps, A, A1, A2, X1, X2) # 出力 if ind > 0 : print("収束しませんでした!") else : print("固有値") print(" ", A1[0][0], A1[1][1], A1[2][2]) print("固有ベクトル(各列が固有ベクトル)") for i1 in range(0, n) : for i2 in range(0, n) : print(" " + str(X1[i1][i2]), end="") print()
/************************************************/ /* 実対称行列の固有値・固有ベクトル(ヤコビ法) */ /* coded by Y.Suganuma */ /************************************************/ using System; class Program { static void Main() { Test1 ts = new Test1(); } } class Test1 { public Test1() { // データの設定 int ct = 1000; int n = 3; double eps = 1.0e-10; double[][] A = new double [][] { new double[] {1.0, 0.0, -1.0}, new double[] {0.0, 1.0, -1.0}, new double[] {-1.0, -1.0, 2.0} }; double[][] A1 = new double [n][]; double[][] A2 = new double [n][]; double[][] X1 = new double [n][]; double[][] X2 = new double [n][]; for (int i1 = 0; i1 < n; i1++) { A1[i1] = new double [n]; A2[i1] = new double [n]; X1[i1] = new double [n]; X2[i1] = new double [n]; } // 計算 int ind = Jacobi(n, ct, eps, A, A1, A2, X1, X2); // 出力 if (ind > 0) Console.WriteLine("収束しませんでした!"); else { Console.WriteLine("固有値"); for (int i1 = 0; i1 < n; i1++) Console.Write(" " + A1[i1][i1]); Console.WriteLine(); Console.WriteLine("固有ベクトル(各列が固有ベクトル)"); for (int i1 = 0; i1 < n; i1++) { for (int i2 = 0; i2 < n; i2++) Console.Write(" " + X1[i1][i2]); Console.WriteLine(); } } } /*************************************************************/ /* 実対称行列の固有値・固有ベクトル(ヤコビ法) */ /* n : 次数 */ /* ct : 最大繰り返し回数 */ /* eps : 収束判定条件 */ /* A : 対象とする行列 */ /* A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値 */ /* X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル */ /* return : =0 : 正常 */ /* =1 : 収束せず */ /* coded by Y.Suganuma */ /*************************************************************/ int Jacobi(int n, int ct, double eps, double[][] A, double[][] A1, double[][] A2, double[][] X1, double[][] X2) { // 初期設定 for (int i1 = 0; i1 < n; i1++) { for (int i2 = 0; i2 < n; i2++) { A1[i1][i2] = A[i1][i2]; X1[i1][i2] = 0.0; } X1[i1][i1] = 1.0; } // 計算 int k = 0, ind = 1; while (ind > 0 && k < ct) { // 最大要素の探索 double max = 0.0; int p = 0, q = 0; for (int i1 = 0; i1 < n; i1++) { for (int i2 = 0; i2 < n; i2++) { if (i2 != i1) { if (Math.Abs(A1[i1][i2]) > max) { max = Math.Abs(A1[i1][i2]); p = i1; q = i2; } } } } // 収束判定 // 収束した if (max < eps) ind = 0; // 収束しない else { // 準備 double s = -A1[p][q]; double t = 0.5 * (A1[p][p] - A1[q][q]); double v = Math.Abs(t) / Math.Sqrt(s * s + t * t); double sn = Math.Sqrt(0.5 * (1.0 - v)); if (s*t < 0.0) sn = -sn; double cs = Math.Sqrt(1.0 - sn * sn); // Akの計算 for (int i1 = 0; i1 < n; i1++) { if (i1 == p) { for (int i2 = 0; i2 < n; i2++) { if (i2 == p) A2[p][p] = A1[p][p] * cs * cs + A1[q][q] * sn * sn - 2.0 * A1[p][q] * sn * cs; else if (i2 == q) A2[p][q] = 0.0; else A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn; } } else if (i1 == q) { for (int i2 = 0; i2 < n; i2++) { if (i2 == q) A2[q][q] = A1[p][p] * sn * sn + A1[q][q] * cs * cs + 2.0 * A1[p][q] * sn * cs; else if (i2 == p) A2[q][p] = 0.0; else A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn; } } else { for (int i2 = 0; i2 < n; i2++) { if (i2 == p) A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn; else if (i2 == q) A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn; else A2[i1][i2] = A1[i1][i2]; } } } // Xkの計算 for (int i1 = 0; i1 < n; i1++) { for (int i2 = 0; i2 < n; i2++) { if (i2 == p) X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn; else if (i2 == q) X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn; else X2[i1][i2] = X1[i1][i2]; } } // 次のステップへ k++; for (int i1 = 0; i1 < n; i1++) { for (int i2 = 0; i2 < n; i2++) { A1[i1][i2] = A2[i1][i2]; X1[i1][i2] = X2[i1][i2]; } } } } return ind; } }
'''''''''''''''''''''''''''''''''''''''''''''''' ' 実対称行列の固有値・固有ベクトル(ヤコビ法) ' ' coded by Y.Suganuma ' '''''''''''''''''''''''''''''''''''''''''''''''' Module Test Sub Main() ' データの設定 Dim ct As Integer = 1000 Dim n As Integer = 3 Dim eps As Double = 1.0e-10 Dim A(,) As Double = {{1.0, 0.0, -1.0}, {0.0, 1.0, -1.0}, {-1.0, -1.0, 2.0}} Dim A1(n,n) As Double Dim A2(n,n) As Double Dim X1(n,n) As Double Dim X2(n,n) As Double ' 計算 Dim ind As Integer = Jacobi(n, ct, eps, A, A1, A2, X1, X2) ' 出力 If ind > 0 Console.WriteLine("収束しませんでした!") Else Console.WriteLine("固有値") For i1 As Integer = 0 To n-1 Console.Write(" " & A1(i1,i1)) Next Console.WriteLine() Console.WriteLine("固有ベクトル(各列が固有ベクトル)") For i1 As Integer = 0 To n-1 For i2 As Integer = 0 To n-1 Console.Write(" " & X1(i1,i2)) Next Console.WriteLine() Next End If End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' 実対称行列の固有値・固有ベクトル(ヤコビ法) ' ' n : 次数 ' ' ct : 最大繰り返し回数 ' ' eps : 収束判定条件 ' ' A : 対象とする行列 ' ' A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値 ' ' X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル ' ' return : =0 : 正常 ' ' =1 : 収束せず ' ' coded by Y.Suganuma ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Function Jacobi(n As Integer, ct As Integer, eps As Double, A(,) As Double, A1(,) As Double, A2(,) As Double, X1(,) As Double, X2(,) As Double) ' 初期設定 For i1 As Integer = 0 To n-1 For i2 As Integer = 0 To n-1 A1(i1,i2) = A(i1,i2) X1(i1,i2) = 0.0 Next X1(i1,i1) = 1.0 Next ' 計算 Dim k As Integer = 0 Dim ind As Integer = 1 Do While ind > 0 and k < ct ' 最大要素の探索 Dim max As Double = 0.0 Dim p As Integer = 0 Dim q As Integer = 0 For i1 As Integer = 0 To n-1 For i2 As Integer = 0 To n-1 If i2 <> i1 If Math.Abs(A1(i1,i2)) > max max = Math.Abs(A1(i1,i2)) p = i1 q = i2 End If End If Next Next ' 収束判定 ' 収束した If max < eps ind = 0 ' 収束しない Else ' 準備 Dim s As Double = -A1(p,q) Dim t As Double = 0.5 * (A1(p,p) - A1(q,q)) Dim v As Double = Math.Abs(t) / Math.Sqrt(s * s + t * t) Dim sn As Double = Math.Sqrt(0.5 * (1.0 - v)) If s*t < 0.0 sn = -sn End If Dim cs As Double = Math.Sqrt(1.0 - sn * sn) ' Akの計算 For i1 As Integer = 0 To n-1 If i1 = p For i2 As Integer = 0 To n-1 If i2 = p A2(p,p) = A1(p,p) * cs * cs + A1(q,q) * sn * sn - 2.0 * A1(p,q) * sn * cs ElseIf i2 = q A2(p,q) = 0.0 Else A2(p,i2) = A1(p,i2) * cs - A1(q,i2) * sn End If Next ElseIf i1 = q For i2 As Integer = 0 To n-1 If i2 = q A2(q,q) = A1(p,p) * sn * sn + A1(q,q) * cs * cs + 2.0 * A1(p,q) * sn * cs ElseIf i2 = p A2(q,p) = 0.0 Else A2(q,i2) = A1(q,i2) * cs + A1(p,i2) * sn End If Next Else For i2 As Integer = 0 To n-1 If i2 = p A2(i1,p) = A1(i1,p) * cs - A1(i1,q) * sn ElseIf i2 = q A2(i1,q) = A1(i1,q) * cs + A1(i1,p) * sn Else A2(i1,i2) = A1(i1,i2) End If Next End If Next ' Xkの計算 For i1 As Integer = 0 To n-1 For i2 As Integer = 0 To n-1 If i2 = p X2(i1,p) = X1(i1,p) * cs - X1(i1,q) * sn ElseIf i2 = q X2(i1,q) = X1(i1,q) * cs + X1(i1,p) * sn Else X2(i1,i2) = X1(i1,i2) End If Next Next ' 次のステップへ k += 1 For i1 As Integer = 0 To n-1 For i2 As Integer = 0 To n-1 A1(i1,i2) = A2(i1,i2) X1(i1,i2) = X2(i1,i2) Next Next End If Loop Return ind End Function End Module
情報学部 | 菅沼ホーム | 目次 | 索引 |