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