「プログラムソース」 4−1、------------------------------------------------------------- #include #include #define N 2 /* ここの数字をかえる事で行列数を変更できる、今は2×2 */ int main(){ int t, i, k; int gyou, retu; double r, r1, r2, kaihi_r; double A[N][N]; double x[N], kaihi_x[N]; for(gyou=0;gyou #include #include #define N 2 /* ここの数字をかえる事で行列数を変更できる、今は2×2 */ double kannsuu1(double []); double kannsuu2(double [],double []); int main() { double a[N][N],b[N][N],q[N][N],r[N][N]; double koyuu[N][N],koyuu_kaihi[N][N]; double cr; int gyou,retu; int h=0; int k,m,p; printf("QR法により、固有値を求めます。\n"); printf("2×2の対称行列を入力して下さい。\n"); for(gyou=0;gyouruijyouhou_t 1行1列を入力して下さい。 1 1行2列を入力して下さい。 2 2行1列を入力して下さい。 3 2行2列を入力して下さい。 1 入力した行列は以下です。 1.000000 2.000000  3.000000 1.000000  累乗法により固有値を求めます。 r=3.5 r=3.4 r=3.46552 r=3.44189 r=3.45253 r=3.44819 r=3.45003 r=3.44926 r=3.44959 r=3.44945 r=3.44951 r=3.44948 r=3.44949 r=3.44949 固有値=3.44949 --------------------------------------------------------------------------- 2−2(ループは実際のソースは100回していますが、それだとメールに実行結果を記述できないので、対角化が完了する20回程度で実行結果を出力しておきました。) C:\Documents and Settings\i865gpen4\My Documents\プログラムソース>qrhou_t QR法により、固有値を求めます。 2×2の対称行列を入力して下さい。 1行1列を入力して下さい。 1 1行2列を入力して下さい。 2 2行1列を入力して下さい。 2 2行2列を入力して下さい。 1 入力した行列は以下です。 1.000000 2.000000  2.000000 1.000000  ベクトルA 2.600000 1.200000  1.200000 -0.600000  固有ベクトル 0.447214 0.894427  0.894427 -0.447214  ベクトルA 2.951220 0.439024  0.439024 -0.951220  固有ベクトル 0.780869 -0.624695  0.624695 0.780869  ベクトルA 2.994521 0.147945  0.147945 -0.994521  固有ベクトル 0.680451 0.732793  0.732793 -0.680451  ベクトルA 2.999390 0.049375  0.049375 -0.999390  固有ベクトル 0.715782 -0.698324  0.698324 0.715782  ベクトルA 2.999932 0.016461  0.016461 -0.999932  固有ベクトル 0.704191 0.710011  0.710011 -0.704191  ベクトルA 2.999992 0.005487  0.005487 -0.999992  固有ベクトル 0.708076 -0.706136  0.706136 0.708076  ベクトルA 2.999999 0.001829  0.001829 -0.999999  固有ベクトル 0.706783 0.707430  0.707430 -0.706783  ベクトルA 3.000000 0.000610  0.000610 -1.000000  固有ベクトル 0.707215 -0.706999  0.706999 0.707215  ベクトルA 3.000000 0.000203  0.000203 -1.000000  固有ベクトル 0.707071 0.707143  0.707143 -0.707071  ベクトルA 3.000000 0.000068  0.000068 -1.000000  固有ベクトル 0.707119 -0.707095  0.707095 0.707119  ベクトルA 3.000000 0.000023  0.000023 -1.000000  固有ベクトル 0.707103 0.707111  0.707111 -0.707103  ベクトルA 3.000000 0.000008  0.000008 -1.000000  固有ベクトル 0.707108 -0.707105  0.707105 0.707108  ベクトルA 3.000000 0.000003  0.000003 -1.000000  固有ベクトル 0.707106 0.707107  0.707107 -0.707106  ベクトルA 3.000000 0.000001  0.000001 -1.000000  固有ベクトル 0.707107 -0.707107  0.707107 0.707107  ベクトルA 3.000000 0.000000  0.000000 -1.000000  固有ベクトル 0.707107 0.707107  0.707107 -0.707107  ベクトルA 3.000000 0.000000  0.000000 -1.000000  固有ベクトル 0.707107 -0.707107  0.707107 0.707107  ベクトルA 3.000000 0.000000  0.000000 -1.000000  固有ベクトル 0.707107 0.707107  0.707107 -0.707107  ベクトルA 3.000000 0.000000  0.000000 -1.000000  固有ベクトル 0.707107 -0.707107  0.707107 0.707107  ベクトルA 3.000000 0.000000  0.000000 -1.000000  固有ベクトル 0.707107 0.707107  0.707107 -0.707107  ベクトルA 3.000000 0.000000  0.000000 -1.000000  固有ベクトル 0.707107 -0.707107  0.707107 0.707107  QR法最終結果(ループ回数20回) ベクトルA 3.000000 0.000000  0.000000 -1.000000  固有ベクトル 0.707107 -0.707107  0.707107 0.707107  -------------------------------------------------------------------------------- 「考察」 問題2の検討 累乗法は絶対最大固有値と、その次に絶対値の大きな固有値との関係で、大きく収束状況が影響される。 また、QR法に関しては今回きっちりと固有値を出力するところまでは至らなかったが、実際にもっと完成度の高いプログラムだと、ループ回数は良好な結果が得られるが、累乗のオーダーの際に実行時間が延びてしまうようである。 実行時間は累乗法と比べて大幅に時間がかかるようだ。 QR法は行列の大きさよりも、固有値の大きさに影響を受けるようだ。 QR法のプログラムはとても煩雑で、とてもむずかしかった。 ウェブ上の様々なプログラムソースを参考にして、自分なりに色々工夫してやってみた。 対称行列Aの対角化が完了した際の、終了条件をうまく表すことができず、しょうがないのでループ回数を強引に指定し、それを終了条件とした。固有値を求めることが目的であったが、固有ベクトルを求める所までしかわからなかった。あとちょっと工夫すれば、固有値を求めることができそうなんだが。 累乗法とQR法の理論的なことも、恐らくほとんど理解できていないので、これを提出した後にもう一度考え直そうと思う。 後、行列数を任意に指定できるようにしようと思ったが、ソースの一番上のdefineのNを変えることで、それと同等の意味を持ちえるプログラムを作ればいいと思ったので、あえて自分で入力するようにするのをやめた。