Jacobi與SOR迭代法的實現與性能比較及均勻間距與Chebyshev插值的實現、性能分析及二者生成的插值誤差比較


  這篇文章給出(1)Jacobi與SOR迭代法的實現與性能比較及(2)均勻間距與Chebyshev插值的實現、性能分析及二者生成的插值誤差比較,給出完整的實現代碼,沒有進行性能優化,僅供參考。

(1)Jacobi與SOR迭代法的實現與性能比較

一、舉例計算

給出線性方程組:

  其中n=100或者n=1000(任選一種,在本報告測試中,選取了n=100),使用Jacobi迭代法和SOR迭代法(=1,1.25,1.5)解此方程,計算結果精確到小數點后8位,結果輸出小數點后至少12位,報告所需要的步數和誤差(用無窮范數表示),比較計算結果。

二、Jacobi迭代法的實現

2.1、實現環境

MATLAB2018b

2.2、實現原理

  整個Jacobi實現分下面幾步實現:

  首先需要給定這個系統的輸入:矩陣A、向量b及初始向量x0,根據題目A與b是確定的,選定n=100,又矩陣A的是三對角矩陣,實現方式用到了MATLAB的內置函數diag來快速實現,具體實現如下:

  A = diag(2*ones(100,1))+diag(ones(99,1),1)+diag(ones(99,1),-1);

而向量b直接取值即可,初始向量x0給定為:x0= 0.01*ones(100,1);

  在確定好輸入之后,其二需要給出Jacobi的運算方式,而其關鍵是計算向量的各個元素值,依據Jacobi的的計算公式:

來進行運算,編寫的函數在規定的迭代次數之前進行運算;

  如果在規定的迭代次數之前所計算的誤差精度大於規定的誤差值時,即或者,繼續執行下面的步驟;

  在上一步結束之后‍需要更新的值,即的值賦給,更新迭代的次數,之后再轉到第二步繼續循環運行,如此反復運行,直到結束。

2.3、數據測試

  在n=100時,在MATLAB輸入如下命令:function [y] = myJocobi(u_x0,u_A,u_b,S_error,N_times);而為了探討經過Jacobi迭代運算之后誤差的計算過程用二范數和無窮范數區別,特地做了實驗來進行說明。當采用二范數時,計算結果如如圖1所示:

1 Jacobi迭代結果(誤差精度計算采用二范數)

  當誤差精度計算采用無窮范數時,計算結果如如圖2所示:

 

2 Jacobi迭代結果(誤差精度計算采用無窮范數)

2.4、數據分析

  當n=100時,在實現精度等要求的前提下,誤差精度計算采用二范數和無窮范數的Jacobi迭代的次數均達到3萬多次,分別為34541及30536次,可以預測當n值取得很大的時候,Jacobi迭代效率會很低。

三、SOR迭代法的實現

3.1、實現環境

MATLAB2018b

3.2、實現原理

  整個SOR迭代算法實現分下面幾步實現:

  首先需要給定這個系統的輸入:矩陣A、向量b及初始向量x0,根據題目A與b是確定的,選定n=100,又矩陣A的是三對角矩陣,而相對於Jacobi迭代,SOR迭代多了一個超松弛因子w(w=1,1.25,1.5)。三對角矩陣A實現方式用到了MATLAB的內置函數diag來快速實現,具體實現如下:

A = diag(2*ones(100,1))+diag(ones(99,1),1)+diag(ones(99,1),-1);

而向量b直接依題取值即可,初始向量x0給定為:x0= 0.01*ones(100,1);

  在確定好輸入之后,其二需要給出SOR迭代的運算函數,而其關鍵是計算向量x的各個元素值xi,依據SOR的的計算公式:

來進行運算,編寫的函數在規定的迭代次數之前進行運算;

  如果在規定的迭代次數之前所計算的誤差精度大於規定的誤差值時,即,繼續執行下面步驟;

  在上一步結束之后‍需要更新的值,即的值賦給,更新迭代的次數,之后再轉到第二步繼續循環運行,如此反復運行,直到結束。

3.3、數據測試

  在n=100時,在MATLAB輸入如下命令:

  [x_result,final_error] = mySOR(x0,A,b,1e-8,50000,1);

  而為了探討經過SOR迭代運算過程中超松弛因子w值不同對迭代的影響,現進行了w=1,1.25,1.5三次測試,測試結果如下:

n=100,超松弛因子=1時,SOR迭代結果如圖3所示:

 

3 超松弛因子=1時,SOR迭代結果

n=100,超松弛因子=1.25時,SOR迭代結果如圖4所示:

 

