MATLAB入門學習-#7-冪法&冪法的加速&反冪法編程練習


這幾種求特徵值和特徵向量的方法,理論講解可以去看數值分析這門課的課本或者下面這個鏈接:【圖文】冪法及反冪法_百度文庫
另外還有一個講的很好的冪法相關的文檔:科學網—圖說冪法求特徵值和特徵向量 - 康建的博文
下面就給出我寫的程序了,統一用的是先用一個函數檢驗是否具有使用某一方法的條件,若有條件再調用計算函數,因此每種方法都有兩個函數。程序還是有問題的,比如對誤差限epsilon,設置好以後會多算一次,就是說程序的順序還是有問題,最近時間很緊張,我就不再去修改了,就把我第一次寫的放上來,把中間一些注意的地方記錄到就好了。

1.冪法(power method)

function [lambda,beta]=power_method(A,times,x0,epsilon)
%這個是一個檢驗A能不能用冪法的函數
%[lambda,beta]=power_method(A,times,x0,epsilon)
%lambda是最後得出的特徵值
%beta是最後得到的特徵值對應的特徵向量
%A是待求矩陣
%times是最大迭代次數
%x0是初始向量
%epsilon是最大誤差
format long;
b=eig(A);      %求A的特徵值所組成的向量
c=size(b);
d=c(1)*c(2);  % 矩陣元素數量,即特徵值的總個數
e=length(unique(b));  % 有幾個代表值
if(d==e)
    fprintf('特徵值互異,是對角化矩陣\n');  %QUESTION1:fprintf
    [lambda,beta]=power_method_cal(A,times,x0,epsilon)  %再去調用計算函數,代碼在下面
else
    error('特徵值有重複,不是對角化矩陣\n');
end
function [alpha,x]=power_method_cal(A,times,x0,epsilon)
%[alpha,x]=power_method_cal(A,times,x0,epsilon)
format long;
k=1;
u=0;

[m,n]=size(x0);
y=zeros(m,n);
y=x0;

while k <= times 
    x=A*y;
    alpha=max(x);   %max()求一個矩陣中最大的元素
    y=x./alpha;
    fprintf('第%d次迭代\n',k);   %QUESTON3:%d  %f   %s
    fprintf('alpha=%.8f\n',alpha)
    disp(x);
    disp(y);
    if abs(alpha-u)<epsilon
        break
    else
        k=k+1;
        u=alpha;
    end      %QUESTION2:end

end

QUESTION1:matlab disp、sprintf、fprintft函數 - hengyaha的博客 - CSDN博客
QUESTION2:matlab中,if,while,for這些語句後面都要用end來結束
QUESTION3:

%3d就是說按照長度爲3的整型輸出,比如10,輸出就是“10”,“”代表空格。
%6.2f就是小數點後保留2位,輸出總長度爲6,比如3.14159,輸出後就是“_ _ _3.14”(前面三個空格)
%c就是輸出字符串
%s就是輸出字符串,和%c是一樣的

2.冪法的加速——原點平移法

function [lambda,beta]=origin_displacement_method(A,times,x0,epsilon,lambda0)
%[lambda,beta]=origin_displacement_method(A,times,x0,epsilon,lambda0)
%lambda是最後得出的特徵值
%beta是最後得到的特徵值對應的特徵向量
%A是待求矩陣
%times是最大迭代次數
%x0是初始向量
%epsilon是最大誤差
%lambda0就是lambda0

b=eig(A);
c=size(b);
d=c(1)*c(2);  % 矩陣元素數量
e=length(unique(b));  % 有幾個代表值
if(d==e)
    fprintf('特徵值互異,是對角化矩陣\n');
    [lambda,beta]=origin_displacement_method_cal(A,times,x0,epsilon,lambda0)
else
    error('特徵值有重複,不是對角化矩陣\n');
end
function [alpha,x]=origin_displacement_method_cal(A,times,x0,epsilon,lambda0)
%[lambda,beta]=origin_displacement_method_cal(A,times,x0,epsilon,lambda0)

k=1;
u=0;

