Vous êtes sur la page 1sur 48

Trois questions essentielles

Un algorithme a pour objectif la résolution d'un problème. Est-ce que


l'algorithme donne :
une réponse ? → terminaison
la bonne réponse ? → correction
la bonne réponse en un temps acceptable ? → complexité

© Ramzi GUETARI 10/18/2021


Exemple : calcul de xn
3

On doit construire une suite y1 ; y2 ; … yk.


Règle du jeu: si j'ai déjà calcule y0 ; y1 ; ; yi − 1, alors je peux calculer
yi = yj × yk , pour 0 ≤ j ; k < i.
Question : trouver le meilleur algorithme tel que :
opt (n) = min {r / ∃ y0 ; y1 ; ; yr suite correcte avec yr = xn}.

© Ramzi GUETARI 10/18/2021


Exemple : calcul de xn
4

Méthode binaire
double power (double x, int n) {
double y = 1.0;
for (int i = 0; i < n; i++)
y *= x;
return y; n = 0, xn = 1
}
n = 1, xn = x
n pair xn = (xn/2)2
n impair xn = (xn/2)2 × x
double power (double x, int n) {
if (n == 0) return 1;
if (n == 1) return x;
if ((n % 2) == 0)
reurtn power(x, n div 2))**2;
return x * power(x, n div 2))**2;
}

© Ramzi GUETARI 10/18/2021


Evaluation d’un algorithme
5

Taille n Opérations
élémentaires

ENTRÉES ALGORITHME RÉSULTATS

Temps Ressources Espace

© Ramzi GUETARI 10/18/2021


Complexité des algorithmes
6

L’exécution d’un programme a toujours un coût. Il existe deux paramètres


essentiels pour évaluer ce coût :
le temps d’exécution : la complexité temporelle.
l’espace mémoire requis : la complexité spatiale.

Historique Vitesse µprocesseur Mémoire


Fin 70 10 MHz 16 Ko
Fin 90 400 MHz (× 40) 64 Mo (× 4000)
Années 2000 3 GHz (× 8) > 3 Go (× 50+)

© Ramzi GUETARI 10/18/2021


Complexité des algorithmes
7

Aujourd’hui, la complexité temporelle est le point sensible.


Objectifs : proposer des méthodes pour :
Estimer le coût d’un algorithme.
Comparer deux algorithmes sans avoir à les programmer.

© Ramzi GUETARI 10/18/2021


Complexité des algorithmes
8

Si l’on prend en compte tous les paramètres : fréquence d’horloge,


nombre de processeurs, temps d’accès disque, ... l’estimation de ces
ressources peut :
Être assez compliquée, voire irréalisable,
Devenir irréaliste dès que l’on change d’architecture.
Pour cela on se contente souvent d’estimer l’influence de la taille des
données sur la taille des ressources nécessaires.
De plus, nous nous limiterons ici au cas d’un seul processeur.

© Ramzi GUETARI 10/18/2021


Exemple : tri par insertion
9

Entrée : A tableau indexé de 1 à n.


Sortie : A trié par ordre croissant.
tri_insertion (A) =
1 for j in 2..n loop
2 a := A(j) ;
3 i := j-1 ;
4 while i > 0 and A(i) > a loop
5 A(i+1) := A(i) ;
6 i := i - 1 ;
end loop ;
7 A(i+1) := a ;
end loop ;
8 return A ;

© Ramzi GUETARI 10/18/2021


Exemple : tri par insertion
10

Estimer le temps d’exécution de cet algorithme : estimer le temps d’exécution


de chaque instruction et le nombre de fois que chaque instruction est exécutée

Chacune des instructions 1 à 7 consiste en au plus 1 affectation, au plus 1


addition/soustraction, au plus 2 accès dans le tableau A et au plus 2
comparaisons
1 for j in 2..n loop
2 a := A(j) ;
3 i := j-1 ;
4 while i > 0 and A(i) > a loop
5 A(i+1) := A(i) ;
6 i := i - 1 ;
end loop ;
7 A(i+1) := a ;
end loop ;
8 return A ;

© Ramzi GUETARI 10/18/2021


Exemple : tri par insertion
11

Pour chaque ligne l, on note cl son temps d’exécution.