4 超松弛因子=1.25時,SOR迭代結果 

n=100,超松弛因子=1.5時,SOR迭代結果如圖5所示:

 

5 超松弛因子=1.5時,SOR迭代結果

3.4、數據分析

  n=100時,在實現精度等要求的前提下,誤差精度計算采用無窮范數的SOR迭代的次數在超松弛因子w分別取1、1.25、1.5時分別為12115、7584及4411次,可以看到,SOR迭代的整體速度較快,而在選取不同的超松弛因子值時,帶來的最終結果卻相差較大,因此可以預測當n值取得很大的時候,SOR迭代效率會比較高,且在選取合適的超松弛因子w時,效率提高會有數量級的提高。

四、JacobiSOR迭代法的運算結果比較

  在前提條件相同的基礎上,n=100時,Jacobi的迭代次數為34541及30536次,而SOR迭代的次數為12115、7584及4411次,誤差精度計算采用無窮范數時,最大的次數比為30536/4411,比例約為7點多,可以看到Jacobi相比與SOR迭代在效率上差很多,而且隨着n的增大,兩者之間的效率會相差越來越明顯。

 

(2)均勻間距與Chebyshev插值的實現、性能分析及二者生成的插值誤差比較

一、舉例計算

  令f(x)=exp(|x|),通過同時在區間[-1,1]上畫出兩種類型的n階多項式,其中n(N)=10,20,比較均勻間距的插值和Chebyshev插值,對於均勻間距的插值,左右插值的基點為-1和1。以0.01的步長采樣,對每種插值類型生成插值誤差,並畫出來進行比較,在這個問題里看是否能看到Runge現象。

二、均勻間距插值的實現

2.1、實現環境

MATLAB2018b

2.2、實現原理

  在實驗中,采用的是Lagrange來實現均勻間距插值和Chebyshev插值,實驗中首先需要實現的就是Lagrange算法插值,對於n次的Lagrange插值,構造的基函數為:

即得到滿足插值條件:

得到插值函數為:

  為了實現n=10,20的均勻間距插值,即對區間[-1,1]進行划相應的等分,核心實現為Lagrange函數,而Lagrange函數接口輸入參數有三個,其一為[-1,1]區間中0.01步長得到的u_x,其二為經過均勻間距的變量值xhk,其三為將划分的變量值經過函數y=exp(|x|)得到的輸出值yhk(hk =11對應n=10或者12對應n=20),在Lagrange函數中,通過使用上文已經構造好的基函數及插值函數公式來進行計算,最后得到經過均勻間距插值的數據結果。

2.3、數據測試

  在數據進行測試時,在MATLAB分別輸入如下命令:

  Ln1 = myLagrange(x11,y11,u_x);

  Ln2 = myLagrange(x12,y12,u_x);

  其中,x11與y11均為均勻間隔插值N(n)=10時,x12與y12均為均勻間隔插值N(n)=20時對數據的處理,最后得到結果如圖6和圖7所示,其中圖6為將原函數與均勻間隔插值N(n)=10及均勻間隔插值N(n)=20圖像分開比較,圖7為三者一同進行比較:

圖6 均勻間隔插值與原函數進行比較-1

圖7 均勻間隔插值與原函數進行比較-2

2.4、數據分析

  從測試結果可以看到,使用均勻間隔插值的時候時可以逼近原函數的,但是存在當n太小的時候,插值函數整體上與原函數有一定的區別,但是在n增大的情況下,插值函數中間段部分與原函數逼近,但是兩端出現了震盪,即出現了Runge現象。

三、Chebyshev插值的實現

3.1、實現環境

MATLAB2018b

3.2、實現原理

  對於Chebyshev插值,其插值區間必須為[-1,1],而題目是剛好吻合的,所以能夠直接使用Chebyshev插值,而對於Chebyshev插值,選取的插值節點以如下公式進行計算:

而在MATLAB中,向量的索引值從1開始,所以需要對公式進行變形,即:

  為了實現n=10,20的Chebyshev插值,即通過上面所列寫的公式取節點值。同樣Lagrange函數接口輸入參數有三個,其一為[-1,1]區間中0.01步長得到的,其二為通過上面所列寫的公式所取節點值xhk,其三為將所取得節點值經過函數y=exp(|x|)得到的輸出值yhk(hk =21對應n=10或者22對應n=20),在Lagrange函數中,通過使用上文已經構造好的基函數及插值函數公式來進行計算,最后得到經過Chebyshev插值的數據結果。

