ベキ乗法を用いて行列の絶対値最大の固有値を求める。
以下は全2分木の隣接行列をベキ乗法で解くためのプログラム。Mは行列のサイズにより適宜書き直す必要あり。
全2分木ではnを3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383とした時のデータを取る。
#include <stdio.h>
#include <math.h>
#define M 383 //入力するnよりも大きくしておくこと
double a[M][M],x[M]={0},y[M];
int n;
void Beki(void);
void Throw(void);
int main(){
int i,j;
printf("行列の大きさ:"); scanf("%d", &n); //解きたい行列のサイズ
Throw(); //行列の要素を代入。
Beki(); //ベキ乗法のcode
return 0;
}
void Beki(void){
double s,xmax,t,b;
int i,j,imax,l,m,triger,number=1000;
x[0] = 1.0;
imax = 50000000; l = 0; xmax = 0.0; s = 0.0;
for(i=0;i<n;i++) s += x[i]*x[i];
for(i=0;i<n;i++) x[i] /= sqrt(s);
for(m=1;m<=imax;m++){
for(i=0;i<n;i++){
y[i] = 0.0;
for(j=0;j<n;j++) y[i] += a[i][j]*x[j];
}
s = 0.0;
for(i=0;i<n;i++) s += y[i]*y[i];
t = 0.0;
for(i=0;i<n;i++) t += y[i]*x[i];
b = s/t; l = m;
if(m >= number){
printf("xmax = %15.12f now = %d \n", xmax,m);
printf("continue ? yes--追加反復回数 no--1:"); //収束が悪ければ追加で反復
scanf("%d", &triger);
number += triger;
if(triger == 1) break;
}
xmax = b;
for(i=0;i<n;i++) x[i] = y[i]/sqrt(s);
}
imax = l;
printf("最大固有値 %15.12f \t 反復回数 %d\n",xmax,imax);
}
void Throw(void){
int i,j;
for(i=0;i<n;i++) a[i][i] = 1;
for(i=0;i<=2;i++){
a[0][i] = 1;
a[i][0] = 1;
}
j = 3;
for(i=1; i<n;i++){
a[i][j] = 1;
a[j][i] = 1;
j++;
a[i][j] = 1;
a[j][i] = 1;
if(j>=n) break;
j++;
}
}