Structures de données IFT-2000 Abder Alikacem Analyse dalgorithmes Département dinformatique et de...

Post on 04-Apr-2015

105 views 0 download

Transcript of Structures de données IFT-2000 Abder Alikacem Analyse dalgorithmes Département dinformatique et de...

Structures de données

IFT-2000

Abder AlikacemAbder Alikacem

Analyse d’algorithmes

Département d’informatique et de génie logiciel

! +

Édition Septembre 2009

Plan

Notions d’analyses d’algorithmes Introduction Efficacité des algorithmes Analyse d’algorithmes Notation Ω (big-omega) Notation Θ Notation o (little-oh) Notation O (big-oh) Baromètres Comparaison entre les classes de complexité Règles de simplification Espace mémoire Compromis espace/temps

Algorithmique

Conception de méthodes pour la résolution de problèmes

Description des donnéesDescription des méthodesPreuve de bon fonctionnement

Complexité des méthodes

Efficacité : temps de calcul, espace nécessaire, ...Complexité intrinsèque, optimalité

Réalisation - implémentation

Organisation des objetsOpérations élémentaires

Efficacité des algorithmes

Habituellement on mesure l’efficacité d’un algorithme (correct) par sa vitesse.

• C’est-à-dire la durée que met l’algorithme à produire ses résultats.

On veut savoir combien de temps cela prend de résoudre une instance I du problème P:

• données(I) + Algorithme(P) ==> résultat(I).• temps mis ?

Efficacité des algorithmes

Ici, on s’intéresse au temps de calcul pour résoudre I:• en microsecondes, cycles d’horloge, nombre d’instructions

exécutées, etc..On prend en compte la taille des données(I):

•en bits, entiers, nombres d’enregistrements...Parfois, on considère aussi la mémoire nécessaire.

Efficacité des algorithmes

Approche empirique: mesure de performances.• essayer l’algorithme sur différents jeux de données bien

choisis.Avantages:

• résultats réalistes. Inconvénients:

• coûteux et long• dépend du processeur, de l’OS et de la charge • dépend de l’implémentation• pas toujours généralisable.

Efficacité des algorithmes

Approche algorithmique:• estimer le nombre de pas de l’algorithme en fonction de la taille des

données.Avantages:

• résultats généraux: on ne dépend pas du processeur, de l’OS ou de l’implémentation

• Estimation rapide et peu coûteux • évite de se fourvoyer.

Inconvénients:• prédictions approximatives.

Efficacité des algorithmes

Les approches empiriques et algorithmique sont complémentaires.• Utiliser l’approche algorithmique pour déterminer comment le

temps de calcul varie avec la taille des données.• Utiliser l’approche empirique afin d’obtenir un temps d’exécution