Pour chaque valeur de j on désigne par tj le nombre d’exécutions du
test de la boucle while.
Chaque quantité dépend de l’état initial du tableau A.
On 1 ≤ tj ≤ j
1 for j in 2..n loop
2 a := A(j) ;
3 i := j-1 ;
4 while i > 0 and A(i) > a loop
5 A(i+1) := A(i) ;
6 i := i - 1 ;
end loop ;
7 A(i+1) := a ;
end loop ;
8 return A ;

© Ramzi GUETARI 10/18/2021


Exemple : tri par insertion
12

On obtient :
Coût Nombre de fois
for j in 2..n loop c1 n
a := A(j) ; c2 n–1
i := j-1 ; c3 n–1
n
while i > 0 and A(i) > a loop c4 Σ j = 2 tj
n
A(i+1) := A(i) ; c5 Σ j = 2 (tj - 1)
n
i := i - 1 ; c6 Σ j = 2 (tj - 1)
end loop ;
A(i+1) := a ; c7 n–1
end loop ;
return A ;

© Ramzi GUETARI 10/18/2021


Exemple : tri par insertion
13

On note T(n) le temps d’exécution de l’algorithme tri_insertion.


On l’obtient en additionnant les produits des colonnes coûts et fois.

n n n
T(n) = c1n + c2 (n – 1) + c3 (n – 1) + c4 Σ t + c Σ (t - 1) + c Σ (t – 1) + c
j=2
j 5
j=2
j 6
j=2
j 7 (n – 1)

© Ramzi GUETARI 10/18/2021


Exemple : tri par insertion
14

Cas favorable : tj = 1

T(n) = (c1 + c2 + c3 + c4 + c7 ) n + (c2 + c3 + c4 + c7 )


T(n) = An + B
C’est une fonction linéaire de n

© Ramzi GUETARI 10/18/2021


Exemple : tri par insertion
15

Cas défavorable : tj = j
n ( n + 1) n ( n + 1)
T(n) = c1n + c2 (n – 1) + c3 (n – 1) + c4 – 1 + c5 +
2 2
n ( n + 1)
c6 + c7 (n – 1)
2

c4 + c5 + c6 2 c –c –c
T(n) = n + c1 + c2 + c3 + 4 5 6 + c7 n – (c2 + c3 + c4 + c7)
2 2

T(n) = An2 + Bn + C
T(n) = Fonction quadratique de n

© Ramzi GUETARI 10/18/2021


Quelle complexité ?
16

On distingue trois sortes de complexités :


la complexité dans le pire des cas : calcul du coût dans le pire des cas,

la complexité en moyenne : on calcule le coût pour chaque donnée


possible puis on divise la somme de ces coûts par le nombre de
données différentes,
la complexité dans le meilleur des cas : on calcule le coût en se
plaçant dans le meilleur des cas.

En analyse de complexité, on étudie généralement le pire cas ce qui


donne une borne supérieure de la complexité de l’algorithme.

© Ramzi GUETARI 10/18/2021


Quelle complexité ?
17

Le cas moyen et le pire cas sont souvent de complexités équivalentes.

Lorsqu’on étudie la complexité d’un algorithme, on ne s’intéresse pas au


temps de calcul réel mais à un ordre de grandeur.

Pour une complexité polynomiale, par exemple, on ne s’intéresse qu’au


terme de plus grand ordre.

On exprime la complexité d’un algorithme comme une fonction f(n) de


N dans R

© Ramzi GUETARI 10/18/2021


Définitions (1 / 5)
18

Soient f et g deux fonctions de N dans R.


On dit que g (n) est une borne approchée asymptotique de f (n) l’on
écrit f (n) ∈ Θ (g (n)) s’il existe deux constante strictement positives c1
et c2 telles que, pour n assez grand, on ait :
0 ≤ c1 . g (n) ≤ f (n) ≤ c2 . g (n)

Ceci revient à dire que f (n) est égale à g (n) à un facteur constant près
pour n assez grand.

Pour indiquer que f (n) ∈ Θ (g (n)) on écrit :


f (n) = Θ (g (n))
Dans le cas du tri par insertion T (n) = Θ (n2)
© Ramzi GUETARI 10/18/2021
Définitions (1 / 5)
19

Illustration intuitive
c2 . g (n)

