Algorithmique et Analyse d’Algorithmes Avant de commencer : attention semaine prochaine Échange de cours La semaine prochaine seulement : I Le cours d’algo aura lieu mardi 13 de 13h30 à 15h I Le cours de BDBC aura lieu jeudi 15 de 9h45 à 11h15 I Les amphis restent ceux prévus sur chaque horaire 1 / 32 Algorithmique et Analyse d’Algorithmes Algorithmique et Analyse d’Algorithmes L3 Info Cours 2 : algorithmes récursifs, analyse en moyenne Benjamin Wack 2016 - 2017 2 / 32 Algorithmique et Analyse d’Algorithmes La dernière fois I Qu’est-ce qu’un algorithme I Notion de coût I Notions de complexité (au pire) et ordres de grandeur Aujourd’hui I Comment écrire un algorithme récursif ? I Comment évaluer son coût ? I Comment évaluer l’efficacité d’un algorithme plus finement que dans le pire cas ? I Tri rapide 3 / 32 Algorithmique et Analyse d’Algorithmes Plan Algorithme récursif Schémas récursifs Analyse de coût Analyse en moyenne Contexte Méthode Tri rapide 4 / 32 Algorithmique et Analyse d’Algorithmes Algorithme récursif Schémas récursifs Notion d’algorithme récursif Aux constructions habituelles on ajoute la possibilité d’appeler l’algorithme lui-même sur une autre donnée. Calcul de la factorielle FACT(n) Données : un entier n Résultat : la valeur de n! = n × (n − 1) × . . . × 2 × 1 if n = 0 return 1 return n×FACT(n − 1) I I I caractéristique de l’algorithme, pas du problème non limité aux entiers, et particulièrement adapté aux structures récursives ce n’est pas de la triche ! Travail fourni = identifier la structure récursive du problème 6 / 32 Algorithmique et Analyse d’Algorithmes Algorithme récursif Schémas récursifs Structure Prérequis I Savoir directement résoudre le problème sur des cas de base I Savoir utiliser une (ou des) instances plus petites pour résoudre le problème « plus petit » = entier inférieur, sous-arbre, liste plus courte... mais pas seulement PAIR(n) Données : un entier n Résultat : booléen « n est-il pair ? » if n = 0 return Vrai else return PAIR(n − 2) Tout chemin d’exécution doit mener à un cas de base en temps fini. 7 / 32 Algorithmique et Analyse d’Algorithmes Algorithme récursif Schémas récursifs Écriture d’un algorithme récursif Un problème qui casse pas des briques On cherche à construire un mur de longueur n avec des briques de longueur 2 ou 3. 2+2+3+2+3+2 3+2+2+2+2+3 3+3+3+2+3 Exemples pour n = 14 Combien y a-t-il de possibilités distinctes ? 8 / 32 Algorithmique et Analyse d’Algorithmes Algorithme récursif Schémas récursifs Analyse du problème I I I I Données : la longueur n du mur (les tailles des briques sont fixées) (la récursivité ne peut donc porter que sur n) Utilisation de sous-problèmes : Une fois la première brique posée il reste un mur de longueur < n. Reconstruction de la solution : Les arrangements de longueur n = ceux commençant par une brique de longueur 2 + ceux commençant par une brique de longueur 3 Cas de base : n = 1 impossible ; pour n = 2 ou 3 un seul choix. BRIQUES(n) if n = 1 return 0 else if n = 2 ou n = 3 return 1 else return BRIQUES(n − 2) + BRIQUES(n − 3) 9 / 32 Algorithmique et Analyse d’Algorithmes Algorithme récursif Schémas récursifs Exemple : Conversion en base 2 Spécification Étant donné un entier n, on cherche à produire à l’écran l’écriture binaire de n. Idée On sait que : I n % 2 donne le dernier bit I les bits les plus à gauche sont aussi ceux de n/2. Remarque Le problème ne se résout pas naturellement de manière impérative : il faut « commencer par la fin ». 10 / 32 Algorithmique et Analyse d’Algorithmes Algorithme récursif Schémas récursifs Exemple : Conversion en base 2 (suite) Structure récursive I Les cas n = 0 et n = 1 sont connus. I On sait résoudre le problème si on a résolu l’instance n/2. Écriture binaire d’un entier ECRITURE_BINAIRE(n) if n < 2 Écrire n else ECRITURE_BINAIRE(n/2) Écrire n % 2 Un algorithme récursif ne se termine en général pas par l’appel récursif. Et si on voulait stocker le résultat dans un tableau ? 11 / 32 Algorithmique et Analyse d’Algorithmes Algorithme récursif Analyse de coût Retour sur la factorielle Rappel Le coût de l’appel d’une procédure est : I le coût du corps de la procédure pour ses paramètres d’appel I plus le coût de l’évaluation de ses paramètres. Calcul de la factorielle FACT(n) if n = 0 return 1 return n × FACT (n − 1) CFACT (0) = 0 D’où CFACT (n) = 2 + CFACT (n − 1) La fonction de coût d’un algorithme récursif obéit généralement elle-même à une équation récursive. 13 / 32 Algorithmique et Analyse d’Algorithmes Algorithme récursif Analyse de coût Quelques équations récursives classiques Coût arithmétique Si C (n) = a + C (n − 1) alors C (n) = a × n + C (0) = O(n) Équations linéaires simples Si C (n) = C (n − 1) + f (n) alors C (n) = C (0) + f (0) + f (1) + · · · + f (n) = C (0) + Pn i=0 f (i) Comme C (0) est constant on peut généralement l’ignorer. En particulier Pn i=1 1 = n = O(n) ; Pn i=1 et de manière plus générale i= Pn i=1 n(n+1) 2 = O(n2 ) i k = O(nk+1 ). 14 / 32 Algorithmique et Analyse d’Algorithmes Algorithme récursif Analyse de coût Quelques équations récursives classiques (2) Coût géométrique Si C (n) = a × C (n − 1) (avec a > 1) alors C (n) = an × C (0) = O(an ) Équations linéaires multiples Plus généralement si on a C (n) = a1 C (n − 1) + a2 C (n − 2) + . . . ak C (n − k) alors sauf cas pathologique on obtient une solution de la forme C (n) = O(nk−1 λn ). autrement dit une croissance au moins exponentielle. 15 / 32 Algorithmique et Analyse d’Algorithmes Algorithme récursif Analyse de coût Cas particuliers Calcul de coût direct Il est parfois possible de donner directement le coût. Ex : l’algorithme d’écriture binaire effectue clairement blog2 (n)c divisions. Chaque appel compte A(n) if n = 0 return 1 else return A(n-1) + A(n-1) + 1 I mathématiquement équivalents I algorithmiquement très différents B(n) if n = 0 return 1 else return 2×B(n-1) + 1 16 / 32 Algorithmique et Analyse d’Algorithmes Algorithme récursif Analyse de coût Cas particuliers (2) PGCD SOUSTRACTIONS (a, b) Données : Deux entiers a et b non nuls Résultat : Le plus grand diviseur commun à a et b if a = b return a else if a > b return SOUSTRACTIONS (a − b, b) else return SOUSTRACTIONS (b, a) « Décroissance » des données en un sens à préciser 17 / 32 Algorithmique et Analyse d’Algorithmes Analyse en moyenne Contexte Motivation Recherche séquentielle en table RECH_SEQ(e, T , n) Données : l’élément e à rechercher, un tableau T de taille n Résultat : le premier indice i tel que T [i] = e, ou −1 s’il est absent i =0 while i < n et puis T [i] 6= e i =i +1 if i < n return i else return −1 Complexité au pire I Pire cas facile à exhiber : e absent de T ou en dernière position I d’où CRECH_SEQ (n) = O(n) 19 / 32 Algorithmique et Analyse d’Algorithmes Analyse en moyenne Contexte Plus finement I Pour tous les autres cas on fait strictement moins de n comparaisons ! I Ce genre d’algorithme est utilisé de façon répétée : le coût d’une exécution « au pire » n’est pas très informatif. Idée : moyenne de coût de plusieurs exécutions On « lisse » les écarts de coûts en prenant en compte les différentes instances possibles : moy CA (n) = moyenne(coût(d)) pour toutes les données d de taille n Mais une moyenne uniforme est-elle représentative ? 20 / 32 Algorithmique et Analyse d’Algorithmes Analyse en moyenne Méthode Calcul de coût moyen Présupposé indispensable Modèle probabiliste de répartition des données i.e. pour une taille n fixée, probabilité pour chacune des données d possibles qu’elle soit donnée en entrée à l’algorithme Il doit correspondre à une réalité d’utilisation : I recherche dans un dictionnaire : la plupart du temps le mot existe I accès mémoire : l’élément recherché est souvent au début (cache) I les algorithmes de tri reçoivent souvent des données presque triées I ... Formule générale : moyenne pondérée X moy CA (n) = d de taille P(d) × coût(d) n 22 / 32 Algorithmique et Analyse d’Algorithmes Analyse en moyenne Méthode Fin de l’exemple : recherche en table Deux paramètres sont nécessaires : I probabilité P(e ∈ T ) notée p I dans le cas où e ∈ T , on supposera équiprobable de le trouver à chacun des indices 0..n − 1. On trouve alors : moy CRECH_SEQ (n) = (1 − p) × n + p × = (1 − p)n + = (1 − p)n + moy En particulier si p = 1 on a CRECH_SEQ (n) = n P i=1 p n(n+1) n 2 p n+1 2 1 ni n+1 2 23 / 32 Algorithmique et Analyse d’Algorithmes Analyse en moyenne Méthode En pratique I L’analyse au pire et au mieux donne déjà des informations sur la complexité moyenne : moy min max CA (n) ≤ CA (n) ≤ CA (n) I Regrouper les données de même coût : moy CA (n) = ... X c × P({d de coût c}) c I Parfois un modèle simplifié s’impose pour que les calculs soient faisables : I I minimiser les paramètres privilégier l’équiprobabilité (P(d) = 1 ) nombrededonnéesdistinctes 24 / 32 Algorithmique et Analyse d’Algorithmes Tri rapide Le tri rapide I aussi appelé QuickSort, Tri par segmentation... I inventé par Tony Hoare en 1961 I utilisé dans de nombreuses librairies comme tri « de référence » Quelques caractéristiques I fondamentalement récursif I en place (pas besoin de tableau auxiliaire) I non stable (les éléments « égaux » ne conservent pas leur ordre initial) 26 / 32 Algorithmique et Analyse d’Algorithmes Tri rapide Principe général D A E C B F E C B F F E 1. Choisir un élément : le pivot D A 2. Partitionner le tableau selon ce pivot : I I éléments inférieurs au pivot à gauche éléments supérieurs au pivot à droite A C B D 3. Trier récursivement les deux sous-tableaux ainsi formés A B C D E F 27 / 32 Algorithmique et Analyse d’Algorithmes Tri rapide Schéma de l’algorithme TriSegmentation (E ) Donnée-résultat Un ensemble E de n éléments comparables Effet de bord E est trié par ordre croissant if E = 6 ∅ pivot := Extrait (E ) // retire l’élément pivot de E (E1 , E2 ) := Segmentation (E,pivot) // E1 éléments plus petits que pivot // E2 éléments plus grands que pivot Assemble ( TriSegmentation (E1 ), pivot, TriSegmentation (E2 )) À instancier avec les contraintes suivantes : I E est représenté dans un tableau I Segmentation en place I Après l’appel à Extrait on ne touche plus au pivot 28 / 32 Algorithmique et Analyse d’Algorithmes Tri rapide Conception récursive I Les appels récursifs opéreront sur des sous-tableaux ⇒ 2 paramètres en plus : les indices entre lesquels on travaille I Reconstruction triviale : E1 et E2 sont triés et leurs éléments sont bien placés par rapport au pivot I Cas de base : tableau de taille 0 ou 1 (déjà trié) TriSegmentation (T , g, d) Donnée-résultat Un tableau T d’éléments comparables Effet de bord T est trié par ordre croissant entre les indices g et d if g < d pivot := T [g] i := Partition (T , g, d, pivot) TriSegmentation (T , g, ?i − 1) TriSegmentation (T , ?i + 1, d) 29 / 32 Algorithmique et Analyse d’Algorithmes Tri rapide La procédure Partition Partition (T , g, d) Donnée-résultat Un tableau T d’éléments comparables Résultat : L’indice i de pivot correctement placé dans le tableau Effet de bord Les éléments de T entre les indices : I g et i − 1 sont tous inférieurs à pivot. i + 1 et d sont tous supérieurs à pivot. i =g while i < d if T [i + 1] ≤ pivot i =i +1 else Échanger T [d] et T [i + 1] d =d −1 I Échanger T [g] et T [i] return i 30 / 32 Algorithmique et Analyse d’Algorithmes Tri rapide Éléments de complexité I Partition peut s’écrire de diverses façons, toutes linéaires en d − g. I Évaluation des paramètres négligeable I D’où CTriSegmentation (d − g) = CPartition (d − g) +CTriSegmentation (i − 1 − g) +CTriSegmentation (d − i − 1) = O(d − g) +CTriSegmentation (i − 1 − g) +CTriSegmentation (d − i − 1) ... mais i est donné par Partition, donc dépend de la donnée. I Intuitivement : l’algorithme est efficace (resp. inefficace) quand le pivot est un élément médian (resp. extrême). I La suite en TD... 31 / 32 Algorithmique et Analyse d’Algorithmes Tri rapide En résumé Aujourd’hui I Un algorithme récursif profite de la présence de sous-problèmes pour résoudre un problème I La complexité en moyenne permet d’évaluer le comportement d’un algorithme dans une situation réaliste décrite par une distribution aléatoire I L’algorithme de tri rapide est récursif, peu performant au pire mais efficace en général La prochaine fois I Invariant I Correction d’un algorithme I Terminaison d’un algorithme Drapeau hollandais I 32 / 32 Algorithmique et Analyse d’Algorithmes Bonus Fonction 91 de McCarthy MC91 (n) if n ≤ 100 return MC91(MC91(n + 11)) else return n − 10 1/1