| 情報学部 | 菅沼ホーム | 目次 | 索引 | 
/************************************************/
/* 実対称行列の固有値・固有ベクトル(ヤコビ法) */
/*      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
			
| 情報学部 | 菅沼ホーム | 目次 | 索引 |