f (n)

c1 . g (n)

n0 f (n) = Θ (g (n)) n

© Ramzi GUETARI 10/18/2021


Définitions (1 / 5)
20

Exemple
1 2
f (n) = n − 3n
2
f (n) = Θ (n2) ? ⇒ Il faut trouver c1, c2 et n0 > 0 telles que :
1 2
c1 . ≤ n − 3n ≤ c2 . n2 pour tout n ≥ n0
n2
2
1 3
c1 ≤ − ≤ c2
2 n
1 3 1 1 1 3
∀ n ≥ 1, − ≤ c2 ≤ et ∀ n ≥ 7, ≤ c1 ≤ −
2 n 2 14 2 n
1 1
On pose donc n0 = 7, c1 = et c2 =
14 2
© Ramzi GUETARI 10/18/2021
Définitions (2 / 5)
21

On dit que g (n) est une borne supérieure asymptotique pour f (n) et
l’on écrit f (n) ∈ O (g (n)) s’il existe un constante c > 0 telle que pour n
assez grand on ait :
0 ≤ f (n) ≤ c . g (n)
Ceci revient à dire que f (n)
( ) est inférieure à g (n)
( ) à une constante près
pour n assez grand.

Pour indiquer que f (n) ∈O (g (n)) on écrit :


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

© Ramzi GUETARI 10/18/2021


Définitions (2 / 5)
22

Illustration intuitive
c . g (n)

f (n)

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

© Ramzi GUETARI 10/18/2021


Définitions (3 / 5)
23

On dit que g (n) est une borne inférieure asymptotique pour f (n) et l’on
écrit f (n) ∈ Ω (g (n)) s’il existe un constante c > 0 telle que pour n assez
grand on ait :
0 ≤ c . g (n) ≤ f (n)
Ceci revient à dire que f (n)
( ) est supérieure à g (n)
( ) à une constante près
pour n assez grand.

Pour indiquer que f (n) ∈ Ω (g (n)) on écrit :


f (n) = Ω (g (n))

© Ramzi GUETARI 10/18/2021


Définitions (3 / 5)
24

Illustration intuitive
f (n)

c . g (n)

n0 f (n) = Ω (g (n)) n

© Ramzi GUETARI 10/18/2021


Définitions (4 / 5)
25

On dit que g (n) est une borne supérieure non asymptotique


approchée pour f (n) et l’on écrit f (n) ∈ o (g (n)) si pour toute
constante c > 0 il existe une constante n0 > 0 telle que :

0 ≤ f (n) < c . g (n) ∀ n > n0

Ceci revient à dire qu’à l’infini, la fonction f (n) devient négligeable par
rapport à la fonction g (n) :

f ( n)
lim
n → +∞
=0
g ( n)

© Ramzi GUETARI 10/18/2021


Définitions (5 / 5)
26

On dit que g (n) est une borne inférieure non asymptotique approchée
pour f (n) et l’on écrit f (n) ∈ ω (g (n)) si pour toute constante c > 0 il
existe une constante n0 > 0 telle que :

0 ≤ c . g (n) < f (n) ∀ n > n0

Ceci revient à dire qu’à l’infini, la fonction f (n) devient arbitrairement


grande par rapport à la fonction g (n) :

f ( n)
lim
n → +∞
=∞
g ( n)
Si la limite existait
© Ramzi GUETARI 10/18/2021
Propriétés (1 / 2)
27

f (n) = Θ (g (n)) ⇒ f (n) = O (g (n))


f (n) = Θ (g (n)) ⇔ f (n) = O (g (n)) et f (n) = Ω (g (n))
Toutes les notations Θ, O, Ω, o, et ω sont transitives.
Seules les notations Θ, O et Ω sont réflexives.
Seules la notation Θ est symétrique
De plus nous avons la symétrie transposée suivante :
f (n) ∈O (g (n)) ⇔ g (n) ∈ Ω (f (n))
f (n) ∈ o (g (n)) ⇔ g (n) ∈ ω (f (n))

© Ramzi GUETARI 10/18/2021


Propriétés (2 / 2)
28

On écrira des expressions du type :

f (n) = h (n) + Θ (g (n))


Pour dire que

f (n) − h (n) = Θ (g (n))

