Sie sind auf Seite 1von 15

Quatrime partie IV Algorithmique

Principaux paradigmes
Diviser pour rgner Algorithmes rcursifs Principe de diviser pour rgner Ex. : Multiplication de Polynmes Ex. FFT Multiplication de matrices Programmation dynamique Distance de Levenshtein
A. Duret-Lutz

Alexandre Duret-Lutz

adl@lrde.epita.fr

18 dcembre 2009
2

Principes Chane de Multiplications de matrices Plus longue sous-squence commune Algorithmes gloutons Principe Distributeur de Monnaie Proprits gloutonnes Le problme de la loutre Codage de Human
2 / 60

A. Duret-Lutz

Algorithmique

1 / 60

Algorithmique

Diviser pour rgner


1

Algorithmes rcursifs
To understand what is recursion you must rst understand recursion.

Diviser pour rgner Algorithmes rcursifs Principe de diviser pour rgner Ex. : Multiplication de Polynmes Ex. FFT Multiplication de matrices Programmation dynamique Distance de Levenshtein
A. Duret-Lutz

Principes Chane de Multiplications de matrices Plus longue sous-squence commune Algorithmes gloutons Principe Distributeur de Monnaie Proprits gloutonnes Le problme de la loutre Codage de Human
3 / 60

Principe de la rcursivit On sait grer des cas simples. (Cas de bases) On sait passer d'un cas compliqu un cas plus simple. On passe des cas compliqus aux cas simples de proche en proche. Avantages Algorithmes concis et faciles prouver Inconvnient Une appel rcursif est assez coteux (temps & espace). On a souvent avantage implmenter des versions non-rcursives. Mais les compilateurs peuvent optimiser les recursions terminales : un appel rcursif en n de fonction est transform en boucle.
A. Duret-Lutz Algorithmique 4 / 60

Algorithmique

Exemple de rcursion terminale

Power(v , n) 1 if n = 0 then return 1 2 return v Power(v , n 1) L'appel Power n'est pas terminal : il y a une multiplication ensuite. Power(v , n) 1 return Power'(v , n, 1) Power'(v , n, res ) 1 if n = 0 then return res 2 return Power(v , n 1, v res ) Maintenant la rcursion est terminale, elle peut tre rcrite : Power'(v , n, res ) 1 if n = 0 then return res 2 n n1 3 res v res 4 goto 1
A. Duret-Lutz Algorithmique 5 / 60

Optimisation des appels terminaux


Pour un compilateur, au milieu d'une fonction Titi (. . .) toute instruction du type  return Toto (. . .)  (o Toto a la mme signature que Titi ) peut tre remplace par une mise jour des arguments suivie d'un goto au dbut de la fonction en question. Cela drcursive les recursions terminales, mais pas uniquement. Cela est fait par GCC partir de -O2 ou si -foptimize-sibling-calls est spci. Parmi les algorithmes vus, sont optimisables automatiquement : BinarySearch Heapify StochasticSelection Le dernier des deux appels rcursifs du quick sort (on a donc intrt y traiter la plus grosse des deux partitions)
A. Duret-Lutz Algorithmique 6 / 60

(tail call optimization)

Diviser pour rgner


Algorithmes en trois tapes : Diviser le problme en plusieurs sous-problmes plus simples Rgner, i.e., rsoudre les sous-problmes (rcursivement ou non) Combiner les rsultats obtenus pour chaque sous-problme en une solution globale. MergeSort et QuickSort sont des algorithmes  diviser pour rgner . (En anglais : divide en conquer algorithms.) Dans le cas de QuickSort l'tape de combinaison est vide. Le complexit est de la forme :
T (n) = D (n) + aT (n/b) + C (n)

Multiplication de Polynmes
P1 (x ) = an x n + + a1 x + a0 P2 (x ) = bn x n + + b1 x + b0 P3 (x ) = P1 (x )P2 (x ) = c2n x 2n + + c1 x + c0

On a ck =

On la rsout gnralement avec le thorme gnral.


A. Duret-Lutz Algorithmique 7 / 60

Problme : Multiplication de deux polynmes Entre : Les ai et bi Sortie : Les ci .


A. Duret-Lutz Algorithmique 8 / 60

i +j =k

ai bj .

Mthode simple
c0 = a0 b0 c1 = a0 b1 + a1 b0

Mthode  diviser pour rgner  (Karatsuba 1/3)


Entre c0 est cn : (n + 2)(n + 1)/2 multiplications. Entre cn+1 est c2n : (n + 1)n/2 multiplications. Total (n + 3)(n + 1)/2 multiplications. On a (n + 3)(n + 1)/2 (2n + 1) additions. Au nal (n2 ) oprations. Supposons P1 (x ) = q1 x + r1 et P2 (x ) = q2 x + r2 . Alors P3 (x ) = q1 q2 x 2 + (q1 r2 + r1 q2 )x + r1 r2 . Mais on peut aussi crire
P3 = q1 q2 x 2 + (q1 q2 + r1 r2 (r1 q1 )(r2 q2 ))x + r1 r2 .

