共軛梯度方法(CG)MATLAB程式設計及其和Gauss_Seidel方法的一個比較
共軛梯度方法(CG)MATLAB程式設計及其和Gauss_Seidel方法的一個比較
共軛梯度法是一種迭代法,不同於Jacobi,Gauss-Seidel和SOR方法。理論上最多n步找到真解,實際計算中考慮到舍入誤差,一般迭代3n~5n步,每步的運算量相當於舉證乘向量的運算量。這種神奇的方法,對應稀疏矩陣特別有效。
% 我們來造一個大型稀疏正定矩陣,比較共軛梯度法和Gauss_Seidei方法迭代速度上的差異。
%為了方便,不妨構造一個三對角矩陣。
clc
clear
profile on
m =1000;%先來一個一千階的方程組,便於CG方法和Gauss_Seidel方法的比較。
e = ones (m,1);
A = spdiags ([ e,4*e,e ],[-1,0,1],m,m);
%full(A)
true_x = rand(m,1);
b = A * true_x;
x0 = rand(m,1);
eps = 1.0e-9;
%測試一千萬階的方程組,CG方法在本機需要若干秒。此時,Gauss_Seidel方法卡死。
[x_CG,~] = CG(A,b,x0,eps);
error_CG = norm(x_CG - true_x,2);
%來看看Gauss_Seidel方法的速度
[x_G,~] = Gauss_Seidel(A,b,x0,eps);
error_G = norm(x_G - true_x,2);
% MATLAB對於特殊的一千萬階大規模方程組的求解也幾乎是秒算,可見其矩陣運算功能的強大。
%不愧矩陣實驗室,畢竟是經過優化的。
x_matlab = A\b;
error_matlab = norm(x_matlab - true_x,2);
profile viewer
p = profile('info');
profsave(p,'profile_results')
可以看得出,CG方法在解這類問題上甩Gauss_Seidel不僅僅是用幾條街來衡量的。這只是在一千階的情況下。
需要注意的是,Gauss_Seidel方法時間主要消耗在了用該方法矩陣A是否收斂的判斷上。實際當中,這一步是多餘的,因為我們可以通過若干步的迭代結果來判斷是否收斂,一般不收斂,很快就會接待到無窮,很少有解震盪不收斂的情況產生。
下面附上兩個子函式:
1、CG.m
function [x,steps] = CG(A,b,x0,eps)
r0 = b - A*x0;
p0 = r0;
if nargin == 3
eps = 1.0e-6;
end
steps = 0;
while 1
if abs(p0) < eps
break;
end
steps = steps + 1;
a0 = r0'*r0/(p0'*A*p0);%多次用到可以存一步。
x1 = x0 + a0*p0;
r1 = r0 -a0*A*p0;
b0 = r1'*r1/(r0'*r0);
%這裡的r'* r雖然後面可能還會用到,但是由於計算量不大,沒有必要再設個新變數將
%其存下了,記憶體上的開銷划不來。
p1 = r1 + b0*p0;
%只是用到前後兩層的向量,所以節省記憶體開銷,計算完後面一層,可以往回覆蓋掉沒用
%的變數。
x0 = x1;
r0 = r1;
p0 = p1;
end
x = x0;
end
2、Gauss_Seidel.m
function [x,out] = Gauss_Seidel(A,b,x0,eps,iterNum)
%% 同Jacobi迭代,只是迭代函式f有所改變。
n = length(b);
if det(A) == 0
error('No Unique Solution Or No Solution!');
end
for i = 1 : n
j = 1;
while A(i,i) == 0
if A(j,i) ~= 0 && A(i,j) ~= 0
tempV = A(j,:);
A(j,:) = A(i,:);
A(i,:) = tempV;
tempS = b(j);
b(j) = b(i);
b(i) = tempS;
else
j = j + 1;
end
if j > n
error('No Exchange Exist!');
end
end
end
D = diag(diag(A));
invD = diag(1./diag(A));
J = invD * (D - A);
invDb = invD * b;
H = eye(n) - tril(A)^-1*A;
if max(abs(eig(H))) >= 1
error('Gauss_Seidel Algorithm Cannot Convergence!')
end
function x = f(x)
for l = 1:n
temp_x = J(l,:)*x + invDb(l);
x(l) = temp_x;
end
end
x = x0;
if nargin == 5
for k = 1:iterNum-1
x = f(x);
end
x_0 = x;
x = f(x);
out = norm(x-x_0,2);
else
if nargin == 3
eps = 1.0e-6;
end
out = 0;
while 1
x_0 = x;
x = f(x);
out = out + 1 ;
if norm( x - x_0 ,2 ) < eps
break;
end
end
end
end
對於實正定方程組而言,CG方法是收斂的。CG方法也有若干改進,比如用cholesky分解,這個後面會寫。
相關文章
- 工程數學上機實驗四:共軛梯度法程式設計程式碼梯度程式設計
- ==和equals方法的比較
- Cesium 比較常用的幾個方法
- jQuery的prop和attr方法比較jQuery
- BigDecimal的equals() 和 compareTo() 方法比較Decimal
- 一文讀懂:梯度消失(爆炸)及其解決方法梯度
- initialize方法與load方法比較
- MATLAB一維插值和二維插值 比較Matlab
- matlab比較兩個矩陣是否相等Matlab矩陣
- MATLAB數字訊號處理(1)四種經典功率譜估計方法比較Matlab
- 併發程式設計:DEMO:比較Stream和forkjoin框架的效率程式設計框架
- Java Optional的orElse()與orElseGet()兩個方法比較 - BaeldungJava
- Linux伺服器程式設計是一個比較剛需的開發方向Linux伺服器程式設計
- 硬體程式設計師和軟體開發程式設計師相比,哪一個就業發展前景比較好呢?程式設計師就業
- 好程式設計師技術解析Hadoop和spark的效能比較程式設計師HadoopSpark
- Go和Python比較的話,哪個比較好?GoPython
- 四種在Javascript比較物件的方法JavaScript物件
- 訪問vector元素方法的效率比較
- 分割陣列的幾種方法比較陣列
- 去除csdn廣告的方法,多種方法比較總結
- Boost.Asio和ACE之間關於Socket程式設計的比較程式設計
- 非同步程式設計模式BeginInvoke和EndInvoke方法非同步程式設計設計模式
- OceanBase簡介及其與MySQL的比較MySql
- 靠譜的少兒程式設計網站比較好用?程式設計網站
- Python 與 PHP:2024 年程式設計前景比較PythonPHP程式設計
- matlab標量或矩陣比較Matlab矩陣
- Matlab學習-視覺化和程式設計Matlab視覺化程式設計
- 函數語言程式設計 vs 物件導向程式設計 vs 程式式程式設計的JS演示比較 - DEV函數程式設計物件JSdev
- 【教程】一個比較良心的C++程式碼混淆器C++
- 機器學習方法(一)——梯度下降法機器學習梯度
- html表格比較寬溢位的解決方法HTML
- 學習AI人工智慧比較快的方法AI人工智慧
- 利用compareTo方法進行字串比較排序字串排序
- .NET CORE下最快比較兩個檔案內容是否相同的方法
- Python程式設計中一些常見的錯誤和處理方法Python程式設計
- 【溫故知新】 程式設計原則和方法論程式設計
- 第03講:Flink 的程式設計模型與其他框架比較程式設計模型框架
- Java程式設計工具有哪些比較好用?常用的有哪些?Java程式設計
- 雙相超程式設計:一種新語言設計方法程式設計