Introduction à la complexite

download Introduction à la complexite

of 11

Transcript of Introduction à la complexite

  • 8/8/2019 Introduction la complexite

    1/11

    Pour une discussion intressante de l'importance de la complexit algorithmique dans l'algorithmique en gnral et dans laprogrammation gnrique en particulier, voir cette entrevue avec Alex Stepanov , concepteur de la bibliothque STL .

    Voir aussi ce chouette texte comparant diverses stratgies pour rsoudre un problme a priori simple l'aide d'outils de la bibliothquestandard de C++.

    Voici une petite introduction (informelle) la joie du calcul de la complexit algorithmique .

    La complexit d'un algorithme est une mesure du temps [1] requis par l'algorithme pour accomplir sa tche, en fonction de la taille [2] de l'chantillon traiter.On dira d'un problme qu'il est aussi complexe que le meilleur algorithme connu pour le rsoudre.

    dans certains cas, par exemple celui des algorithmes de tri, on connat les algorithmes optimaux, donc pour lesquels il est possible dedmontrer (par l'absurde) qu'il est impossible de faire mieux que le meilleur algorithme connu. Dans la plupart des cas, toutefois, larecherche de l'algorithme optimal se poursuit.

    Cela peut sembler vident a posteriori, mais voil: pour calculer la complexit d'un algorithme donn, il convient tout d'abord de compter le nombred'oprations impliques par son excution.

    Les exemples donns ici le sont selon la notation C++, mais l'emploi de pseudocode aurait amplement suffi la dmonstration. Laplupart des bouquins d'algorithmique utilisent une notation se rapprochant de celle du langage Pascal.

    Notation O

    La notation la plus utilise pour noter la complexit d'un algorithme est la notation O (pour ordre de... ), qui dnote un ordre de grandeur . Par exemple,

  • 8/8/2019 Introduction la complexite

    2/11

  • 8/8/2019 Introduction la complexite

    3/11

  • 8/8/2019 Introduction la complexite

    4/11

  • 8/8/2019 Introduction la complexite

    5/11

    const int INDICE_INVALIDE = -1;int trouver_indice (const int tab[], const int TAILLE, const int val){

    int indice, plafond, plancher;bool trouve;

    //// Initialisation//indice = INDICE_INVALIDE;plafond = TAILLE - 1;plancher = 0;trouve = false;//// Traitement//while (!trouve && plancher tab[MILIEU]

    plancher = MILIEU + 1;}//// Production du rsultat//return indice;

    19 (3*(10/2)+4 ) oprations pour un tableau de 10 lments;154 (3*(100/2)+4 ) oprations pour un tableau de 100 lments;1504 (3*(1000/2)+4 ) oprations pour un tableau de 1000 lments;15004 (3*(10000/2)+4 ) oprations pour un tableau de 10000 lments;

    Notez toutefois que dans le pire cas, cet algorithme ncessitera :

    34 (3*(10)+4 ) oprations pour un tableau de 10 lments;304 (3*100+4 ) oprations pour un tableau de 100 lments;3004 (3*1000+4 ) oprations pour un tableau de 1000 lments;30004 (3*10000+4 ) oprations pour un tableau de 10000 lments;

    La croissance de complexit concrte est assez visible [5]. Mais puisque nous voulons ici prsenter la complexit logarithmique, nous procderons avec unemeilleure solutionune qui sera moins complexe selon notre dfinition de la complexit.

    La solution de complexit logarithmique

    Examinons maintenant une solution plus efficace, et analysonsrapidement le nombre d'oprations impliques (en fonction deTAILLE ) :

    On y compte quatre oprations avant le coeur du traitement, et uneautre tout juste aprs, ce qui fait en sorte que nous ayons cinq

    oprations faire quoi qu'il arrive .

    Le traitement en tant que tel peut se dcomposer comme suit :

    deux oprations dans le teste de la condition de poursuite de laboucle;

    trois oprations si, l'intrieur de la boucle, le premier test decondition est un succs (si on entre dans le if );trois oprations si, l'intrieur de la boucle, le premier test decondition choue mais le second est un succs (si on entre dans leelse if ); ettrois oprations si, l'intrieur de la boucle, le premier test decondition choue et qu'il en va de mme pour le second (si onentre dans le else ).

    Quoiqu'il arrive, on devra rpter 2+3 , donc cinq oprations uncertain nombre de fois . La grande question ici est : combien de fois ?

  • 8/8/2019 Introduction la complexite

    6/11

    }Nous n'entrerons pas dans les calculspas qu'ils soient inintressants,mais simplement parce qu'ils sont un peu plus mathmatiques que ce quece cours est en droit de visersinon pour faire remarquer qu' chaque itration, il peut se produire une de trois choses suivantes :

    ou on trouve la valeur recherche (cas du if ), ce qui complte la tche;ou on rduit la taille de l'chantillon de moiti pour n'en explorer que la moiti infrieure, ayant convenu que la valeur recherche ne peut pas setrouve au-dessus (cas du else if );ou on rduit la taille de l'chantillon de moiti pour n'en explorer que la moiti suprieure, ayant convenu que la valeur recherche ne peut pas setrouve en-dessous (cas du else ).

    Le pire cas est donc d'liminer successivement la moiti des lments restant explorer jusqu' ce qu'il n'en reste plus qu'un seul, qui sera alors le bon ouencore qui indiquera que l'lment cherch est absent du tableau. Analysons un peu plus ce pire cas :

    si on explore un tableau de 10 lments, on aura besoin au pire de 4 itrations (le tableau dbutera 10 lments, puis passera 5 , puis 2 ,

    puis un seul);si on explore un tableau de 100 lments, on aura besoin au pire de 7 itrations (le tableau dbutera 100 lments, puis passera 50 , puis 25 , puis 12 , puis 6 , puis 3 , puis un seul);si on explore un tableau de 1000 lments, on aura besoin au pire de 10 itrations (le tableau dbutera 1000 lments, puis passera 500 ,puis 250 , puis 125 , puis 62 , puis 31 , puis 15 , puis 7 , puis 3 , puis un seul).

    Vous pouvez vous amuser calculer d'autres valeurs. L'quation gnrale dit que cet algorithme est de complexit O(b+(i*log 2 n) ) o n est la tailledu tableau, b est le nombre incontournable d'oprations (ici, b==5 ) et i est la complexit d'une seule itration (ici, i==5 aussi, mais c'estaccidentel).

    Le tableau suivant prsente les le nombre d'oprations requis selon la complexit, pour diffrentes tailles de tableaux.

    Taille O( 3*TAILLE+4 ) O( 3*(TAILLE/2)+4 ) O( 5+5*log 2 (TAILLE) )

    10 34 19 25

    100 304 154 40

    1000 3004 1504 55

    10000 30004 15004 75

    100000 300004 150004 90

    1000000 3000004 1500004 105

    Ce qu'il faut retenir ici, c'est l'volution de la complexit. Simplement en traant la courbe des valeurs calculs pour certaines tailles choisies

  • 8/8/2019 Introduction la complexite

    7/11

    d'chantillons, on peut souvent voir s'il s'agit ou non d'une complexit logarithmique.

    Remarquez que la courbe de l'algorithme logarithmique est tellement peu accentue par rapport aux deux autres qu'on la voit peine sur le graphique (etencore: celui-ci ne prsente que des valeurs propres des tailles de tableau allant jusqu' 1000 , ce qui est bien petit en informatique.

    L'avantage de la solution de complexit logarithmique sur les deux autres est trs net. En fait, si on avait ajout au graphique les chantillons plus grands,la courbe logarithmique serait toutes fins pratiques disparue de notre champ de vision..

    On peut amliorer lgrement l'algorithme de complexit logarithmique en ajoutant quelques variables temporaires. C'est une optimisation locale, mais quipeut le rendre encore un petit peu plus efficace.

    On aurait alors :

  • 8/8/2019 Introduction la complexite

    8/11

    const int INDICE_INVALIDE = -1;int trouver_indice (const int tab[], const int TAILLE, const int val){

    int ndx, plafond, plancher,// pour optimiser le traitement dans la bouclendx_cur, val_cur;

    bool trouve;//// Initialisation//ndx = INDICE_INVALIDE;plafond = TAILLE - 1;plancher = 0;trouve = false;//// Traitement//while (!trouve && plancher ValeurCur plancher = ndx_cur + 1 ;}return Indice;

    }

    Questions de notation

  • 8/8/2019 Introduction la complexite

    9/11

    Nous avons crit plus haut que notre algorithme tait de complexitO(5+5*(n)) .

    On trouve donc, dans le calcul de sa complexit, une addition, unemultiplication, et un calcul de logarithme.

    Pourquoi dit-on alors qu'il s'agit l d'une complexit logarithmique ?

    Le raisonnement est le suivant :

    d'abord, l'addition d'une constante la complexit est un dtail inconsquent sur sa complexit relle. Plus la taille de l'chantillon traiter crot,moins l'addition d'une constante la complexit de l'algorithme devient importante. Ainsi, on simplifiera la complexit O(5+5*(log 2 n) ) pour

    obtenir O(5*(log 2 n) );ensuite, la multiplication par une constante a elle aussi de moins en moins d'importance sur la complexit relle de l'algorithme si on regarde sonpoids relatif sur des chantillons de grande taille. Ainsi, moins de faire des optimisations trs pointues, on dira souvent que la complexitO(5*(log 2 n) ) est quivalente O( log 2 n ). Ceci est moins vident dans le graphique prcdent, mais devient visible sur de grandes valeurs de n ;ainsi, notre algorithme, vu de faon gnrale, entre dans la grande classe des algorithmes complexit logarithmique .

    Algorithmes complexit linaire

    Nous avons dj vu un algorithme de complexit linaire un peu plus haut.

    Par complexit linaire , ou O(n) , on dnotera des algorithmes pour lesquels le nombre d'tapes effectuer variera en proportion directe de lataille de l'chantillon traiter (si l'chantillon crot par un facteur de 100 , la complexit sera accrue elle aussi par un facteur de 100 ).

    Pensez un algorithme qui parcourt chaque lment d'une liste chane, ou qui fait la somme des lments d'un tableau (ici O(3+n*5 ))...

  • 8/8/2019 Introduction la complexite

    10/11

    void echanger(int &a, int &b){

    int temp = a;a = b;b = temp;

    }void tri_bulle (int tab[], const int TAILLE){

    int somme_elements (const int tab[], const int TAILLE){

    int somme = 0;for (int compteur = 0; compteur < TAILLE; ++compteur)

    somme += tab[compteur]; // attention aux dbordements!return Somme;

    }

    ...ce qui donnerait, avec une liste chane ( O(2+n*5 ))...

    int somme_elements (Noeud *p){

    int somme = 0;while (p)

    {somme += p->valeur; // mettons; attention aux dbordements!p = p-> successeur;

    }return somme;

    }

    La simplification normale s'applique : on limine l'addition de constantes, puis la multiplication par des constantes, pour raliser que la croissance de la

    complexit dpend directement de la taille de l'chantillon. C'est l la donne intressante du calcul.

    Algorithmes complexit quadratique

    On dira d'un algorithme de complexit O(n 2 ) qu'il est de complexit quadratique . Vous comprenez srement le principe du calcul de la complexitmaintenant, alors nous n'entrerons pas ici dans les dtails.

    Nous n'irons pas plus loin dans notre description en surface de la complexit algorithmique. Notons seulement qu'il existe plusieurs autres niveaux decomplexit (par exemple, des complexits comme O(n 3 ), O(n 4 ), ou des complexits mettant en relation plusieurs variables comme O(n+m 2 )).

    Ce qui est vraiment retenir ici est qu'il est possible de calculer la complexit d'un algorithme, et de comparer la complexit relative de deux algorithmespour choisir le plus efficace. Certains algorithmes en apparence simples sont extrmement lents; il convient donc de choisir nos solutions avec prudence.

    Exemple d'algorithme complexit quadratique : un algorithme de tri bulles , comme dans leprogramme ci-aprs (qui met en ordre de manire inefficace les lments d'un tableau). L'algorithme

    propos droite est de complexit O((2+n)*(2+n) ) dans le meilleur cas, et O((2+n)*(5+n) )dans le pire cas; on parle donc aprs simplification d'un algorithme O(n*n ), ou plus simplementO(n 2 ).

    for (int i = 0; i < TAILLE; i++)

  • 8/8/2019 Introduction la complexite

    11/11

    for (int i 0; i < TAILLE; i++)for (int j = i+ 1; j < TAILLE; j++)

    if (tab[i] > tab[j])echanger (tab[i], tab[j]);

    }

    En terminant, il existe des horreurs algorithmiques (dites non polynomiales , dont lacomplexit ne s'exprime pas sous la forme d'un polynme) qu'il faut viter si on en a lechoix. On parle par exemple d'algorithmes de complexit O(2 n ). Vous pouvez vous amuser tracer la courbe dnotant le nombre d'oprations pour ce genre d'algorithme... a fait carrment peur! Pour en savoir plus, lisez cepetit texte .

    [1] Le terme temps doit tre pris ici au sens de nombre d'tapes requis pour arriver une solutionon parle donc d'un temps discret, pas continu. On peutexaminer le temps requis pour excuter un algorithme donn dans le meilleur cas possible, dans le pire cas possible, et dans le cas moyen.

    [2] Le terme taille doit tre pris ici au sens de nombre d'lments dans l'chantillon traiter par l'algorithme. Souvent, on utilisera un tableau contenant unnombre donn d'lments ou une chane de caractres dont on peut connatre le nombre de caractres constitutifs comme chantillon traiter, pourfaciliter les calculs.

    [3] En serait-il autant d'une fonction accdant au i -me lment d'une liste chane?

    [4] Une itration est un tour de boucle .

    [5] Nous verrons plus loin qu'il s'agit l d'un algorithme de complexit linaire (O(n ), o n est la taille du tableau).