. . . . . .

cn = a0 bn + + an b0 cn+1 = a1 bn + + an b1 c2n = an bn

On fait alors 3 multiplications au lieu de 4. Gnralisons : si degr(P ) = 2m 1 = n 1, alors P1 (x ) = an1 x n1 + + a1 x + a0 peut s'crire On utilise donc une approche diviser pour rgner.
Q1 (x )

P1 (x ) = (an1 x n/21 + + an/2 ) x n/2 + (an/21 x n/21 + + a0 ).


R1 (x )

P3 (x ) = x n Q1 (x )Q2 (x ) + x n/2 (Q1 (x )Q2 (x ) + R1 (x )R2 (x ) (R1 (x ) Q1 (x ))(R2 (x ) Q2 (x ))) + R1 (x )R2 (x )


A. Duret-Lutz Algorithmique 10 / 60

A. Duret-Lutz

Algorithmique

9 / 60

Mthode  diviser pour rgner  (Karatsuba 2/3)


Attend deux tableaux P1 et P2 de taille n (avec n = 2m ) reprsentant les coecients de deux polynmes de degr n 1. Retourne un tableau de taille 2n 1 contenant les coecients du produit. Karatsuba(P1 , P2 , n) 1 if n = 1 (1) 2 return [P1 [0] P2 [0]] n (n) 3 R1 P1 [0 : n 2 1]; Q1 P1 [ 2 : n 1] n 4 R2 P2 [0 : 2 1]; Q2 P2 [ n : n 1 ] (n) 2 n 5 T1 Karatsuba(R1 , R2 , 2 ) T (n 2) n n 6 T2 Karatsuba(Q1 , Q2 , 2 ) T(2) 7 T3 Q1 R1 ; T4 R2 Q1 (n) 8 T5 Karatsuba(T3 , T4 , n ) T (n 2 2) 9 X [0 : n 2] T2 ; X [n 1] 0; X [n : 2n 2] T 1 (n) 3n n 3n 10 X [ n (n) 2 : 2 2] X [ 2 : 2 2] + T1 + T2 + T5 11 return X (1)
A. Duret-Lutz Algorithmique 11 / 60

Mthode  diviser pour rgner  (Karatsuba 3/3)


On a directement :
T (n) =
(1) 3T (n/2) + (n)

si n = 1 si n > 1

Par application du thorme gnral (a = 3, b = 2, f (n) = (n) domine par nlog 3 ) on obtient :
2

T (n) = (nlog 3 ) = O(n1.59 )


2

A. Duret-Lutz

Algorithmique

12 / 60

Autre approche de la multiplication de polynmes


Un polynme de degr n 1 est dni de manire unique par ses n coecients. Il est aussi dni de manire unique par ses valeurs en n points dirents (cf. unicit du polynme de Lagrange). Multiplier deux polynmes reprsents par leurs valeurs prises aux mmes points est trs simple : (P Q )(x ) = P (x ) Q (x ). D'o l'ide de changer de reprsentation : Karatsuba (nlog 3 ) P1 P2 P = P1 P2 reprsentation par coecients
2

valuation d'un polynme


Combien cote l'valuation d'un polynme P de degr n 1 en un point x ?
v = an1 x n1 + an2 x n2 + + a1 x + a0 = (( ((an1 x + an2 )x + an3 )x + )x + a1 )x + a0

reprsentation par valeurs


A. Duret-Lutz

P1 P2

Produit terme terme (n)


Algorithmique

P = P1 P2
13 / 60

Eval(P , n, x ) 1 xi = 1 2 v = P [0] 3 for i from 1 to n 1 do 4 xi xi x 5 v v + P [i ] xi 6 return v 2n 2 mult., n 1 additions.


A. Duret-Lutz

Complexit ?

Complexit ?

EvalHorner(P , n, x ) 1 xi = 1 2 v = P [n 1] 3 for i from n 2 to 0 do 4 v (v x ) + P [i ] 5 return v n 1 mult., n 1 additions.


14 / 60

Algorithmique

valuation en n points
valuer un polynme de degr n 1 en un point cote (n). Il n'est pas possible de faire mieux. (Pourquoi ?) valuer un polynme de degr n 1 en n points coterait (n2 ) si l'on enchane les n valuations. Avec une telle complexit, il est inutile de chercher reprsenter un polynme par valeurs pour pouvoir le multiplier plus vite : la conversion initiale est dj plus chre que Karatsuba... Heureusement, en choisissant les points d'valuation astucieusement, on peut faire (beaucoup) mieux que (n2 ). L'astuce consiste valuer le polynme aux racines n-imes de l'unit :
k =e n
2 ik
n

FFT : Transforme de Fourier rapide (1/4)