© Ramzi GUETARI 10/18/2021


Classes de complexité
29

Lors de l’analyse de complexité, on essaie de se ramener aux classes


suivantes (présentées par complexité croissante) :
Complexité logarithmique.
Complexité linéaire.
Complexité quasi linéaire.
Complexité polynomiale
Complexité exponentielle.

© Ramzi GUETARI 10/18/2021


Complexité logarithmique
30

Coût en Θ (log n)
Exemple : Recherche dichotomique dans un tableau trié A (1 .. n)

© Ramzi GUETARI 10/18/2021


Complexité linéaire
31

Coût en Θ (n)
Exemple : Calcul du produit scalaire de deux vecteurs de Rn

© Ramzi GUETARI 10/18/2021


Complexité quasi linéaire
32

Coût en Θ (n log n)
Exemple : Tri par fusion

© Ramzi GUETARI 10/18/2021


Complexité polynomiale
33

Coût en Θ (nk) k > 1


Exemple : Multiplication de deux matrices carrées d’ordre n : Θ (n3)

© Ramzi GUETARI 10/18/2021


Complexité exponentielle
34

Coût en Θ (an) a > 1


Exemple : Tours de Hanoï

© Ramzi GUETARI 10/18/2021


Comparaison
35
f (n)
f (n) = 2n f (n) = n3 f (n) = n log n

f (n) = n

f (n) = log n

n
© Ramzi GUETARI 10/18/2021
Comparaison
36

T (n) n = 10 n = 20 n = 30 n = 40 n = 50 n = 60
log n 1 µs 1.3 µs 1.5 µs 1.6 µs 1.7 µs 1.8 µs
n 10 µs 20 µs 30 µs 40 µs 50 µs 60 µs
n log n 10 µs 26 µs 44 µs 64 µs 85 µs 107 µs
n2 100 µs 400 µs 900 µs 1.6 ms 2.5 ms 3.6 ms
n3 1 ms 8 ms 27 ms 64 ms 125 ms 216 ms
n5 0.1 s 3s 24 s 1.7 mn 5 mn 13 mn
2n 1 ms 1s 18 mn 13 jours 36 ans 366 siècles
3n 60 mn 1 heure 6 ans 3900 siècles 2×108 siècles 1,3×1013 siècles

© Ramzi GUETARI 10/18/2021


Constatations
37

La croissance de 2n et 3n (an, a > 1) devient rapidement déraisonnable.


Il s’agit du phénomène d’explosion combinatoire.
Ces algorithmes sont inutilisables pour si la taille du problème devient
importante.

© Ramzi GUETARI 10/18/2021


Amélioration du matériel (1 / 2)
38

N : la taille de la plus grande instance traitable en une heure


Quelle taille traitable en une heure si les machines sont 100 ou 1000
fois plus rapides ?

T (n) = Θ (n2) T (n) = Θ (2n)

Aujourd’hui : T (N) = k N2 Aujourd’hui : T (N) = k 2N


N’= 10 N N’= N + 6.67
kN '2 k 2N '
Demain : T’(N’) = Demain : T’(N’) =
100 100

log2 (100) + N = N’

© Ramzi GUETARI 10/18/2021


Amélioration du matériel (1 / 2)
39

T(n) Aujourd’hui Rapidité : 100 fois Rapidité : 1000 fois

n N 100 N 1000 N
n2 N 10 N 32 N
n3 N 4.6 N 10 N
n5 N 2.5 N 4N
2n N N+7 N + 10
3n N N+4 N+6

Cas linéaire et polynomiale, on profite pleinement de la puissance


Cas exponentiel, le surcroît de la puissance n’apporte presque rien

© Ramzi GUETARI 10/18/2021


Analyse d’algorithmes
40

Il est important de connaître la complexité en temps des algorithmes.


En pratique on distingue :
Les « bons » algorithmes : les polynomiaux.
Les autres qui mènent à une explosion combinatoire. Il faut les éviter.

Avoir de l’objectivité et du recul par rapport à la théorie :


Choix entre un algorithme simple et lent et un algorithme rapide et
compliqué.
Lorsque la taille du problème est petite, un algorithme lent et simple peut
suffire.

© Ramzi GUETARI 10/18/2021


Exemples
41

