Skip to content
Snippets Groups Projects
Verified Commit 8d8fbe98 authored by iliya.saroukha's avatar iliya.saroukha :first_quarter_moon:
Browse files

wip: wrote part about encoding

parent 8a55fcc8
No related branches found
No related tags found
No related merge requests found
......@@ -230,3 +230,142 @@ le résultat de la DCT, de son inverse, de la DCT quantifiée et finalement de
l'inverse quantifiée.
# Huffman Adaptatif
Dans ce travail pratique nous allons implémenter l'algorithme de compression
Huffman Adaptatif. Celui-ci aura pour but de construire un arbre binaire où
chaque noeud **externe** représentera un caractère dans la chaîne fournie pour
l'encodage et la valeur des noeuds **internes** correspondra à la somme des
poids de ses enfants (i.e. nombre d'occurrence du caractère).
## Structure de l'arbre
Pour la structure de l'arbre binaire, nous avons privilégié l'utilisation des
`dataclass` en `python` qui peuvent s'apparenter à de simples structures tels
qu'elles existent en `C`. Ceci nous permet d'éviter d'écrire des constructeurs
et des méthodes spécifiques à cette classe. Il est possible de se rendre compte
que la structure est bel et bien récursive du fait que les champs `left` et
`right` sont des références vers le même type `Node`.
```python
@dataclass
class Node:
weight: int = 0
nyt_code: str | None = None
value: str = "NYT"
left: Node | None = None
right: Node | None = None
```
## Encodage
Dans la phase d'encodage, le but sera donc de construire itérativement l'arbre
en y insérant au fur et à mesure les caractères rencontrés dans la chaîne
fournie à la fonction d'encodage. Celle-ci est présentée ci-dessous :
```python
def encode(input: str) -> str:
tree = Node()
encoded: list[str] = []
seen: set[str] = set()
for c in input:
insert_char(tree, c)
prefix = find_char(tree, c)
if c not in seen:
seen.add(c)
encoded.append(prefix.nyt_code)
encoded.append(compute_code(c))
else:
encoded.append(compute_prefix(tree, c))
pprint.pp(tree)
pprint.pp(tree)
print(f'Nombre de swaps: {swap_count}')
return ' '.join(encoded)[1:]
```
Nous allons donc commencer par insérer dans l'arbre le nouveau caractère
rencontré via la fonction `insert_char`. Suite à cela nous ferons une recherche
dans l'arbre pour calculer la partie NYT (_Not Yet Transmitted_) qui servira
de préfixe au code fixe du caractère. Si ce caractère n'a pas encore été
rencontré, il sera aussi inséré dans une structure de données de type `set` qui
permet de stocker des données sans doublons. Ceci est critique du fait que
le code NYT établi à l'insertion initiale du caractère a possiblement changé
suite aux divers _swaps_ qui ont possiblement eu lieu. Ces _swaps_ se produisent
lorsque le poids du sous-arbre gauche est supérieur à celui de droite. Par
conséquent, si nous allons insérer à nouveau un caractère connu au préalable
(i.e. présent dans le `set`), nous allons recalculer le préfixe NYT du caractère
via la fonction `compute_prefix` en parcourant l'arbre jusqu'à retrouvé ce
caractère.
### Résultat de l'encodage
Pour la chaîne de caractères "darkvador", le résultat de l'encodage sera le
suivant :
```bash
Nombre de swaps: 4
Code final: 000011 0 000000 00 01101 100 00110 1100 10001 10 0 11100 01010 110
```
Ci-dessous, le lecteur peut observer l'arbre qui fut construit dynamiquement au
moment de l'encodage. Il est nécessaire de mentionner le fait que le champ
`value` des noeuds internes est égale à `NYT` du fait que c'est la valeur par
défaut d'un noeud de type `Node`, cependant le **vrai** noeud NYT est celui dont
la valeur du champ `weight` est égale à 0. Celui-ci est donc aussi le noeud
terminal de l'arbre.
```bash
Node(weight=9,
nyt_code=None,
value='NYT',
left=Node(weight=2, nyt_code='', value='d', left=None, right=None),
right=Node(weight=7,
nyt_code=None,
value='NYT',
left=Node(weight=2,
nyt_code='0',
value='a',
left=None,
right=None),
right=Node(weight=5,
nyt_code=None,
value='NYT',
left=Node(weight=2,
nyt_code='00',
value='r',
left=None,
right=None),
right=Node(weight=3,
nyt_code=None,
value='NYT',
left=Node(weight=1,
nyt_code='100',
value='k',
left=None,
right=None),
right=Node(weight=2,
nyt_code=None,
value='NYT',
left=Node(weight=1,
nyt_code=None,
value='NYT',
left=Node(weight=0,
nyt_code=None,
value='NYT',
left=None,
right=None),
right=Node(weight=1,
nyt_code='11100',
value='o',
left=None,
right=None)),
right=Node(weight=1,
nyt_code='1100',
value='v',
left=None,
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment