Programmation dynamique : Optimisation d un produit matriciel Option Informatique 2015
De quoi s agit-il? n matrices rectangulaires A 1,, A n. On veut calculer le produit B = A 1 A n. i {1,, n}, A i est de format p i 1 p i. Divers parenthésages sont envisageables. Ils donnent tous le même résultat (associativité), mais... peut-être pas avec la même efficacité!
Attention aux matrices en caml! Comment définir une matrice 10 10 d entiers? matrice = vecteur de vecteurs type = int vect vect let lgn = make_vect 10 0;; let mat = make_vect 10 lgn;; mat.(3).(1) 5;; mat;; on voulait modifier le terme (ligne 4, colonne 2)... c est raté! Le constater...
Attention aux matrices en caml! Solution correcte : mat = make_vect 10 [ ];; for i = 0 to 9 do mat.(i) make_vect 10 0 done;; mat.(3).(1) 5;; mat;; on peut aussi utiliser make_matrix
Produit de 2 matrices A = [ a i,j ] 1 i p 1 j q C = AB = [ c i,j ] 1 i p 1 j r et B = [ b i,j ] 1 i q 1 j r avec : (i, j) {1,, p} {1,, r}, c i,j = Algorithme naïf q k =1 a i,k b k,j
Produit de 2 matrices en caml let mult_matrices a b = let p = vect_length a in let q = vect_length a.(0) in let q = vect_length b in let r = vect_length b.(0) in if q <> q then failwith "produit impossible" else let c = make_matrix p r 0 in for i = 1 to p do for j = 1 to r do for k = 1 to q do c.(i-1).(j-1) c.(i-1).(j-1) + a.(i-1).(k-1) * b.(k-1).(j-1) done done done; c;; Coût = pqr multiplications
Parenthésages possibles pour n = 3 A 1 (A 2 A 3 ) (A 1 A 2 ) A 3 Total : 2
Parenthésages possibles pour n = 4 A 1 (A 2 (A 3 A 4 )) A 1 ((A 2 A 3 ) A 4 ) (A 1 A 2 ) (A 3 A 4 ) (A 1 (A 2 A 3 )) A 4 ((A 1 A 2 ) A 3 ) A 4 Total : 5
Impact du parenthésage sur le côut global A 1 de format 10 100, A 2 de format 100 5, A 3 de format 5 50. (A 1 A 2 ) A 3 10 100 5 + 10 5 50 = 7500 A 1 (A 2 A 3 ) 100 5 50 + 10 100 50 = 75000 Rapport de 1 à 10...!
Et si on les essaie tous? P n = nombre de parenthésages pour n matrices. P 1 = 1.
Et si on les essaie tous? P n = nombre de parenthésages pour n matrices. P 1 = 1. Pour tout n 2 : P n = n 1 k =1 P k P n k. P 10 = 4 862; P 20 = 1 767 263 190; P 30 > 10 15 C est beaucoup trop...! On peut montrer que P n = 1 n ( ) 2n 2 n 1 4n 1 n 3/2 π
Parenthésage optimal Structure nécessaire d un parenth. Opt. de A i A j : pour un certain k {i,, j 1} : parenth. opt. de A i A k + parenth. opt. de A k +1 A j Car sinon, on pourrait réduire strictement le nb de multiplications scalaires en remplaçant le parenthésage de A i A k ou de A k +1 A j par un parenthésage meilleur.
Parenthésage optimal Notation m (i, j) = nb minimal de multiplications pour A i A j. Objectif calculer m (1, n). Formule de récurrence 0 si i = j m (i, j) = min { } m (i, k ) + m (k + 1, j) + p i 1 p k p j si i < j On définit pour chaque (i, j) : s (i, j) = un entier k {i,, j 1} t.q. m (i, j) = m (i, k ) + m (k + 1, j) + p i 1 p k p j.
Calcul des m (i, j) et des s (i, j) Approche récursive complexité exponentielle.
Calcul des m (i, j) et des s (i, j) Approche récursive complexité exponentielle. Approche tabulaire :
Calcul des m (i, j) et des s (i, j) Approche récursive complexité exponentielle. Approche tabulaire : Calcul des m(i,i)
Calcul des m (i, j) et des s (i, j) Approche récursive complexité exponentielle. Approche tabulaire : Calcul des m(i,i+1)
Calcul des m (i, j) et des s (i, j) Approche récursive complexité exponentielle. Approche tabulaire : Calcul des m(i,i+2)
Calcul des m (i, j) et des s (i, j) Approche récursive complexité exponentielle. Approche tabulaire : Calcul de m(1,n)
Calcul des m (i, j) et des s (i, j) let calc_opt p = let n = (vect_length p) - 1 in let m = make_matrix (n+1) (n+1) 0 in let s = make_matrix (n+1) (n+1) 0 in for l = 2 to n do for i = 1 to n-l+1 do let j = i+l-1 in m.(i).(j) ; for k = i to j-1 do let q = m.(i).(k) + m.(k+1).(j) + p.(i-1) * p.(k) * p.(j) in if q < m.(i).(j) then ( m.(i).(j) q; s.(i).(j) k ) done done done; (m,s);;
Construction d une solution optimale Récursivement : ( Ai A s(i,j) ) ( As(i,j)+1 A j ) let rec aff_opt s i j = if i = j then ( print_char A ; print_int i ) else ( print_char ( ; aff_opt s i s.(i).(j); aff_opt s (s.(i).(j) + 1) j; print_char ) ; );;
Construction d une solution optimale let par_opt_et_nb_mult p = let (m,s) = calc_opt p in let n = (vect_length p) - 1 in aff_opt s 1 n; print_newline (); print_string "Nombre de multiplications = "; print_int m.(1).(n); print_newline () ;; par_opt_et_nb_mult [ 10;100;5;50 ];; ((A1A2)A3) Nombre de multiplications = 7500 par_opt_et_nb_mult [ 56;27;171;10;100;5;50 ];; ((A1(A2(A3(A4A5))))A6) Nombre de multiplications = 58195
b y e