Cette séance a pour objet l’étude d’une méthode de compression de données inventée par David Albert Huffman en 1952. Cette méthode permet de réduire la longueur du codage d’un alphabet et repose sur la création d’un arbre binaire.
Différents types de codages
Dans la suite, nous utiliserons un alphabet composé seulement des 8 lettres A, B, C, D, E, F, G et H.
On cherche à coder chaque lettre de cet alphabet par une séquence de chiffres binaires.
- Combien de bits sont nécessaires pour coder chacune des 8 lettres de l’alphabet ?
Réponse
Il faut coder 8 caractères, on a donc besoin de 3 bits, puisque $2^3 = 8$.
- Quelle est la longueur en octets d’un message de 1 000 caractères construit sur cet alphabet ?
Réponse
- $1000 \times 3 = 3000$ bits sont nécessaires.
- $\dfrac{3000}{8} = 375$ octets sont nécessaires.
- Proposer un code de taille fixe pour chaque caractère de l’alphabet de 8 lettres.
Réponse
A : 000 ; B : 001 ; C : 010 ; D : 011 ; E : 100 ; F : 101 ; G : 110 et H : 111.
On considère maintenant le codage suivant, la longueur du code de chaque caractère étant variable.
Lettre | A | B | C | D | E | F | G | H |
---|---|---|---|---|---|---|---|---|
Code | 10 | 001 | 000 | 1100 | 01 | 1101 | 1110 | 1111 |
- En utilisant la table précédente, donner le code du message : CACHE.
Réponse
CACHE : 00010000111101
- Quel est le message correspondant au code 001101100111001.
Réponse
001101100111001 : BADGE
Dans un texte, chacun des 8 caractères a un nombre d’apparitions différent. Cela est résumé dans le tableau suivant, construit à partir d’un texte de 1 000 caractères.
Lettre | A | B | C | D | E | F | G | H |
---|---|---|---|---|---|---|---|---|
Nombre | 240 | 140 | 160 | 51 | 280 | 49 | 45 | 35 |
- En utilisant le code de taille fixe proposé à la question 3., quelle est la longueur en bits du message contenant les 1 000 caractères énumérés dans le tableau précédent ?
Réponse
Si on utilise 3 bits pour chaque caractère, il faut $1000 \times 3 = 3000$ bits pour coder le message.
- En utilisant le code de la question 4., quelle est la longueur du même message en bits ?
Réponse
$N = f(A)\cdot l(A) + f(B)\cdot l(B) + f(C)\cdot l(C) + f(D)\cdot l(D) + f(E)\cdot l(E) + f(F)\cdot l(F) + f(G)\cdot l(G) + f(H)\cdot l(H)$ où $f(x_i)$ est la fréquence du caractère $x_i$ et $l(x_i)$ la longueur (en bits) du codage du caractère $x_i$. A.N. $N = 240 \times 2 + 140 \times 3 + 160 \times 3 + 51 \times 4 + 280 \times 2 + 49 \times 4 + 45 \times 4 + 35 \times 4 = 2660$
Codage de Huffman
L’objectif du codage de Huffman est de trouver le codage proposé à la question 4.
Le codage de Huffman minimise la taille en nombre de bits du message codé en se basant sur le nombre d’apparition de chaque caractère (un caractère qui apparaît souvent aura un code plutôt court).
- Pour déterminer le code optimal, on considère 8 arbres, chacun réduit à une racine, contenant le symbole et son nombre d’apparitions.
graph TD A("A | 240") B("B | 140") C("C | 160") D("D | 51") E("E | 280") F("F | 49") G("G | 45") H("H | 35")
- On fusionne ensuite les deux arbres contenant les plus petits nombres d’apparitions (valeur inscrite sur la racine), et on affecte à ce nouvel arbre la somme des nombres d’apparitions de ses deux sous-arbres. Lors de la fusion des deux arbres, le choix de mettre l’un ou l’autre à gauche n’a pas d’importance. Nous choisissons ici de mettre le plus fréquent à gauche (s’il y a un cas d’égalité, nous faisons un choix arbitraire).
graph TD A("A | 240") B("B | 140") C("C | 160") D("D | 51") E("E | 280") F("F | 49") I("80") --> G I("80") --> H G("G | 45") H("H | 35")
- On recommence jusqu’à ce qu’il n’y ait plus qu’un seul arbre.
-
Combien d’étapes (combien de fusions d’arbres) sont nécessaires pour que cet algorithme se termine ?
-
En suivant l’algorithme précédent, construire l’arbre de Huffman.
graph TD A(" ") --> B(" ") B --> X("X") B --> Y("Y") A --> Z("Z")
Dans le cas de l’arbre ci-dessus le code de X est 00 (deux fois à gauche), le code de Y est 01, et celui de Z est 1.
-
Sur chaque arête de l’arbre construit à la question 10., inscrire 0 ou 1 selon que l’arête joint un fils gauche ou un fils droit.
-
Quel est le code de F ?
Le code suivant permet, à partir d’un fichier nommé texte.txt, de construire l’arbre de Huffman puis un dictionnaire qui associe à chaque caractère du fichier d’entrée son code sous forme d’une séquence de bits (liste de 0 et de 1).
Implémentation en Python de l’algorithme
- Écrire le code (et la spécification !) de la classe
Noeud
, nœud d’un arbre binaire. Par rapport à l’implémentation réalisée lors des TP précédenrs, ajouter le champlettre
initialisé à la chaîne de caractères vide et la méthode suivante :
|
|
-
Écrire les codes (et la spécification !) des fonctions
est_vide
,est_feuille
,parcours_prefixe
qui, respectivement teste si un nœud est vide, teste si un nœud est une feuille et finalement affiche l’arbre. -
Écrire le code de la fonction
creation_table_frequences
dont la spécification est
|
|
Tester la fonction avec l’instruction :
|
|
- Lire le document sur
les files de priorité
Écrire le code de la fonction
construction_arbre_huffman
dont la spécification est
|
|
et l’algorithme (cf. Cormen, Algorithmes)
- Écrire une fonction nommée
codes_huffman_parcours
dont la spécification est :
|
|
- Écrire une fonction nommée
encodage
dont la spécification est :
|
|
- Écrire une fonction nommée
decodage
dont la spécification est :
|
|