LA PLUS GRANDE SOMME CONTIGUË


Le but est d’élaborer un algorithme permettant de calculer la plus
grande somme contiguë d'une séquence d'entiers placés dans un
tableau.
Étant donné un tableau A [0 .. n − 1] de n nombres entiers positifs ou
négatifs, comment déterminer la valeur maximale des sommes
correspondantes aux sections de la forme A [i .. j[. On notera que 0
est la somme de n'importe quelle section vide A [i .. i[.

© Ramzi GUETARI 10/18/2021


Exemples
42

LA PLUS GRANDE SOMME CONTIGUË


Par exemple, si le tableau contient les dix éléments:

i 0 1 2 3 4 5 6 7 8 9
A 31 -41 59 26 -53 58 97 -93 -23 84

la somme maximale est A [2 .. 6] = 187.

© Ramzi GUETARI 10/18/2021


Exemples
43
LA PLUS GRANDE SOMME CONTIGUË – Algorithme « naïf »
L'idée la plus simple est de calculer toutes les sommes et de rechercher la
plus grande, par un algorithme du style :
PROCEDURE sum (int n , int a[ ]) {
Maximum ← 0;
FOR i ← 0 TO n - 1 DO
FOR j ← i TO n - 1 DO
Sum ← 0
FOR k ← i TO j DO
Sum ← Sum + a[k]
END-FOR
IF (Sum > Maximum) THEN
Maximum ← Sum
END-IF
END-FOR
END-FOR
Return Maximum
END

Il est facile de voir que la comparaison entre Maximum et Somme est


effectuée O (n3) fois.
© Ramzi GUETARI 10/18/2021
Exemples
44

LA PLUS GRANDE SOMME CONTIGUË – Algorithme 2


Une meilleure idée consiste à ne pas recalculer systématiquement les
sommes mais à utiliser la relation:
PROCEDURE sum (int n , int a[ ])
Maximum ← 0;
FOR i ← 0 TO n - 1 DO
Sum ← 0
FOR j ← i to n - 1 DO
Sum ← Sum + a[j]
IF Sum > maximum THEN
Maximum ← Sum
END-IF
END-FOR j +1 j
END-FOR
Return Maximum ∑a = ∑a
k =i
k
k =i
k + a j +1
END

© Ramzi GUETARI 10/18/2021


Exemples
45

LA PLUS GRANDE SOMME CONTIGUË – Algorithme 3

Mais on peut encore mieux faire. L'idée cette fois est de parcourir une
seule fois le tableau et de maintenir simultanément deux maximums : la
plus grande somme « max1 » et un « max2 » qui est remis à zéro chaque
fois qu’il devient négatif. La plus grande somme recherchée est égale soit
à « max1 » soit à « max2 » d'où l'algorithme:

© Ramzi GUETARI 10/18/2021


Exemples
46

LA PLUS GRANDE SOMME CONTIGUË – Algorithme 3


PROCEDURE sum (int n , int a[ ])
int max1 ← 0, max2 ← 0, i ;
FOR i ← 0 TO n-1 DO
max2 = max2 + a[i] ;
IF max2 < 0 THEN
max2 ← 0 ;
END-IF

IF max2 > max1 THEN


max1 ← max2 ;
END-IF
END-FOR

Return max1 ;
END
© Ramzi GUETARI 10/18/2021
Exemples
47

LA PLUS GRANDE SOMME CONTIGUË – Algorithme 3 : COMPLEXITÉ

Il est clair que cet algorithme est en O (n).

Peut-on mieux faire ?

La réponse est non car tout algorithme résolvant ce problème est obligé
de parcourir l'intégralité des données, donc a une complexité au moins
linéaire.

© Ramzi GUETARI 10/18/2021


Exemples
48

LA PLUS GRANDE SOMME CONTIGUË – CONCLUSION

Sur un PC à 400 MHz, pour un tableau de taille 107 Jon Bentley donne
l’estimation suivante (Programming Pearls, Addison-Wesley, 2000) ) des
temps d'exécution:

Algorithme 1 : O (n3) 2 : O (n2) 3 : O (n)


Temps 41000 ans 1,7 semaines 0,48 seconde

© Ramzi GUETARI 10/18/2021

Vous aimerez peut-être aussi