Compression de données avec l'algorithme LZ78
Objectifs
Comprendre l'impact du choix d'une structure de données dans le temps d'exécution d'un algorithme.
Le TP doit être fait en binôme.
Codeur: Responsable pour l'implementation.
Navigateur: Responsable pour veiller à la qualité du code (?)
Sprint 1
Sprint 2
Sprint 3
10
60
110
120
170
180
0
40min
10min
On bosse
On discute
Le binôme doit alterner les rôles de codeur et de navigateur à chaque sprint
Si ta tata tasse ta tata, ta tata tassée sera
si_ta_tata_tasse_ta_tata_ta_tata_tassee_sera
,'s'
,'i'
,'t'
,'a'
,'_t'
,'at'
,'a_'
,'ta'
,'ss'
,'e'
,'_ta'
,'_tat'
,'a_t'
,'a_ta'
,'tas'
,'se'
,'e_'
,'ser' ]
,'_'
1
2
3
[ ''
0
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
dico:
code:
[ 0,'s',
0,'i',
0,'_',
0,'t',
0,'a',
3,'t',
5,'t',
5,'_',
4,'a',
1,'s',
0,'e',
6,'a',
12,'t',
8,'t',
14,'a',
9,'s',
1,'e',
11,'_',
18,'r'
s
i
_
t
a
t
a
_
t
a
_
t
a
s
s
e
_
t
a
t
a
_
t
a
_
t
a
t
a
_
t
a
t
a
s
s
e
e
s
_
e
r
a
_
,'ta_'
20
9,'_',
,5]
Algorithme de compression de données
entrée:
Compression
s=dico[0]+'s'
_t=dico[3]+'t'
Un bon Anglais ne plaisante jamais, quand il s’agit d’une chose aussi sérieuse qu’un pari, répondit Phileas Fogg. Je parie vingt mille livres contre qui voudra que je ferai le tour de la terre en quatre-vingts jours ou moins, soit dix-neuf cent vingt heures ou cent quinze mille deux cents minutes. Acceptez-vous ?
Avant LZ78 : 440723 octets (430 kB)
Après LZ78: 253266 octets (247 kB)
Taux compression: (430-247)/430 = 0.42
Jules Verne, Le tour du monde en 80 jours.
Algorithme de compression de données
entrée:
[ 0,'a',0,'b',0,'r',1,'c',1,'d',1,'b',3,'a' ]
dico:
Décompression
0
original:
Algorithme de compression de données
1
2
3
4
5
6
7
[ 0,'a'
,0,'b'
,0,'r'
,1,'c'
,1,'d'
,1,'b'
,3,'a' ]
[''
,'a'
,'b'
,'r'
,'ac'
,'ad'
,'ab'
,'ra']
a
b
r
ac
ad
ab
ra
Objectifs: Questions 1, 2 et 3
Quiz
Lisez le code suivant
Qu'est-ce qu'il ira afficher?
A) Erreur
B) 9,9,0
C) 10,9,10
D) 9,9,Erreur
liste = [ i for i in range(10) ]
print( liste[-1] )
print( liste[9] )
print( liste[10] )
Lisez le code suivant
Qu'est-ce qu'il ira afficher?
A) Erreur
B) 2,8,2
C) 2,4,6
D) 3,9,3
liste = [ i for i in range(10) ]
print( liste[ 2:8:2 ] )
Lisez le code suivant
Qu'est-ce qu'il ira afficher?
A) Erreur
B) 1,2,3,4,5,6,7
C) 0,1,2,3,4,4,4
D) 0,1,2,3,4,5,6
liste = [ i if i < 4 else 4 for i in range(10) ]
print( liste[:7] )
Lisez le code suivant
Qu'est-ce qu'il ira afficher?
A) 3
B) 9
C) 7
D) 1
liste = [ 3,1,5,9,4,2,7 ]
x = itertools.reduce( lambda x,y: x if x > y else y, liste )
print(x)
Indexation de listes:
Le dernière élément:
Expression dans liste:
Une ligne if:
liste[ début : fin : pas ]
liste[-1]
[fn(x) for x in iterable]
val_si_vrai if teste else val_si_faux
Pour computer la taux de compression il faut computer les nombres d'octets dans la liste alternée des entiers et caractères.
Dans la prochaine sprint on va converter la liste dans une chaine d'octets.
Et si l'entier dépasse 255?
b'\x00a\x00b\x00r\x01c\x01d\x01b\x03a'
lz78_compresse_bin("abracadabra")
\x00 : [0]10
\x0A : [10]10
\x10 : [16]10
\xFF : [255]10
Algorithme de compression de données
[ 0,'a',0,'b',0,'r',1,'c',1,'d',1,'b',3,'a' ]
Algorithme de compression de données
0
255
['',
,'a'
,'b'
,'r'
,'ac'
,'ad'
,'ab'
,'ra']
...
256
257
258
259
260
261
dico:
...\x00a
code:
\x00\x00b
\x00\x00r
\x00\xFFc
\x00\xFFd
\x00\xFFb
\x01\x01a
Et si l'entier dépasse 255?
[ ...
,0,'a'
,0,'b'
,0,'r'
,255,'c'
,255,'d'
,255,'b'
,257,'a' ]
Objectifs: Questions 4, 5, 6 et 7
Question 5
lz78_compresse_bin
Peer Review (?)
Objectifs: Questions 8, 9 et 10
bytearray(b'\x00a\x01a\x02a\x03a\x04a\x05a\x06a\x07a\x08a\ta\na\x0ba \x0ca\ra\x0ea\x0fa\x10a\x11a\x12a\x13a\x14a\x15a\x16a\x17a\x18a\x19a \x1aa\x1ba\x1ca\x1da\x1ea\x1fa a!a"a#a$a%a&a\'a(a)a*a+a,a-a.a/a0a1a 2a3a4a5a6a7a8a9a:a;a<a=a>a?a@aAaBaCaDaEaFaGaHaIaJaKaLaMaNaOaPaQaRaSa TaUaVaWaXaYaZa[a\\a]a^a_a`aaabacadaeafagahaiajakalamanaoapaqarasataua vawaxayaza{a|a}a~a\x7fa\x80a\x81a\x82a\x83a\x84a\x85a\x86a\x87a\x88a \x89a\x8aa\x8ba\x8ca\x8da\x8ea\x8fa\x90a\x91a\x92a\x93a\x94a\x95a\x96a \x97a\x98a\x99a\x9aa\x9ba\x9ca\x9da\x9ea\x9fa\xa0a\xa1a\xa2a\xa3a\xa4a \xa5a\xa6a\xa7a\xa8a\xa9a\xaaa\xaba\xaca\xada\xaea\xafa\xb0a\xb1a\xb2a \xb3a\xb4a\xb5a\xb6a\xb7a\xb8a\xb9a\xbaa\xbba\xbca\xbda\xbea\xbfa\xc0a \xc1a\xc2a\xc3a\xc4a\xc5a\xc6a\xc7a\xc8a\xc9a\xcaa\xcba\xcca\xcda\xcea \xcfa\xd0a\xd1a\xd2a\xd3a\xd4a\xd5a\xd6a\xd7a\xd8a\xd9a\xdaa\xdba\xdca \xdda\xdea\xdfa\xe0a\xe1a\xe2a\xe3a\xe4a\xe5a\xe6a\xe7a\xe8a\xe9a\xeaa \xeba\xeca\xeda\xeea\xefa\xf0a\xf1a\xf2a\xf3a\xf4a\xf5a\xf6a\xf7a\xf8a \xf9a\xfaa\xfba\xfca\xfda\xfea\xffa\x01\x00a\x01\x01a\x01\x02a\x01\x03a \x01\x04a\x01\x05a\x01\x06a\x01\x07a\x00\x14')
Algorithme de compression de données
\ta
\na
\xff
>>> lz78_compresse_bin("a"*35000)
\x01\x00
Algorithme de compression de données
La vitesse du code actuel (avant la question 13) c'est frustrant!
Pour comprimer Moby Dick il faut plusieurs minutes.
Le point de faiblesse c'est la structure de donné qu'on utilise.
L'algorithme serait 1000 fois (!!!) plus rapide si on utilise une hash (python dictionnaire) au lieu d'une liste pour garder le dictionnaire.
Temps d'exécution
en utilisant une liste: > 30 minutes
en utilisant une hash: 2 secondes
Algorithme de compression de données
Disons qu'on a une liste dico avec 10^6 éléments.
Chaque fois qu'on appelle la fonction position, dans le pire cas on doit lire tous les 10^6 éléments.
Imaginez qu'au lieu d'avoir une seule liste, on a 1000 liste de 1000 éléments chaque.
Algorithme de compression de données
dico: [e1,e2,...e10^6]
dico1: [e32,e41,e85...e951245]
dico2: [e17,e19,e39...e1000000]
dico1000: [e5,e23,e60...e977801]
.
.
.
tel que,
hash( e32 ) = 1
hash( e41 ) = 1
hash( e17 ) = 2
hash( e23 ) = 1000
hash( e85 ) = ?
Group Review