3.3、數據測試

  在數據進行測試時,在MATLAB分別輸入如下命令:

  Ln3 = myLagrange(x21,y21,u_x);

  Ln4 = myLagrange(x22,y22,u_x);

  其中,x21與y21均為Chebyshev插值N(n)=10時,x22與y22均為Chebyshev插值N(n)=20時對數據的處理,最后得到結果如圖8和圖9所示,其中圖8為將原函數與Chebyshev插值N(n)=10及Chebyshev插值N(n)=20圖像分開比較,圖9為三者一同進行比較:

 

圖8 Chebyshev插值與原函數進行比較-1

 

圖9 Chebyshev插值與原函數進行比較-2

3.4、數據分析

  從測試結果可以看到,使用Chebyshev插值的時候時可以更快地逼近原函數的,且當n比較小的時候,插值函數整體上與原函數區別不大。隨着n的增大,插值函數與原函數越來越逼近,在誤差允許情況下,能夠很好的替換原函數,且避免了均勻間隔插值兩端出現震盪的情況(Runge現象)。

四、均勻間距插值與Chebyshev插值誤差比較

  為了進行均勻間隔插值與Chebyshev插值誤差比較,需要計算誤差余項,通過對誤差余項的定義得到余項的表達式:

  通過對誤差余項的化簡可以得到:

而在本次實驗中f(x)=exp(|x|),通過對化簡,得到余項公式:

  均勻間隔插值與Chebyshev插值通過計算化簡后的余項即進行比較,其中在N(n)=10時,輸入Rn_1 = myRn_solve(u_x,x11);

Rn_3 = myRn_solve(u_x,x21);

得到當前N(n)值時,間隔與Chebyshev插值誤差,結果如圖10所示:

10 n=10時,插值誤差(余項)的對比 

  在N(n)=20時,輸入Rn_2 = myRn_solve(u_x,x12);

           Rn_4 = myRn_solve(u_x,x22);

得到當前N(n)值時,均勻間隔與Chebyshev插值誤差,結果如圖11所示:

11 n=20時,插值誤差(余項)的對比

  通過測試結果可以看出,在同一基礎條件下,均勻間隔插值與Chebyshev插值的誤差主要是在兩端點處相差較大,而且隨着n的增大,端點出的相差程度會更明顯,從這也反映了均勻間隔插值帶來的Runge現象影響。

附錄

(1)Jacobi與SOR迭代法的實現代碼

math_test.m

 1 %Jacobi迭代計算
 2 %function [y] = myJocobi(u_x0,u_A,u_b,S_error,N_times) 
 3 % [x_result,final_error] = myJacobi(x0,A,b,1e-8,50000);
 4 % 
 5 % if abs(final_error) < 1e-8
 6 %     fprintf('final_error*10^8=%f\n',abs(final_error)*1e8);
 7 % end
 8 
 9 
10 
11 
12 
13 %SOR迭代計算
14 %function [xx,y] = mySOR(u_x0,u_A,u_b,S_error,N_times,u_w)
15 [x_result,final_error] = mySOR(x0,A,b,1e-8,50000,1);
16 
17 if abs(final_error) < 1e-8
18     fprintf('final_error*10^8=%f\n',abs(final_error)*1e8);
19 end

 

myJacobi.m

 1 function [xx,y] = myJacobi(u_x0,u_A,u_b,S_error,N_times)
 2 %S_error 為規定的需要達到誤差值
 3 %N_times 為規定的最大迭代次數
 4     u_count = 1; 
 5     u_error = 1; %初始化默認誤差為1
 6     
 7     u_x = zeros(100,1); %初始化
 8     u_ax_toal = 0;
 9     
10     while(abs(u_error) > S_error)
11         
12        
13         
14         for i=1:100
15             
16             for j=1:100
17                 if j ~= i  %如果 cnt不等於i
18                     u_ax = u_A(i,j)*u_x0(j);
19                     u_ax_toal = u_ax_toal + u_ax;
20                 end
21             end
22             
23             u_x(i) = (u_b(i) - u_ax_toal)/u_A(i,i);
24             u_ax_toal = 0;
25         end
26         
27         
28         %u_error = norm(u_x-u_x0,2);   %求二范數
29         u_error = norm(u_x-u_x0,inf);   %求無窮范數
30         
31         u_x0 = u_x;
32         
33         if u_count>=N_times
34             break;
35         end
36         
37         fprintf('u_error  %d: %16.14f\n',u_count,u_error);
38         
39         u_count = u_count + 1;
40     end
41     
42     y = u_error;
43     xx = u_x0;
44 end

 

