You are on page 1of 4

MÈTODES NUMÈRICS

Grau i llicenciatura de Matemàtiques UAB, 2010–2011.


Pràctica flotant. Sistemes lineals.
L’objectiu d’aquesta pràctica és implementar la resolució de diversos sistemes lineals Ax = b mitjançant la
descomposició LU .

1 Algorisme
Sigui A matriu n × n no singular. Farem la seva descomposició LU mitjançant eliminació gaussiana amb
pivotatge maximal per columnes. El procés es porta a terme en n − 1 passos, començant amb A(0) := A. En el
pas k, partim de
 
u0,0 ··· ··· ··· u0,k u0,k+1 ··· u0,n−1
 l1,0 u1,1 ··· ··· u1,k u1,k+1 ··· u1,n−1 
 
 
 l2,0 l2,1 u2,2 ··· u2,k u2,k+1 ··· u2,n−1 
 
 .. .. .. .. .. .. .. 
(k)
 . . . . . . . 
A =
 
(k) (k) (k)
 lk,0 lk,1 ··· lk,k−1 ak,k ak,k+1 ··· ak,n−1 

(k) (k) (k)
 
 l
 k+1,0 lk+1,1 · · · lk+1,k−1 ak+1,k ak+1,k+1 · · · ak+1,n−1 

 .. .. .. .. .. .. .. 

 . . . . . . .


(k) (k) (k)
ln−1,0 ln−1,1 · · · ln−1,k−1 an−1,k an−1,k+1 · · · an−1,n−1
i trobem  
u0,0 ··· ··· ··· u0,k u0,k+1 ··· u0,n−1
l1,0 u1,1 ··· ··· u1,k u1,k+1 ··· u1,n−1
 
 
 

 l2,0 l2,1 u2,2 ··· u2,k u2,k+1 ··· u2,n−1 

 .. .. .. .. .. .. .. 
 . . . . . . . 
A(k+1) = ,
 
 lk,0 lk,1 ··· lk,k−1 uk,k uk,k+1 ··· uk,n−1 
(k+1) (k+1)
 
 lk+1,0 lk+1,1 ··· lk+1,k−1 lk+1,k ak+1,k+1 · · · ak+1,n−1 
 
 .. .. .. .. .. .. .. 

 . . . . . . . 

(k+1) (k+1)
ln−1,0 ln−1,1 ··· ln−1,k−1 ln−1,k an−1,k+1 · · · an−1,n−1
mitjançant el següent algorisme.
Algorisme 1.1
∀i = 0, 1, . . . , n − 1
si := i
∀k = 0, 1, . . . , n − 2
(k) (k)
trobem imax ∈ {k, k + 1, . . . , n − 1} : |aimax ,k | = maxi=k,...,n−1 |ai,k |
intercanviem les files k i imax de A(k) (tota la fila, lk,j , limax ,j variant j incloses)
intercanviem sk i simax
∀i = k + 1, k + 2, . . . , n − 1
(k) (k)
li,k := ai,k /ak,k
∀j = k + 1, k + 2, . . . , n − 1
(k+1) (k) (k)
ai,j := ai,j − li,k ak,j .
En aquestes recurrències, s és un vector d’ı́ndexs on “enregistrem” els intercanvis de files que fem durant
l’eliminació gaussiana (el podeu pensar com un element del grup simètric de n elements). En acabar, obtindrem
 
u0,0 u0,1 ··· u0,n−1
 
 l1,0 u1,1 ··· u1,n−1 
A(n−1) =  ,
 
.. .. .. ..

 . . . . 

ln−1,0 · · · ln−1,n−2 un−1,n−1
on ja es troben emmagatzemades les matrius L i U , que són
   
1 0 ··· 0 u0,0 u0,1 ··· u0,n−1
   
 l1,0 1 ··· 0   0 u1,1 ··· u1,n−1 
L= , U = . .
   
.
.. . .. .. ..   .. .. .. ..

 . . 

 . . . 

ln−1,0 · · · ln−1,n−2 1 0 ··· 0 un−1,n−1

Degut als intercanvis de files que hem fet, les matrius L i U no són descomposició de A, sinó d’una permutació
de les seves files. Concretament,

e⊤
 
s1
..
P A = LU, P = , (1)
 
.
e⊤
sn−1

on esi és el si –èsim vector de la base canònica de Rn .


Arribats a aquest punt, podem resoldre el sistema Ax = b resolent dos sistemes triangulars,

Ly = P b
Ax = b ⇐⇒ P Ax = P b ⇐⇒ LU x = P b ⇐⇒ ,
Ux = y

amb una substitució cap a endavant i una altra cap a endarrera, que es poden implementar d’acord amb
l’algorisme detallat seguidament (noteu que, d’acord amb (1), multiplicar per l’esquerra per P equival a permutar
files segons s).
Algorisme 1.2
∀i = 0, 1, . . . , n − 1
Xi−1
yi = bsi − li,j yj
j=0
∀i = n − 1, n − 2, . . . , 0
 n−1
X 
xi = yi − ui,j xj /ui,i .
j=i+1

Recordeu que, a la pràctica, totes les matrius A(k) es generen sobre el vector C apuntat per a.

2 Guió
1. Escriviu una rutina amb prototipus

void lu_desc (double *a, int n, int piv, int *s);

que, donats n = n i A = A(0) guardada per columnes dins el vector C apuntat per a, trobi A(n−1) i la
permutació s seguint l’algorisme 1.1. Ha de tornar la matriu A(n−1) guardada per columnes dins el vector
apuntat per a, i la permutació s dis el vector apuntat per s. El paràmetre piv indica si la rutina ha de
fer pivotatge maximal per columnes o no (no n’ha de fer si piv = 0, altrament sı́).
2. Escriviu una rutina amb prototipus

