Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös
ANALYSE D’ALGORITHMES
Analyse d’algorithmes
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös ii
Questions fondamentales de notre vie professionnelle :? Ça va prendre combien de temps de faire ce calcul ?? Pourquoi mon code plante avec OutOfMemoryError ?
on a besoin de principes pour étudier la performance d’algorithmes
performance : temps de calcul, usage de mémoire, usage d’autres ressources (caches,entrée-sortie, résaux. . . )
→ importance théorique (théorie de complexité)
→ importance pratique : on veut une approche scientifique de caractériser et pré-dire la performance
Temps de calcul — démarche scientifique
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös iii
modèle→ prédiction→ expérience
1. définir : modèle de l’entrée + notion de taille (modèle permet la simulation)
2. identifier : partie criticale du code (pour un algorithme itératif, cette partie est àl’intérieur de la boucle le plus profondement imbriquée)
3. modèle de coût : opération typique (comparaison ou déplacement dans un tri,accès aux cases du tableau, opération arithmétique dans algorithme numérique, . . . )
4. donner la fréquence d’opérations typiques en fonction de la taille de l’entrée
Une bonne caractérisation du temps de calcul nous permet de le considérer comme un hypothèse
scientifique testable sur le comportement de l’algorithme. Après qu’on a implanté l’algorithme,
on peut expériencer avec des entrées différentes, en mesurant le temps actuel d’exécution, et en
comptant les opérations typiques.
Meilleur, pire, moyen
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös iv
Typiquement, il y a beaucoup d’entrées possibles avec la même taille n, et le tempsde calcul peut dépendre de l’entrée actuelle et non pas seulement de sa taille.
Temps de calcul T (n) pour entrée de taille n :? meilleur cas : minT (n) parmi toutes entrées de taille n? pire cas : maxT (n) parmi toutes entrées de taille n? moyen cas : T (n) en espérance (notion probabiliste !) il faut assumer une distribution sur entrées de taille n : p.e., permutation
au hasard pour moyen cas d’un tri on peut également décrire l’écart-type, et d’autres propriétés de T (n),
ce dernier considéré comme une variable aléatoire avec la distributionimpliée par l’entrée + l’algorithme
Expérimentation
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös v
on a un algorithme⇒ implémenter + tester
expérimentation avec plusieurs jeux d’entrées :simulation ou repositoire de benchmarks
évaluation des résultats :? développer un hypothèse sur le comportement si on n’a pas une meilleure
idée? valider une prédiction développée
on mesure :? temps actuel d’exécution : il faut rapporter de l’information sur l’environ-
nement de test : CPU, RAM, système d’exploitation, . . .? compte d’opérations : ne dépend pas de l’environnement
expériences reproductibles !⇒ falsifiabilité de la prédiction + vérifiabilité de tests
Temps actuel de calcul
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös vi
? dans le code...long T0 = System.currentTimeMillis(); // temps de début...long dT = System.currentTimeMillis()-T0; // temps (ms) dépassé
// ou avec System.nanoTime() pour précision de 10−9s
? dans la ligne de commande (time)
? profilage de code dans l’IDE (Eclipse/Netbeans/. . . )
Nombre d’opérations
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös vii
? dans le codeprivate static final boolean COUNT=true;private static int op_count=0; // nombre de comparaisonsprivate static void insert(double[] T, int n, double x)
// T[0]<=T[1]<=...<=T[n-1] déjà triéint j=n;while(j>0 ) if (COUNT) $op_count++;if (T[j-1]<= x) break;T[j]=T[j-1];j--;
T[j]=x;
public static void insertionSort(double[] T)
for (int n=1; n<T.length; n++) insert(T,n,T[n]);if (COUNT)
System.out.println(T.length+"\t"+op_count);
? profilage avec l’IDE (par ligne ou méthode)
Conception d’expériences
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös viii
1. répéter avec la même taille⇒ moyen + dispersion statistique
2. répéter avec tailles différentes : doubler
notre hypothèse T (n) ∼ a · nb : T (2n)T (n) ∼
a(2n)b
anb= 2b
→ visualiser sur log-log : la pente indique l’exposant b
Tri par insertion : expérimentation
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös ix
Expériences : ordre aléatoire (chaque ordre également probable)tailles n = 500,1000,2000, . . . , chaque répété 100 fois,on compte les comparaisons
y = 0.4279x R = 0.99394
0.001
0.01
0.1
1
10
100
1000
0.01 0.1 1 10 100 1000 10000
Temps (ms)
Comparaisons (millions)
nombre de comparaisons est un bon indicateur du temps de calcul
Tri par insertion 2
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös x
y = 1E-07x2 + 0.0001x R = 0.99999
0.01
0.1
1
10
100
1000
500 2000 8000 32000
temps moyen (ms)
n (nombre d'éléments à trier)
y = 0.2499x2 + 2.734x R = 1
0.01
0.1
1
10
100
1000
10000
500 2000 8000 32000
opérations en moyenne (millions) M
illions
n (nombre d'éléments à trier)
régression quadratique semble appropriée
Tri par insertion
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xi
Entrée: T [0..n− 1] // n > 01 for i← 1,2, . . . , n− 1 do2 x← T [i]; j ← i
3 while j > 0 && T [j − 1] > x do T [j]← T [j − 1]; j ← j − 1
4 T [j]← x
5 end
1. entrée : taille n, éléments distincts2. le plus fréquemment executé : boucle interne3. opération typique : comparaison
meilleur cas : n− 1 comparaisons (déjà trié)
pire cas :
Cpire(n) =n−1∑i=1
i =n(n− 1)
2=
1
2n2 −
1
2n ∼ n2/2
Tri par insertion – moyen cas
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xii
lors du placement du k-ème élément (à l’indice T [k − 1]), le nombre de compa-raisons en moyenne :
tk =1
k·1+
1
k·2+· · ·+
1
k·(k−1)+
1
k·(k−1) =
k(k + 1)/2− 1
k=k + 1
2−
1
k
nombre de comparaisons en total :
Cmoyen(n) =n∑
k=1
tk =n∑
k=1
(k + 1
2−
1
k
)=n(n+ 3)
4−Hn
avec le nombre harmonique
Hn = 1 +1
2+
1
3+ · · ·
1
n∼ lnn
Donc, Cmoyen(n) ∼ n2/4
Notation tilde
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xiii
Définition [notations tilde et petit-o]. Pour deux fonctions f, g : N→ R, on écrit
f(n) ∼ g(n) si et seulement si limn→∞
f(n)
g(n)= 1 «f est asymptotiquement égal à g»
f(n) = o(g(n)
)si et seulement si lim
n→∞
f(n)
g(n)= 0 «f est négligeable par rapport à g»
As is typical in such expressions, the terms after the leading term are relatively small (for exam-ple, when N = 1,000 the value of ! N 2/2 " N/3
499,667 is certainly insignificant by com-parison with N 3/6 ! 166,666,667). To allow us to ignore insignificant terms and therefore sub-stantially simplify the mathematical formulas that we work with, we often use a mathemati-cal device known as the tilde notation (~). This notation allows us to work with tilde approxi-mations, where we throw away low-order terms that complicate formulas and represent a negli-gible contribution to values of interest:
Definition. We write ~f (N ) to represent any function that, when divided by f (N ), approaches 1 as N grows, and we write g(N ) ~ f (N ) to indicate that g(N )/f (N ) approaches 1 as N grows.
For example, we use the approximation ~N 3/6 to de-scribe the number of times the if statement in ThreeSum is executed, since N 3/6 ! N 2/2 " N/3 di-vided by N 3/6 approaches 1 as N grows. Most of-ten, we work with tilde approximations of the form g (N) ~af (N ) where f (N ) = N b (log N ) c with a, b, and cconstants and refer to f (N ) as the order of growth of g (N ). When using the logarithm in the order of growth, we gener-ally do not specify the base, since the constant a can absorb that detail. This usage covers the relatively few functions that are commonly encountered in studying the order of growth of a program’s running time shown in the table at left (with the exception of the exponential, which we defer to CONTEXT). We will describe these functions in more de-tail and briefly discuss why they appear in the analysis of algorithms after we complete our treatment of ThreeSum.
function tildeapproximation
orderof growth
N 3/6 ! N 2/2 " N/3 ~ N 3/6 N 3
N 2/2 ! N/2 ~ N 2/2 N 2
lg N + 1 ~ lg N lg N
3 ~ 3 1
Typical tilde approximations
order of growth
description function
constant 1
logarithmic log N
linear N
linearithmic N log N
quadratic N 2
cubic N 3
exponential 2 N
Commonly encounteredorder-of-growth functions
Leading-term approximation
N 3/6
N (N! 1)(N! 2)/6
166,167,000
1,000
166,666,667
N
1791.4 Q Analysis of Algorithms
n3/6− n2/2 + n/3 ∼ n3/6n2/2− n/3 = o(n3)
Ordre de croissance
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xiv
On peut caractériser la croissance d’une fonction quelconque f en choisissant unefonction g t.q.
∃c ∈ R+ : f(n) ∼ c · g(n) «f est de même ordre de croissance que g»
Ici, on veut choisir g à la carte, sur une échelle standard de fonctions communes :chaque ordre est négligéable par rapport aux ordres supérieurs
croissance g(n)constante 1 = o(logn)logarithmique logn = o(n)linéaire n = o(n logn)linéarithmique n logn = o(n2)quadratique n2 = o(n3)cubique n3
polynomiale na logb n = o(An) ∀a, b ∀A > 1exponentielle 2n,3n, en, . . . = o(n!)
c’est juste les ordres les plus communs (p.e., n log2(n)log logn
est un ordre de croissance assez rarement vu)
la base du logarithme est omise dans l’ordre de croissance : pour tout a, b > 1
on a loga n = c · logb n avec constante c = loga b qui ne dépend pas de n
Ordre de croissance en pratique
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xv
there exists a large class of problems for which it seems that an exponential algorithm is the best possible choice.
These classifications are the most common, but certainly not a complete set. The order of growth of an algorithm’s cost might be N 2 log N or N 3/2 or some similar func-
tion. Indeed, the detailed analysis of algorithms can require the full gamut of mathematical tools that have been developed over the centuries.
A great many of the algorithms that we con-sider have straightforward performance charac-teristics that can be accurately described by one of the orders of growth that we have considered. Accordingly, we can usually work with specific propositions with a cost model, such as mergesort uses between ½ N lg N and N lg N compares that immediately imply hypotheses (properties) such as the order of growth of mergesort’s running time is linearithmic. For economy, we abbreviate such a statement to just say mergesort is linearithmic.
The plots at left indicate the importance of the order of growth in practice. The x-axis is the problem size; the y-axis is the running time. These charts make plain that quadratic and cubic algorithms are not feasible for use on large prob-lems. As it turns out, several important prob-lems have natural solutions that are quadratic but clever algorithms that are linearithmic. Such algorithms (including mergesort) are critically important in practice because they enable us to address problem sizes far larger than could be addressed with quadratic solutions. Naturally, we therefore focus in this book on developing loga-rithmic, linear, and linearithmic algorithms for fundamental problems.
1K
T
2T
4T
8T
64T
512T
logarithmic
expo
nent
ial
constant
linea
rithmic
linea
r
quad
ratic
cubi
c
2K 4K 8K 512K
100T
200T
500T
logarithmic
exponential
constant
problem size
problem size
linea
rithmic
linea
r
100K 200K 500K
time
time
Typical orders of growth
log-log plot
standard plot
cubicquadratic
188 CHAPTER 1 Q Fundamentals
there exists a large class of problems for which it seems that an exponential algorithm is the best possible choice.
These classifications are the most common, but certainly not a complete set. The order of growth of an algorithm’s cost might be N 2 log N or N 3/2 or some similar func-
tion. Indeed, the detailed analysis of algorithms can require the full gamut of mathematical tools that have been developed over the centuries.
A great many of the algorithms that we con-sider have straightforward performance charac-teristics that can be accurately described by one of the orders of growth that we have considered. Accordingly, we can usually work with specific propositions with a cost model, such as mergesort uses between ½ N lg N and N lg N compares that immediately imply hypotheses (properties) such as the order of growth of mergesort’s running time is linearithmic. For economy, we abbreviate such a statement to just say mergesort is linearithmic.
The plots at left indicate the importance of the order of growth in practice. The x-axis is the problem size; the y-axis is the running time. These charts make plain that quadratic and cubic algorithms are not feasible for use on large prob-lems. As it turns out, several important prob-lems have natural solutions that are quadratic but clever algorithms that are linearithmic. Such algorithms (including mergesort) are critically important in practice because they enable us to address problem sizes far larger than could be addressed with quadratic solutions. Naturally, we therefore focus in this book on developing loga-rithmic, linear, and linearithmic algorithms for fundamental problems.
1K
T
2T
4T
8T
64T
512T
logarithmic
expo
nent
ial
constant
linea
rithmic
linea
r
quad
ratic
cubi
c
2K 4K 8K 512K
100T
200T
500T
logarithmic
exponential
constant
problem size
problem size
linea
rithmic
linea
r
100K 200K 500K
time
time
Typical orders of growth
log-log plot
standard plot
cubicquadratic
188 CHAPTER 1 Q Fundamentals
so the table focuses on that situation. Knowing the order of growth of the running time of an algorithm provides precisely the information that you need to understand limita-tions on the size of the problems that you can solve. Developing such understanding is the most important reason to study performance. Without it, you are likely have no idea how much time a program will consume; with it, you can make a back-of-the-envelope calculation to estimate costs and proceed accordingly.
Estimating the value of using a faster computer. You also may be faced with this basic question, periodically: How much faster can I solve the problem if I get a faster computer? Generally, if the new computer is x times faster than the old one, you can improve your running time by a factor of x. But it is usually the case that you can address larger prob-lems with your new computer. How will that change affect the running time? Again, the order of growth is precisely the information needed to answer that question.
A famous rule of thumb known as Moore’s Law implies that you can expect to have a computer with about double the speed and double the memory 18 months from now, or a computer with about 10 times the speed and 10 times the memory in about 5 years. The table below demonstrates that you cannot keep pace with Moore’s Law if you are using a quadratic or a cubic algorithm, and you can quickly determine whether that is the case by doing a doubling ratio test and checking that the ratio of running times as the input size doubles approaches 2, not 4 or 8.
order of growth of time2x
factor10x
factor
for a program that takes a few hours for input of size N
description function predicted time for 10N predicted time for10Non a 10x faster computer
linear N 2 10 a day a few hours
linearithmic N log N 2 10 a day a few hours
quadratic N 2 4 100 a few weeks a day
cubic N 3 8 1,000 several months a few weeks
exponential 2 N 2 N 2 9N never never
Predictions on the basis of order-of-growth function
194 CHAPTER 1 Q Fundamentals
L’ordre de croissance nous aide à prédire ce qui se passequand la taille de l’entrée devient plus grand : p.e., onexamine T (2n)/T (n) ou T (10n)/T (n).
«Loi» de Moore : puissance de calcul (vitesse CPU, mé-moire, stockage) se double chaque 18 mois ⇒ 10 foisplus rapide dans 5 ans.Les algorithmes linéaires et linéarithmiques nous per-mettent à exploiter les développement technologiquesau maximum. Par contre, la technologie ne sauve pas unalgorithme de temps exponentiel.
[Sedgewick & Wayne Algorithms]
Bornes sur l’ordre de croissance
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xvi
Quoi faire si f n’est asymptotiquement égale à aucune fonction sur notre échelle ?On peut toujours essayer de borner la croissance de f par une autre fonction quiconverge !On définit alors la notation O , Ω et Θ pour bornes supérieures, inférieures, et àdeux côtés.
Supposons qu’il existe g− : N → R avec a > 0 ou/et g+ : N → R avec b > 0
t.q. g− ∼ ag(n) ou/et g+(n) ∼ bg(n).
si on écrit
f(n) ≤ g+(n) f = O(g) (grand O)
g−(n) ≤f(n) f = Ω(g) (grand Omega)
g−(n) ≤f(n) ≤ g+(n) f = Θ(g) (Theta)
temps actuel varie d’un ordinateur à l’autre, mais l’ordre de croissance reste la même selon O, Ω
et Θ.
Tri par tas : analyse
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xvii
HEAPSORT(A[1..n]) // tri du tableau A[1..n]H1 for i← bn/2c, . . . ,1 do sink(A[i], i) // heapifyH2 while n > 1 doH3 échanger A[1]↔ A[n]H4 sink(A[1],1)H5 n← n− 1
structure du tas binaire sur n éléments : arbre binaire complet
opérations à compter : affectations dans sink(x, i) = hauteur du nœud i
heapify : on définitH(n) = somme des hauteurs dans le tas avec n nœuds internes
nombre d’affectations au total : H(n)
Somme des hauteurs
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xviii
1 2 3 4 5 6 7
8 9 10 11
12 13 14 15
+1 +2 +1 +3 +1 +2 +1
+4 +1 +2 +1
+3 +1 +2 +1
11 01 1
1 0 01 0 11 1 01 1 1
1 0 0 01 0 0 11 0 1 01 0 1 11 1 0 01 1 0 11 1 1 01 1 1 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+1
+2
+1
+3
+1
+2
+1
+4
+1
+2
+1
+3
+1
+2
+1
somme des hauteurs de noeuds dans un arbre binaire complet
affectation de bits pour compter en binaire
même que le nombre de bits à bousculer quand on compte jusqu’à n
compter jusqu’à n = 2t : H(1) = 1;H(2t) = 2 ·H(2t−1)+1 avec solutionH(2t) = 2 · 2t − 1 pour t ≥ 0.
Somme des hauteurs 2
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xix
compter jusqu’à 2t ≤ n < 2t+1 (avec t = blgnc)
écrire n =∑ti=0 bi2
i, bi ∈ 0,1 avec sa représentation binaire
H(n) = btH(2t)+bt−1H(2t−1)+ . . .+b0H(20) = 2n−t∑
i=0
bi︸ ︷︷ ︸poids binaire de n
Preuve altérnative : crédit-débit, pour compter de 0 à n, il faut payer $1 pourchaque opération de bit.
? mettre $1 à côté chaque fois bit incrémenté 0→ 1
? récupérer quand 1→ 0 est nécessaire sur ce bit? après n incrémentation, on a dépensé 2n ($1 pour 0→ 1, $1 mis à côté),
et il reste ‖n‖ =∑ti=0 bi sur le compte d’épargne
⇒ H(n) = 2n− ‖n‖.
coût amorti d’incrémentation binaire est 2n−‖n‖n ≤ 2− 1
n = Θ(1)
Tri par tas : analyse 2
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xx
après heapify, on appelle sink sur (n− 1), (n− 2), (n− 3), . . . ,1 éléments
hauteur de l’arbre binaire complet avec k > 0 nœuds internes = 1 + blg kc
nombre bits pour écrire k > 0 en binaire : 1 + blg kc
S(n) = somme des bits dans les représentations binaires de 1,2, . . . , n− 1 :
Formule pour S(n) ?
Tri par tas : analyse 3
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxi
Calculer S(n) = somme des bits dans les représentations binaires jusqu’à n− 1 :si t = blgnc, ou 2t ≤ n < 2t+1
11 01 1
1 0 01 0 11 1 01 1 1
1 0 0 01 0 0 11 0 1 01 0 1 1
1
2
3
4
5
6
7
8
9
10
11
0
1+t
n
000
0000
0000
0000
01t
S(n) = n(t+ 1
)−(2t+1 − 1
)lgn = t+ u
S(n) = n lgn− n (u+ 21−u − 1)︸ ︷︷ ︸∈[0.9139··· ,1]
+1
Tri par tas : conclusion
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxii
Thm. Le tri par tas sur n éléments fait ∼ 2n lgn comparaisons au pire.
Preuve. Pendant heapify, on fait 2(H(n) − n) ∼ 2n comparaisons. Ensuite,le nombre de comparaisons est 2
(S(n)− n
)au pire (2 enfants inspectés sauf à la
dernière itération). Au total, c’est ∼ 2S(n), or S(n) ∼ n lgn.
Diviser pour régner
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxiii
divide-and-conquer
Démarche algorithmique à un problème de structure récursive :
? partitionner le problème dans des sous-problèmes similaires,? chercher la solution optimale aux sous-problèmes par récursion,? combiner les résultats.
Récursion pour temps de calcul
T (n) = τpartition(n) +∑
i=1,...,m
T (ni)︸ ︷︷ ︸m sous-problèmes
+τcombiner(n)
Recherche dichotomique
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxiv
recherche d’élément x dans un tableau trié a[0..n− 1]
Algo BSEARCH(x, a[], i, n) // binary search// cherche élément x dans l’intervalle
a[i], a[i+ 1], . . . , a[i+ n− 1]
Entrée : valeur recherchée x, tableau a[], indice de départ i ≥ 0, longueur n ≥ 0Sortie : indice j avec i ≤ j < i+ n t.q. x = a[j], ou valeur négative s’il n’existe pas
B1 if n = 0 then return −(i+ 1) // cas terminal : échec, valeur retournée < 0B2 m = i+ b(n− 1)/2c // indice de l’élément au milieuB3 if x < a[m] then return BSEARCH
(x, a, i, b(n− 1)/2c
)B4 else if x > a[m] then return BSEARCH
(x, a,m+ 1, d(n− 1)/2e
)B5 else return m // cas terminal x = a[m] : succès
échec — nombre de comparaisons au pire (appels récursifs de Ligne B4)en notant d(n− 1)/2e = bn/2c :
Cn =
0 n = 0Cbn/2c+ 2 n > 0
→ Cn = 2(1 + blgnc
)(deux fois la longueur de l’encodage binaire de n)
Calculer xn
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxv
Calculer xn comme le produit∏ni=1 x nécessite (n− 1) multiplications, mais on
peut faire beaucoup mieux :
xn =
1 n = 0xn/2 · xn/2 n > 0, n est pairx · xbn/2c · xbn/2c n > 0, n est impair
Algo POWER(x, n) // calcule xn, n ∈ N, x ∈ RP1 if n = 0 then return 1 // cas terminalP2 else
P3 y ← POWER
(x,⌊n2
⌋)// appel récursif
P4 if n mod 2 = 0 then return y · y // exposant n est nombre pairP5 else return x · y · y // exposant n impair
Exponentiation
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxvi
R(n) : nombre d’appels récursifs pour calculer xn
R(n) =
0 n = 0R(bn/2c) + 1 n > 0
Taille de l’entrée : b(n) = nombre de bits dans la représentation binaire de n
R′(b) =
0 b = 0R′(b− 1) + 1 b > 0
Solution : R′(b) =∑bi=1 1 = b, et après resubstitution, on trouve
R(n) = b(n) =⌈lg(n+ 1)
⌉= 1 +
⌊lgn
⌋︸ ︷︷ ︸
si n > 0
.
Nombre de multiplications = b(n) + nombre de bits ’1’ (=longueur + poids) récurrence pour b(n) : b(0) = 0 et pour n > 0, b(n) = b(bn/2c) + 1
Méthode de la bissection
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxvii
ou comment trouver la solution à n’importe quelle équation ?Problème [recherche de racine] : on a une fonction réelle f : R → R calculable,trouver x t.q. f(x) = 0
Exemple : trouver la racine de l’équation
ex = 1 +√x ou f(x) = ex − (1 +
√x) = 0.
x
-1
0
1
2
0 0.25 0.5 0.75 1
y=1+√x y=e^x y=e^x-(1+√x)
Il y a une solution à x = 0 et une autre entre 0.5 et 0.6 :
e0.5−1−√
0.5 = −0.058 · · · < 0 et e0.6−1−√
0.6 = 0.047 · · · > 0
Bissection 2
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxviii
Théorème. [Bernard Bolzano, 1817] Soit f : [a, b]→ R une fonction continue.Si f(a) ≤ 0 ≤ f(b), ou si f(a) ≥ 0 ≥ f(b), alors il existe c ∈ [a, b] t.q.f(c) = 0.
Si une application continue sur une intervalle est parfois positive et parfois négative, elle atteint
aussi le 0.
Dichotomie adaptée à une intervalle rélle :? sous-tâche : trouver la racine de f(x) = 0 à x ∈ [a, b] t.q. f(a) ·f(b) <
0 (bracketing)? partition par m = (a+ b)/2 ; examiner f(m)
si f(m) 6= 0, continuer avec [a,m] ou [m, b] selon le signe de f(m)
? cas de base b− a ≤ ε pour précision ε (=«on a une racine à m± ε/2»)
Bissection : algorithme
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxix
Algorithme BISECTION(f, a, b, ε) // trouve la solution de f(x) = 0, a ≤ x ≤ b.Entrée : fonction continue f , intervalle [a, b] pour bracketing avec f(a) · f(b) ≤ 0Sortie : valeur x ∈ [a, b] t.q. ∃x′ ∈ [x− ε/2, x+ ε/2]: f(x′) = 0
B1 ` = b− a // longueur de l’intervalleB2 y = f(a) ; if y · f(b) ≥ 0 then erreur // on exige signes opposés de f(a), f(b)B3 if y > 0 then échanger a↔ b ; // maintenant f(a) < 0 < f(b)B4 while ` > ε
B5 m = (a+ b)/2 ; z = f(m) // centre de l’intervalle et son image zB6 if z = 0 then return m // possiblement jamais avec notre précision. . .B7 if z < 0 then a = m else b = m
B8 ` = `/2B9 return (a+ b)/2 // précision maximale atteinte
Temps de calcul : E(`) = nombre de fois la fonction f est évaluée, en fonctionde la longueur de l’intervalle ` = (b− a).Nombre d’itérations : r = min
k ∈ N : `/2k ≤ ε
.
Alors E(`) = 2 + r = 2 +⌈lg(`/ε)
⌉.
il suffit de faire r = 40 itérations pour précision 2−40 ≈ 10−12.
Diviser pour régner - temps logarithmique
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxx
Démarche :? partitionner le problème dans des sous-problèmes de tailles similaires,? chercher la solution optimale dans un des sous-problèmes,? utiliser/ajuster la solution au sous-problème comme nécessaire dans O(1)
p sous-problèmes (p = 2,3, . . . ),temps t (constante) pour préparer la récurrence et traiter le résultatrécursion typique pour temps de calcul :
T (n) =
t0 n ≤ 1T(bn/pc
)+ t n > 1
Solution : temps logarithmique
T (n) = t0 + tblogp(n)c ∼t
lg plgn = Θ(logn)
Diviser pour régner - tournoi
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxxi
Algorithme MAXREC // diviser-pour-règner : tournoi à éliminationEntrée : séquence x = xi`−1
i=0, indice de début s, taille nSortie : max
xs, xs+1, . . . , xs+n−1
// appel initial pour la séquence entière : MAXREC(x,0, `)
D1 if n = 0 then return −∞ // cas terminalD2 if n = 1 then return xs // cas terminalD3 p = bn/2c // couper en deuxD4 g = MAXREC(x, s, p) // vainqueur du sous-problème gaucheD5 d = MAXREC(x, s+ p, n− p) // vainqueur du sous-problème droitD6 if d > g then return d else return g // combiner
Nombre de comparaisons (Ligne D6) : M(0) = M(1) = 0 et pour n > 1,
M(n) = M(bn/2c
)+M
(dn/2e
)+1 solution M(n) = n− 1 pour tout n > 0
Diviser pour régner - temps linéaire
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxxii
Démarche :? partitionner le problème dans des sous-problèmes de tailles similaires,? chercher la solution optimale dans les sous-problèmes,? combiner les résultats en temps O(1) (ou sous-linéaire en général)
Partition : n1, n2 . . . , np avec∑i ni = n et ni = n
p +O(1).
Récurrence typique :
T (n) =
t0 n ≤ 1∑pi=1 T
(ni)
+ t n > 1
Solution : temps linéaire
T (n) ∼(t0 +
t
p− 1
)n = Θ(n)
Fusion de deux tableaux
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxxiii
Tri par Diviser-pour-règner ?? «Couper» le tableau en deux, trier les deux moitiés par récurrence⇒ on a besoin d’un algorithme pour combiner (fusionner) deux tableaux triés
Algo FUSION(A[0..n− 1], B[0..m− 1]) // A,B : tableaux triésF1 initialiser C[0..n+m− 1] // on place le résultat dans CF2 i← 0; j ← 0; k ← 0 // i est l’indice dans A ; j est l’indice dans BF3 while i < n && j < m doF4 if A[i] ≤ B[j] then C[k]← A[i]; i← i+ 1F5 else C[k]← B[j]; j ← j + 1F6 k ← k + 1F7 while i < n do C[k]← A[i]; i← i+ 1; k ← k + 1F8 while j < m do C[k]← B[j]; j ← j + 1; k ← k + 1
Temps de calcul : (n+m) affectations, et (n+m− 1) comparaisons (au pire)
Tri par fusion
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxxiv
9 6 3 0 2 1 8 7 5 4
9 6 3 0 2 1 7 5 4
division 50-50% sans réarrangement
récursion
0 2 3 6 9 1
récursion
4 5 7 8
fusionner en O(n)
8
n/2 éléments n/2 éléments
0 1 2 3 4 5 6 7 8 9
Algo MERGESORT(A[0..n− 1], g, d) // appel initiel avec g = 0, d = n
// récursion pour trier le sous-tableau A[g..d− 1]M1 if d− g < 2 then return // cas de base : tableau vide ou un seul élémentM2 m←
⌊(d+ g)/2
⌋// m est au milieu
M3 MERGESORT(A, g,m) // trier partie gaucheM4 MERGESORT(A,m, d) // trier partie droiteM5 FUSION(A, g,m, d) // fusion des résultats
Dans Ligne M5, on appelle une version qui fusionne les sous-tableauxA[g..m−1]et A[m..d− 1] et copie le résultat dans A[g..d− 1]
Tri par fusion : analyse
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxxv
nombre de comparaisons au pire pour n éléments :
C(n) =
0 n = 0,1C(bn/2c
)+ C
(dn/2e
)+ (n− 1) n > 1
on peut écrire un petit programme pour calculer C(n) à n = 0,1,2,3, . . . !
2
8
32
128
512
2048
8192
32768
131072
2 8 32 128 512 2048 8192
n
C(n) n lg(n) 6n n
Somme des bits
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxxvi
Combinatorial correspondence
SN = number of bits in the binary rep. of all numbers < N
11011
100101110111
1000100110101011110011011110
11011
100101110111
1000100110101011110011011110
11011
100101110111
1000100110101011110011011110
5 1
Same recurrence as mergesort (except for 1):
= + +
11011
100101110111
1000100110101011110011011110
:5/2 :5/2
:5 = :5/2 + :5/2 +5 1
*5 = :5 +5 136
longueur totale des représenta-tions binaires 1, . . . , n− 1 :même récurrence que lescomparaisons dans le tri par fu-sion !
on sait la solution exacte :
C(n) = S(n) = n lgn− n (u+ 21−u − 1)︸ ︷︷ ︸∈[0.9139··· ,1]
+1
avec u = lgn = lgn− blgnc
Tri par fusion
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxxvii
Théorème. Le tri par fusion fait
C(n) = n lgn− nA(lgn
)+ 1 ∼ n lgn
comparaisons au pire pour trier n éléments, où
lgn = lgn−blgnc ∈ [0,1) A(u) = u+21−u−1 ∈ [0.9139 · · · ,1]
2
8
32
128
512
2048
8192
2 8 32 128 512 2048 8192
nlg(n)-C(n) n C(n)-(nlg n-n)
Diviser pour régner - temps linéarithmique
Analyse d’algorithmes ? IFT2015 H2020 ? UdeM ? Miklós Csűrös xxxviii
Démarche :? partitionner le problème dans des sous-problèmes de tailles similaires,? chercher la solution optimale dans les sous-problèmes,? combiner les résultats en temps linéaire
Partition : n1, n2 . . . , np avec∑i ni = n et ni = n
p +O(1).
Récurrence typique :
T (n) =
t0 n ≤ 1∑pi=1 T
(ni)
+ tn n > 1
Solution : temps linéarithmique
T (n) ∼ tn logp n =t
lg pn lgn = Θ(n logn)