précis. (associé à une implantation, à un système d'exploitation , et à un type de compilateur particuliers)

Avantage: estimer le temps que prend l’algorithme pour des tailles de données plus grands que ceux des tests effectifs.

Efficacité des algorithmes

Comment choisir parmi les différentes approches pour résoudre un problème?

Exemple: Liste chaînée ou tableau?

2 objectifs à atteindre:1. Concevoir un algorithme facile à comprendre, coder et

déboguer.2. Concevoir un algorithme qui utilise de façon efficace les

ressources de l’ordinateur.

Efficacité des algorithmes

Objectif (1): concerne le génie logiciel

Objectif (2): Algorithmes et structures de données.

Lorsque l’objectif (2) est important, comment peut-on mesurer l’efficacité d’un algorithme?

Analyse d’algorithme

Analyse empirique: exécuter le programme Analyse assymptotique d’algorithmes

Ressources critiques: temps, espace mémoire,...

Facteurs affectant le temps d’exécution:machine, language, programmeur, compilateur, algorithme et structure de données.

Le temps d’exécution dépend du volume de l’entrée.

Analyse d’un algorithme

Analyse détaillée :• Avantage :Très précise• Désavantage : Long à calculer

Solution: Analyse asymptotique du comportement de l’algorithme lorsque le(s) paramètre(s) de l’algorithme tendent vers l’infini:

• Avantage: Parfois facile à calculer• Désavantage: Parfois moins précis

Mesure indépendante de l'implémentation : Temps d'exécution d'un algorithme = fonction(taille du problème)

Notation (big-omega)

Détermine une borne inférieureDéfinition formelle : f(n) = (g(n)) s’il existe deux constantes positives

n0 et c tel que cg(n) <= f(n) pour tout n>n0

f(n) = (g(n))

n

tem

ps

cg(n)

f(n)

n0

Notation (big-omega)

Étant donné deux fonctions f(n) et g(n), f(n) = (g(n)) ssi:• b > 0, n, f(n) / g(n) >= b

• Limn f(n) / g(n) +

Exemple

f(n) = 3n2+6n+4 et g(n) = n+3 limn f(n) / g(n) =

3n2+6n+4 est (n+3)

3n2+6n+4 est (n)

On dit « f(g) est en oméga g(n) »

Notation

Relation d’équivalence, correspond à la complexité exacte

Définition formelle : f(n) = (g(n)) s’il existe trois constantes positives n0,c1 et c2 tel que c1g(n) <= f(n) <= c2g(n) pour tout n>n0

f(n) = (g(n))

n

tem

ps

c1g(n)

f(n)

n0

n0

c2g(n)

Notation

Étant donné deux fonctions f(n) et g(n), f(n) = (g(n)) ssi: a,b > 0, n, a <= f(n) / g(n) <= b

• Limn f(n) / g(n)

Exemple:f(n) = 3n2+6n+4 et g(n) = n2+3

limn f(n) / g(n) = 3n2+6n+4 est (n2+3)

3n2+6n+4 est (n2)

Autre propriété:

f(n) = (g(n)) ssi f(n) = O(g(n)) et f(n) = (g(n))

Notation o (little-oh)

Détermine une borne supérieure stricteDéfinition formelle : f(n) = O(g(n)) s’il existe deux constantes positives

n0 et c tel que f(n) < cg(n) pour tout n>n0

f(n) = O(g(n))

n

tem

ps

cg(n)

f(n)

n0

Notation O (big-oh)

Détermine une borne supérieure Définition formelle : f(n) = O(g(n)) s’il existe deux constantes positives

n0 et c tel que f(n) <= cg(n) pour tout n>n0

f(n) = O(g(n))

n

tem

ps

cg(n)

f(n)

n0

Notation O (big-oh)

Cherche une fonction simple qui décrit le comportement de l’algorithme dans le pire cas.

• Exemples : O(n), O(n2),O(log n)L’analyse est simplifié selon les règles suivantes:

• Les constantes sont éliminées• Seul le monôme avec le degré le plus élevé est conservé

Exemple: f(n) = 3n2+5n+4 est O(n2)

0 10 20 30 40 50 600

500

1000

1500

2000

2500

3000

3500

4000

n (taille des données)

f(n) vs n2

f(n)

n2

f(n)

Exemple

void triSelection(int tab[MAXTAB], int n){

int PositionMin, temp, i, j;

for (i = n-1; i > 0; i--){

PositionMin = i;for (j = 0; j < i; j++){

if (tab[j] < tab[PositionMin]){

PositionMin = j;}

}temp = tab[i];tab[i] = tab[PositionMin];tab[PositionMin] = temp;

}}

void triSelection(int tab[MAXTAB], int n){

int PositionMin, temp, i, j;

for (i = n-1; i > 0; i--){

PositionMin = i; //b1for (j = 0; j < i; j++){

if (tab[j] < tab[PositionMin]){

PositionMin = j;}

}temp = tab[i];tab[i] = tab[PositionMin];tab[PositionMin] = temp;

}}

// i * a

//b2

Qu’est-ce qu’un baromètre?Comment ça fonctionne?Comment choisir le choisir ?

Baromètres

Baromètres

Qu’est-ce qu’un baromètre?•C’est une instruction qui s’exécute au moins autant de fois que

chacune des autres.Comment ça fonctionne?:

•Sélectionne un ensemble d’instructions significatives B={b1…bk}•On détermine le nombre d’exécution de chacun des baromètres

dans B•Temps total est la somme du nombres de d’exécution de chaque

baromètreComment choisir l’ensemble B?

•Mettre systématiquement certains types d’instructions(boucles,conditions,etc.)

•Estimer leurs nombres d’exécution maximal et minimal selon que l’on calcul le meilleur ou le pire cas.

•Simplifier B en gardant seulement les instructions qui s’exécutent le plus souvent.

Baromètres

Boucle tant que (pour): chaque fois qu’on passe dessus, il s’exécute le nombre de fois que la condition est vraie+1 (quand la condition est fausse).

Bloc interne d’un while: chaque fois qu’on passe sur le while, on passe sur ses instructions autant de fois que la condition est vraie.

