Vous êtes sur la page 1sur 4

Algorithmique et Programmation Projet : d´ecomposition LU creuse

Ecole normale sup´erieure D´epartement d’informatique td-algo@di.ens.fr

2011-2012

Le pivot de Gauss (et les m´ethodes comparables) reste une des m´ethode les plus efficace pour r´esoudre des syst`emes lin´eaires A·x = y. Quand la matrice A est dense, il la complexit´e du processus est de l’ordre de O n 3 op´erations (mˆeme si des algorithmes plus rapides existent en th´eorie). Par contre, quand A est creuse (c’est-`a-dire que la plupart des coefficients sont ´egaux `a z´ero), il est possible d’utiliser des algorithmes plus efficaces. Les syst`emes creux apparaissent naturellement dans un grand nombre de situations, et on peut gˆerer des matrices creuses beaucoup plus grandes que les denses. L’objectif de ce projet est de programmer un algorithme qui prend en entr´ee une matrice creuse A, avec la promesse qu’elle est inversible, ainsi qu’un vecteur y, et qui renvoie un vecteur x solution. La technique qu’on va utiliser est la d´ecomposition LU, qui consiste `a d´eterminer une matrice L (resp. U ) triangulaire inf´erieure (resp. sup´erieure) telle que A = L · U . On impose de plus que L n’ait que des 1 sur la diagonale. Ceci permet au passage de stocker L et U dans une seule matrice de taille n × n (L

La

et U ne se “recouvrent” que sur la diagonale, mais on a pas besoin de stocker la diagonale de L

d´ecomposition LU est d´ecrite en d´etail dans [1], entre autres. Une fois cette d´ecomposition calcul´ee, on peut r´esoudre le syst`eme lin´eaire efficacement : on r´esout d’abord U ·z = y, puis ensuite L·x = z. L’astuce c’est que c’est facile quand les matrices sont triangulaires.

).

1 Syst`emes triangulaires

On s’attaque d’abord au probl`eme de la r´esolution de syst`emes triangulaires. Supposons qu’on a une matrice triangulaire inf´erieure L. On peut ´ecrire :

L =

l 11

l 21

22

0

L

o`u l 11 est un r´eel, l 21 un vecteur de taille n 1 et L 22 une matrice triangulaire inf´erieure de taille n 1. Le probl`eme devient donc de r´esoudre :

D’o`u il sort que :

l 11

l 21

L 22 ·

0

l 11 · x 1 =

y 1

x 2 =

x

1

y

y

2

1

L 22 · x 2 = y 2 x 1 · l 21

Ceci permet de d´eterminer x 1 et de se ramener r´ecursivement `a un probl`eme plus petit. Si on d´eroule la r´ecurrence (et qu’on optimise un peu l’espace) on aboutit `a un code du style :

1:

x y

2:

for i = 1 to n do

3:

if x i = 0 then

4:

x i x i /L ii

5:

for each j > i for which L ij

= 0 do

6:

x j x j L ji · x j

7:

end for

8:

end if

9: end for

1

1.1

Version `a L creuse et x, y denses

On va maintenant supposer que la matrice L est creuse. Un vecteur creux est repr´esent´e par deux tableaux, l’un donnant la position des coefficients non-nuls, et l’autre leurs valeurs. La matrice L est repr´esent´ee colonne par colonne, et chaque colonne est un vecteur creux. L’algorithme est assez bien adapt´e `a ¸ca, et la boucle for de la ligne 5 va ˆetre acc´el´er´ee d’autant, car le test sera dor´enavant gratuit.

1.2 Version `a L creuse et x, y creux

