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)