Développement d’un utilitaire de compression de données basé sur le code de Huffman avec Haskell
(lazamar.github.io)Implémentation d’un programme de compression de données utilisant le codage de Huffman
- Qu’est-ce que le code de Huffman ?
- Il permet de compresser des données en associant chaque caractère à une séquence de bits unique
- Les caractères fréquents sont associés à des séquences de bits courtes, tandis que les caractères rares sont associés à des séquences plus longues
- Exemple : pour la chaîne
aaab,aest associé à1etbà0, ce qui donne la compression1110
Code sans préfixe
- Qu’est-ce qu’un code sans préfixe ?
- Aucun mot de code ne doit être le préfixe d’un autre mot de code
- Exemple : pour
aaabc,aest associé à1,bà00etcà01, ce qui donne la compression1110001
Génération d’un code sans préfixe
- Méthode de génération d’un code sans préfixe
- Placer tous les caractères comme feuilles d’un arbre binaire complet
- Étiqueter la branche de gauche avec
1et celle de droite avec0 - Le chemin de la racine jusqu’à une feuille décrit le mot de code de chaque caractère
Écriture de l’encodeur
-
Définition des types
- Définition des types
Bit,Code,FreqMap,CodeMap,Weight,HTree HTreeest composé deLeafetFork
- Définition des types
-
Fonction d’encodage
- Fonction qui convertit une chaîne en bits
- Calcule la fréquence de chaque caractère à l’aide de
FreqMap, puis génère l’arbre de Huffman sur cette base - Génère le mot de code de chaque caractère à partir de l’arbre de Huffman
-
Fonction de décodage
- Fonction qui reconvertit les bits en chaîne d’origine
- Décode séquentiellement les bits à l’aide de l’arbre de Huffman
Intégration avec les fichiers binaires
- Encodage de données binaires
- Lit les octets comme des caractères à l’aide du module
Data.ByteString.Char8 - Encode les données binaires en utilisant l’encodeur de texte
- Lit les octets comme des caractères à l’aide du module
Sérialisation
- Fonction de sérialisation
- Convertit
FreqMapet les bits en octets réels, puis les enregistre dans un fichier - Utilise la monade
Putpour générer efficacement unByteString
- Convertit
Désérialisation
- Fonction de désérialisation
- Convertit les données lues depuis le fichier en
FreqMapet en bits - Utilise la monade
Getpour désérialiserFreqMap
- Convertit les données lues depuis le fichier en
Intégration complète du code
- Fonctions de compression et de décompression de fichiers
- Fonction
compress: lit un fichier, génère la table de fréquences, encode les données, puis les enregistre dans un fichier compressé - Fonction
decompress: lit un fichier compressé, décode les données, puis les enregistre dans le fichier d’origine
- Fonction
Améliorations
-
Multithreading
- Décode en parallèle les différentes sections du fichier
- Ajoute une table indiquant les limites des sections et la taille attendue après décodage afin de permettre le traitement parallèle
-
Encodage en un seul passage
- Génère la table de fréquences en temps réel pendant l’encodage
- Il n’est pas nécessaire d’inclure la table de fréquences au début du fichier
-
Code de Huffman canonique
- Décode en complexité temporelle
O(1)en indexant un vecteur au lieu de parcourir l’arbre
- Décode en complexité temporelle
-
Génération de code plus rapide
- Si l’on tente un encodage en un seul passage, il faut accélérer la génération de la table de codes
Avis de GN⁺
-
Avantages du codage de Huffman
- Il permet une compression efficace des données en associant les caractères fréquents à des séquences de bits courtes
- Il permet de traiter de gros volumes de données tout en minimisant l’usage mémoire
-
Avantages de Haskell
- Il permet d’écrire un code modulaire en tirant parti des avantages de la programmation fonctionnelle
- L’évaluation paresseuse permet d’optimiser l’utilisation de la mémoire
-
Projets aux fonctionnalités similaires
- Il existe divers outils de compression de données comme gzip et bzip2
- Il est important de comparer les avantages et les inconvénients de chaque outil pour choisir le plus adapté
-
Points à considérer lors de l’adoption de nouvelles technologies
- Il faut choisir un algorithme adapté en tenant compte des performances et de l’usage mémoire
- L’application de techniques d’optimisation comme l’encodage en un seul passage peut améliorer l’efficacité
1 commentaires
Avis Hacker News
Il existe des algorithmes in-place basés sur des tableaux, ce qui réduit le besoin d’allouer des arbres et de suivre des pointeurs
Dire qu’il faut empêcher qu’un mot de code soit le préfixe d’un autre mot de code n’est pas techniquement exact
aest un préfixe du code dec, mais si on le traite à l’envers, il reste décodable sans ambiguïtéJe me demande s’il existe des tutoriels similaires qui abordent des fonctionnalités plus avancées pour écrire des programmes Haskell (transformateurs de monades, lenses, etc.)
Le cours de programmation fonctionnelle de Coursera (Scala) propose un exercice similaire sur le codage de Huffman
J’ai utilisé des codes de Huffman pour exécuter un programme de macros du processeur MICMAC avec un minimum de microcycles et de micro-instructions
Informations supplémentaires sur le codage de Huffman : Rosetta Code Huffman Coding
Question pour les programmeurs Haskell : je me demande ce que vaut Haskell en matière de performances pour les développeurs qui cherchent à écrire du code optimisé
Un commentaire pour remercier du partage
Il y a une coquille dans le tableau de la section "Creating prefix-free codes"
0010(il est actuellement indiqué à tort comme0110)Le codage arithmétique est meilleur sur presque tous les plans