Sei sulla pagina 1di 18

Vidali Ireneo

Corso di laurea in Ingegneria Aerospaziale

Matricola 578538

LABORATORIO DI METODI NUMERICI


ESERCITAZIONE NUMERO 1
In questa esperienza di laboratorio si chiedeva di risolvere un sistema lineare, Ax = b, con i vari metodi appresi durante lo svolgimento del corso. La matrice A deve essere quadrata, sparsa (il numero di elementi diversi da zero deve essere molto piccolo rispetto alle dimensioni della matrice), simmetrica (AT= A), e definita positiva (cio preso un vettore x n, con x 0, deve essere xTAx > 0). Il vettore b il vettore termine noto, mentre il vettore x il vettore soluzione. Lo svolgimento della prova inizia con la definizione di un file.m, chiamato inizio.m, allinterno del quale vengono inizializzate le principali variabili che saranno poi richiamate per limplementazione dei vari metodi. In particolare stata adottata come matrice A la matrice di Poisson presente nella gallery del programma Matlab.
% inizio % definizione delle dimensioni della matrice n = 50; A = gallery('poisson',n); % definizione del vettore soluzione al passo 0 x0 = zeros(size(A,1),1); % definizione del vettore dei termini noti b = ones(size(x0));

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

Analogamente a quanto in precedenza considerato,


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.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:

M-1Ax = M-1b Il precondizionamento efficiente se k2 (M-1A) << k2 (A) cio se M-1

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

Tornati nella command window si implemeta la function. >> visualizzazione(itmax,errore_g,errore_gc,errore_gcpj,errore_gcpc);

10

andamento dei vari metodi gradiente gradiente con. prec. Jacobi prec. Cholesky

10

10 norma del residuo

10

-2

10

-4

10

-6

10

-8

1000

2000

3000

4000 5000 6000 n di terazioni

7000

8000

9000 10000

10

andamento del gradiente gradiente

10

10 norma del residuo

10

-2

10

-4

10

-6

10

-8

1000

2000

3000

4000 5000 6000 n di terazioni

7000

8000

9000 10000

10

andamento del gradiente coniugato gradiente con.

10

10 norma del residuo

10

-2

10

-4

10

-6

10

-8

10

20

30

40 50 60 n di terazioni

70

80

90

100

10

andamento del gradiente con. prec. Jacobi prec. Jacobi

10

10 norma del residuo

10

-2

10

-4

10

-6

10

-8

10

20

30

40 50 60 n di terazioni

70

80

90

100

10

andamento del gradiente con. prec. Cholesky prec. Cholesky

10

10 norma del residuo

10

-2

10

-4

10

-6

10

-8

10

15

20 25 n di terazioni

30

35

40

45

VISUALIZZAZIONE CON SUBPLOT


function[]=visualizzazione_sub(itmax,errore_g,errore_gc,errore_gcpj,errore_gcpc) % function per la visualizzazione figure(1) iter = zeros(1,itmax); 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); 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');

xlabel('n di terazioni'); ylabel('norma del residuo'); legend('prec. Cholesky'); grid on

>> 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 norma del residuo

10

-2

10

-4

10

-6

10

-8

1000

2000

3000

4000 5000 6000 n di terazioni

7000

8000

9000 10000

10

andamento del gradiente gradiente

10

andamento del gradiente coniugato gradiente con.

norma del residuo

10

norma del residuo 0 2000 4000 6000 n di terazioni 8000 10000

10

10

-5

10

-5

10

-10

10

-10

20

40 60 n di terazioni

80

100

10

andamento del gradiente con. prec. Jacobi prec. Jacobi

10

andamento del gradiente con. prec. Cholesky prec. Cholesky

norma del residuo

10

norma del residuo 0 20 40 60 n di terazioni 80 100

10

10

-5

10

-5

10

-10

10

-10

10

20 30 n di terazioni

40

50

Potrebbero piacerti anche