Bloc interne d’un si: chaque fois qu’on passe sur le si et que la condition est vraie, on passe sur ses instructions

Autres instructions: chaque fois qu’on passe dessus, elles s’exécutent une fois.

Exemple (suite)

for (i = n-1; i>0; i--)

{Coût b1 /* PositionMin = i */

Coût i*a; /* pour exécuter la boucle interne*/

Coût b2; /* pour l'échange de tab[i] et tab[PositionMin] */

}

Exemple (suite)Exemple (suite)

1

1

)(n

i

baiS

b = b1 + b2

1

1

1

1

n

i

n

i

biaS

bnnnaS )1(2

)1(

bnabnaS 2

2

2

f(n) = an2 + bn + c

a = 0.0001724, b = 0.0004, c = 0.1

n f(n) an2 % du n2

125 2.8 2.7 94.7

250 11.0 10.8 98.2

500 43.4 43.1 99.3

1000 172.9 172.4 99.7

2000 690.5 689.6 99.9

Retour sur la notation O( ) (big-oh)

Évaluer le coût d'un algorithme Rechercher la fonction g(n) qui est la plus proche au dessus ou égale à f(n). Nous dirons alors f(n) est O(g(n)).

f(n) = O(g(n))

n

tem

ps

cg(n)

f(n)

n0

Notation O(g(n)) (big-oh)

Pour un nombre n assez grand f(n) an2

Temps d'exécution d'un algorithme A est f(n) = an2 + bn + c

g(n) = n2

On écrit : A est O(n2) On lit : l'algorithme A tourne en O(n2)

Classes :O(1), O(n), O(n2), O(n3), O(log n), …

f(n)

1

log n

n2n2n

Notation O(g(n)) (big-oh)

Classes :O(1), O(n), O(n2), O(n3), O(log n), …

n

Comparaison entre les classes

0

2

4

6

8

10

12

1 2 3 4 5 6 7 8 9 10

x

log( x )

xx VSVS log(x)log(x)

Comparaison entre les classes

0

5

10

15

20

25

30

35

40

45

50

0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30

x

x log( x )

xx VSVS x log(x)x log(x)

Comparaison entre les classes

0

50

100

150

200

250

300

350

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

x2

x log( x )

xx22 VSVS x log(x)x log(x)

Comparaison entre les classes

0

1000

2000

3000

4000

5000

6000

7000

8000

9000

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

x

x2

x3

xx VSVS xx22 VSVS xx33

Comparaison entre les classes

0

200000

400000

600000

800000

1000000

1200000

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

x3

2n

O(1) < O(log(n)) < O(n) < O(nlog(n)) < O(n2) < O(n3) < O(2n) < O(10n)

Comparaison entres les classes

O(1). Constant ou borné parfait.O(log(n)). Logarithmique excellentO(n). Linéaire très bonO(n log(n) ) bon.O(na) polynomial acceptableO(an) exponentiel inacceptableO(n!) factoriel beurk.

Augmenter la puissance du PC ?

0

5

10

15

20

25

30

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

x

x log( x )

x log( x )/1,2

Augmenter la puissance du PC

0

50

100

150

200

250

300

350

400

450

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

x2

0,5

Meilleur algorithme ou ordinateur?

On suppose que l’ordinateur utilisé peut effectuer 106 opérations à la seconde

Exemple (suite et fin)

1

1

)(n

i

baiS

b = b1 + b2

1

1

1

1

n

i

n

i

biaS

bnnnaS )1(2

)1(

bnabnaS 2

2

2

L’algorithme est en O(n2)

int minimumOn2(int tableau[],int taille){ int i,j; for(i=0;i<taille;i++) { j=0; while(j<taille && tableau[i]<=tableau[j] ) {

j++; } if(j == taille) return tableau[i]; } return tableau[i];}

int minimumOn(int tableau[],int taille){ int i,min = tableau[0]; for(i=0;i<taille;i++) {

if( tableau[i]<min) min = tableau[i]; } return min;}

Algorithme #1

Algorithme #2

Exemple: chercher le minimum dans un tableau d’entiers

Autres exemplesFusionner(x,y)

n = taille(x)+taille(y)pour i=1:n ….

v(i) = …..…..

fin

Résoudre(P(n))

Si n = 1 ,...c’est finiSinon

A=Résoudre(P(1:n/2))B=Résoudre(P(n/2+1:n))Fusionner(A,B)

pour i=1:n s = 0;pour j=i:n

s =s+A(i,j)*b(i)Finc(i)=s

fin

O(nlog2n)

O(n)

O(n2)Ab=c

Simplifier les séries

Sommes ou produits avec un nombre variable de termes.

Série Formule Résultat Exemple O()

constante k=1..N a aN 3+3+...+3(10 fois) N

somme de logs k=1..N log(k) log(N!) log(2)+log(3)+..log(100) N log(N)

arithmétique k=1..N k N(N+1)/2 1+2+...+10 N2

somme de carrés k=1..N k2 N(N+1)(2N+1)/6 1+22+32+..102 N3

somme de puissances

k=1..N ka (a entier)   1+23+33+..103 (a=3) Na+1

de polynômes de degré a

k=1..N Pa(k)   k=1..N k(k+1)..(k+a) Na+1

géométrique binaire

k=0..N 2k 2N+1-1 1+2+4+..+128 2N

géométrique entière

k=0..N ak (a entier) (aN+1-1)/(a-1) 1+3+9+..+81 (a=3) aN

factorielle k=1..N k N!2N (N/e)N 1*2*..*100 NN+0.5

Pire cas, meilleur cas et cas moyen

Toutes les entrées d’une longueur donnée ne nécessitent pas le même temps d’exécution.

Exemple. Recherche séquentielle dans un tableau de taille n: Commencer au début du tableau et considérer

chaque élément jusqu’à ce que l’élément cherché soit

trouvé.

Meilleur cas: O(1)

Pire cas: O(n)

Cas moyen: O(n/2)

Règles de simplification

1. Toujours négliger les constantes multiplicatives:

2n2 = O(n2)

2. Négliger les termes d’ordre inférieur:

5n2 + 3n = O(n2) + O(n) = O(n2)

3. O(n2) x O(n3) = O(n5)

Règles de simplification

Si f(n) O(g(n))

et g(n) O(h(n)),

alors f(n) O(h(n)).

Règles de simplification

Si f(n) O(kg(n))

où k >0 est une constante

alors f(n) O(g(n)).

Règles de simplification

Si f1(n) O(g1(n))

et f2(n) O(g2(n)),

alors f1(n) + f2(n) O(max(g1(n), g2(n))).

Exemple: n + nlog n O(nlog n)

Règles de simplification

Si f1(n) O(g1(n))

et f2(n) O(g2(n)) alors

f1(n)*f2(n) O(g1(n) * g2(n))

Exemple: (3n2 +3)(n2+5nlog n) O(n4)

Règles de simplification

Si p(n) est un polynôme de degré k

alors p(n) (nk)

Règles de simplification

logk (n) O(n)

pour toute constante k>0

logk(n) = O(n)

logk(n) cn

≤ 1

lim n→∞

logk(n) cn

= lim n→∞

k(k − 1)logk−2(n)

k logk−1(n) cn

lim n→∞

= cn

=

(règle de l’Hôpital) ...

=lim n→∞

k! cn = 0

Exemples

Exemple 1: a = b;

Temps constant: (1).

Exemple 2:

somme = 0;for (i=1; i<=n; i++) somme += n;

Temps: (n)

Exemples

Exemple 3:

somme = 0;for (i=1; i<=n; i++) for (j=1; j<=i; j++) somme++;

Temps: (1) + O(n2) = O(n2)

On peut montrer : (n2)

Exemples

Exemple 4:

somme = 0;for (j=1; j<=n; j++) for (i=1; i<=n; i++) somme++;for (k=0; k<n; k++) A[k] = k;

Temps: (1) + (n2) + (n) = (n2)

Exemples

Exemple 5:

somme = 0;for (k=1; k<=n; k*=2) for (j=1; j<=n; j++) somme++;

Temps: (nlog n)

Exemples

lSum = 0;

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

lSum++;

lSum = 0;

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

for( int j = 0; j < n; ++j)

lSum++;

Exemples

lSum = 0;

for( int i = 0; i < n; ++i ) lSum++;

for( int j = 0; j < n; ++j) lSum++;

lSum = 0;

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

for( int j = 0; j < n*n; ++j)

lSum++;

Exemples

lSum = 0;

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

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

lSum++;

lSum = 0;

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

for( int j = 0; j < n*n; ++j)

for( int k = 0; k < j; ++k)

lSum++;

Exemples

lSum = 0;

for( int i = 1; i <= n; ++i )

for( int j = 1; j < i*i; ++j)

if( j % i == 0) for( int k = 0; k < j; ++k)

lSum++;

Analyse de problèmes

Borne supérieure: Borne supérieur sur le meilleur algorithme connu.

Borne inférieure: Borne inférieure sur tous les algorithmes possibles.

Exemple: Trier un tableau de taille n nécessite O(n) étapes et peut se faire en O(nlog n) étapes.

Temps de calcul

Exemple

T(n) = O(n4).

De combien le temps de calcul augmente-t-il

si n est multiplié par 10 ?

T(n) = O(n4) = cn4

T(10n) = c(10n)4 = 104 cn4 = 10 000 T(n)

Logarithmes

logb(n) = k ⇔ bk = n

logb(n) = loga(n) / loga(b)

logb(n) = O(log(n)) (la base ne compte pas)

Le log apparaît lorsque systématiquement, on découpe le problème en deux morceaux de même taille

Logarithmes et exposants

log(xy) = log(x) + log(y)

log(xa) = alog(x)

a(b+c) = abac

abc = (ab)c

Temps de calcul

Exemple

T(n) = O(n logn).

De combien le temps de calcul augmente-t-il si n est multiplié par 10 ?

T(n) = cn log(n)

T(10n) = c(10n) log(10n)

T(10n) = 10cn log(n) + 10cn log(10)

T(10n) = 10T(n) + dn

Recherche binaire

point milieu données initialement triées

Analyse par télescopage

T(n) = T(n/2)  + O(1)

T(n/2) = T(n/4)  + O(1)

T(n/4) = T(n/8)  + O(1)

…. = ….

T(2) = T(1)  + O(1)

Analyse par télescopage

T(n) = T(n/2)  + O(1)

T(n/2) = T(n/4)  + O(1)

T(n/4) = T(n/8)  + O(1)

…. = ….

T(2) = T(1)  + O(1)

Analyse par télescopage

T(n) = T(n/2)  + O(1)

T(n/2) = T(n/4)  + O(1)

T(n/4) = T(n/8)  + O(1)

…. = ….

T(2) = T(1)  + O(1)

Analyse par télescopage

T(n) = T(n/2)  + O(1)

T(n/2) = T(n/4)  + O(1)

T(n/4) = T(n/8)  + O(1)

…. = ….

T(2) = T(1)  + O(1)

Analyse par télescopage

T(n) = T(n/2)  + O(1)

T(n/2) = T(n/4)  + O(1)

T(n/4) = T(n/8)  + O(1)

…. = ….

T(2) = T(1)  + O(1)

Analyse par télescopage

T(n) = T(n/2)  + O(1)

T(n/2) = T(n/4)  + O(1)

T(n/4) = T(n/8)  + O(1)

…. = ….

T(2) = T(1)  + O(1)

⇒ T (n)= T (1) + O(1) = O(log n) i=1

log n

Temps de calcul

Exemple

T(n) = O( log n).

De combien le temps de calcul augmente-t-il si n est multiplié par 1000 ?

T(n) = c log(n)

T(1000n) = c log(1000n)

T(1000n) = c log(n) + c log(1000)

T(1000n) = T(n) + 10c

Code source

template <typename Comparable>

int binarySearch( const vector<Comparable> & a, const Comparable & x )

{

int low = 0;

int high = a.size( ) - 1;

int mid;

while( low < high )

{

mid = ( low + high ) / 2;

if( a[ mid ] < x ) low = mid + 1;

else high = mid;

}

return ( low == high && a[ low ] == x ) ? low : NOT_FOUND;

}

Limitation de l’analyse

Si on pense que T(n) = Θ (f(n)), on peut valider expérimentalement T(n)/f(n) = c

Considérez des n suffisamment grands

Lors de l’analyse, on choisit souvent le pire des cas, mais celui-ci peut être significativement pire que le cas moyen !

Limitation de l’analyse

T(n)/f(n)

Espace mémoire

La quantité d’espace mémoire utilisé peut aussi être étudiée à l’aide de l’analyse asymptotique.

En général:Temps: Algorithme manipulant les

structures de données.

Espace: Structure de données

Compromis espace/temps

Il est souvent possible de réduire le temps d’exécution au prix d’augmenter l’espace mémoire et vice versa.

Fichiers compressésTable des valeurs d’une fonctionsInsérer un nœud dans une liste chaînée

Espace disque: Un programme sera d’autant plus rapide qu’il requiert peu d’accès disque.