Supposons qu’en plus le vecteur y soit creux, et qu’on souhaite renvoyer un vecteur x creux. L`a, quelques petites modifications sont n´ecessaires. En effet, rien n’interdit que la ligne 6 cr´e´ee de nouveaux coefficients non-nuls dans x. Il n’est donc pas possible de repr´esenter x de fa¸con creuse. Pour faire face `a ce probl`eme, on alloue avant le d´emarrage de l’algorithme un tableau de taille n initialement rempli de z´eros. Ce tableau va servir `a repr´esenter x. Ligne 1, il faut donc copier le vecteur (creux) y dans le vecteur (dense) x. A la fin de la proc´edure, il faudra scanner le vecteur x pour pouvoir en former une repr´esentation creuse et la renvoyer. Ce probl`eme algorithmique est abord´e en d´etail dans [2]. Malheureusement, il est possible que ce processus de balayage de x `a la fin, ainsi que les n ´etapes engendr´ees par les lignes 2 et 3, dominent asymptotiquement la complexit´e totale de la proc´edure. Par exemple, si y est enti`erement nul sauf y n , alors seul un nombre constant d’op´erations arithm´etiques sont n´ecessaires, et pourtant la complexit´e de l’algorithme sera de l’ordre de n. Pour faire face `a ce probl`eme, on suppose que l’algorithme prend en entr´ee une liste χ des indices de x qui seront non-nuls dans le r´esultat. On suppose ´egalement qu’on a sous la main deux fonctions :

Scatter : prend en argument un vecteur dense et un vecteur creux, et copie le vecteur creux dans le vecteur dense (en un temps proportionnel aux nombre d’entr´ees non-nulles dans le vecteur creux). Gather-Zero : prends en argument un vecteur dense et une liste d’entiers, et forme un vecteur creux en extrayant du vecteur dense les coefficients aux positions sp´ecifi´ees par la liste d’entiers. Ces positions sont ensuite mises `a z´ero dans le vecteur dense. On peut alors modifier l’algorithme en :

1:

Scatter(x, y)

2:

for each i χ do

3:

x i x i /L ii

4:

for each j > i for which L ij

= 0 do

5:

x j x j L ji · x i

6:

end for

7: end for

8:

return Gather-Zero(x, χ)

Notez que ce qui se passe lignes 4–6 ressemble beaucoup `a ce que fait Scatter. Le temps d’ex´ecution de cette nouvelle proc´edure ne domine a priori plus n. Il reste `a d´eterminer χ et `a le trier efficacement. Les coefficients de x peuvent devenir non-nuls aux lignes 1 et 5. On peut d´eterminer χ par une proc´edure de marquage dans un graphe. On consid`ere le graphe orient´e `a n sommets G L tel que i est reli´e `a j

si L ji = 0 (en fait c’est le graphe dont la matrice d’adjacence est la transpos´ee de L). Ce graphe est acyclique car L est triangulaire. Dans G L on souhaite marquer les sommets correspondants aux positions

`

non-nulles dans x. A cause de la ligne 1, on marque les positions non-nulles dans y. A cause de la ligne 5, il faut aussi marquer les sommets dont les pr´ed´ecesseurs sont marqu´es. Par cons´equent, χ est l’ensemble des sommets accessibles depuis y dans G L , qu’on peut calculer par un simple parcours en profondeur (on peut noter que chaque arˆete travers´ee pendant le parcours correspond d’ailleurs `a une op´eration arithm´etique r´ealis´ee ligne 5). Il reste cependant mettre les ´el´ements de χ dans l’ordre. Il est clair que pour calculer x j , il est suffisant que les valeurs de tous ses pr´ed´ecesseurs dans G L soient d´ej`a connues. En d’autre terme, il est suffisant que χ d´ecrive un tri topologique de G L (et on peut le calculer avec un parcours en profondeur). Avec cette nouvelle technique, on peut calculer x en un temps proportionnel `a la taille de x et au nombre d’op´erations arithm´etiques n´ecessaires `a son calcul.

2 D´ecomposition LU creuse via les syst`emes triangulaires

On va calculer la d´ecomposition LU colonne par colonne. Bien sˆur, on veut des versions creuses de L et U . Lors de sa k-i`eme ´etape, l’algorithme utilise les colonnes 1 `a (k 1) de L, et la k-`eme colonne

2

de A. On peut ´ecrire :

o`u

