Desenvolvimento de um utilitário de compressão de dados baseado em código Huffman com Haskell
(lazamar.github.io)Implementação de um programa de compressão de dados com codificação Huffman
- O que é código Huffman?
- Realiza compressão de dados mapeando cada caractere para uma sequência única de bits
- Caracteres que aparecem com frequência são mapeados para sequências de bits curtas, enquanto caracteres raros são mapeados para sequências mais longas
- Exemplo: para a string
aaab,aé mapeado para1ebpara0, resultando na compressão1110
Código sem prefixo
- O que é um código sem prefixo?
- Garante que nenhuma palavra-código seja prefixo de outra palavra-código
- Exemplo: no caso de
aaabc,aé mapeado para1,bpara00ecpara01, resultando na compressão1110001
Geração de código sem prefixo
- Como gerar um código sem prefixo
- Colocar todos os caracteres como folhas de uma árvore binária completa
- Rotular o ramo esquerdo com
1e o ramo direito com0 - O caminho da raiz até a folha descreve a palavra-código de cada caractere
Escrevendo o codificador
-
Definições de tipos
- Definição dos tipos
Bit,Code,FreqMap,CodeMap,WeighteHTree HTreeé composto porLeafeFork
- Definição dos tipos
-
Função de codificação
- Função que converte uma string em bits
- Usa
FreqMappara calcular a frequência de cada caractere e, com base nisso, gera a árvore de Huffman - Gera a palavra-código de cada caractere a partir da árvore de Huffman
-
Função de decodificação
- Função que converte bits de volta para a string original
- Usa a árvore de Huffman para decodificar os bits sequencialmente
Integração com arquivos binários
- Codificação de dados binários
- Usa o módulo
Data.ByteString.Char8para ler bytes como caracteres - Usa o codificador de texto para codificar os dados binários
- Usa o módulo
Serialização
- Função de serialização
- Converte
FreqMape bits em bytes reais para salvar no arquivo - Usa a monad
Putpara gerarByteStringde forma eficiente
- Converte
Desserialização
- Função de desserialização
- Converte os dados lidos do arquivo em
FreqMape bits - Usa a monad
Getpara desserializarFreqMap
- Converte os dados lidos do arquivo em
Integração do código completo
- Funções de compressão e descompressão de arquivos
- Função
compress: lê o arquivo, gera o mapa de frequências, codifica os dados e salva o arquivo compactado - Função
decompress: lê o arquivo compactado, decodifica os dados e salva o arquivo original
- Função
Melhorias
-
Multithreading
- Decodifica seções do arquivo em paralelo
- Adiciona uma tabela com limites de seções e tamanho esperado da decodificação para permitir processamento paralelo
-
Codificação em passagem única
- Gera o mapa de frequências em tempo real enquanto codifica
- Elimina a necessidade de incluir o mapa de frequências no início do arquivo
-
Código Huffman canônico
- Decodifica em complexidade
O(1)indexando um vetor em vez de percorrer a árvore
- Decodifica em complexidade
-
Geração de código mais rápida
- Se tentar codificação em passagem única, é necessário acelerar a geração do mapa de códigos
Opinião do GN⁺
-
Vantagens da codificação Huffman
- Permite compressão eficiente de dados ao mapear caracteres frequentes para sequências de bits curtas
- Pode lidar com grandes volumes de dados minimizando o uso de memória
-
Vantagens do Haskell
- Permite escrever código modular aproveitando os benefícios da programação funcional
- Pode otimizar o uso de memória por meio de avaliação preguiçosa
-
Projetos com funcionalidade semelhante
- Existem várias ferramentas de compressão de dados, como gzip e bzip2
- É importante comparar vantagens e desvantagens de cada ferramenta para escolher a mais adequada
-
Pontos a considerar ao adotar novas tecnologias
- É preciso escolher o algoritmo adequado considerando desempenho e uso de memória
- Técnicas de otimização, como codificação em passagem única, podem aumentar a eficiência
1 comentários
Comentários no Hacker News
Existem algoritmos in-place baseados em arrays, o que reduz a necessidade de alocar árvores e seguir ponteiros
Não é tecnicamente correto dizer que uma palavra-código não pode ser prefixo de outra palavra-código
Fiquei curioso se existe algum tutorial semelhante que cubra recursos mais avançados de escrita de programas em Haskell, como monad transformers, lenses etc.
O curso de programação funcional da Coursera (Scala) oferece uma tarefa semelhante de codificação Huffman
Usei códigos Huffman para executar programas de macro do processador MICMAC com o mínimo de microciclos e microinstruções
Mais informações sobre codificação Huffman: Rosetta Code Huffman Coding
Pergunta para programadores Haskell: como é o desempenho de Haskell para quem quer escrever código otimizado?
Um comentário agradecendo por compartilhar
Há um erro de digitação na tabela da seção "Creating prefix-free codes"
Codificação aritmética é melhor em quase todos os aspectos