共軛梯度方法(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分解,這個後面會寫。
相關文章
- 工程數學上機實驗四:共軛梯度法程式設計程式碼梯度程式設計
- 基於matlab的邊緣提取方法的比較Matlab
- Matlab並行程式設計方法Matlab並行行程程式設計
- Cesium 比較常用的幾個方法
- jQuery的prop和attr方法比較jQuery
- Jacobi迭代、Gauss_Seidel迭代和最佳因子SOR迭代的比較IDE
- 一文讀懂:梯度消失(爆炸)及其解決方法梯度
- 比較JS合併陣列的各種方法及其優劣JS陣列
- 【探索】兩種查詢和刪除重複記錄的方法及其效能比較
- 一個非常Strong的程式設計學習方法程式設計
- initialize方法與load方法比較
- 機器學習方法(一)——梯度下降法機器學習梯度
- MATLAB一維插值和二維插值 比較Matlab
- 程式設計賺錢的7個方法程式設計
- matlab比較兩個矩陣是否相等Matlab矩陣
- Java Optional的orElse()與orElseGet()兩個方法比較 - BaeldungJava
- MATLAB數字訊號處理(1)四種經典功率譜估計方法比較Matlab
- 併發程式設計:DEMO:比較Stream和forkjoin框架的效率程式設計框架
- 目前比較全的CSS重設(reset)方法總結CSS
- UITableView設定全屏分隔線的幾種方法比較UIView
- 發現一個可以讓程式設計師提神的方法程式設計師
- 不同備份方法的特性比較
- 硬體程式設計師和軟體開發程式設計師相比,哪一個就業發展前景比較好呢?程式設計師就業
- 去除csdn廣告的方法,多種方法比較總結
- Linux伺服器程式設計是一個比較剛需的開發方向Linux伺服器程式設計
- 一個程式語言比較網站網站
- VC++中的一個不足及其改善方法 (轉)C++
- Go和Python比較的話,哪個比較好?GoPython
- 訪問vector元素方法的效率比較
- 分割陣列的幾種方法比較陣列
- 四種在Javascript比較物件的方法JavaScript物件
- 頁面註冊js的方法比較JS
- 【機器學習之數學】02 梯度下降法、最速下降法、牛頓法、共軛方向法、擬牛頓法機器學習梯度
- 流行程式設計方法的一點看法行程程式設計
- 一個字串比較的題字串
- 五個方法成為更好的程式設計師程式設計師
- 好程式設計師技術解析Hadoop和spark的效能比較程式設計師HadoopSpark
- Boost.Asio和ACE之間關於Socket程式設計的比較程式設計