void lu_res (double *a, int n, int *s, int p, double *b, double *x);

que, donats n = n, A(n−1) guardada per columnes dins el vector apuntat per a, p = p i b apuntant a una
matriu n × p guardada per columnes, amb columnes {b0 , . . . , bp−1 }, resolgui els p sistemes lineals Axi = bi
seguint l’algorisme 1.2. Ha de tornar les solucions {x0 , . . . , xp−1 } com a columnes d’una matriu n × p,
guardada per columnes al vector apuntat per x.
3. Porteu a terme els testos que creieu convenients per a assegurar-vos de la correcció de les dues rutines
anteriors.
4. Escriviu un programa principal que, donat n a la lı́nia de comandes, generi una matriu aleatòria n × n,
triı̈ b perquè la solució sigui (1, 1, . . . , 1)⊤ i resolgui el sistema Ax = b, primer sense fer pivotatge i després
fent-ne. En tots dos casos, escriviu el residu màxim,
n−1
X
max |bi − ai,j xj |
i=0,...,n−1
j=0

i l’error màxim,
max |xi − 1|.
i=0,...,n−1

Recordeu que es poden generar nombres aleatoris entre 0 i 1 fent

((double)rand())/RAND_MAX

(la funció rand() està declarada a stdlib.h).


Experimenteu amb diversos valors de n i observeu com el pivotatge redueix els errors.
5. Retoqueu el programa principal de l’apartat anterior perquè escrigui el temps emprat en la descomposició
LU . Comproveu experimentalment que el nombre d’operacions és O(n3 ). Tenint en compte que, més
concretament, el nombre total d’operacions per fer la descomposició LU és 2n3 /3 + O(n2 ) (comptant
suma i producte com operacions diferents), trobeu estimacions del rendiment efectiu del vostre programa.
Compareu-les amb el pic teòric de la màquina.
Per a mesurar temps d’execució del programa de manera portable, podeu usar la funció clock(), que està
declarada a time.h. Aquesta funció torna el nombre de “ticks” que han transcorregut des de l’inici del
programa. La macro CLOCKS_PER_SEC dóna el nombre de “ticks” que hi ha a un segon (que depèn de la
implementació). Aixı́, per a mesurar el temps transcorregut entre dos punts del programa, podeu fer

time_t t0, t1;


/* Vull mesurar des d’aqui ... */
t0=clock();
/* ... fins a aqui */
t1=clock();
printf("temps: %.3f s\n", ((double)(t1-t0))/CLOCKS_PER_SEC);

6. Considerem les matrius de Hilbert de dimensió n,


 
Hn = 1/(i + j + 1) .
i,j=0,1,...,n−1

Escriviu una nova versió del programa principal de l’apartat anterior, que, donat n, resolgui el sistema
lineal Hn x = b, havent triat b perquè la solució sigui x = (1, 1, . . . , 1)⊤ , i escrigui l’error i el residu màxims.
Experimenteu amb diversos valors de n i observeu com, per valors de n petits, malgrat tenir un bon residu
obtenim un error enorme.
Les matrius de Hilbert són un exemple de matrius mal condicionades.
7. Escriviu una rutina per invertir matrius, amb prototipus

void lu_inv (double *a, int n, double *am1];

que, donats n = n i A guardada per columnes dins el vector apuntat per a, torni A−1 guardada per
columnes dins el vector apuntat per am1, usant les dues rutines que heu programat anteriorment.
8. A l’apartat 6 heu vist que, en fer la descomposició LU amb pivotatge, l’error, tot i disminuir respecte de
no pivotar, encara és gran. Això és degut a que les matrius de Hilbert són molt mal condicionades.
Per a una matriu A = (ai,j )i,j=0,1,...,n−1 , es defineix el seu nombre de condició en norma del suprem per

µ∞ (A) = kAk∞ kA−1 k∞ ,

on
n−1
X
kAk∞ = max |ai,j |.
i=0,1,...,n−1
j=0

Es pot prendre log10 µ∞ (A) com a fita del nombre de xifres significatives que es perden en resoldre el
sistema Ax = b. Acostuma a ser una fita bastant pessimista.
Escriviu un programa principal que, donada n a la lı́nia de comandes, escrigui µ∞ (Hn ). Tabuleu aquesta
quantitat per diversos valors de n.

3 Lliurament
La data lı́mit és el 10 de juny de 2011 a les 23:59:59 CEST (21:59:59 UT). Les pràctiques fora de termini seran
acceptades, però la nota serà multiplicada per 0.85n , on n és el nombre de dies de retard (diferència entre el
temps de lliurament i el termini arrodonit a dies cap a amunt). Heu de fer un lliurament al campus virtual amb:
• El codi, que ha de constar almenys de 4 fitxers:
– Un fitxer lup.c amb el codi de les rutines lu_desc(), lu_res() i lu_inv().
– Un fitxer lup.h amb els prototipus de les rutines anteriors.
– Fitxers testpiv.c i condhlb.c, amb els programes principals corresponents executables correspo-
nents als punts 5 i 8 del guió, respectivament.
• La memòria en format PDF, dins un fitxer memoria.pdf.
Els executables dels punts 5 i 8 del guió s’han de poder generar mitjançant
make testpiv_lagr
make condhlb
suposant que al directori on compileu hi ha el fitxer Makefile que trobareu al campus virtual (recordeu de
canviar-li el nom per tal de treure-li el .txt).

You might also like