[m,n]=size(x0);
y=zeros(m,n);
y=x0;
I=eye(m);
A=A-lambda0*I;
while k <= times 
    x=A*y;
    alpha=max(x);
    y=x./alpha;
    fprintf('第%d次迭代\n',k);
    fprintf('alpha=%.8f\n',alpha)
    fprintf('特徵值爲%.8f\n',alpha+lambda0)
    disp(x);
    disp(y);
    if abs(alpha-u)<epsilon
        break
    else
        k=k+1;
        u=alpha;
    end

end

3.冪法的加速——埃特肯(Aitken)

function [lambda,beta]=power_method_aitken(A,x0,times,epsilon)
%[lambda,beta]=power_method_aitken(A,x0,times,epsilon)
%lambda是最後得出的特徵值
%beta是最後得到的特徵值對應的特徵向量
%A是待求矩陣
%x0是初始向量
%times是最大迭代次數
%epsilon是最大誤差
format long;
b=eig(A);
c=size(b);
d=c(1)*c(2);  % 矩陣元素數量
e=length(unique(b));  % 有幾個代表值
if(d==e)
    fprintf('特徵值互異,是對角化矩陣\n');
    [lambda,beta]=power_method_aitken_cal(A,x0,times,epsilon);
else
    error('特徵值有重複,不是對角化矩陣\n');
end
function [lambda,x]=power_method_aitken_cal(A,x0,times,epsilon)
%[alpha,x]=power_method_aitken_cal(A,x0,times,epsilon)
format long;
k=1;
u=1;

[m,n]=size(x0);
y=zeros(m,n);
x=x0;
alpha0=0;
alpha1=0;

while k <= times 
    alpha=max(x);
    y=x./alpha;
    x=A*y;
    alpha2=max(x);
    lambda=alpha0-((alpha1-alpha0)^2)/(alpha2-2*alpha1+alpha0);
    fprintf('第%d次迭代\n',k);
    fprintf('alpha0=%.8f\n',alpha0);
    fprintf('alpha1=%.8f\n',alpha1);
    fprintf('alpha2=%.8f\n',alpha2);
    fprintf('lambda=%.8f\n',lambda);
    disp(x);
    disp(y);
    if abs(lambda-u)<epsilon
        break
    else
        k=k+1;
        u=lambda;
        alpha0=alpha1;
        alpha1=alpha2;
    end

end

4.反冪法(inverse power method)

function [lambda,beta]=inverse_power_method(A,x0,lambda_star,times,epsilon)
%[lambda,beta]=inverse_power_method(A,x0,lambda_star,times,epsilon)
%lambda是最後得出的特徵值
%beta是最後得到的特徵值對應的特徵向量
%A是待求矩陣
%x0是初始向量
%lambda_star是特徵值lambda的近似值
%times是最大迭代次數
%epsilon是最大誤差
format long;
b=eig(A);
c=size(b);
d=c(1)*c(2);  % 矩陣元素數量
e=length(unique(b));  % 有幾個代表值
if(d==e)
    fprintf('特徵值互異,是對角化矩陣\n');
    [lambda,beta]=inverse_power_method_cal(A,x0,lambda_star,times,epsilon);
else
    error('特徵值有重複,不是對角化矩陣\n');
end

function [lambda,x]=inverse_power_method_cal(A,x0,lambda_star,times,epsilon)
%[lambda,beta]=inverse_power_method_cal(A,x0,lambda_star,times,epsilon)
format long;
k=1;
u=1;

[m,n]=size(x0);
y=zeros(m,n);
x=x0;

I=eye(m);
H=A-lambda_star.*I;
[L,U]=lu(H);     %LU分解函數(matlab自帶)
while k <= times 
    beta_b=max(x);
    y=x./beta_b;
    z=L\y;
    x=U\z;
    beta_b=max(x);
    fprintf('第%d次迭代\n',k);
    lambda=lambda_star+1/beta_b;
    fprintf('lambda=%.8f\n',lambda);
    disp(x);
    disp(z);
    if abs(1/beta_b-1/u)<epsilon
        break
    else
        k=k+1;
        u=beta_b;
    end

end
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章