Soit A un polynme de degr n 1 tel que n = 2m . Notons a le tableau des coecients de A(X ). La transforme de Fourier discrte (DFT) du tableau a est le tableau b = F (a) o
k) = b[k ] = A(n n 1 j =0 kj a[j ]n

A(x ) = a[n 1]x n1 + a[n 2]x n2 + + a[1]x + a[0]

k } = {1, i , 1, i }. Rappel : {4 k C'est la base de la transforme de Fourier rapide (FFT).


A. Duret-Lutz Algorithmique 15 / 60

pour k [[0, n[[

Un calcul naf de F (A) demande (n2 ) oprations. Le choix des points d'valuation nous permet de faire ces calculs plus rapidement avec une approche diviser pour rgner.
A. Duret-Lutz Algorithmique 16 / 60

FFT : Transforme de Fourier rapide (2/4)


L'ide : sparer a en deux tableaux Even(a) et Odd (a) forms respectivement des n/2 valeurs d'indices pairs et impairs.
b[k ] =
=
n1 kj a[j ]n

FFT : Transforme de Fourier rapide (3/4)


On voit apparatre la rcurrence :
k [[0, n[[, F (a)[k ] = k [[0, n[[, F (a)[k ] =
n1 j =0 n/21 j =0 kj a[j ]n kj k Even(a)[j ]n /2 + n n/21 km Odd (a)[j ]n /2

j =0 n/21

posons j = 2m ou j = 2m + 1
2km

m=0 n/21 m=0 n/21 m=0

a[2m]n

n/21 m=0

2km+k a[2m + 1]n

k a[2m](n )km + n
2

n/21

j =0 k k [[0, n/2[[, F (a)[k ] = F (Even(a))[k ] + n F (Odd (a))[k ]

m =0 n/21 km k km Even(a)[m]n/2 + n Odd (a)[m]n /2 m=0


Algorithmique 17 / 60

2 km a[2m + 1](n )

Pour trouver les termes de [[n/2, n[[ on s'appuie sur la priodicit des (k +n/2)j k +n/2 kj k. racines de l'unit : n = n = n /2 /2 et n
k [[0, n/2[[,
A. Duret-Lutz

k F (Odd (a))[k ] F (a)[k ] = F (Even(a))[k ] + n k F (Odd (a))[k ] F (a)[k + n/2] = F (Even(a))[k ] n


Algorithmique 18 / 60

A. Duret-Lutz

FFT : Transforme de Fourier rapide (4/4)


Calcul de la transforme discrte d'un tableau A de n lments (Cooley-Tukey, 1965). FFT(A, n) 1 if n = 1 then return A 2 for k from 0 to n/2 do 3 E [k ] A[2k ] 4 O [k ] A[2k + 1] 5 FE FFT(E , n/2) 6 FO FFT(O , n/2) 7 for k from 0 to n/2 1 do 8 t e 2i k /n FO [k ] //std::polar(1.,(2*k*M_PI)/n) 9 B [k ] FE [k ] + t 10 B [k + n/2] FE [k ] t 11 return B T (n) = 2T (n/2) + (n) = T (n) = (n log n)
A. Duret-Lutz Algorithmique

Transforme de Fourier inverse (1/2)


b [k ] =
n1 kj j =0 a[j ]n

peut tre vu matriciellement comme b = Wa o

1 1 1 1 1 2 n 1 n n n 1 2 ( n 1 ) 2 4 ij ] n n W = 1 n = [n . . . . ... . . . . . . . . 2 ( n 1 ) ( n 1 )( n 1 ) n 1 1 n n n 1 ij [n ] en considrant [pij ] = WW 1 . On a Montrons que W 1 = n (i j )k 1 1 ik kj pij = n . Clairement pii = 1. Et si i = j , k n n = n k n n ( ) 1 ( ) 1 1 1 i j k k =0 (n ) = 1 = 1 = 1 = 0. Donc P = Id . On en dduit que 1 n1 kj
i n

n n

a[k ] =

n j =0

b[j ]n

19 / 60

A. Duret-Lutz

Algorithmique

20 / 60

Transforme de Fourier inverse (2/2)


Connaissant b = F (a) comment utiliser F pour retrouver a ?
b[k ] =
n1 j =0 kj a[k ] = 1 a[j ]n n n1
kj b[j ]n

Application au produit de polynmes


Attend deux tableaux P1 et P2 de taille n (avec n = 2m ) reprsentant les coecients de deux polynmes de degr n 1. Retourne un tableau de taille 2n contenant les coecients du produit. ProductFFT(P1 , P2 , n) 1 A[0 : n 1] P1 ; A[n : 2n 1] 0 (n) 2 B [0 : n 1] P2 ; B [n : 2n 1] 0 (n) 3 FA FFT(A, 2n) (n log n) 4 FB FFT(B , 2n) (n log n) 5 for k in 0 to 2n 1 (n) (n) 6 FR [k ] FA[k ] FB [k ] 7 R FFT(FR , 2n) (n log n) 8 for k in 0 to 2n 1 (n) 9 R [k ] R [k ]/n (n) 10 return R (n) T (n) = (n log n)
A. Duret-Lutz Algorithmique

a[k ] =

j =0 n1 j =0

kj b[j ]n

b = F (a) a = F (b) n

On peut donc rutiliser la FFT pour calculer son inverse. Le surcot de (n) oprations (calculs des conjugus et divisions par n) tant ngligeable devant le cot en (n log n) de la FFT.
A. Duret-Lutz Algorithmique 21 / 60

22 / 60

Comparaison des trois produits de polynmes


produit naf (7,4 s) Mesure des implmentations des trois algorithmes de multiplication prsents, appliqus des polynmes de degr n croissant. 7s 6s 5s 4s 3s Karatsuba (1,4 s) 2s 1s FFT (0,14 s) 0s
23 / 60

Multiplication de matrices classique

Pour deux matrices A et B de taille n n, on calcule C


i [[1, n]], j [[1, n]],

ci , j =

= AB

avec

k =1

ai ,k bk ,j

Quelle est la complexit du calcul de tous les coecients de C ?

n=

A. Duret-Lutz

1500 2000 2500 3000 3500 4000 4500 5000 5500 6000 6500 7000 7500 8000 8500 9000 9500 10000 10500 11000 11500 12000 12500 13000 13500 14000 14500
Algorithmique

A. Duret-Lutz

Algorithmique

24 / 60

Multiplication de matrices rcursive


Pour cet algorithme et le suivant, on suppose que n est une puissance de 2 (c'est--dire n = 2m ) ; il est toujours possible de s'y ramener en compltant les matrices avec des lignes et des colonnes remplies de 0. n Dcoupons chacune de ces matrices en quatre blocs de taille n 2 2 :
A1,1 A1,2 A= , A2,1 A2,2 B1,1 B1,2 B= , B2,1 B2,2 C1,1 C1,2 C= C2,1 C2,2

Algorithme de Strassen
Comme dans l'algorithme prcdent, on suppose les matrices n dcoupes en quatre blocs de taille n 2 2. Posons
M1 M3 M5 M7
=(A1,1 + A2,2 )(B1,1 + B2,2 ) =A1,1 (B1,2 B2,2 ) =(A1,1 + A1,2 )B2,2 =(A1,2 A2,2 )(B2,1 + B2,2 )

On a alors :
C1,1 C1,2 C2,1 C2,2
=A1,1 B1,1 + A1,2 B2,1 =A1,1 B1,2 + A1,2 B2,2 =A2,1 B1,1 + A2,2 B2,1 =A2,1 B1,2 + A2,2 B2,2

M2 =(A2,1 + A2,2 )B1,1 M4 =A2,2 (B2,1 B1,1 ) M6 =(A2,1 A1,1 )(B1,1 + B1,2 )

on a alors

C1,1 =M1 + M4 M5 + M7 C2,1 =M2 + M4

Ceci suggre un algorithme rcursif de calcul des coecients de C . Quelle est sa complexit ?
A. Duret-Lutz Algorithmique 25 / 60

Ceci suggre un second algorithme rcursif de calcul des coecients de C . Quelle est sa complexit ?
A. Duret-Lutz Algorithmique 26 / 60

C1,2 =M3 + M5 C2,2 =M1 M2 + M3 + M6

Programmation dynamique
1

Programmation dynamique
Principes Chane de Multiplications de matrices Plus longue sous-squence commune Algorithmes gloutons Principe Distributeur de Monnaie Proprits gloutonnes Le problme de la loutre Codage de Human
27 / 60

Diviser pour rgner Algorithmes rcursifs Principe de diviser pour rgner Ex. : Multiplication de Polynmes Ex. FFT Multiplication de matrices Programmation dynamique Distance de Levenshtein
A. Duret-Lutz

Il s'agit encore une fois de dnir le problme rcursivement Mais cette fois-ci, les dirents sous-problmes partagent des sous-sous-problmes. On veut viter de recalculer chaque sous problme plusieurs fois On stocke ces rsultats dans un tableau.

Algorithmique

A. Duret-Lutz

Algorithmique

28 / 60

Distance de Levenshtein (1/4)


Distance d'dition entre deux chanes (string edit distance ). Si a, b sont deux lettres et u , v deux mots :
dL (u , ) = |u | dL (, v ) = |v | dL (au , bv ) = min (1 + dL (u , bv ), 1 + dL (au , v ), a=b + dL (u , v ))

Distance de Levenshtein (2/4)


Implmentation rcursive directe : StringEditDistance(u , v ) 1 if length(u ) = 0 then 2 return length(v ) Notons n = |uv |. 3 if length(v ) = 0 then 4 return length(u ) T (n) = (1) + T (n 1) 5 if u [0] = v [0] then + T (n 1) + T (n 2) 6 cost 0 T (n) (1) + 2T (n 1) 7 else T (n) = (2n ) 8 cost 1 9 d1 StringEditDistance(u [1..], v ) 10 d2 StringEditDistance(u , v [1..]) 11 d3 StringEditDistance(u [1..], v [1..]) 12 return min(1 + d1 , 1 + d2 , cost + d3 )
A. Duret-Lutz Algorithmique 30 / 60

Exemples :
dL (maks , make ) = 1 dL (maks , emacs ) = 2

1 remplacement 1 insertion, 1 remplacement

A. Duret-Lutz

Algorithmique

29 / 60

Distance de Levenshtein (3/4)


Exercice : reprsenter l'arbre correspondant au calcul rcursif de StringEditDistance("bank","brake"). Reprer les nuds identiques. En fusionnant les nuds identiques, on peut obtenir la grille suivante, o par exemple on voit que la distance entre "ban" et "bra" est 2. Chaque entre de cette grille se calcule partir des voisins nord, nord-ouest, et ouest. b r a k e 0 1 2 3 4 5 b 1 0 1 2 3 4 a 2 1 1 1 2 4 n 3 2 2 2 2 3 k 4 3 3 3 3 3 Les lignes de ce tableau peuvent tre calcules en crasant la prcdente.

A. Duret-Lutz Algorithmique

Distance de Levenshtein (4/4)


StringEditDistance(u , v ) (|u | |v |) oprations 1 for i 0 to length(u ) do 2 D [i ] i 3 for j 1 to length(v ) do 4 old D [0] 5 D [0] j 6 for i 1 to length(u ) do 7 if u [i 1] = v [j 1] then 8 cost 0 9 else 10 cost 1 11 tmp min(1 + D [i 1], 1 + D [i ], cost + old ) 12 old D [i ] 13 D [i ] tmp 14 return tmp
A. Duret-Lutz Algorithmique

31 / 60

32 / 60

Programmation dynamique : principes


Le mot  programmation  n'est pas celui qu'on imagine. Il faut le prendre dans le sens  plannication ,  optimisation  : on cherche un meilleur chemin parmi des choix possibles. L'approche s'applique aux problmes qui ont des sous-structures optimales. C'est--dire que l'on peut construire une solution optimale partir de solutions optimales pour des sous-problmes. Casser le problme en sous-problmes plus petits. Trouver des solution optimale pour ces sous-problmes, par la mme mthode, rcursivement. Utiliser les solutions optimales de chaque sous-problme pour trouver une solution optimale du problme original. chaque tape, mmoizer le rsultat, c'est--dire sauvegarder le rsultat correspondant chaque entre, pour ne pas le recalculer.
A. Duret-Lutz Algorithmique 33 / 60

Chane de multiplications de matrices 1/10


Soient n matrices A1 , A2 , . . . An dont on veut calculer le produit A1 A2 An . On peut valuer cette expression aprs l'avoir parenthse pour lever toute ambigut sur l'ordre des multiplications. La multiplication de matrices tant associative, le rsultat est indpendant du parenthsage.
A1 A2 A3 A4 = (A1 (A2 (A3 A4 ))) = (A1 ((A2 A3 )A4 )) = ((A1 A2 )(A3 A4 )) = ((A1 (A2 A3 ))A4 ) = (((A1 A2 )A3 )A4 )
A. Duret-Lutz Algorithmique 34 / 60

Chane de multiplications de matrices 2/10


Le parenthsage peut avoir un impact sur le cot du produit. Le produit d'une matrice de taille p q par une matrice de taille q r gnre une matrice de taille p r aprs pqr multiplications. Soient trois matrices A1 , A2 et A3 de dimensions 10 100, 100 5 et 5 50. Combien de multiplications pour ((A1 A2 )A3 ) ? (A1 (A2 A3 )) ? Moralit ?
A. Duret-Lutz Algorithmique 35 / 60

Chane de multiplications de matrices 3/10


Problme Soient A1 , A2 , . . . An , n matrices de dimensions pi 1 pi . Comment choisir le parenthsage de A1 A2 An pour minimiser le nombre de multiplications scalaires ? Solution bovine On teste tous les cas possibles. Soit P (n) le nombre de parenthsages possibles pour n matrices. si n = 1 sinon P (n) dsigne aussi le nombre d'arbres binaires de n feuilles. On peut montrer que 1 n 4n C2n = 3/2 (1 + O(1/n)) P (n + 1) = n+1 n
P (n) =
n1 k =1 P (k )P (n k )

Nombre de parenthsages exponentiel en n.


A. Duret-Lutz Algorithmique

ne nombre de Catalan = C2

n n

n 1 C2 n

36 / 60

Chane de multiplications de matrices 4/10


Sous-structure optimale Nous notons Ai ..j la matrice rsultant de l'valuation du produit Ai Ai +1 Aj . Un parenthsage optimal de A1 A2 An spare le produit entre Ak et Ak +1 pour un certain k . Dans notre solution optimale on commence donc par calculer les matrices A1..k et Ak +1..n puis on les multiplie pour obtenir A1..n . Le cot du calcul est la somme des cots des calculs des matrices A1..k et Ak +1..n et de leur produit. Le parenthsage du sous-produit A1 Ak (et celui de Ak +1 An ) doit tre optimal : sinon, on le remplace par un parenthsage plus conomique, et on obtient un parenthsage global plus ecace que... le parenthsage optimal ! Une solution optimale une instance du problme de multiplication d'une suite de matrices utilise donc uniquement des solutions optimales aux instances des sous-problmes.
A. Duret-Lutz Algorithmique 37 / 60

Chane de multiplications de matrices 5/10


Dnition rcursive d'une solution optimale Sous-problme : cot minimum d'un parenthsage de
Ai Ai +1 Aj On note m[i , j ] le nombre minimum de multiplications scalaires pour Ai ..j . i , m[i , i ] = 0 car Ai ..i = Ai . Considrons i < j , et supposons le produit Ai Ai +1 Aj coup entre Ak et Ak +1 . Alors m[i , j ] = m[i , k ] + m[k + 1, j ] + pi 1 pk pj . On doit choisir k pour minimiser m[i , j ]. m[i , j ] =

A. Duret-Lutz

0 si i = j mini k <j {m[i , k ] + m[k + 1, j ] + pi 1 pk pj } si i < j On note s [i , j ] le k minimum pour Ai Ai +1 Aj .


Algorithmique

38 / 60

Chane de multiplications de matrices 6/10

BestCost(p, i , j ) 1 if i = j then return 0 2 m[i , j ] + 3 for k i to j 1 do 4 q BestCost(p , i , k ) + BestCost(p , k + 1, j ) + pi 1 pk pj 5 if q < m[i , j ] then m[i , j ] q 6 return m[i , j ] Si n = j i + 1, on a
T (n) = (1) +
=2
n 1 k =1 n1 k =1

Chane de multiplications de matrices 7/10


Le nombre de sous problme Ai ..j avec i j est restreint. Il y a n(n + 1)/2 = (n2 ) possibilits. L'algorithme BestCost rencontre chaque sous-problme un nombre exponentiel de fois d'o sa complexit. Cette proprit, dite des sous-problmes superposs, est celle qui permet de faire de la programmation dynamique. 0 si i = j mini k <j {m[i , k ] + m[k + 1, j ] + pi 1 pk pj } si i < j En rsout le problme diagonale par diagonale : On calcule m[i , j ] pour i = j , facile c'est 0. On calcule m[i , j ] pour i j = 1 en fonction des prcdents. On calcule m[i , j ] pour i j = 2 en fonction des prcdents. etc.
m[i , j ] =
39 / 60 A. Duret-Lutz Algorithmique 40 / 60

(T (k ) + T (n k ) + 1)

T (k ) + n = (2n )

A. Duret-Lutz

Algorithmique

Chane de multiplications de matrices 8/10


MatrixChain(p) 1 n length(p) 1 2 for i 1 to n do m[i , i ] 0 3 for l 2 to n do 4 for i 1 to n l + 1 do 5 j i +l 1 6 m[i , j ] + 7 for k 1 to j 1 do 8 q m[i , k ] + m[k + 1, j ] + pi 1 pk pj 9 if q < m[i , j ] then 10 m[i , j ] q 11 s [i , j ] k 12 return (m, s )
A. Duret-Lutz Algorithmique 41 / 60

Chane de multiplications de matrices 9/10


j

1
10

2
0

4
540

5
640

m
840

1
640

2
260

390 240 80 0 2

4
0

1200 15 0

100 0 5

5
10

2
A1

3
1

4
1
A2

5
3 2

3 3
A3

2 i 3 3
3 3
A4

4
A5

A1 A1 A2 A3 A4 A5

10 15 0 si i = j 15 8 m[i , j ] = 82 mini k <j {m[i , k ] + m[k + 1, j ] + pi 1 pk pj } 25 5 10 Meilleur parenthsage : ((A1 (A2 A3 ))(A4 A5 ))
A. Duret-Lutz Algorithmique 42 / 60

A2

A3

A4

A5

Chane de multiplications de matrices 10/10

Plus longue sous-squence commune (1/4)


Problme Entre : deux chanes, p.ex. "loutre" et "troupe". Sortie : une plus longue sous-squence commune, "oue" ou "tre". Approche bovine Il y a 2n sous-squences dans une squence de n lettres. Une telle aproche demande donc un temps exponentiel en la taille des chanes. Sous-structure optimale Notons X = x1 x2 xm et Y = y1 y2 yn les chanes d'entre, et Z = z1 z2 zk une PLSC. Notons de plus Xi le i eprxe de X , c.--d. Xi = x1 x2 xi . On a : xm = yn = zk = xm = yn et Zk 1 est une PLSC de Xm1 et
Yn1 xm = yn zk = xm = Z est une PLSC de Xm1 et Y xm = yn zk = yn = Z est une PLSC de X et Yn1
Algorithmique

L'algorithme MatrixChain possde trois boucles imbriques qui font chacune au plus n itrations. Un dcompte plus prcis permet de montrer T (n) = (n3 ).
T (n) = O(n3 )

A. Duret-Lutz

Algorithmique

43 / 60

A. Duret-Lutz

44 / 60

Plus longue sous-squence commune (2/4)


Dnition rcursive de la longueur :
0 C [i , j ] = C [i 1, j 1] + 1 max(C [i , j 1], C [i 1, j ])

Plus longue sous-squence commune (3/4)


LCS(X , Y ) 1 m length(X ) 2 n length(Y ) 3 for i 0 to m do C [i , 0] 0 4 for j 1 to n do C [0, j ] 0 5 for i 1 to m do 6 for j 1 to n do 7 if xi = yj then 8 C [i , j ] C [i 1, j 1] + 1 9 B [i , j ] 10 else if C [i 1, j ] C [i , j 1] then 11 C [i , j ] C [i 1, j ] 12 B [i , j ] 13 else 14 C [i , j ] C [i , j 1] 15 B [i , j ] 16 return (B , C )
A. Duret-Lutz Algorithmique

si i = 0 ou j = 0 si i , j > 0 et xi = yi si i , j > 0 et xi = yi

On voit tout de suite que la procdure pour calculer la longueur maximale sera en (mn) : il sut de remplir le tableau ligne par ligne jusqu' obtenir C [m, n]. Pour produire la PLSC il faut retenir les choix qui ont t faits, comme dans MatrixChain. On utilise un tableau B pour cela.
A. Duret-Lutz Algorithmique 45 / 60

46 / 60

Plus longue sous-squence commune (4/4)


L 0 T R O U P E 0 0 0 0 0 0 0

Algorithmes gloutons
1

O 0

U 0

T 0 1

R 0 2 2 2 2 2

E 0 Diviser pour rgner Algorithmes rcursifs Principe de diviser pour rgner Ex. : Multiplication de Polynmes Ex. FFT Multiplication de matrices Programmation dynamique Distance de Levenshtein
A. Duret-Lutz

0 0 0 0 0 0

0 0 1 1 1 1

0 0 2 2 2

1 1 2

1 1 2 2

2 2 2 3

Principes Chane de Multiplications de matrices Plus longue sous-squence commune Algorithmes gloutons Principe Distributeur de Monnaie Proprits gloutonnes Le problme de la loutre Codage de Human
48 / 60

A. Duret-Lutz

Algorithmique

47 / 60

Algorithmique

Algorithmes gloutons
Rsolvent un problme d'optimisation, comme la programmation dynamique. Leur mthode est compltement dirente. Un algorithme glouton rsoud un problme pas pas en faisant localement le choix qu'il estime le meilleur. Il espre ainsi trouver la meilleure solution globale. P.ex. un algorithme glouton du voyageur de commerce visite toujours la ville non-visite la plus proche de la dernire ville visite. Ingrdients : un ensemble de candidats pour crer la solution une fonction select, pour choisir le meilleur candidat ajouter la solution une fonction feasible vrie si un ensemble de candidats est faisable une fonction is_solution indique quand une solution a t trouve
A. Duret-Lutz Algorithmique

Principe d'un algorithme glouton


Notons C l'ensemble des candidats et S une tentative de solution. 1 while not is _solution(S ) and C = do 2 x select (C , S ) 3 C C \ {x } 4 if feasible (S {x }) then 5 S S {x } 6 return S

49 / 60

A. Duret-Lutz

Algorithmique

50 / 60

Rendu de Monnaie
La monnaie : C = {2, 2, 1, 1, .50, .50, .20, .20, .10, , .10}. Soit v = 1.90 rendre avec le moins de pices possible. L'algorithme glouton : is _solution(S ) = v = select (C , S ) = max C
feasible (S ) =
v
i S i

Proprits gloutonnes
Proprit du choix glouton : on peut arriver une solution globalement optimale en eectuant un choix localement optimal. Le choix peut dpendre des choix faits jusque l, mais pas des choix qui seront faits ensuite (e.g. solutions des sous-problmes). Dans le rendu de monnaie partir des pices v1 v2 vn on montre que pour tout montant v tel que vi < v vi +1 , il n'existe pas de solution optimale qui n'utilise pas vi +1 . Sous-structure optimale : une solution optimale du problme contient la solution optimale de sous-problmes. Dans le rendu de monnaie, si S {x } est une solution optimale pour rendre v partir de C , alors S est une solution optimale pour rendre v valeur (x ) partir de C \ {x }.
51 / 60 A. Duret-Lutz Algorithmique 52 / 60

i S i

La solution trouve : S = {1, .50, .20, .20}. Cette solution est-elle optimale ? Ici, oui. En gnral, cela dpend de C . Par exemple avec C = {1, .50, .30, .30, .30, .5, .5, .5} la solution gloutonne serait {1, .50, .30, .5, .5} et non {1, .30, .30, .30}.
A. Duret-Lutz Algorithmique

Le problme de la loutre (1/2)


Une loutre est au bord d'une rivre en train de pcher des poissons pour sa petite famille, les poissons ne psent pas tous le mme poids et ont des valeurs caloriques direntes. La loutre veut maximiser le nombre de calories qu'elle va rapporter sachant qu'elle ne peut porter qu'au plus 10 kilos de poisson. Si la loutre sait dcouper un poisson, elle peut appliquer une stratgie gloutonne. Elle choisit les poissons en commenant par celui dont le ratio calories/kilos est le plus lev ; elle dcoupe le dernier poisson pour ne pas dpasser 10kg. Sans dcoupage une stratgie gloutonne n'est pas applicable. P.ex. 3 poissons : La solution gloutonne utilise un poisson 2kg 6000kcal de 2kg et un de 4kg, alors que la 4kg 10000kcal solution optimale est 4kg+6kg. 6kg 12000kcal
A. Duret-Lutz Algorithmique 53 / 60

Le problme de la loutre (2/2) : Prog. Dyn.


Pour la loutre sans dcoupage, le problme a bien la proprit de sous-structure optimale (si on retire un poisson de x kg de la solution et du problme, et si la loutre ne peut porter que (10 x )kg alors la nouvelle solution est optimale) mais il n'a pas la proprit du choix glouton. On peut rsoudre le problme de la loutre (sans dcoupage) par la programmation dynamique... Notons wi et ci les poids et calories des dirents poissons. On note Sk ,w les calories de la solution optimale pour les k premiers poissons jusqu' concurrence du poids w . On a si k = 0 ou w = 0 si k > 0 et 0 < w < wk sik > 0 et wk w D'o un algorithme faisant 1 + k passes sur un tableau S [0..w ].
k

0 Sk ,w = Sk 1,w max(Sk 1,w , ck + Sk 1,w w )


A. Duret-Lutz Algorithmique

54 / 60

Codage de Human (1/6)


Le codage de Human est une mthode de compression de texte. Chaque caractre est reprsent de manire optimale par une chane binaire, appel un code. Pour conomiser de l'espace, on utilise des codes de longueur variables. Ce code est bas sur une proprit statistique : plus un caractre est frquent, plus son code est de longueur petite. Aucun code n'est prxe d'un autre code : on parle de codage prxe. (La dcompression est aise : on lit bit bit jusqu' reconnatre un mot du code.)

Codage de Human (2/6)


lettre a b c d e f frquence 45% 13% 12% 16% 9% 5% code de longueur xe 000 001 010 011 100 101 code de longueur variable 0 101 100 111 1101 1100 Un chier compos de 100000 caractres avec les frquences du tableau occupe 300000 bits avec les codes de longueur xe et 224000 bits avec le code de longueur variable. conomie : 25%.

A. Duret-Lutz

Algorithmique

55 / 60

A. Duret-Lutz

Algorithmique

56 / 60

Codage de Human (3/6)


Un arbre binaire peut tre utilis pour reprsenter n'importe quel codage binaire. Les artes de l'arbre sont tiquetes par des 0 (gauche) et 1 (droite). Le code de chaque lettre est donc un chemin dans l'arbre. Chaque feuille correspond une lettre donne. Dcoder un caractre se fait en suivant un chemin de la racine une feuille, le codage est l'opration inverse. On ajoute des cumuls de frquences sur les nuds.

Codage de Human (4/6)


100 a : 45 0 25 c : 12 0 1 1 0 b : 13 55 1 14 0 30 1 d : 16

0 1 e:9 f:5 Exemple de dcodage : 110001001101 = face .


A. Duret-Lutz Algorithmique 58 / 60

A. Duret-Lutz

Algorithmique

57 / 60

Codage de Human (5/6)


Un codage prxe optimal est forcment reprsent par un arbre binaire complet (sinon cela signie que prxes ne sont pas utiliss). L'arbre possde alors |C | feuilles (le nombre de lettres) et |C | 1 nuds internes. L'algorithme glouton de Human part d'un ensemble de |C | feuilles et eectue un ensemble de |C | 1 fusions pour construire l'arbre nal.
Human(C ) 2 n |C | 3 F C 3 for i 1 to n 1 do 6 z NewNode () 7 LeftChild (z ) x ExtractMin(F ) 7 RightChild (z ) y ExtractMin(F ) 7 freq (z ) freq (x ) + freq (y ) 9 Insert (F , z ) 16 return ExtractMin(F )
A. Duret-Lutz Algorithmique

Codage de Human (6/6)


Si la le de priorit F est implmente par un tas. T (n) = O(n) + (n 1)O(log n) = O(n log n) On peut montrer que Le codage de Human est un codage prxe optimal. (Il n'existe pas de codage prxe donnant de meilleure rduction.) La compression maximale accessible partir d'un codage de caractres peut tre obtenue avec un codage prxe. Le codage de Human est donc un codage de caractre optimal. Cela ne veut pas dire qu'il n'existe pas de meilleures compressions : simplement elles ne sont pas bases sur des codages de caractres.
59 / 60 A. Duret-Lutz Algorithmique 60 / 60

Das könnte Ihnen auch gefallen