mySOR.m

 1 function [xx,y] = mySOR(u_x0,u_A,u_b,S_error,N_times,u_w)
 2    
 3 %S_error 為規定的需要達到誤差值
 4 %N_times 為規定的最大迭代次數
 5     u_count = 1; 
 6     u_error = 1; %初始化默認誤差為1
 7     
 8     u_x = zeros(100,1); %初始化
 9     u_ax_toal_last = 0;
10     u_ax_toal_now = 0;
11      
12     
13     while(abs(u_error) > S_error)
14         
15         for i=1:100
16             if i==1
17                 for j=2:100
18 
19                         u_ax = u_A(i,j)*u_x0(j);
20                         u_ax_toal_last = u_ax_toal_last + u_ax;
21                 end
22                 
23                 u_x(i) = (1-u_w)*u_x0(i) + u_w*((u_b(i) - u_ax_toal_last)/u_A(i,i));
24                 
25                 u_ax_toal_last = 0;
26             end
27             
28             if i>=2 && i<=99
29                 for j=1:i-1
30 
31                         u_ax = u_A(i,j)*u_x(j);
32                         u_ax_toal_now = u_ax_toal_now + u_ax;
33                 end
34 
35                 for j=i+1:100
36 
37                         u_ax = u_A(i,j)*u_x0(j);
38                         u_ax_toal_last = u_ax_toal_last + u_ax;
39                 end
40                 
41                 u_x(i) = (1-u_w)*u_x0(i) + u_w*((u_b(i) - u_ax_toal_last - u_ax_toal_now)/u_A(i,i));
42                 
43                 u_ax_toal_last = 0;
44                 u_ax_toal_now = 0;
45             end
46             
47             
48             if i==100
49                 for j=1:99
50 
51                         u_ax = u_A(i,j)*u_x(j);
52                         u_ax_toal_now = u_ax_toal_now + u_ax;
53                 end
54                 
55                 u_x(100) = (1-u_w)*u_x0(100) + u_w*((u_b(100) - u_ax_toal_now)/u_A(100,100));
56                 
57                 u_ax_toal_now = 0;
58             end
59             
60             
61         end
62         
63         
64         %u_error = norm(u_x-u_x0,2);   %求二范數
65         u_error = norm(u_x-u_x0,inf);   %求無窮范數
66         
67         u_x0 = u_x;
68         
69         if u_count>=N_times
70             break;
71         end
72         
73         fprintf('u_error  %d: %16.14f\n',u_count,u_error);
74         
75         u_count = u_count + 1;
76     end
77     
78     y = u_error;
79     xx = u_x0; 
80 end

 

three_matrix.m

1 A = diag(2*ones(100,1))+diag(ones(99,1),1)+diag(ones(99,1),-1);
2 
3 x0 = 0.01*ones(100,1);
4 
5 
6 b = zeros(100,0);
7 b(1) = 1;
8 b(100) = -1;
9 b = b';

 

 

(2)均勻間距與Chebyshev插值的實現

math_test_plot_Ln.m

 1 u_x = -1:0.01:1;
 2 u_y = exp(1).^abs(u_x);  % y = e^|x|
 3 
 4 
 5 
 6 % %均勻間距插值,使用等間距節點作為插值節點
 7 % % title('均勻間距插值')
 8 % 
 9 % %subplot(3,1,1);
10 % plot(u_x,u_y,'-.b')
11 % hold on
12 % %title('原函數')
13 % title('均勻間距插值')
14 % 
15 % 
16 % %subplot(3,1,2);
17 % x11 = -1:0.2:1; %n=10
18 % y11 = exp(1).^abs(x11);
19 % Ln1 = myLagrange(x11,y11,u_x);
20 % % Rn_1 = exp(1)*myRn_solve(u_x,x11);
21 % Rn_1 = myRn_solve(u_x,x11);
22 % plot(u_x,Ln1,'-k')
23 % % title('均勻間距插值 N = 10')
24 % hold on
25 % 
26 % %subplot(3,1,3);
27 % x12 = -1:0.1:1; %n=20
28 % y12 = exp(1).^abs(x12);
29 % Ln2 = myLagrange(x12,y12,u_x);
30 % Rn_2 = myRn_solve(u_x,x12);
31 % plot(u_x,Ln2,'-r')
32 % % title('均勻間距插值 N = 20')
33 % hold on
34 % 
35 % legend('原函數','均勻間距插值 N = 10','均勻間距插值 N = 20')
36 
37 
38 
39 
40 % %切比雪夫插值,使用切比雪夫節點作為插值節點
41 % subplot(3,1,1);
42 % 
43 plot(u_x,u_y,'-.b')
44 % title(' 原函數 ')
45 hold on
46 title('Chebyshev插值 N=10');
47 
48 % subplot(3,1,2);
49 x21 = myChebyshev(10);%n=10
50 y21 = exp(1).^abs(x21);
51 Ln3 = myLagrange(x21,y21,u_x);
52 Rn_3 = myRn_solve(u_x,x21);
53 plot(u_x,Ln3,'-r');
54 % title('Chebyshev插值 N=10');
55 hold on
56 
57 % subplot(3,1,3);
58 x22 = myChebyshev(20);%n=20
59 y22 = exp(1).^abs(x22);
60 Ln4 = myLagrange(x22,y22,u_x);
61 Rn_4 = myRn_solve(u_x,x22);
62 plot(u_x,Ln4,'-b');
63 % title('Chebyshev插值 N=20');
64 
65 legend('原函數','Chebyshev插值 N=10','Chebyshev插值 N=20')

 

