Kodowanie Huffmana

Transkrypt

Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Kodowanie Huffmana
Dawid Duda
4 marca 2004
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Podstawowe oznaczenia i definicje
Statyczne kody Huffmana
Wymagania wobec kodu
Podstawowa idea
Podsumowanie
Dynamiczne kody Huffmana
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Praktyka
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Podstawowe oznaczenia i definicje
Podstawowe oznaczenia i definicje:
I
alfabet wejściowy: A = {a1 , a2 , . . . , am }
I
informacja własna litery:
i(A) = log
I
1
= − log P(A)
P(A)
entropia (średnia informacja własna):
X
X
H=
P(Ai )i(Ai ) = −
P(Ai ) log P(Ai )
(1)
(2)
I
Tw. Shannona: średnia ilość bitów przypadająca na jeden
zakodowany symbol nie jest mniejsza od entropii źródła
I
kod prefiksowy: kod, w którym żadne słowo kodowe nie jest
prefiksem innego słowa kodowego
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wymagania wobec kodu
Podstawowa idea
Podsumowanie
Co chcemy uzyskać:
I
każdemu symbolowi z alfabetu chcemy przypisać
jednoznacznie słowo kodowe
I
symbolom rzadko występującym chcemy przypisać dłuższe
słowa kodowe, a częściej występującym krótsze
I
chcemy móc jednoznacznie dekodować zakodowane dane
I
ale takich kodów jest wiele, który wybrać?
I
no i jak wybrać, aby taki kod móc szybko zbudować?
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wymagania wobec kodu
Podstawowa idea
Podsumowanie
Cel: optymalny kod spełniający wymienione wymagania.
Kluczowe obserwacje:
I
dla każdego jednoznacznie dekodowalnego kodu istnieje nie
gorszy (w sensie średniej ilości bitów na symbol) kod
prefiksowy
I
w kodzie optymalnym częściej występującym symbolom będą
odpowiadały krótsze słowa kodowe a rzadziej występującym
dłuższe
I
w kodzie optymalnym dwa symbole występujące najrzadziej
będą miały słowa kodowe o tej samej długości
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
A
a2
a1
a3
a4
a5
P(A)
0.4
0.2
0.2
0.1
0.1
A
a2
a1
a3
a40
c(A)
c(a2 )
c(a1 )
c(a3 )
c(a4 )
c(a5 )
c(A)
c(a2 )
c(a1 )
c(a3 )
α1
A
a2
a30
a1
P(A)
0.6
0.4
c(A)
α3
c(a2 )
c(a300 ) = 0
c(a2 ) = 1
α3 = 0
Dawid Duda
c(a2 )
c(a1 )
c(a3 )
c(a4 )
c(a5 )
P(A)
0.4
0.4
0.2
c(A)
c(a2 )
α2
c(a1 )
c(a30 ) = α3 · 0
c(a1 ) = α3 · 1
α2 = α3 · 0
c(a3 ) = α2 · 0
c(a40 ) = α2 · 1
α1 = α2 · 1
c(a4 ) = α1 · 0
c(a5 ) = α1 · 1
A
a300
a2
P(A)
0.4
0.2
0.2
0.2
Wymagania wobec kodu
Podstawowa idea
Podsumowanie
=
=
=
=
=
1
01
000
0010
0011
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wymagania wobec kodu
Podstawowa idea
Podsumowanie
Algorytm konstrukcji drzewa Huffmana:
1. umieść m liści na liście L
2. dopóki lista L zawiera przynajmniej dwa elementy wykonuj
2.1
2.2
2.3
2.4
usuń z listy L dwa elementy x oraz y o najmniejszej wadze
stwórz nowy wierzchołek p, który będzie rodzicem x i y
ustaw wagę wierzchołka p na sumę wag x i y
umieść wierzchołek p na liście L
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wymagania wobec kodu
Podstawowa idea
Podsumowanie
Algorytm Huffmana generuje optymalny kod, ale jaka jest jego
średnia długość l? Twierdzenie:
H(S) ≤ l ≤ H(S) + 1
Dawid Duda
Kodowanie Huffmana
(3)
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wymagania wobec kodu
Podstawowa idea
Podsumowanie
Istnieje możliwość dokładniejszego oszacowania. Niech
Pmax = max {P(ai )}m
i=1
wówczas
I
Pmax < 0.5 =⇒ l ≤ H(S) + Pmax
I
Pmax ≥ 0.5 =⇒ l ≤ H(S) + Pmax + 0.086
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wymagania wobec kodu
Podstawowa idea
Podsumowanie
Zalety:
I
kod Huffmana minimalizuje sumę ważoną długości kodów, tj.
jest optymalnym kodem prefiksowym
I
procedura budowy drzewa Huffmana jest szybka i prosta
w implementacji
I
zarówno kodowanie jak i dekodowanie jest proste i efektywne
Wady:
I
do budowy drzewa konieczne są statystyki kodowanej
wiadomości
I
do przekazywanej/zapisywanej wiadomości trzeba dołączyć
opis drzewa
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Cel: stworzenie jednoprzebiegowego algorytmu kodującego
Metoda: utrzymywanie drzewa Huffmana obliczonego zgodnie
z częstościami wystąpień symboli w dotychczas przetworzonym
fragmencie
Co zyskamy:
I
tylko jeden przebieg
I
nie trzeba przesyłać drzewa
Problem: jak szybko uaktualniać drzewo Huffmana?
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Wierzchołkom w drzewie przypisujemy wagę, która dla liści jest
równa ilości wystąpień kodowanego symbolu w dotychczasowym
tekście, a dla wierzchołków wewnętrznych sumie wag dzieci. Niech
Mt = ai1 ai2 . . . aik będzie dotychczas przetworzonym fragmentem.
Następna litera aik+1 będzie zakodowana oraz odkodowana przy
użyciu drzewa Huffmana dla Mt .
Główna trudność: jak szybko zmodyfikować drzewo dla Mt aby
otrzymać drzewo dla Mt+1 ? Proste zwiększenie o 1 wagi
wierzchołka i jego rodziców nie zawsze da drzewo Huffmana.
Rozwiązanie: wykorzystać własność sąsiedztwa
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Do wyprowadzenia algorytmu wykorzystamy pewną charakteryzację
drzew Huffmana:
Własność sąsiedztwa
Drzewo binarne o p liściach oraz nieujemnych wagach
wierzchołków wi jest drzewem Huffmana wtedy i tylko wtedy gdy:
1. waga każdego wierzchołka jest sumą wag jego dzieci
2. istnieje niemalejąca numeracja wierzchołków zgodna
z niemalejącym uporządkowaniem według wagi taka, że dla
1 ≤ j ≤ p − 1 wierzchołki 2j − 1 i 2j są sąsiadami i ich
wspólny rodzic ma wyższy numer
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Rozwiązanie: aktualizacje drzewa wykonamy w dwóch fazach:
1. przekształcenie drzewa do takiej postaci, w której proste
zwiększenie wagi odpowiednich wierzchołków nie zaburzy
własności sąsiedztwa
2. zwiększenie wagi wierzchołka odpowiadającego
przetwarzanemu symbolowi i jego rodzicom
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Pytanie: co zrobić z drzewem, aby można było po prostu
zwiększyć wagi wierzchołków?
Odpowiedź: zaczynając od wierzchołka, który odpowiada
kodowanemu symbolowi, zamieniać aktualny wierzchołek
z wierzchołkiem o najwyższym numerze (w sensie numeracji
z własności sąsiedztwa) spośród wierzchołków o tej samej wadze
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Dawid Duda
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Dawid Duda
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
procedure update;
q := wierzchołek odpowiadający otrzymanej literze;
if (q = wierzchołek 0) and (k < m - 1) then
dodaj q dwoje dzieci (numeracja: lewe, prawe, rodzic)
q := prawe dziecko
if q jest sąsiadem wierzchołka 0 then
zamień q z liściem o tej samej wadze i najw.
zwiększ wagę q o 1
q := rodzic q
while q nie jest korzeniem
zamień q z wierz. o tej samej wadze i najw.
zwiększ wagę q o 1
q := rodzic q
Dawid Duda
Kodowanie Huffmana
numerze
num.
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Obserwacje:
I
zamiany wierzchołków, wykonywane przez algorytm, nie
powodują, że drzewo przestaje być drzewem Huffmana dla
Mt (co wynika z własności sąsiedztwa)
I
po zwiększeniu odpowiednich wag (w drzewie otrzymanym
przez wykonanie zamian) dostaniemy drzewo Huffmana dla
Mt+1 (co ponownie wynika z własności sąsiedztwa)
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Ile nas to kosztuje? O ile więcej bitów wygeneruje algorytm FGK
w porównaniu z klasycznymi kodami Huffmana?
Odpowiedź: Jeżeli S jest ilością bitów wygenerowanych przez
oryginalny algorytm Huffmana, S 0 ilością bitów wygenerowanych
przez algorytm FGK, a m rozmiarem alfabetu, to zachodzi:
S 0 ≤ 2S + m
Dawid Duda
Kodowanie Huffmana
(4)
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Pytanie: Czy można lepiej?
Odpowiedź: Tak, używając algorytmu Vittera można mieć:
S0 < S + m
Dawid Duda
Kodowanie Huffmana
(5)
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Podstawowa idea:
I
ograniczyć ilość zamian, w których wierzchołek q porusza się
w górę drzewa, do co najwyżej jednego przy każdym
wywołaniu update
I
konstruować drzewo w ten sposób, aby minimalizowało
nie
P
tylko sumę ważoną długości ścieżek w drzewie
j wj Lj , ale
P
również sumę nieważoną długości ścieżek j Lj oraz długość
najdłuższej ścieżki maxj {Lj } - intuicyjnie powinno to
ograniczyć długość słowa kodowego dla następnej litery
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Klasyfikacja zamian:
I
↑ wierzchołek q przesuwa się do góry o jeden poziom
I
→ wierzchołek q zamieniamy z wierzchołkiem z tego samego
poziomu
I
↓ wierzchołek q zamieniamy z wierzchołkiem na niższym
poziomie
I
↑↑ wierzchołek q zamieniamy z wierzchołkiem położonym
o dwa poziomy wyżej
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Niejawna numeracja
Pomysł: numerować wierzchołki drzewa w sposób odpowiadający
reprezentacji wizualnej:
I
wierzchołki numerujemy w sposób zgodny z poziomami
drzewa: wierzchołki na tym samym poziomie mają numery
niższe niż te na następnym, wyższym poziomie
I
wierzchołki na tym samym poziomie numerujemy rosnąco
od lewej do prawej
Gdy używamy niejawnej numeracji, nie będzie zamian typu ↓.
Oprócz tego, jeżeli wierzchołek przesuwa się do góry w zamianie
typu ↑, to ten, który przesuwa się w dół, jest liściem.
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Niezmiennik algorytmu
Kluczem do polepszenia algorytmu jest uniknięcie zamian typu ↑
poza pierwszą iteracją pętli while. Aby to zrobić będziemy
utrzymywać następujący niezmiennik:
I
dla każdej wagi w , wszystkie liście o wadze w poprzedzają
w niejawnej numeracji wszystkie wierzchołki wewnętrzne
o wadze w
Można pokazać, że drzewoP
Huffmana, które spełnia ten
niezmiennik, minimalizuje j Lj oraz maxj {Lj }.
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Kilka definicji:
I
blok - klasa równoważności relacji na wierzchołkach drzewa:
wierzchołki v i x są w relacji, jeśli mają tą samą wagę oraz
obydwa są wierzchołkami lub obydwa są liśćmi (w algorytmie
FGK nie zwracaliśmy uwagi na liście/wierzch. wewn.)
I
lider bloku - wierzchołek o najwyższym numerze należący
do bloku
Bloki są połączone w listę w kolejności rosnącej wagi, blok liści
zawsze poprzedza blok wierzchołków wewnętrznych o tej samej
wadze.
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
procedure update;
leafToIncrement := 0;
q := wierzchołek odpowiadający otrzymanej literze;
if (q = wierzchołek 0) and (k < m - 1) then
dodaj q dwoje dzieci, prawe odpowiadające literze
q := wierzchołek, który właśnie został tatusiem
leafToIncrement := prawe dziecko q
else
zamień q z liderem jego bloku
if q jest sąsiadem wierzchołka 0 then
leafToIncrement := q;
q := rodzic q
while q nie jest korzeniem
slideAndIncrement(q);
if leafToIncrement 6= 0 then
slideAndIncrement(leafToIncrement);
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
procedure slideAndIncrement(p);
wt := waga wierzchołka p;
b := następny blok na liście po bloku wierzchołka p;
if p jest liściem and
b jest blokiem wierzch. wewn. o wadze wt
or p jest wierzch. wewn. and
b jest blokiem liści o wadze wt+1
then
zjedź wierzch. p w drzewie w kierunku wierzch. z b
p.weight := wt + 1;
if p jest liściem then
p := nowy rodzic p
else
p := dawny rodzic p
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Dawid Duda
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wstęp
Algorytm FGK (Faller, Gallager i Knuth)
Algorytm Vittera
Podsumowanie
I
długość danych zakodowanych algorytmem Vittera może się
różnić od długości danych zakodowanych statycznym
algorytmem Huffmana co najwyżej o długość alfabetu
I
algorytm jest dosyć skomplikowany, ale Vitter opublikował
jego wzorcową implementację
I
algorytm wymaga specyficznych struktur danych, opisanych
dokładnie w pracach Vittera
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Wyniki testów
Typ
pliku
Postscript
BMP
Poczta
Źródła w C
WAV
Rozmiar
początkowy
506197
481078
1657081
1331200
1000000
Stat. kody
Huffmana
334785
448533
1112169
778081
763453
Dawid Duda
FGK
Vitter
334907
448821
1112278
778207
763933
334891
448739
1112264
778182
763717
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Współczynnik kompresji
Typ
pliku
Postscript
BMP
Poczta
Źródła w C
WAV
Średnio
Stat. kody
Huffmana
0,6614
0,9323
0,6712
0,5845
0,7635
0,7226
Dawid Duda
FGK
Vitter
0,6616
0,9329
0,6712
0,5846
0,7639
0,7229
0,6616
0,9328
0,6712
0,5846
0,7637
0,7228
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Dawid Duda
Kodowanie Huffmana
Wstęp
Statyczne kody Huffmana
Dynamiczne kody Huffmana
Praktyka
Gdzie szukać dalszych informacji:
I
Khalid Sayood, „Kompresja danych - wprowadzenie”,
wydawnictwo Read Me, kwiecień 2002.
I
Jeffrey S. Vitter, „Design and Analysis of Dynamic Huffman
Codes”, JACM Vol. 34, październik 1987.
I
Jeffrey S. Vitter, „Dynamic Huffman Coding”, ACM
Transactions on Mathematical Software Vol. 15, czerwiec
1989.
Dawid Duda
Kodowanie Huffmana
Długość kodów Huffmana
Algorytm Huffmana generuje optymalny kod, ale jaka jest jego
średnia długość l? Twierdzenie:
H(S) ≤ l ≤ H(S) + 1
Dawid Duda
Kodowanie Huffmana
(6)
Długość kodów Huffmana
Lemat (Kraft, McMillan):
I
(McMillan) Niech C będzie jednoznacznie dekodowalnym
kodem. Niech A = {a1 , a2 , . . . , am } będzie alfabetem
wejściowym oraz niech li = |C (ai )|. Wówczas:
m
X
2−li ≤ 1
(7)
i=1
I
(Kraft) Dla dowolnego ciągu dodatnich liczb całkowitych
{li }m
i=1 spełniającego (7) istnieje jednoznacznie dekodowalny
kod o długościach {li }m
i=1
Dawid Duda
Kodowanie Huffmana
Długość kodów Huffmana
Wpierw pokażemy, że H(S) ≤ l. Prawdopodobieństwo wystąpienia
litery ai oznaczmy przez P(ai ). Wtedy mamy:
l=
m
X
P(ai )li
(8)
i=1
H(S) − l
= −
m
X
P(ai ) log P(ai ) −
i=1
m
X
m
X
P(ai )li
i=1
1
=
P(ai ) log
− li
P(ai )
i=1
m
h i
X
1
− log 2li
=
P(ai ) log
P(ai )
i=1
−li m
X
2
=
P(ai ) log
P(ai )
i=1
Dawid Duda
Kodowanie Huffmana
Długość kodów Huffmana
Nierówność Jensena: dla każdej wklęsłej funkcji (∩) f (x)
zachodzi:
E [f (X )] ≤ f (E [X ])
Ponieważ funkcja log jest wklęsła, wobec tego:
" m
#
−li m
X
X
2
P(ai ) log
H(S) − l =
≤ log
2−li
P(ai )
i=1
(9)
(10)
i=1
Ponieważ P
kod jest optymalny, to z lematu Krafta-McMillana (7)
−li ≤ 1, a więc
mamy że m
i=1 2
H(S) − l ≤ 0
co kończy pierwszą część dowodu.
Dawid Duda
Kodowanie Huffmana
Długość kodów Huffmana
Górna granica - wiemy, że kod jest optymalny, więc wystarczy
pokazać istnienie kodu takiego, że l ≤ H(S) + 1. Zdefiniujmy:
1
li = log
(11)
P(ai )
Ponieważ ∀x. ∃ ∈ [0, 1). dxe = x + to zgodnie z (11) mamy:
log
1
1
≤ li ≤ log
+1
P(ai )
P(ai )
Dawid Duda
Kodowanie Huffmana
(12)
Długość kodów Huffmana
Zauważmy, że z lewej nierówności z (12) mamy:
2−li ≤ P(ai )
wobec czego, sumując obustronnie, otrzymujemy:
m
X
2−li ≤
i=1
m
X
P(ai ) = 1
i=1
skąd z kolei, przez drugą część lematu Krafta-McMillana, istnieje
jednoznacznie dekodowalny kod o długościach {li }.
Długość tego kodu możemy oszacować następująco:
l=
m
X
P(ai )li <
i=1
m
X
P(ai ) log
i=1
1
+ 1 = H(S) + 1
P(ai )
co kończy dowód. Dawid Duda
Kodowanie Huffmana
(13)

Podobne dokumenty