Université François Rabelais de Tours Laboratoire de Mathématiques et Physique Théorique Mathématiques Discrètes et Algorithmique UE 5-4 Option Semestre 5 2. Quelques algorithmes classiques Dans ce chapitre nous présenterons quelques algorithmes classiques, ce qui nous permettra d’une part de nous familiariser avec le langage algorithmique (le pseudo-code) et d’autre part d’introduire des notions essentielles à l’algorithmique. 2.1. La division euclidienne. Rappelons tout d’abord la définition de la division euclidienne. Théorème 2.1. Soient a ∈ N et b ∈ N tels que b 6= 0. Il existe un unique couple (q, r) ∈ N2 tel que a = qb + r 0≤r ≤b−1 où On peut calculer le couple (q, r) avec l’algorithme suivant. Données : a, b ∈ N, b > 0 Résultat : (q, r) tel que a = bq + r q := 0 r := a tant que r ≥ b faire q := q + 1 r := r − b fin retourner (q, r) Algorithme 2: Division Euclidienne Exemple 2.2. Appliquons cet algorithme avec les les valeurs suivantes : test Initialisation 1ère boucle 2ère boucle 3ère boucle 4ère boucle valeurs (14, 3). Les variables prennent successivement du tant que 14 ≥ 3 11 ≥ 3 8≥3 5≥3 2≥3 q 0 1 2 3 4 r 14 11 8 5 2 On a bien 14 = 4 ∗ 3 + 2. Notation : Soient (a, b) ∈ N2 tels que b > 0. On écrira a mod b pour désigner le reste de la division euclidienne de a par b et a ÷ b pour désigner le quotient. On rappelle que le pgcd(a, b) est le plus grand diviseur commun de a et b. On a Théorème 2.3. Soit (a, b) ∈ N2 − {(0, 0)}. Il existe r, s ∈ Z tels que pgcd(a, b) = ra + sb L’algorithme pour calculer r et s de ce théorème est basée sur le résultat suivant : Lemme 2.4. Soit a = bq + r où a, b, q, r ∈ N. On a pgcd(a, b) = pgcd(b, r) L’algorithme le plus connu pour calculer r, s est l’algorithme d’Euclide étendu. Plutôt que de décrire l’algorithme, donnons un exemple concret : 65 = 9 · 7 + 2 9=2·4+1 et donc pgcd(65, 9) = 1. On a 1 = 9 − (2 · 4) = 9 − 4 · (65 − 9 · 7) = 29 · 9 − 4 · 65. 1 2 Cet algorithme n’est pas très efficace car il necessite la mémorisation de toutes les étapes de calculs intermédiaires. Nous allons présenter un algorithme bien plus efficace, l’algorithme de Blankinship. Supposons que nous voulions calculer le pgcd de 252 et 198. Pour calculer u et v on construit la matrice suivante ! 252 1 0 M0 := 198 0 1 puis on applique l’algorithme d’Euclide dans la première colonne tout en étendant les manipulations de lignes au reste de la matrice. Ce sera plus clair sur un exemple : Ancienne Matrice ! 252 1 0 M0 := 198 0 1 ! 54 1 −1 M1 := 198 0 1 ! 54 1 −1 M2 := 36 −3 4 ! 18 4 −5 M3 := 36 −3 4 Pivot Manipulation 198 L1 := L1 − L2 54 L2 := L2 − 3L1 36 L1 := L1 − L2 18 L2 := L2 − 2L1 Nouvelle matrice ! 54 1 −1 M1 := 198 0 1 ! 54 1 −1 M2 := 36 −3 4 ! 18 4 −5 M3 := 36 −3 4 ! 18 4 −5 M4 := 0 −11 14 L’algorithme s’arrête lorsque la première colonne contient le pgcd. On a alors Dans l’algorithme , on notera M := 18 = 4 × 252 − 5 × 198 ! a u1 v1 . b u2 v2 Données : a, b ∈ N∗ Résultat : (u, v) tel que d = au + bv u1 := 1 v1 := 0 u2 := 0 v2 := 1 tant que a > 0 et b > 0 faire si a ≥ b alors q := a ÷ b a := a − q × b u1 := u1 − q × u2 v1 := v1 − q × v2 sinon q := b ÷ a b := b − q × a u2 := u2 − q × u1 v2 := v2 − q × v1 fin fin si a>0 alors pgcd := a u := u1 v := v1 sinon pgcd := b u := u2 v := v2 fin retourner (u, v) Algorithme 3: Algorithme de Blankinship 3 Démonstration de l’algorithme : On définit les matrices suivantes : ! ! 1 λ 1 0 U (λ) = , L(λ) = 0 1 λ 1 Soit M une matrice à deux lignes. On voit facilement que la matrice 1. U (λ)M est obtenue à partir de M en ajoutant λ-fois la deuxième ligne de M à la première ; 2. L(λ)M est obtenue à partir de M en ajoutant λ-fois la première ligne de M à la deuxième. Dans l’algorithme de Blankinship, on multiplie sucessivement la matrice M par des matrices E1 , . . . , En de type U (λ) ou L(λ). On pose E = En . . . E1 . Lorsque l’algorithme se termine on a ! ! d u v 0 u′ v ′ En . . . E1 M = ou En . . . E1 M = 0 u′ v ′ d u v On a donc (nous n’étudierons que le premier cas, le deuxième étant similaire) ! ! ! a a d u v ,E . , I2 = E =E ′ ′ b b 0 u v ! u v . En regardant le coefficient [1, 1] dans l’égalité ci-dessus, on a Par identification on obtient E = u′ v ′ d = au + bv. 2.2. Ecriture des nombres dans différentes bases. La manière conventionnelle d’écrire les nombres est l’écriture décimale. On utilise les chiffres 0–9 pour représenter les puissances de 10. Par exemple lorsqu’on écrit 34765 on veut dire 3 × 104 + 4 × 103 + 7 × 102 + 6 × 101 + 5 × 100 . En fait, tout nombre entier positif peut jouer le rôle de base. Théorème 2.5. Soit b ∈ N∗ . Tout nombre entier n s’écrit uniquement sous la forme n = ak bk + ak−1 bk−1 + . . . + a1 b + a0 où ai est un entier tel que 0 ≤ ai ≤ b − 1 pour tout i = 0, . . . , k et ak 6= 0. Cette expression est appelée l’écriture de n en base b. Démonstration. On ne montrera que l’existence. L’idée est simple : appliquer l’algorithme de division euclidienne. Premièrement on divise n par b n = bq0 + a0 où 0 ≤ a0 < b. On divise alors q0 par b : q0 = bq1 + a1 où 0 ≤ a1 < b. On continue q0 q1 = = qk−2 qk−1 = = bq1 bq2 .. . bqk−1 b.0 + a1 + a2 .. . + ak−1 + ak où 0 ≤ a1 < b où 0 ≤ a2 < b où 0 ≤ ak < b où 0 ≤ ak+1 < b On doit avoir qk = 0 pour un certain k ∈ N puisque n > q0 > q1 > . . . ≥ 0. et une suite strictement décroissante d’entier se termine par 0. Finalement, on a n = bq0 + a0 = b(bq1 + a1 ) + a0 = b(b(bq2 + a2 ) + a1 ) + a0 = ... = ak bk + ak−1 bk−1 + . . . + a1 b + a0 4 Exemple 2.6. Ecrivons 456 en base 9. On applique l’algorithme de la preuve : 456 = 50 = 5 = 9 · 50 + 9·5 + 9·0 + 6 5 5 et on obtient 456 = 5 · 92 + 5 · 9 + 6. Définition 2.7. On écrit (ak , ak−1 , . . . a1 , a0 )b pour représenter l’entier n en base b : n = ak bk + ak−1 bk−1 + . . . + a1 b + a0 . Voici un algorithme, pour calculer l’écriture en base b d’un nombre n. Données : n, b ∈ N, b > 1 Résultat : (ak , . . . , a1 , a0 ) tel que n = ak bk + . . . + a1 b + a0 q := n k := 0 tant que q 6= 0 faire ak := q mod b q := q ÷ b k := k + 1 fin retourner (ak , . . . , a1 , a0 ) Algorithme 4: Ecriture en base b Exemple 2.8. Appliquons l’algorithme à n = 201 et b = 2 : Initialisation boucle 1 boucle 2 boucle 3 boucle 4 boucle 5 boucle 6 boucle 7 boucle 8 q 201 100 50 25 12 6 3 1 0 k 0 1 0 0 0 0 0 0 0 Liste des ak ∅ (1) (0, 1) (0, 0, 1) (1, 0, 0, 1) (0, 1, 0, 0, 1) (0, 0, 1, 0, 0, 1) (1, 0, 0, 1, 0, 0, 1) (1, 1, 0, 0, 1, 0, 0, 1) On obtient 201 = 27 + 26 + 23 + 20 = (11001001)2. Proposition 2.9. Soit (n, b) ∈ N avec b > 1. Le nombre de chiffres dans l’écriture de n en base b est ⌊logb (n)⌋ + 1 := ⌊ log n ⌋+1 log b Démonstration. Montrons que tout n tel que bk−1 ≤ n < bk peut s’écrire avec k chiffre en base b. On procède par induction sur k. Initialisation. Si 1 ≤ n < b alors n = (n)b et n s’écrit avec 1 chiffre en base b. Hérédité. Soit k > 1. Supposons que le résultat est vrai pour k − 1 et soit n tel que bk−1 ≤ n < bk . Soit n−r (q, r) ∈ N2 tel que n = bq + r avec 0 ≤ r < b. On a alors q = et b n−r bk < = bk−1 b b bk−1 − b n−r > = bk−2 − 1 b b et comme q est un entier on obtient bk−2 ≤ q < bk−1 . L’hypothèse de récurrence implique que q s’écrit avec k − 1 chiffres en base b i.e. (q)b = (ak−2 , . . . , a0 ) où ak−2 6= 0. Alors (n)b = (ak−2 , . . . , a0 , r) 5 et n s’écrit avec k chiffres en base b. On applique le logarithme à l’inégalité bk−1 ≤ n < bk . On obtient log(bk−1 ) ≤ log n < log bk c’est à dire k − 1 ≤ log n <k log b et ⌊logb (n)⌋ + 1 = k. 2.3. Exponentation modulaire rapide. En cryptographie, il est extrêmement important de pouvoir calculer rapidement bm mod n. Ce genre d’opération est généralement effectué sur des nombres qui contiennent 150, 200 voire 300 chiffres. Dans ce contexte il est hors de question de d’abord calculer bm puis de réduire modulo n. L’idée est d’utiliser l’écriture binaire de m (en base 2). Soit m = (ak−1 , . . . , a1 , a0 )2 . On a alors k−1 bm = bak−1 ·2 . . . ba1 ·2 ba0 k Pour calculer bm il suffit donc de calculer b, b2 , (b2 )2 , (b4 )2 . . . b2 . Lorsqu’on a ces valeurs, il suffit de mulj tiplier entre elles les valeurs b2 qui vérifient aj = 1. On obtient ainsi bn . Exemple 2.10. Supposons que l’on veuille calculer 311 . On a 311 = 38 · 32 · 3. On calcule successivement 32 = 9, 34 = 92 = 81, 38 = (81)2 = 6561. Finalement on obtient 311 = 6561 · 9 · 3 = 177 147. Dans le cas modulaire, c’est encore plus simple, on peut (et il faut) réduire modulo n à chaque étape. Données : b, m, n ∈ N∗ Résultat : bm mod n n = (ak−1 , . . . , a0 )2 x := 1 power := b mod n pour i = 0 à k − 1 faire si ai = 1 alors x := x · power mod m fin power := power × power fin retourner x Algorithme 5: Exponentiation modulaire Exemple 2.11. On utilise l’algorithme pour calculer 3644 mod 645. Tout d’abord, on calcule que 645 = (1010000100)2. On a i=0 i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 =0 =0 =1 =0 =0 =0 =0 =1 =0 =1 x=1 x=1 x = 81 x = 81 x = 81 x = 81 x = 81 x = 471 x = 471 x = 36 power power power power power power power power power power = 32 mod 645 = 9 = 92 mod 645 = 81 = 812 mod 645 = 111 = 1112 mod 645 = 66 = 662 mod 645 = 486 = 4862 mod 645 = 126 = 1262 mod 645 = 396 = 3962 mod 645 = 81 = 812 mod 645 = 111 = 1112 mod 645 = 36 2.4. Algorithme de tri : Premiers exemples. Un algorithme de tri est, en informatique ou en mathématiques, un algorithme qui permet d’organiser une collection d’objets selon un ordre déterminé. Dans ce cours, nous allons étudier de nombreux algorithmes de tri. Nous commençons ici avec les plus simples, le tri à bulle et le tri par insertion. 6 Le tri à bulle. C’est un algorithme de tri qui consiste à faire remonter progressivement les plus grands éléments d’un tableau. Données : Liste d’entiers L = (a1 , a2 , . . . , an ) Résultat : Liste d’entier triée pour i=1 à n-1 faire pour j=1 à n-i faire si aj > aj+1 alors échanger aj et aj+1 fin fin fin retourner L Algorithme 6: Tri à bulle Exemple 2.12. Appliquons l’algorithme à la liste [3, 2, 4, 1, 5]. i=1 j=1 3 2 4 1 5 j=2 2 3 4 1 5 j=3 2 3 4 1 5 j=4 2 3 1 4 5 i=2 j=1 2 3 1 4 5 j=2 2 3 1 4 5 j=3 2 1 3 4 5 i=3 j=1 2 1 3 4 5 j=2 1 2 3 4 5 i=4 j=1 1 2 3 4 5 −→ 2 3 4 1 5 −→ 2 3 1 4 5 −→ 2 1 3 4 5 −→ 1 2 3 4 5 Le tri par insertion. C’est la méthode utilisée par les joueurs de carte. Il consiste à déplacer les éléments de la liste “vers la gauche” jusqu’à "leurs places". Données : Liste d’entiers L = (a1 , a2 , . . . , an ) Résultat : Liste d’entier triée pour i=2 à n faire j := i ; tant que j > 1 et aj−1 > aj faire Echanger aj et aj−1 ; j := j − 1 fin fin retourner L Algorithme 7: Tri par insertion Exemple 2.13. Appliquons l’algorithme à la liste [3, 5, 2, 9, 7]. 7 i=2 3 5 2 9 7 −→ 3 5 2 9 7 i=3 3 5 2 9 7 −→ 2 3 5 9 7 i=4 2 3 5 9 7 −→ 2 3 5 9 7 i=5 2 3 5 9 7 −→ 2 3 5 7 9