math_test_plot_Rn.m

 1 u_x = -1:0.01:1;
 2 u_y = exp(1).^abs(u_x);  % y = e^|x|
 3 
 4 
 5 
 6 % 均勻間距插值
 7 
 8 x11 = -1:0.2:1; %n=10
 9 y11 = exp(1).^abs(x11);
10 Ln1 = myLagrange(x11,y11,u_x);
11 % Rn_1 = exp(1)*myRn_solve(u_x,x11);
12 Rn_1 = myRn_solve(u_x,x11);
13 
14 
15 
16 x12 = -1:0.1:1; %n=20
17 y12 = exp(1).^abs(x12);
18 Ln2 = myLagrange(x12,y12,u_x);
19 Rn_2 = myRn_solve(u_x,x12);
20 
21 
22 
23 
24 
25 % 切比雪夫插值,使用切比雪夫節點作為插值節點
26 
27 x21 = myChebyshev(10);%n=10
28 y21 = exp(1).^abs(x21);
29 Ln3 = myLagrange(x21,y21,u_x);
30 Rn_3 = myRn_solve(u_x,x21);
31 
32 
33 
34 x22 = myChebyshev(20);%n=20
35 y22 = exp(1).^abs(x22);
36 Ln4 = myLagrange(x22,y22,u_x);
37 Rn_4 = myRn_solve(u_x,x22);
38 
39 
40 
41 %繪制插值余項的最大值
42 plot(u_x,Rn_1,'-k',u_x,Rn_3,'-r');
43 title('N=10時 插值誤差(余項)的對比');
44 legend('均勻間距插值','Chebyshev插值');
45 
46 % %繪制插值余項的最大值
47 % plot(u_x,Rn_2,'-k',u_x,Rn_4,'-r');
48 % title('N=20時 插值誤差(余項)的對比');
49 % legend('均勻間距插值','Chebyshev插值');

 

myChebyshev.m

1 function x = myChebyshev(n)
2    
3 x = zeros(1,n+1);
4 for k = 1:n+1
5     x(k) = cos(((2*k-1)*pi)/(2*(n+1)));  %此處從1開始,所以是2*k-1,否則為2*k+1
6 end

 

myLagrange.m

 1 function y = myLagrange(x0,y0,x)
 2 %f11 = myLagrange(x11,y11,u_x);
 3 % x11 = -1:0.2:1; %n=10
 4 % y11 = exp(1).^abs(x11);
 5 
 6 
 7 u_N=1:length(x0); 
 8 
 9 
10 
11 y=zeros(size(x));
12 
13 for i=u_N
14     u_ij=find(u_N~=i);   
15     y1=1;
16     for j=1:length(u_ij)
17         y1=y1.*(x-x0(u_ij(j)));  
18     end
19     
20     y2=1;
21     for j=1:length(u_ij)
22         y2=y2.*(x0(i)-x0(u_ij(j)));  
23     end
24     
25     y=y+y0(i)*y1/y2;
26 
27 end

 

myRn_solve.m

 1 function u_Rn = myRn_solve(x,x0)
 2 
 3 % x11 = -1:0.2:1; %n=10
 4 % y11 = exp(1).^abs(x11);
 5 % f11 = myLagrange(x11,y11,u_x);
 6 % Rn_1 = exp(1)*myRn_solve(u_x,x11);
 7 
 8 u_Wn = zeros(1,length(x));
 9 u_Rn = zeros(1,length(x));
10 for i = 1:length(x)
11     u_Wn(i) = prod(x(i)*ones(1,length(x0))-x0);
12 end
13 
14 u_Rn = u_Wn*exp(1)/factorial(length(x0));
15 end

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM