Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Matricola 578538
Il primo metodo utilizzato per la risoluzione del sistema lineare stato il metodo diretto.
function [] = metodo_diretto(A,b,x0) % implementazione metodo diretto % le istruzioni tic toc consentono di conoscere il tempo impiegato da Matlab % nello svolgere la parte di programma compresa tra le due righe di codice tic % implementazione del metodo frontale, questo metodo riordina la matrice A in % modo da minimizzare il riempimento dei fattori triangolari utilizzati per la % sua fattorizzazione, A = LU, quindi viene risolto il sistema Ly = b Ux = y x = A\b; toc
% calcolo della norma dellerrore errore_md = norm(x-x0); % visualizzazione della norma dellerrore fprintf('errore: %d\n\n',errore_md);
Il metodo viene implementato nella command window richiamando i vari programmi. >> inizio; >> metodo_diretto(A,b,x0); Elapsed time is 0.353262 seconds. errore: 5.471630e+003 Il secondo metodo utilizzato per la risoluzione del sistema lineare il metodo del gradiente (chiamato anche steepest descent).
function [itmax,errore_g] = gradiente(A,b,x0) % implementazione del metodo del gradiente % definizione dei parametri itmax = input('inserire il numero di iterazioni massime da eseguire: '); toll = input('inserire il valore della tolleranza: '); it = 1; x = x0; r = b - A*x; errore = norm(r); % calcolo della norma del vettore b normb = norm(b); % creazione di un vettore opportuno, atto a salvare la norma del % residuo ad ogni iterazione; questo vettore verr poi utilizzato nello % script "visualizzazione" per tracciare landamento del metodo errore_g = zeros(1,itmax); tic % definizione del ciclo iterativo while errore > toll && it <= itmax errore_g(it) = errore; % creazione della variabile ausiliaria z z = A*r; % calcolo alfa alfa = (r'*r)/(z'*r); % aggiornamento del vettore soluzione x
x = x + alfa*r; % aggiornamento del valore del residuo r = r - alfa*z; % assegnazione, alla variabile errore, del nuovo valore della norma del % residuo errore = norm(r); % incremento del conteggio delle iterazioni iter = iter + 1; end if iter <= itmax errore_g = errore_g(1:iter-1); end toc % visualizzazione del risultato del metodo if iter <= itmax fprintf('il metodo converge in %d iterazioni\n\n',iter); else fprintf('il metodo non converge nel numero di iterazioni fissate\n\n'); end
Il metodo viene implementato nella command window richiamando i vari programmi. >> inizio; >> [itmax,errore_g] = gradiente(A,b,x0); inserire il numero di iterazioni massime da eseguire: 10000 inserire il valore della tolleranza: 1e-08 Elapsed time is 1.386993 seconds. il metodo converge in 9710 iterazioni
1 1 (con e n rispettivamente n autovalore massimo e minimo della matrice A) molto grande, dunque il fattore di riduzione 1 n dellerrore (costante asintotica dellerrore): molto vicino a 1. 1 + n Una stima del numero di iterazioni necessarie per ridurre la norma A dellerrore di una tolleranza
Nei casi realistici il numero di condizionamento di A: k2 (A) = data dalla seguente relazione: k
1 2 * log( ) * ( K 2 ( A) +1) 2
Il numero di iterazioni proporzionale a k2 (A) quindi sar molto grande. Ne possibile andare a determinare una stima approssimata riferendosi a quanto prima rappresentato. Ottengo dallimplementazione dello script seguente in matlab il massimo e il minimo autovalore della matrice presa in esame.
format short A = gallery('poisson',50); B= eig(A); C=max (B); D=min(B); disp (C) disp(D)
in command window ottengo la restituzione della seguente coppia di valori. 7.9924 0.0076 K2(A)= 0.9981 e dunque risulta essere che k= Il terzo metodo utilizzato per la risoluzione del sistema lineare il metodo del gradiente coniugato.
function [itmax,errore_gc] = gradientecon(A,b,x0) % implementazione del metodo del gradiente coniugato % definizione dei parametri itmax = input('inserire il numero di iterazioni massime da eseguire: '); toll = input('inserire il valore della tolleranza: '); iter = 1; x = x0; r = b - A*x; p = r; errore = norm(r); % calcolo della norma del vettore b normb = norm(b); % creazione di un vettore opportuno, atto a salvare la norma del % residuo ad ogni iterazione; questo vettore verr poi utilizzato nello % script "visualizzazione" per tracciare landamento del metodo errore_gc = zeros(1,itmax); tic % definizione del ciclo iterativo while errore > toll*normb && iter <= itmax errore_gc(iter) = errore; % creazione della variabile ausiliaria z z = A*p;
% calcolo alfa alfa = (p'*r)/(z'*p); % aggiornamento del vettore soluzione x x = x + alfa*p; % creazione di una variabile ausiliaria che memorizzi il valore del % residuo al passo k a = r; % aggiornamento del residuo r = r - alfa*z; % calcolo beta beta = (r'*r)/(a'*a); % aggiornamento della direzione di ricerca p p = r + beta*p; % aggiornamento del valore della variabile errore errore = norm(r); % incremento del conteggio delle iterazioni iter = iter + 1; end if iter <= itmax errore_gc = errore_gc(1:iter-1); end toc % visualizzazione del risultato del metodo if iter <= itmax fprintf('il metodo converge in %d iterazioni\n\n',iter); else fprintf('il metodo non converge nel numero di iterazioni fissate\n\n'); end
Il metodo viene implementato nella command window richiamando i vari programmi. >> inizio; >> [itmax,errore_gc] = gradientecon(A,b,x0); inserire il numero di iterazioni massime da eseguire: 10000 inserire il valore della tolleranza: 1e-08 Elapsed time is 0.017110 seconds. il metodo converge in 94 iterazioni
In questo metodo cambia la scelta dei vettori direzione di ricerca p k , scelti in modo da verificare le seguenti condizioni: p0 = r0
p k + = r k+1 + k p k 1
i coefficienti k sono scelti in modo da rendere linsieme dei vettori pk A-ortogonale, cio: p k + TA p k = 0 1 Da questa propriet si pu arrivare a concludere che, p k , dovendo essere ortogonale ad un insieme linearmente indipendente di k vettori, necessariamente il vettore nullo, pertanto il vettore soluzione in aritmetica esatta xn , cosa non verificata nellimplementazione del metodo in quanto nei calcoli sono stati eseguiti arrotondamenti e quindi errori di approssimazione. Anche il metodo del gradiente coniugato converge linearmente ma la costante asintotica dellerrore pi piccola rispetto al caso precedente:
=
K 2 ( A) 1 K 2 ( A) +1
Una stima del numero di iterazioni necessarie per ridurre la norma A dellerrore di una tolleranza data dalla seguente relazione: k
1 2 * log( ) * ( K 2 ( A) +1) . 2
in command window ottengo la restituzione della seguente coppia di valori. 7.9924 0.0076 K2(A)=0.940171474 e ancora se ne pu dedurre un numero di iterazioni molto grande per giungere a convergenza. Una stima del numero di iterazioni possibile grazie alla formula precedente metodo di jacobi Si prende ora in considerazione la relativa implementazione dei metodi con precondizionatore. Tali metodi vanno ad accelerare la convergenza delle rispettive iterazioni in esame in modo tale da rendere il metodo competitivo con i vari metodi diretti.
function [itmax,errore_gcpj] = jacobi(A,b,x0) % implementazione del metodo del gradiente coniugato precondizionato Jacobi % creazione della matrice M % speye(M,N) forma una matrice sparsa ponendo i termini sulla diagonale % principale uguali ad 1 M = speye(size(A)); for i=1:size(A,1) % size(A,1) calcola il numero di righe della matrice A M(i,i) = A(i,i); end % definizione dei parametri itmax = input('inserire il numero di iterazioni massime da eseguire: '); toll = input('inserire il valore della tolleranza: '); iter = 1; x = x0; r = b - A*x; % residuo p = M\r; ro = r'*p; errore = norm(r); % calcolo della norma del vettore b normb = norm(b); % creazione di un vettore opportuno, atto a salvare la norma del % residuo ad ogni iterazione; questo vettore verr poi utilizzato nello % script "visualizzazione" per tracciare landamento del metodo errore_gcpj = zeros(1,itmax); tic % definizione del ciclo iterativo while errore > toll*normb && iter <= itmax errore_gcpj(iter) = errore; % creazione della variabile ausiliaria z z = A*p; % calcolo alfa alfa = (p'*r)/(z'*p); % aggiornamento del vettore soluzione x x = x + alfa*p; % aggiornamento del valore del residuo r = r - alfa*z; % calcolo g g = M\r; % attribuisco ai valori sulla diagonale della matrice % M i valori sulla diagonale della matrice A
% creazione di una variabile ausiliaria dove salvare ro al passo k a = ro; % aggiornamento di ro ro = r'*g; % calcolo beta beta = ro/a; % aggiornamento della direzione di ricerca p p = g + beta*p; % aggiornamento del valore dell'errore errore = norm(r); % incremento del conteggio delle iterazioni iter = iter + 1; end if iter <= itmax errore_gcpj = errore_gcpj(1:iter+1); end toc % visualizzazione del risultato del metodo if iter <= itmax fprintf('il metodo converge in %d iterazioni\n\n',iter); else fprintf('il metodo non converge nel numero di iterazioni fissate\n\n'); end
Il metodo viene implementato nella command window richiamando i vari programmi. >> inizio; >> [itmax,errore_gcpj] = jacobi(A,b,x0); inserire il numero di iterazioni massime da eseguire: 10000 inserire il valore della tolleranza: 1e-08 Elapsed time is 0.024273 seconds. il metodo converge in 94 iterazioni Il precondizionamento, come stato in precedenza accennato, utilizzato per ottenere una convergenza pi rapida. Il precondizionamento consiste nel premoltiplicare il sistema per linversa di una opportuna matrice M:
A-1.
Se M = D con D matrice diagonale tale che dii = aii otteniamo il precondizionatore di Jacobi. metodo di choleski
function [itmax,errore_gcpc] = cholesky(A,b,x0) % implementazione del metodo del gradiente coniugato precondizionato Cholesky % creazione della matrice M R = cholinc(A,'0'); M = R'*R; % definizione dei parametri itmax = input('inserire il numero di iterazioni massime da eseguire: '); toll = input('inserire il valore della tolleranza: '); iter = 1; x = x0; r = b - A*x; p = M\r; ro = r'*p; errore = norm(r); % calcolo della norma del vettore b normb = norm(b); % creazione di un vettore opportuno, atto a salvare la norma del % residuo ad ogni iterazione; questo vettore verr poi utilizzato nello % script "visualizzazione" per tracciare landamento del metodo errore_gcpc = zeros(1,itmax); tic % definizione del ciclo iterativo while errore > toll*normb && iter <= itmax errore_gcpc(iter) = errore; % creazione della variabile ausiliaria z z = A*p; % calcolo alfa alfa = (p'*r)/(z'*p); % aggiornamento del vettore soluzione x x = x + alfa*p; % aggiornamento del valore del residuo r = r - alfa*z; % calcolo g
g = M\r; % creazione di una variabile ausiliaria che consente di salvare la variabile % ro al passo k a = ro; % aggiornamento del valore di ro ro = r'*g; % calcolo beta beta = ro/a; % aggiornamento della direzione di ricerca p p = g + beta*p; % aggiornamento del valore dell'errore errore = norm(r); % incremento del valore del conteggio dell'iterazione iter = iter + 1; end if iter <= itmax errore_gcpc = errore_gcpc(1:iter+1); end toc % visualizzazione del risultato del metodo if iter <= itmax fprintf('il metodo converge alla iterazione numero: %d\n\n',iter); else fprintf('il metodo non converge nel numero di iterazioni fissate\n\n'); end
Il metodo viene implementato nella command window richiamando i vari programmi. >> inizio; >> [itmax,errore_gcpc] = cholesky(A,b,x0); inserire il numero di iterazioni massime da eseguire: 10000 inserire il valore della tolleranza: 1e-08 Elapsed time is 0.470775 seconds. il metodo converge alla iterazione numero: 43 In questo caso la matrice di precondizionamento M, stata posta uguale a LLT, dove L il fattore triangolare inferiore della fattorizzazione incompleta di Cholesky (da qui il nome del metodo). La fattorizzazione incompleta si ottiene a partire dallalgoritmo della fattorizzazione di Cholesky, applicando poi la seguente condizione:
aij = 0 lij = 0 Viene ora riportata la visualizzazione grafica dei risultati ottenuta per quanto riguarda i vari metodi di risoluzione del sistema lineare preso in esame
function [] = visualizzazione (itmax,errore_g,errore_gc,errore_gcpj,errore_gcpc) % function per la visualizzazione % definizione di ci che verr visualizzato nel primo grafico figure(1) iter = zeros(1,itmax); % visualizzazione del grafico tramite la funzione semilog semilogy(1:length(errore_g),errore_g,'k-'); hold on semilogy(1:length(errore_gc),errore_gc,'g-'); semilogy(1:length(errore_gcpj),errore_gcpj,'r-'); semilogy(1:length(errore_gcpc),errore_gcpc,'m-'); hold off title('andamento dei vari metodi'); xlabel('n di terazioni'); ylabel('norma del residuo'); legend('gradiente','gradiente con.','prec. Jacobi','prec. Cholesky'); grid on figure(2) iter = zeros(1,itmax); semilogy(1:length(errore_g),errore_g,'k-'); title('andamento del gradiente'); xlabel('n di terazioni'); ylabel('norma del residuo'); legend('gradiente'); grid on figure(3)
iter = zeros(1,itmax); semilogy(1:length(errore_gc),errore_gc,'g-'); title('andamento del gradiente coniugato'); xlabel('n di terazioni'); ylabel('norma del residuo'); legend('gradiente con.'); grid on figure(4) iter = zeros(1,itmax); semilogy(1:length(errore_gcpj),errore_gcpj,'r-'); title('andamento del gradiente con. prec. Jacobi'); xlabel('n di terazioni'); ylabel('norma del residuo'); legend('prec. Jacobi'); grid on figure(5) iter = zeros(1,itmax); semilogy(1:length(errore_gcpc),errore_gcpc,'m-'); title('andamento del gradiente con. prec. Cholesky'); xlabel('n di terazioni'); ylabel('norma del residuo'); legend('prec. Cholesky'); grid on
10
andamento dei vari metodi gradiente gradiente con. prec. Jacobi prec. Cholesky
10
10
-2
10
-4
10
-6
10
-8
1000
2000
3000
7000
8000
9000 10000
10
10
10
-2
10
-4
10
-6
10
-8
1000
2000
3000
7000
8000
9000 10000
10
10
10
-2
10
-4
10
-6
10
-8
10
20
30
40 50 60 n di terazioni
70
80
90
100
10
10
10
-2
10
-4
10
-6
10
-8
10
20
30
40 50 60 n di terazioni
70
80
90
100
10
10
10
-2
10
-4
10
-6
10
-8
10
15
20 25 n di terazioni
30
35
40
45
figure(2) iter = zeros(1,itmax); subplot (2,2,1); semilogy(1:length(errore_g),errore_g,'k-'); title('andamento del gradiente'); xlabel('n di terazioni'); ylabel('norma del residuo'); legend('gradiente'); grid on iter = zeros(1,itmax); subplot (2,2,2); semilogy(1:length(errore_gc),errore_gc,'g-'); title('andamento del gradiente coniugato'); xlabel('n di terazioni'); ylabel('norma del residuo'); legend('gradiente con.'); grid on iter = zeros(1,itmax); subplot (2,2,3); semilogy(1:length(errore_gcpj),errore_gcpj,'r-'); title('andamento del gradiente con. prec. Jacobi'); xlabel('n di terazioni'); ylabel('norma del residuo'); legend('prec. Jacobi'); grid on iter = zeros(1,itmax); subplot (2,2,4); semilogy(1:length(errore_gcpc),errore_gcpc,'m-'); title('andamento del gradiente con. prec. Cholesky');
>> visualizzazione_sub(itmax,errore_g,errore_gc,errore_gcpj,errore_gcpc);
10
andamento dei vari metodi gradiente gradiente con. prec. Jacobi prec. Cholesky
10
10
-2
10
-4
10
-6
10
-8
1000
2000
3000
7000
8000
9000 10000
10
10
10
10
10
-5
10
-5
10
-10
10
-10
20
40 60 n di terazioni
80
100
10
10
10
10
10
-5
10
-5
10
-10
10
-10
10
20 30 n di terazioni
40
50