Complexité 1. Définition de la complexité Les algorithmes se caractérisent par la taille des données qu'ils manipulent et l'ensemble des traitements qu'ils opèrent sur ces données. ex de taille : • nombres : le nombre lui même ou le nombre de bits (nb de chiffre en base 2) • liste, tableau, matrice, . . . : La nombre d'éléments • arbres : Nb de noeuds • graphes : Nb de noeud et/ou nb d'arêtes ex de traitement : • affectations • allocation mémoire (pour l'espace) • comparaisons • arithmétique ,. . . Pour un même problème, les algorithmes qui le résolve se classent selon leur complexité. Définition (complexité) : La complexité d'un algorithme est la mesure du nombre d'opérations fondamentales qu'il effectue sur un jeu de données. La complexité est exprimée comme une fonction de la taille du jeu de données. Soit Dn l'ensemble des données de taille n et T(d) le coût de l'algorithme sur la donnée d. Complexité au meilleur : Tmin(n) = min d ∈ D T d : plus petit nombre d'opérations qu'aura à exécuter l'algorithme sur un jeu de données de taille n. C'est la borne inférieure de la complexité de l'algorithme sur un jeu de données de taille n. n Complexité au pire : Tmax(n) = max d ∈D T d : plus grand nombre d'opérations qu'aura à exécuter l'algorithme sur un jeu de données de taille n. n Complexité en moyenne : Tmoy(n) = ∑ d ∈D n p d T d : moyenne des complexités pour les données de taille n avec p(d) la probabilité de voir apparaître la donnée d. Attention : les complexités au meilleur et au pire ne sont que des indications, elles montrent les limites au dessus et en deça desquelles l'algorithme n'ira pas. La complexité en moyenne montre le comportement général de l'algorithme et ne donne une bonne mesure que si le coût varie peu avec les données et si les cas extrêmes sont rares. Dans la pratique on s'intéresse à la complexité au meilleur et au pire. Définition (optimalité) : Un algorithme est dit optimal si sa complexité est la complexité minimale parmi les algorithmes de sa classe. 2. Exemple : le tri insertion • • principe : n éléments, dans un tableau T, indicés de 1 à n. On considère que les éléments de 1 à j-1 sont triés (donc au départ j = 2). On insère le jième élément à la bonne place par décalage. Algorithme : Tri Insertion coût pour j=2 à longueur(T) fois c1 n* v = T[j] c2 n-1 i = j-1 c3 n-1 tant que i>0 et T[i] > v c4 n ∑ tj ** j=2 T[i+1] = T[i] c5 n ∑ t j−1 j=2 i=i-1 c6 n ∑ t j−1 j=2 T[i+1] = v c7 n-1 * une affectation de plus pour le test de sortie de boucle (lorsque j = longueur(T)+1) ** tj correspond au nombre de fois que le test de la boucle tant que s'exécute (compris entre 1 et j). • Le coût total T n est donc : n n j=2 j =2 T n=c 1 nc 2c 3c7 n−1c 4 ∑ t jc 5c6 ∑ t j−1 au meilleur (si le tableau est trié) : t j vaut toujours 1 T n=c 1 nc 2c 3c7 c 4 n−1=c 1c 2c 3c 4c7 n−c 2c3 c 4c7 au pire, lorsque le tableau est trié dans l'ordre décroissant, t j= j , on sait que : n ∑ j=2 nn1 j= −1 et 2 n ∑ j−1= j=2 n n−1 2 n n1 nn−1 −1 c 5c 6 2 2 c c 1 c4 2 5 6 d'où : T n= c 4c5c6 n c 1c2 c 3 − − c7 n−c 2c3c 4c 7 2 2 2 2 donc : T n=c 1 nc 2c 3c7 n−1c 4 T(n) est de la forme an 2bnc , c'est donc une fonction quadratique de n. en moyenne : en moyenne, lors de l'insertion de l'élément v, il y a , dans la partie triée, autant d'éléments supérieurs à v que d'éléments inférieurs à v et donc que t j= j/2 . Cela conduit à une complexité quadratique similaire à celle du pire cas avec des facteurs ¼ au lieu de ½. La complexité en moyenne est parfois difficile à établir. Le cas « au pire » ou « au mieux » est souvent représenté par une seule configuration qu'il convient alors d'examiner. Pour le cas moyen, toutes les configurations doivent être considérées. Pour éviter une démarche exhaustive, un étude probabiliste ardue doit parfois être menée. 3. Notations • • • Pour n∈ℕ g n={ f n ∣ ∃c 1 , c 2 0 et n0 tel que 0c 1 g n f nc 2 g n ∀ nn0 } Une fonction f(n) appartient à g n si elle peut être, à partir d'un certain n0, encadrée par deux fonctions qui sont des multiples de g(n). On dit que g(n) borne asymptotiquement f(n). On note abusivement pour dire f n∈ g n . exemple 1 : montrons que f n= g n 2 2 1 2 n n=n 3 2 on doit déterminer trois constantes n 1, n2, c 0 avec 2 2 1 2 2 c 1 n n nc2 n pour nn 0 3 2 2 1 divisons par n2 : c 1 c 2 3 2n • On peut par exemple choisir c1 = 2/3, n0 = 3, d'où l'on déduit que l'inégalité fonctionne pour c2 = 5/6. 2 3 2 exemple 2 : montrons que n3 ≠ n 2 . c 1 n n c 2 n en divisant par n2 il vient c 1nc 2 on peut choisir c1 = 1 mais aucune constante n2 ne peut convenir car n est arbitrairement grand. • Pour donner une borne supérieure ou inférieure asymptotique, on utiliser les notations : O g n={ f n ∣ ∃c 0 et n0 tel que 0 f nc g n ∀ nn0 } (borne supérieure) Ω g n={ f n ∣ ∃c 0 et n 0 tel que 0c g n f n ∀ nn0 } (borne inférieure) 4. Usages • • • • • Nous nous intéressons quasi exclusivement à la complexité en temps des algorithmes. Il est parfois intéressant d'observer la complexité en espace mémoire, en bande passante requise, etc. Pour que les résultats de l'analyse d'algorithme soit comparable, il faut avoir un modèle de la machine sur laquelle l'algorithme sera implémenté. On prendra comme référence un modèle de machine à accès aléatoire et à processeur unique où les opérations sont exécutées l'une après l'autre sans opérations simultanées. Une complexité est généralement donnée en ordre de grandeur, lorsque n devient grand, les termes les moins significatifs sont négligés. Ainsi pour le tri par insertion, on notera : - meilleur cas : n - pire cas : n 2 - en moyenne : n 2 Les algorithmes sont en général comparés sur leur complexité au pire, aussi celle-ci est donné en O(f(n)). Classes de complexité : – constant : O1 On rencontre cette complexité quand toutes les instructions sont exécutées une seule fois qu'elle que soit la taille n du problème. – sub-linéaire : O log n Ce cas de figure se rencontre quand la taille du problème est divisée par une entité constante à chaque itération (ex : recherche dichotomique) – linéaire : O n boucle de 1 à n et le corps de la boucle effectue un travail de durée constante et indépendante de n. O n log n algorithmes quasi-linéaires où à chaque itération la taille du problème est divisée par une constante avec à chaque fois un parcours linéaire des données. – – polynomiale : O nk concerne des algorithmes considérés comme lents lorsque k > 3. boucles imbriquées chacune allant de 1 à n exponentielle : O k n pour k >= 2 donné, concerne des algorithmes considérés – comme impraticables (exemple : 2n pour les tours de Hanoï) factorielle : O n ! log 2 n n nlog 2 n n2 n3 2n 1 0 0 1 1 2 10 3,32 33,2 100 1 000 1 024 100 6,64 664 10 000 10 1 000 9,965 9965 1 000 000 10 6 1,26×10 9 30 ∞ ( 101000log 2 = 10300 ) 10 1 000 000 19;931 19 931 568 109 29,89 29897352854 1018 1027 ∞ 2n ~+1 (x 2) (=> si 2x plus de données, on ajoute une opération) x2 + 2n ≈ x2 x4 x8 carré 1012 1018 ∞ Si 109 opérations par secondes log 2 n n nlog 2 n n2 n3 2n 10-6 s 10-5 s 1 000 10-8 s 10-5 s 10-3 s 1s ∞ 1 000 000 2 x 10-8 s 2 x 10-2 s 103 s = 16,6 min 31 ans ∞ 109 3 x 10-8 s 30 s 109 sec = 31 ans 31 x 109 années ∞ 100 5. Dernier exemple : tri rapide écrire algorithme complexité partition : O(n) au pire : n appels à partition => O(n2) −3 10 s 400×109 siècles au mieux : tableau toujours coupé en deux : O(n log2 n) en moyenne : • Idée : choisir le pivot aléatoirement, mais quelle sera alors la complexité attendue. • la complexité est fonction du nombre de comparaisons (si on considère l'arbre des appels, à la racine, il y a n comparaisons, n-1 pour l'étage du dessous, etc., choisir un pivot amène à réduire le nombre d'étages). • analyse : remarquons tout d'abord que toutes les comparaisons se font avec le pivot. Soit x 1x 2 ...x n la suite des éléments triés. Quelle est la probabilité que les éléments x i et x j avec i j soient comparés ? C'est la probabilité que x i ou x j soit choisi comme pivot avant qu'ils soient séparés et cela par un pivot x k avec ik j . Dans toute suite x i , x i 1 ,... , x j , comme le pivot est choisi de manière xi x j soient comparés est aléatoire uniformément la probabilité que et 2 / j−i1 En prenant toutes les valeurs de i et j possibles, on trouve : n−1 n ∑ ∑ 2/ j−i 1 i=1 ji n−1 n−i1 = 2∑ i=1 n ∑ 1/ k k=2 n avec n Hn=∑ k=1 1 k le nième nombre harmonique 2 ∑ ∑ 1/k i=1 k=1 2nHn Puisque ln n≤Hn≤ln n 1 , tri rapide est : O n log n . Hn=ln n1 donc le temps attendu de l'algorithme