Gauss-Seidel
Scopo
Risolve un sistema lineare del tipo Ax = b attraverso l’algoritmo iterativo di
Gauss-Seidel, con A matrice sparsa e b vettore dei termini noti.
Specifiche e Comportamento
Per la realizzazione di tale algoritmo abbiamo utilizzato un’unica funzione,
gausiedel.m che utilizza le seguenti sintassi possibili.
Sintassi
[x] = gausiedel(A, b)
[x, NITER] = gausiedel(A, b)
[x] = gausiedel(A, b, TOL)
[x] = gausiedel(A, b, TOL, MAXITER)
[x, NITER] = gausiedel(A, b, TOL)
[x, NITER]= gausiedel(A, b, TOL, MAXITER)
Parametri di input
1. A (obbligatorio) : matrice di numeri con m righe ed n colonne.
2. b (obbligatorio) : vettore dei termini noti.
3. k (facoltativo) : numero di cifre significative utilizzate per il calcolo della
soluzione (10^-k), se omesso la tolleranza è pari all’epsilon macchina.
Bisogna indicare il numero di cifre significative che si vogliono ottenere nel
calcolo (k positivo).
4. MAXITER (facoltativo) : numero massimo di iterazioni
all’algoritmo, se omesso MAXITER si imposta al valore 1000.
consentito
Parametri di output
1. x (obbligatorio) : vettore soluzione del sistema Ax = b.
2. NITER (facoltativo) : numero di iterazioni effettuate dall’algoritmo per il
calcolo della soluzione ottenuta.
Descrizione
Analizziamo ora una descrizione formale dei vari modi in cui può essere utilizzata
tale funzione dall’utente :
[x] = gausiedel(A, b)
risolve il sistema lineare Ax = b, con A matrice sparsa, b vettore dei termini
noti, restituendo il vettore soluzione. Il metodo iterativo terminerà con una
tolleranza pari all'epsilon macchina o ad un numero massimo
di iterazioni pari
a 1000.
[x, NITER] = gausiedel(A, b)
risolve il sistema lineare Ax = b, restituendo il vettore x, soluzione calcolata del
sistema, ed il numero di iterazioni effettuate per il calcolo di tale soluzione. Il
metodo iterativo terminerà con una tolleranza pari all'epsilon macchina o ad un
numero massimo di iterazioni pari a 1000.
[x, NITER] = gausiedel(S, b,k)
risolve il sistema con una tolleranza TOL=10^-k (dove k è il numero di cifre
significative esatte). Il metodo iterativo terminerà se si giunge alla tolleranza
imposta oppure se si giunge ad un numero massimo di iterazioni pari a 1000.
[x, NITER] = gausiedel(S, b, k, MAXITER)
risolve il sistema limitando a MAXITER il numero di iterazioni da effettuare. l
metodo iterativo terminerà se si giunge alla tolleranza imposta oppure se si
giunge ad un numero massimo di iterazioni pari a MAXITER.
ESEMPIO D'USO
Analizziamo ora il risultato di un’esempio d’uso basato su tali parametri di ingresso : matrice
1500x1500 con elementi pari a 9 sulla diagonale principale e 1 sulle due diagonali adiacenti.
Richiamando il seguente script file:
format long
n=1500;
A=9*eye(n)+diag(ones(n-1,1),1)+diag(ones(n-1,1),-1);
A = sparse(A);
spy(A)
indice_condizionamento=condest(A)
xsol = rand(length(A),1);
b = A*xsol;
[x, NITER] = gausiedel(A, b);
errore=norm(x-xsol)/norm(x)
numero_iterazioni=NITER
Otteniamo:
indice_condizionamento =
1.571428571428571
errore =
1.094258536091669e-016
numero_iterazioni =
18
Richiamando sulla stessa matrice A,
[x, NITER] = gausiedel(A, b,10);
Otteniamo :
indice_condizionamento =
1.571428571428571
errore =
3.563365286007379e-012
numero_iterazioni =
12
Richiamando la function gausiedel nella seguente maniera:
[x, NITER] = gausiedel(A, b,eps,10);
Otteniamo:
indice_condizionamento =
1.571428571428571
errore =
2.595270241660143e-010
numero_iterazioni =
10
Richiamando la function nella seguente maniera:
[x, NITER] = gausiedel(A, b,50,10);
Otteniamo:
indice_condizionamento =
1.571428571428571
Warning: la tolleranza indicata è troppo elevata, è
posta pari a eps
> In gausiedel at 47
In gauss_errore at 20
errore =
2.507364375013947e-010
numero_iterazioni =
10
Matrice 100x100 risultante dalla discretizzazione attraverso l'equazione di
Poisson.
format long
A = gallery('poisson', 10); %di ordine n^2
spy(A)
indice_condizionamento=condest(A)
xsol = rand(length(A),1);
b = A*xsol;
[x, NITER] = gausiedel(A,b);
errore=norm(x-xsol)/norm(x)
numero_iterazioni=NITER
Otteniamo:
indice_condizionamento =
69.863370896510318
errore =
2.177630186169446e-015
numero_iterazioni =
405
Situazioni di errore
Le varie situazioni di errore che possono verificarsi sono le seguenti :
Omissione del vettore dei termini noti:
gausiedel(A);
Otteniamo:
termini noti
??? Error using ==> gausiedel at 21
Bisogna inserire la matrice A, e
Error in ==> gauss_errore at 21
gausiedel(A);
Omissione parametri di output:
il
vettore
dei
gausiedel(A, b)
Otteniamo:
??? Error using ==> gausiedel at 63
Indicare almeno il termine che risulterà essere il
vettore soluzione
Error in ==> gauss_errore at 21
gausiedel(A,b);
Inserimento di una matrice non sparsa:
format long
n=1500;
A=rand(n);
spy(A)
indice_condizionamento=condest(A)
xsol = rand(length(A),1);
b = A*xsol;
[x, NITER] = gausiedel(A, b,16);
errore=norm(x-xsol)/norm(x)
numero_iterazioni=NITER
Otteniamo:
??? Error using ==> gausiedel at 24
matrice non sparsa
Error in ==> gauss_errore at 20
[x, NITER] = gausiedel(A, b,50,10);
MAXITER è pari a NaN
[x, NITER] = gausiedel(A, b,15,NaN);
Otteniamo:
indice_condizionamento =
1.571428571428571
Warning: il numero di iterazioni deve
numero positivo,sarà
impostato a 1000
> In gausiedel at 50
In gauss_errore at 23
errore =
1.450996268306523e-016
numero_iterazioni =
17
essere
un
La diagonale contiene elementi nulli:
A=9*eye(n)+diag(ones(n-1,1),1)+diag(ones(n-1,1),-1);
A = sparse(A);
A(1)=0;
Otteniamo:
??? Error using ==> gausiedel at 27
sulla diagonale ci sono elementi nulli, per applicare
Gauss-Siedel
trasformare la matrice
Error in ==> gauss_errore at 20
[x, NITER] = gausiedel(A, b,12,10);
La matrice sparsa non è quadrata:
A=rand(n,10); %per una matrice non quadrata
A=sparse(A);
[x, NITER] = gausiedel(A, b,16);
Otteniamo:
??? Error using ==> gausiedel at 30
La matrice A deve essere quadrata
Error in ==> gauss_errore at 20
[x, NITER] = gausiedel(A, b,12,10);
La variabile b non è un vettore:
b=rand(3,2);
[x, NITER] = gausiedel(A, b,16);
Otteniamo:
??? Error using ==> gausiedel at 33
b deve essere il vettore dei termini noti
Error in ==> gauss_errore at 20
[x, NITER] = gausiedel(A, b,12,10);
La lunghezza di S non corrisponde con la lunghezza di b:
b=rand(3,1);
[x, NITER] = gausiedel(A, b,16);
Otteniamo:
??? Error using ==> gausiedel at 36
La matrice A e il vettore b hanno diversa lunghezza
Error in ==> gauss_errore at 20
[x, NITER] = gausiedel(A, b,12,10);
Codice e documentazione interna
Gauss-Seidel
%Metodo di gauss-siedel per la risoluzione di un sistema lineare
Ax=b
%con A sparsa
%[x] = gausiedel(A, b)
%parametri di input della funzione
%A (obbligatorio) – matrice sparsa di numeri con m righe ed n
colonne.
%b (obbligatorio) – vettore dei termini noti.
%function [x,Niter]=gausiedel(A,b,k,MaxIter)
%k (facoltativo) – numero di cifre significative utilizzate per
il calcolo
%della soluzione
%MAXITER (facoltativo) – numero massimo di iterazioni consentito
all’algoritmo.
%Parametri di output:
%x (obbligatorio) – vettore soluzione del sistema Ax = b.
%NITER
(facoltativo)
–
numero
di
iterazioni
effettuate
dall’algoritmo per il calcolo della soluzione ottenuta.
function [x,Niter]=gausiedel(A,b,k,MaxIter)
%controllo sul numero di parametri in ingresso
if nargin < 2
error('Bisogna inserire la matrice A, e il vettore dei
termini noti');
end
if(issparse(A)==0)
error('matrice non sparsa')
end
if(find(diag(A)==0))
error('sulla diagonale ci sono elementi nulli, per applicare
Gauss-Siedel trasformare la matrice')
end
if size(A,1) ~= size(A,2)
%numero di righe diverso numero di
colonne
error('La matrice A deve essere quadrata')
end
if(isvector(b)==0)
error('b deve essere il vettore dei termini noti')
end
if length(A) ~= length(b)
error('La matrice A e il vettore b hanno diversa lunghezza')
end
if nargin<4
MaxIter=1000;
if nargin<3
TOL=eps;
end
end
if nargin>2
TOL=max(10^(-k),eps);
if(TOL==eps)
warning('la tolleranza indicata è troppo elevata, è
posta pari a eps')
end
if (MaxIter<1 |isnan(MaxIter))
warning('il numero di iterazioni deve essere un numero
positivo,sarà impostato a 1000')
MaxIter=1000;
end
end
x=zeros(length(A), 1);
xk=x;
Niter=0;
%controllo sul numero di parametri in uscita
if nargout < 1
error('Indicare almeno il termine che risulterà essere il
vettore soluzione')
end
while(((norm(x-xk)>TOL*norm(xk))| Niter==0) && (Niter<MaxIter))
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%
% Niter==0 è fondamentale affinchè non si esca dal ciclo alla
prima
% iterazione, infatti inizialmente norm(xk) è = 0, norm(x-xk)
= 0 si
% esce.
%if(Niter==0)
%
norm(x-xk)
% norm(xk)
%end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%
xk=x;
for i=1:length(x)
x(i)=(-(A(i,1:i-1)*x(1:i1)+A(i,i+1:length(x))*x(i+1:length(x)))+b(i))/A(i,i);
end
Niter=Niter+1;
end
Scarica

Gauss-Seidel - UniNa STiDuE