L 11

l 21

L 31

0

1

l 32

0

0

L 33

·

U 11

0

0

u

u

12

22

0

U 13

u 23

U 33

=

A 11

a 21

A 31

a

a

a

12

22

32

A 13

a 23

A 33

L 11 , U 11 et A 11 sont des sous-matrices de taille k 1

l 21 , u 23 , a 21 et a 23 sont des vecteurs ligne

l 32 , u 12 , a 12 et a 13 sont des vecteurs colonne

u 22 et a 22 sont des r´eels

L 31 , L 33 , U 13 , U 33 , A 13 , A 31 et A 33 sont des sous-matrices de la bonne taille.

Pour que l’algorithme avance d’une ´etape, il faut d´eterminer l 32 , u 12 et u 22 . On trouve, en regardant le produit matrice-matrice ci-dessus que

a

12

= L 11 · u 12

a 22 = l 21 · u 12 + u 22

a 32 = L 31 · u 12 + u 22 · l 32

On pourrait donc calculer le vecteur (creux) u 12 en r´esolvant un syst`eme triangulaire creux avec

membre droit creux (par la technique de la section 1.2), puis ensuite calculer u 22 et l 32 , mais le probl`eme c’est qu’on a acc`es `a L par colonnes, et non par lignes. Pour contourner ce probl`eme, on r´esout :

L 11

l 21

L 31

0

1

0

0

0 ·

I

u

u

12

22

α

=

a

a

a

12

22

32

et on obtient α = u 22 · l 32 (il restera `a effectuer la division).

3 Travail demand´e

Vous devez ´ecrire deux programmes en C. L’un prend en argument une matrice creuse et calcule sa d´ecomposition LU creuse (on ´ecrit la d´ecomposition sous forme d’une seule matrice dans un fichier). En- suite, un programme prend en argument un fichier contenant la d´ecomposition LU et un fichier contenant un vecteur creux, puis g´en`ere la solution du syst`eme lin´eaire et l’´ecrit dans un fichier. Vous pouvez vouloir calculer ensuite le produit matrice-vecteur pour v´erifier que la solution calcul´ee est bien une solution. Une petite perte de pr´ecision est possible. Vous avez essentiellement deux possibilit´es : calculer le pattern (c.a.d. l’emplacement des entr´ees non- vides) de L et U `a la vol´ee, en mˆeme temps que les coefficients. Ou bien calculer d’abord le pattern, puis les coefficients ensuite. La deuxi`eme solution semble avoir l’approbation des experts, car elle simplifie au maximum la partie “num´erique” du calcul, qui est cens´ee ˆetre la plus lourde, et permet de l’ex´ecuter le plus vite possible. Enfin, pour ce projet, vous pouvez faire comme bon vous semble. Votre programme devra lire les matrices dans des fichiers au format suivant : la premi`ere ligne du fichier contient, s´epar´e par des espaces, les dimensions de la matrice puis le nombre de coefficients non- nuls. Toutes les lignes suivantes contiennent, s´epar´es par des espaces, deux entiers et un flottant. Chaque ligne d´ecrit un coefficient de la matrice. Par exemple, la matrice suivante :

est d´ecrite par le fichier :

5

5

8

1

1

1.000

2

2

1.050

3

3

1.500e-02

1

4

6

4

2

2.505e+02

4

4

-280

4

5

33.32

5

5

12

1

0

0

0

0

0

10.5

0

250.5

0

0

0

.015

0

0

3

6

0

0

280

0

0

0

0

33.32

12

R´ef´erences

[1] Thomas H. Cormen, Clifford Stein, Ronald L. Rivest, and Charles E. Leiserson. l’algorithmique. Dunod, 2nd edition, 2001.

[2] Timothy A. Davis. Direct Methods for Sparse Linear Systems (Fundamentals of Algorithms 2). Society for Industrial and Applied Mathematics, Philadelphia, PA, USA, 2006.

Introduction `a

4