Cours d’Algorithmique I Treizième fiche de TD – Preuves par récurrence – Divide & conquer Département Informatique, Réseaux et Multimédia — Polytech Marseille — usage interne Année 2016-17 Semaine du 12/12/16 1 Preuve par récurrence — Calcul de nombre de feuilles On considère des arbres pour établir des relations entre le nombre de feuilles et le nombre de nœuds internes dans ces arbres. Soient N F (A) le nombre de feuilles d’un arbre A et N I(A) son nombre de nœuds internes. Etablir que, pour tout arbre binaire A, on a la relation N F (A) = N I(A) + 1. 2 Preuve par récurrence — Une famille d’arbres ternaires Par analogie avec ce qui a été vu en cours, on considère la famille d’arbres ternaires suivante. La famille est caractérisée par le fait que tout nœud interne vérifie l’une des trois propriétés suivantes: 1) les trois fils du nœud sont des feuilles ; 2) les deux premiers fils du nœud sont des feuilles et le troisième fils est de profondeur 1 ; 3) les trois fils du nœud sont, dans l’ordre de profondeur k, k + 1 et k + 2. Donner les arbres en question, pour des profondeurs allant de 0 à 3. Montrer par récurrence que, pour toute profondeur p donnée, l’arbre est unique. 3 Une fonction bizarre ... int bizarre_rec ( int a , int b ) {if ( a == 1 || a == 2 || a == b ) return( 1 ) ; else if ( bizarre( b ) && a % b == 0 ) return( 0 ) ; else return( bizarre_rec( a , b + 1 ) ) ; } La fonction ci-contre a été vue en TD il y a quelques semaines. C’est un prédicat qui dit si le nombre fourni est premier ou non. En donner un preuve précise. int bizarre ( int a ) {assert( a > 0 ) ; return( bizarre_rec( a , 2 ) ) ; } En déduire ensuite un algorithme qui multiplie deux entiers binaires avec cette même complexité. 4 Divide and conquer — Multiplication de matrices de Strassen On souhaite calculer le produit de matrices C = A · B où A, B et C sont des matrices carrées de taille n. L’algorithme classique utilise n2 produits scalaires de vecteurs de taille n, donnant lieu à une complexité globale de n3 multiplications (les additions sont négligeables). ! ! On peut considérer les matrices découpées en quatre sous-matrices A11 A12 B11 B12 B= carrées de taille n/2, comme indiqué ci-contre. On obtient alors le A = A B21 B22 21 A22 résultat grâce à : C11 = A11 · B11 + A12 · B21 ; C12 = A11 · B12 + ! A12 · B22 ; C21 = A21 · B11 + A22 · B21 et C22 = A21 · B12 + A22 · B22 . C C 11 12 Il faut 8 multiplications de matrices de taille n/2 et la complexité C= C21 C22 de l’algorithme restera à n3 . V. Strassen a proposé (1969) un algorithme qui calcule les 7 produits Mi M1 = (A11 + A21 ) · (B11 + B22 ) ci-contre, pour obtenir le résultat grâce à des additions matricielles. M2 = (A21 + A22 ) · B11 Montrer que cette approche donne lieu à une complexité de nlog2 7 ' n2.807 . M3 = A11 · (B12 − B22 ) L’algorithme de Coppersmith-Winograd a une complexité de n2.376 . On ne M4 = A22 · (B21 − B11 ) sait pas s’il est optimal. M5 = (A11 + A12 ) · B22 M6 = (A21 − A11 ) · (B11 + B12 ) C11 = M1 + M4 − M5 + M7 C12 = M3 + M5 M7 = (A12 − A22 ) · (B21 + B22 ) C =M +M −M C =M −M +M +M 21 2 4 5 22 1 2 3 6