Aritmetické kódován´ı
Transkript
Aritmetické kódován´ı
České vysoké učenı́ technické Fakulta elektrotechnická Teorie informace a kódovánı́ Aritmetické kódovánı́ Karel Horák Petr Ryšavý 26. května 2013 OBSAH Aritmetické kódovánı́ Obsah 1 Úvod do aritmetického kódovánı́ 4 2 Aritmetické kódovánı́ s konečnou přesnostı́ 4 3 Implementace s konečnou přesnostı́ 5 4 Dekódovánı́ 7 5 Souhrnný přı́klad 7 6 Možné zobecněnı́ 9 A Vzorová implementace 11 2 / 16 OBSAH Aritmetické kódovánı́ Značenı́ Označme M délku bloku, který pomocı́ aritmetického kódovánı́ kódujeme. Předpokládejme, že kódujeme abecedu Λ pomocı́ binárnı́ho kódu, tedy že hledáme kódovánı́ Λ 7→ {0, 1}. Pak pro libovolné slovo u ∈ Λ∗ značı́me pu pravděpodobnost, že zdroj vyšle slovo u. Předpokládejme, že ≺ značı́ lexikografické uspořádánı́ na Λ∗ . Jako Fu označme kumulativnı́ pravděpodobnost všech slov, které jsou v lexikografickém uspořádánı́ před u u, tj. Fu = X pu . (1) v≺u Kód slova u ∈ ΛM značı́me cu . Délku tohoto kódového slova pak značı́me lu = |cu |. Pro znak i ∈ Λ označme jeho pravděpodobnost pi a podslovo uk uk+1 · · · ul slova u označme ulk . Znak na pozici j slova u označme uj . 3 / 16 1 Úvod do aritmetického kódovánı́ Aritmetické kódovánı́ 1 Úvod do aritmetického kódovánı́ Aritmetické kódovánı́ je blokové kódovánı́, které vyžaduje na vstupu pravděpodobnosti jednotlivých kódovaných znaků z abecedy Λ. Dále vyžaduje, aby abeceda Λ měla přiřazené lexikografické uspořádánı́ ≺. Aritmetické kódovánı́ je založené na kódovánı́ bloků délky M pomocı́ funkce Fu , která každému slovu u ∈ ΛM přiřazuje kódové slovo, které je binárnı́m vyjádřenı́m Fu ořı́znutým na délku lu . Délka lu = d− log2 pu e + 1 (2) se volı́ tak, aby výsledný kód byl bezprefixový. Pro výpočet pravděpodobnosti všech lexikograficky předcházejı́cı́ch slov se použı́vá rekurzivnı́ho předpisu Fuj = Fuj−1 + puj−1 · Fuj , 1 1 (3) 1 kde j ∈ {2, 3, . . . , |u|}. Výpočet hodnoty F pro slova délky 1 lze provést pomocı́ zadaných pravděpodobnostı́ pi pro jednotlivé znaky i ∈ Λ. Podrobný popis toho jak aritmetické kódovánı́ funguje pro neomezenou přesnost lze nalézt v [Moser, 2012, kapitola 4.3]. Na internetu lze také najı́t výkladová videa k tématu aritmetického kódovánı́. Povedená série videı́ začı́ná videem [mathematicalmonk, 2011]. 2 Aritmetické kódovánı́ s konečnou přesnostı́ Při aritmetickém kódovánı́ každé slovo z u ∈ ΛM ztotožňujeme s intervalem reálných čı́sel hcu , cu +2−lu ). Tyto intervaly jsou disjunktnı́, a dı́ky tomu je aritmetické kódovánı́ bezprefixové. Pokud pracujeme s omezenou přesnostı́, pak okraje těchto intervalů nemusı́me být schopnı́ vyjádřit přesně. To znamená, že jejich hornı́, resp. dolnı́ mez může být zaokrouhlená. Pokud pracujeme s n bitovými proměnnými, pak nejmenšı́ interval, který lze vyjádřit má délku 2−n . To znamená, že tyto intervaly nezaokrouhlı́me vı́ce než o 2−n na každé straně. Označme tuto nepřesnost jako ε. Protože požadujeme stále bezprefixovost zı́skaného kódu, musı́ být zaokrouhlenı́ intervalů směrem dovnitř. Jinak bychom neměli garantované, že se intervaly nebudou protı́nat. Dolnı́ mez počtu bitů na znak je vždy daná entropiı́. Odhadněme nynı́ tu hornı́. Při aritmetickém kódovánı́ definujeme délku zakódovaného bloku jako lu = d− log2 pu e + 1. (4) Všimneme si, že zaokrouhlenı́ na logaritmu na celou část nahoru nenı́ nikdy 1 nebo vı́ce. Platı́ tedy lu = d− log2 pu e + 1 < − log2 pu + 2. (5) Očekávaná délka kódu na znak je pak L(CA ) 1 X 1 X H(X1M ) + 2 = lu pu < (−pu log2 pu + 2pu ) = . M M M M M M u∈Λ (6) u∈Λ Protože kódujeme bezpamnět’ový zdroj, vyplývá odtud, že entropie vztažená na jeden znak je rovna entropii prvnı́ho znaku. Platı́ tedy L(CA ) 2 < H(X1 ) + . M M (7) Toto platı́, pokud máme k dispozici neomezenou přesnost při výpočtu. Interval hF, F + pi ), kterým jsme kódovali prvnı́ znak při neomezené přesnosti je ale při počı́tánı́ s omezenou přesnostı́ 4 / 16 3 Implementace s konečnou přesnostı́ Aritmetické kódovánı́ kratšı́, a to nejvýše o 2ε. Mı́ra informace, kterou nám dá znalost intervalu o šı́řce nenı́ − log2 pi , ale − log2 (pi − 2ε), protože se tento interval zkrátil. Předpokládejme přitom, že ∀i : pi > 2ε. Pokud v rovnicı́ch (4), (6) a (7) nahradı́me log2 pi za log2 (pi − 2ε), pak zı́skáme novou slabšı́ hornı́ mez pro délku kódu na znak jako X L(CA ) 2 pi log2 (pi − 2ε). < − M M i∈Λ (8) Všimněme si, že suma − i∈Λ pi log2 (pi − 2ε) je pro kladné ε vždy většı́ než entropie jednoho znaku. To znamená, že kódovánı́ s nepřesnostı́ způsobenou počı́tánı́m může být horšı́ než s nekonečnou přesnostı́. Přitom pro rostoucı́ délku kódu se počet bitů na znak aritmetického kódovánı́ s neomezenou přesnostı́ blı́žı́ k entropii. Upravme tedy dále výraz (8). Logaritmus z tohoto členu lze přepsat jako P log2 (pi − 2ε) = log2 pi − 2ε pi pi = log2 pi − log2 pi . p2 − 2ε (9) Taylorův rozvoj funkce log2 x v bodě 1 je (x − 1) · log2 e. Protože je logaritmus konkávnı́ funkce, platı́ pro každé x, že log2 x ≤ (x − 1) · log2 e. Dosazenı́m do rovnice (9) zı́skáváme pi ln e 2ε 1 2ε log2 (pi − 2ε) < log2 pi − − 1 · log2 e = log2 pi − · = log2 pi − · . p2 − 2ε ln 2 pi − 2ε ln 2 pi − 2ε (10) Pokud nás zajı́má asymptotická střednı́ délka kódu na znak, pak musı́me počı́tat s limitou pro M jdoucı́ do nekonečna v rovnici (8). Dosadı́me sem z (10) a zı́skáváme L(CA ) X 1 2ε lim < pi log2 pi − · M →∞ M ln 2 p i − 2ε i∈Λ = H(X) + 1 X 2ε pi . ln 2 i∈Λ pi − 2ε (11) Označme pmin pravděpodobnost nejméně četného znaku. Pro všechna i pak platı́ pi > pmin , a tedy můžeme rovnici (11) přepsat jako 1 X 2ε 1 2ε L(CA ) < H(X) + pi = H(X) + . M →∞ M ln 2 i∈Λ pmin − 2ε ln 2 pmin − 2ε lim (12) Vidı́me tedy, že kódovánı́ je horšı́ než aritmetické kódovánı́ s neomezenou přesnostı́. To se dalo očekávat, protože jsme kódové slovo ztotožnili s kratšı́m intervalem (dı́ky zaokrouhlovánı́ o nejvýše ε na každém konci intervalu), než tomu bylo původně. Naopak vidı́me, že pokud bude v rovnici (12) ε → 0, pak zı́skáme stejný závěr jako v přı́padě neomezené přesnosti, a to že aritmetické kódovánı́ se blı́žı́ v limitě k entropii. V textu [Sayir, 1999] je tato vlastnost aritmetického kódovánı́ dokázána stejným způsobem jako zde pro libovolnou kódovou abecedu, nejenom pro binárnı́. Závěry jsou stejné, a to že kódovánı́ se blı́žı́ k optimálnı́mu v přı́padě neomezené přesnosti. 3 Implementace s konečnou přesnostı́ V kapitole 2 jsme ukázali, že umı́me zakódovat prvnı́ znak, a to dı́ky předpokladu, že ∀i : pi > 2ε. Kódový znak se pak zobrazil na interval mezi Fi a Fi+1 . V přı́padě konečné přesnosti byl pak tento interval zkrácen o nejvýše 2ε. Jenomže jak roste délka slova, docházı́ k tomu, že i délka intervalu, na který se zobrazuje dané slovo se zkracuje. Takto bychom brzy překročili přesnost ε a dvě zdrojová slova by se zobrazila na jedno kódové slovo. Musı́me tedy výpočet kódových slov provádět jinak, abychom nedostali interval, který již nenı́ zobrazitelný. Na počátku je kódové slovo kdekoliv z intervalu I0 = h0, 1). Hodnoty Fi pro slovo i rozdělujı́ tento interval na části. Po načtenı́ prvnı́ho znaku se omezı́me na odpovı́dajı́cı́ 5 / 16 3 Implementace s konečnou přesnostı́ Aritmetické kódovánı́ podinterval I1 intervalu I0 . Při načtenı́ dalšı́ho znaku je interval I1 opět rozdělen (ve stejném poměru jako I0 ) na části odpovı́dajı́cı́ jednotlivým znaků. Vybereme tedy jeho podinterval I2 a takto pokračujeme dále. Zı́skáváme tedy zanořujı́cı́ se posloupnost intervalů I0 ⊇ I1 ⊇ I2 ⊇ · · · . Vyplývá to ze vztahu 3 pro rekurzivnı́ výpočet pravděpodobnosti slov, které jsou v lexikografickém pořadı́. Platı́ totiž Fuj = Fuj−1 + puj−1 Fuj . 1 1 1 Pravděpodobnost puj−1 je délkou intervalu Ij−1 . Vidı́me tedy, že dolnı́ mez při přechodu z Ij−1 1 do In se posunula o stejnou relativnı́ část jako při přechodu z I0 do Ij . To samé platı́ pro hornı́ mez. Přı́klad 1 (Z [Bodden et al., 2007]) Předpokládejme, že kódujeme zdrojovou abecedu o čtyřech znacı́ch Λ = {a, b, c, d} s pravděpodobnostmi pa = 0,5, pb = 0,25 a pc = pd = 0,125. Pak interval I0 = h0, 1) je rozdělen tak, že na znak a připadne jeho podinterval h0, 0,5), na znak b podinterval h0,5, 0,75), na znak c pak h0,75, 0,875) a na d konečně h0,875, 1). Pokud je prvnı́ načtený znak a, pak platı́ I1 = h0, 0,5). Interval I1 je opět rozdělen na části přı́slušejı́cı́ jednotlivým znakům. A to opět v poměru 4 : 2 : 1 : 1. Pokud je druhým načteným znakem b, pak je I2 = h0,25, 0,375). Při výpočtu pak můžeme mı́sto uchovávánı́ dolnı́ meze intervalu udržovat celý interval, tedy i jeho hornı́ mez. Pokud vı́me, že dolnı́ mez má binárnı́ rozvoj začı́najı́cı́ na 0 a že totéž platı́ i pro hornı́ mez, můžeme vypsat nulu, protože je již jistá na začátku kódového slova. Při výpisu se ale můžeme zbavit informace o tom, že nula je počátečnı́ znak. Interval totiž můžeme rozšı́řit do původnı́ho (nebo části původnı́ho rozsahu) Přı́klad 2 (Pokračovánı́ přı́kladu 1) Po zakódovánı́ prvnı́ho vstupnı́ho znaku vidı́me, že I1 = h0, 0,5). To znamená, že prvnı́m znakem je určitě znak 0. Jenomže interval, kterému odpovı́dá počátečnı́ znak nula je právě I1 . Můžeme tedy tento interval roztáhnout na I10 = h0, 1) a zároveň vypsat čı́slo 0. Tı́m jsme neztratili žádnou informaci. Druhým intervalem je po této úpravě a načtenı́ znaku b interval I2 = h0,5, 0,75). Nynı́ vidı́me, že prvnı́m výstupnı́m znakem je určitě znak 1. To znamená, že můžeme znak jedna vypsat a přeškálovat interval h0,5, 1) na interval h0, 1). Zı́skáme takto interval I20 = h0, 0,5). Nynı́ vidı́me, že můžeme v této úvaze pokračovat a vypsat 0. Zı́skáme takto interval I200 = h0, 1) a máme na zakódovánı́ znaků ab vypsáno 010. Problém může nastat, pokud náš interval má dolnı́ mez menšı́ než 12 a hornı́ mez většı́ než 1 2 . Pokud se toto stane po načtenı́ znaku, pak nemůžeme vypsat dalšı́ cifru. To se ale může opět opakovat a takto se nám zmenšuje velikost intervalu, až narazı́me na mez danou přesnostı́ výpočtu. Proto je třeba roztáhnout současný interval Ij ⊆ h 14 , 34 ) na celý interval od nuly do jedné. Při vypisovánı́ vlastně totiž stále nevı́me, jestli bude na výpisu sekvence 011 · · · 1 nebo sekvence znaků 100 · · · 0. To znamená, že na každé takovéto roztaženı́ intervalu okolo středu si potřebujeme někde poznačit, že toto roztaženı́ proběhlo. Počet takovýchto roztaženı́ značı́me do počitadla zvaného straddle counter. [Sayir, 1999] V okamžiku, když poznáme o který přı́pad jde, tak vypı́šeme 0 a s jedniček nebo 1 a s nul podle odpovı́dajı́cı́ho vstupu. Jako s jsme označili hodnotu straddle counter. D 7 9 , D 16 16 6 10 16 , 16 Přı́klad 3 Předpokládejme, že po načtenı́ znaku zı́skáme interval . Vidı́me, že tento interval můžeme roztáhnout okolo středu. Zı́skáme nový interval a straddle counter nastavı́me na 1. Vidı́me že tuto operaci můžeme opakovat ještě dvakrát. Zı́skáme interval h0, 1) D a straddle counter rovný 3. Pokud nynı́ načteme znak a zı́skáme interval 14 , 1 , pak vidı́me, 16 že před vytvořenı́m straddle counteru jsme se přesunuli nad střed intervalu 12 . To znamená, že 6 / 16 4 Dekódovánı́ Aritmetické kódovánı́ musı́me vypsat 1000 za hodnotu straddle counter a rozšı́řit interval na můžeme vypsat 11 za dalšı́ roztaženı́. D 12 16 , 1 . Kromě toho pak Během výpočtu nenı́ výhodné počı́tat v plovoucı́ řádové čárce, ale je lepšı́ počı́tat s bezznaménkovou celočı́selnou proměnnou. Všechny meze pak budou mı́sto desetinného zápisu celá čı́sla z intervalu h0, 2n ), kde n je počet bitů. Přı́klad 4 (Pokračovánı́ přı́kladu 2) Uvažujme 16-ti bitové proměnné. Interval I0 = h0, 1) pak uchováváme jako interval celých čı́sel h0, 16). Interval I1 = h0, 0,5) je celočı́selně h0, 8). Jedné polovině odpovı́dá čı́slo 8. Vidı́me, že výstup začı́ná nulou, vypisujeme 0 a interval roztáhneme na h0, 16). Po načtenı́ znaku b zı́skáváme interval h8, 12). Vidı́me, že můžeme vypsat znak 1 a roztáhnout tento interval na h0, 8) Nynı́ můžeme vypsat 0 a opět interval roztáhnout na h0, 16). Zı́skali jsme stejný výstup jako v předchozı́m přı́padě. V přı́kladě 3 jsme viděli pouze přı́pady, kdy jsme kódovali přesně. Nepřesnost dané omezeným počtem bitů se neprojevily, protože hodnoty Fi pro znaky i ∈ Λ jsme byli schopnı́ zobrazit přesně. To se ale nemusı́ stát vždy. Musı́me tedy občas zaokrouhlovat. Interval musı́me zkrátit na obou koncı́ch o nejvýše 2−n tak, abychom zı́skali čı́slo, které jsme při dané přesnosti schopnı́ zobrazit. Přı́klad 5 (Z [Sayir, 1999]) Předpokládejme, že kódujeme abecedu o třech znacı́ch Λ = {a, b, c} s pravděpodobnostmi pa = 0,2, pb = 0,5 a pc = 0,3. Dále předpokládejme, že máme k dispozici pouze 4-bitové registry. Počátečnı́ interval je h0, 16). Pokud načteme jako prvnı́ znak a, pak bychom v přı́padě přesného kódovánı́ dostali interval h0, 3,2). Čı́slo 3,2 ale nemůžeme zobrazit, protože nenı́ celé. Musı́me tedy interval zaokrouhlit dolů a zı́skáme interval h0, 3) s kterým dále počı́táme. Můžeme vypsat 0 a interval roztáhnout na h0, 6). Znovu vypı́šeme 0 a zı́skáme h0, 12) nynı́ už nemůžeme škálovat dále, takže musı́me načı́t dalšı́ znak. Nynı́ se již umı́me vypořádat se všemi možnými problémy, které mohou nastat. Je tedy na čase předvést pseudokód algoritmu 1. 4 Dekódovánı́ Dekódovánı́ probı́há podobným algoritmem jako kódovánı́. Vezmeme blok a zkoumáme, do kterého intervalu patřı́. Přı́stup je stejný jako v okamžiku, když máme k dispozici neomezenou přesnost. Poté co zjistı́me prvnı́ pı́smeno, odmažeme odpovı́dajı́cı́ část vstupu, roztáhneme přı́pustný interval a můžeme opět zjišt’ovat dalšı́ znak. V paměti pak držı́me mı́sto celého vstupu jen jeho odhad omezený na dostupnou přesnost. Vı́ce ukáže přı́klad. Přı́klad 6 (Pokračovánı́ přı́kladu 4) Chceme dekódovat kódové slovo 010, vı́me li-že pa = 0,5, pb = 0,25 a pc = pd = 0,125. Při kódovánı́ byl počátečnı́ interval I0 = h0, 16). Vstupu a odpovı́dal interval h0, 8), vstupu b interval h8, 12), vstupu c interval h12, 14) a vstupu d interval h14, 16). Protože výstup začı́nal nulou, vidı́me, že prvnı́m načteným znakem bylo pı́smeno a. Po roztaženı́ intervalu a odmazánı́ prvnı́ 0 zı́skáváme vstup 10. Počátečnı́ znak 1 odpovı́dá znakům b, c, d. Ze vstupu tedy musı́me načı́st dalšı́ bit. Celý vstup 10 může odpovı́dat jen znaku b. Druhým zakódovaným znakem je tedy b. Původnı́ slovo bylo ab. 5 Souhrnný přı́klad Nynı́ si ukážeme celkový přı́klad kódovánı́ a následného dekódovánı́. Zadané hodnoty vstupnı́ch pravděpodobnostı́ pocházejı́ z [Sayir, 1999]. V této publikaci je ale během načı́tánı́ třetı́ho znaku chyba. 7 / 16 5 Souhrnný přı́klad Aritmetické kódovánı́ Require: n bitové proměnné function ArithmeticCoding I ← h0, 2n ) . I je interval, ve kterém je kódové slovo s←0 while true do if I ⊆ 0, 2n−1 then D I ←2·I . Roztáhni interval odpovı́dajı́cı́ 0, 21 na interval h0, 1). Print(s, 0) s←0 else if I ⊆ 2n−1 , 2n then D I ← 2 · I − 2n . Roztáhni interval odpovı́dajı́cı́ 12 , 1 na interval h0, 1). Print(s, 1) s←0 else if I ⊆ 2n−2 , 3 · 2n−2 then D I ← 2 · I − 2n−1 . Roztáhni interval odpovı́dajı́cı́ 41 , 34 na interval h0, 1). s←s+1 else if ¬HasInput() then . Musı́me ještě identifikovat poslednı́ znak určenı́m intervalu if h2n−2 , 2n−1 ) ⊆ I then Print(s + 1, 0) else Print(s + 1, 1) end if return else x ← Read() Il ← LowerBound(I), Ih ← UpperBound(I) I ← hdIl + (Ih − Il ) · Fx e , bIl + (Ih − Il ) · (Fx + px )c) . Najdi podinterval, který odpovı́dá právě načtenému znaku x end if end while end function function Print(s, x) Print(x) PrintNTimes(¬x, s) end function . Vytiskni 100 · · · 0 nebo 011 · · · 1 podle hodnoty s Algoritmus 1: Aritmetické kódovánı́ 8 / 16 6 Možné zobecněnı́ Aritmetické kódovánı́ Přı́klad 7 (Pokračovánı́ přı́kladu 5) Mějme 4 bitové proměnné. Zakódujeme slovo abbacbc při zadaných pravděpodobnostech pa = 0,2, pb = 0,5 a pc = 0,3. Postup ukazuje tabulka 1. Poslednı́ výstup 01 je z toho důvodu, že máme nenulový straddle counter. Musı́me nějak dát dekodéru vědět, že interval je někde ve středu rozsahu. Proto musı́me vypsat nějaké čı́slo z tohoto intervalu. Vidı́me, že kódovým slovem je 0001000111001. Vstup a b b a c b c Interval I [0, 16) [0, 3) [0, 6) [0, 12) [3, 8) [6, 16) [8, 13) [0, 10) [0, 2) [0, 4) [0, 8) [0, 16) [12, 16) [8, 16) [0, 16) [4, 11) [0, 14) [10, 14) [4, 12) [0, 16) straddle counter s 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 Operace get input ×2 ×2 get input ×2 get input ×2 − 16 get input ×2 ×2 ×2 get input ×2 − 16 ×2 − 16 get input ×2 − 8 get input ×2 − 16 ×2 − 8 ×2 Výstup 0 0 0 1 0 0 0 1 1 10 01 Tabulka 1: Postup při kódovánı́ v přı́kladu 7 Přı́klad 8 (Pokračovánı́ přı́kladu 7) Nynı́ se pokusı́me dekódovat slovo 0001000111001. Postup během výpočtu ukazuje tabulka 2. Vidı́me že výsledné slovo je podle očekávánı́ abbacbc. 6 Možné zobecněnı́ Aritmetické kódovánı́ lze zobecnit i na složitějšı́ model, než je bezpamět’ový zdroj. Lze ho použı́t na libovolný model, u kterého jsme schopnı́ spočı́st pravděpodobnost pro libovolné slovo u ∈ Λ∗ . Rozdı́l je pouze v tom, že intervaly Ij nerozdělujeme ve stejném poměru jako při prvnı́m kroku. Rozdělenı́ intervalu závisı́ na znacı́ch dřı́ve načtených — pokud budeme uvažovat Markovský model zdroje tak na předchozı́m načteném znaku. Uvažujme Markovský zdroj s maticı́ přechodu P 2/10 5/10 3/10 P = 5/10 2/10 3/10 3/12 3/12 6/12 Zakódujme bloky o délce 3. Porovnáme nynı́ střednı́ délku kódového slova v přı́padě, že na straně kodéru známe dokonalý model zdroje, a v přı́padě, že známe pouze pravděpodobnosti výskytu jednotlivých znaků. V přı́padě, že použijeme Markovský model, je střednı́ délka kódového slova 9 / 16 6 Možné zobecněnı́ Aritmetické kódovánı́ Interval I Odhad vstupu [0, 16) [0, 3) [0, 6) [0, 12) [3, 8) [6, 16) [8, 13) [0, 10) [0, 2) [0, 4) [0, 8) [0, 16) [12, 16) [8, 16) [0, 16) [4, 11) [0, 14) 1 1 2 4 4 8 8 1 1 3 7 14 14 12 9 9 10 Vstup 0001000111001 000111001 000111001 00111001 0111001 0111001 111001 111001 11001 11001 1001 001 01 01 1 Operace load first 4 bits output symbol ×2 (and read next bit) ×2 (and read next bit) output symbol ×2 (and read next bit) output symbol ×2 − 16 (and read next bit) output symbol ×2 (and read next bit) ×2 (and read next bit) ×2 (and read next bit) output symbol ×2 − 16 (and read next bit) ×2 − 16 (and read next bit) output symbol ×2 − 8 (and read next bit) output symbol Výstup a b b a c b c Tabulka 2: Postup při kódovánı́ v přı́kladu 8 rovna 12,066888 — pokud závislosti mezi jednotlivými symboly zanedbáme, budeme potřebovat v průměru 13,498051 bitů pro zakódovánı́ třı́ symbolů. Vidı́me tedy, že použitı́ komplexnějšı́ho modelu nám umožnı́ dosáhnout lepšı́ komprese. Přı́pad, kdy se mı́sto bezpamět’ového modelu zdroje použije komplexnějšı́ model je rozebı́rán v [Bodden et al., 2007, kapitola 9]. 10 / 16 A Vzorová implementace Aritmetické kódovánı́ A Vzorová implementace Zde uvádı́me přı́klad implementace aritmetického kódovánı́ v jazyce Java. package coder ; import model . Model ; import java . util . ArrayList ; public class ArithmeticCoder { private Model model ; private int block ; private private private private private private final final final final final final int int int int int int ONE HALF ZERO QUARTER QUARTER3 PRECISION = = = = = = 16; 8; 0; 4; 12; 4; private final Integer [] empty = {}; public ArithmeticCoder ( Model model , int block ) { this . model = model ; this . block = block ; } public int [] encode ( int message []) { ArrayList < Integer > output = new ArrayList < Integer >() ; int lower = ZERO ; int upper = ONE ; int straddle = 0; model . reset () ; System . out . print ( " & " ) ; for ( int i = 0; i < block ; ++ i ) { long range = upper - lower ; int symbol = message [ i ]; int probability [] = model . getProbability () ; int probTotal = arraySum ( probability , probability . length ) ; model . observe ( symbol ) ; System . out . printf ( " [% d , % d ) & % d & get input & \\\\\ n % d & " , lower , upper , straddle , symbol ) ; upper = lower + ( int ) (( range * arraySum ( probability , symbol ) ) / probTotal ) ; lower = lower + ( int ) Math . ceil (( double ) ( range * arraySum ( probability , symbol - 1) ) / probTotal ) ; while ( upper <= HALF || lower >= HALF ) { if ( upper <= HALF ) { System . out . printf ( " [% d , % d ) & % d & $ \\ times 2 $ & 0 " , lower , upper , straddle ) ; output . add (0) ; for (; straddle > 0; -- straddle ) { output . add (1) ; System . out . print ( " 1 " ) ; 11 / 16 A Vzorová implementace Aritmetické kódovánı́ } upper = 2 * upper ; lower = 2 * lower ; } else { System . out . printf ( " [% d , % d ) & % d & $ \\ times 2 - % d$ & 1 " , lower , upper , straddle , ONE ) ; output . add (1) ; for (; straddle > 0; -- straddle ) { output . add (0) ; System . out . print ( " 0 " ) ; } upper = 2 * upper - ONE ; lower = 2 * lower - ONE ; } System . out . print ( " \\\\\ n & " ) ; } while ( lower >= QUARTER && upper <= QUARTER3 ) { System . out . printf ( " [% d , % d ) & % d & $ \\ times 2 $ - % d & \\\\\ n & " , lower , upper , straddle , HALF ) ; lower = 2 * lower - HALF ; upper = 2 * upper - HALF ; straddle ++; } } if ( lower <= QUARTER ) { System . out . printf ( " [% d , % d ) & % d & $ \\ times 2 $ & 0 " , lower , upper , straddle ) ; output . add (0) ; for (; straddle > 0; -- straddle ) { output . add (1) ; System . out . print ( " 1 " ) ; } } else { System . out . printf ( " [% d , % d ) & % d & $ \\ times 2 - % d$ & 1 " , lower , upper , straddle , ONE ) ; output . add (1) ; for (; straddle > 0; -- straddle ) { output . add (0) ; System . out . print ( " 0 " ) ; } } System . out . print ( " \\\\\ n " ) ; return toJavaArray ( output ) ; } public int [] decode ( int message []) { ArrayList < Integer > output = new ArrayList < Integer >() ; int int int int code = 0; i = 0; lower = ZERO ; upper = ONE ; model . reset () ; System . out . printf ( " & & % s & load first % d bits & \\\\\ n " , binary ( message , 0) , PRECISION ) ; for (; i < PRECISION ; ++ i ) { code = 2* code + ( i < message . length ? message [ i ] : 0) ; } 12 / 16 A Vzorová implementace Aritmetické kódovánı́ while ( true ) { long range = upper - lower ; int probability [] = model . getProbability () ; int probTotal = arraySum ( probability , probability . length ) ; for ( int j = 0; j < probability . length ; ++ j ) { int upper0 = lower + ( int ) (( range * arraySum ( probability , j + 1) ) / probTotal ) ; int lower0 = lower + ( int ) Math . ceil (( double ) ( range * arraySum ( probability , j ) ) / probTotal ) ; if ( lower0 <= code && code < upper0 || j + 1 == probability . length ) { System . out . printf ( " ˜[% d , % d ) & % d & % s & output symbol & % d \\\\\ n " , lower , upper , code , binary ( message , i ) , j + 1) ; output . add ( j + 1) ; upper = upper0 ; lower = lower0 ; model . observe ( j + 1) ; if ( output . size () == block ) return toJavaArray ( output ) ; break ; } } while ( upper <= HALF || lower >= HALF ) { if ( upper <= HALF ) { System . out . printf ( " ˜[% d , % d ) & % d & % s & $ \\ times 2 $ ( and read next bit ) & \\\\\ n " , lower , upper , code , binary ( message , i ) ) ; lower = 2* lower ; upper = 2* upper ; code = 2* code ; } else { System . out . printf ( " ˜[% d , % d ) & % d & % s & $ \\ times 2 - % d$ ( and read next bit ) & \\\\\ n " , lower , upper , code , binary ( message , i ) , ONE ) ; lower = 2* lower - ONE ; upper = 2* upper - ONE ; code = 2* code - ONE ; } code += ( i < message . length ? message [ i ++] : 0) ; } while ( lower >= QUARTER && upper <= QUARTER3 ) { System . out . printf ( " ˜[% d , % d ) & % d & % s & $ \\ times 2 - % d$ ( and read next bit ) & \\\\\ n " , lower , upper , code , binary ( message , i ) , HALF ) ; lower = 2* lower - HALF ; upper = 2* upper - HALF ; code = 2* code - HALF + ( i < message . length ? message [ i ++] : 0) ; } } } private int arraySum ( int array [] , int count ) { int subtotal = 0; 13 / 16 A Vzorová implementace Aritmetické kódovánı́ for ( int i = 0; i < count ; ++ i ) subtotal += array [ i ]; return subtotal ; } private int [] toJavaArray ( ArrayList < Integer > list ) { int out [] = new int [ list . size () ]; for ( int i = 0; i < list . size () ; ++ i ) { out [ i ] = list . get ( i ) ; } return out ; } private String binary ( int message [] , int i ) { StringBuffer output = new StringBuffer () ; for (; i < message . length ; ++ i ) { output . append ( message [ i ]) ; } return output . toString () ; } } Zdrojový kód 1: Implementace aritmetického kódovánı́ package model ; public interface Model { public void reset () ; public int [] getProbability () ; public void observe ( int symbol ) ; } Zdrojový kód 2: Datová struktura sloužı́cı́ pro uchovávánı́ pravděpodobnostnı́ho modelu package model ; public class IIDModel implements Model { private int probability []; public IIDModel ( int probability []) { this . probability = probability ; } public void reset () {} public int [] getProbability () { return probability ; } public void observe ( int symbol ) {} } Zdrojový kód 3: Model bezpamnět’ového zdroje package model ; public class MCModel implements Model { private int probability [][]; private int lastObserved = 0; public MCModel ( int probability [][]) { this . probability = probability ; } public void reset () { 14 / 16 A Vzorová implementace Aritmetické kódovánı́ lastObserved = 0; } public int [] getProbability () { if ( lastObserved == 0) return getIIDModel () . getProbability () ; else return probability [ lastObserved - 1]; } public void observe ( int symbol ) { lastObserved = symbol ; } public IIDModel getIIDModel () { int m = probability . length ; long _probability [] = new long [ m ]; for ( int i = 0; i < m ; ++ i ) { for ( int j = 0; j < m ; ++ j ) { _probability [ j ] += probability [ i ][ j ]; } } int _iprob [] = new int [ m ]; for ( int i = 0; i < m ; ++ i ) { _iprob [ i ] = ( int ) ( _probability [ i ] / m ) ; } return new IIDModel ( _iprob ) ; } } Zdrojový kód 4: Model Markovského zdroj 15 / 16 REFERENCE Aritmetické kódovánı́ Reference [Bodden et al., 2007] Bodden, E., Clasen, M., and Kneis, J. (2007). Arithmetic coding revealed. In Sable Technical Report 2007-5, Sable Research Group, School of Computer Science. (McGill University, Montréal. http://paginas.fe.up.pt/˜vinhoza/itpa/ bodden-07-arithmetic-TR.pdf. [mathematicalmonk, 2011] mathematicalmonk (2011). ouYV3rBtrTI. http://www.youtube.com/watch?v= [Moser, 2012] Moser, S. M. (2012). Information theory (lecture notes). http://moser.cm. nctu.edu.tw/docs/it_script_v27.pdf. [Sayir, 1999] Sayir, J. (1999). On Coding by Probability Transformation. ETH series in information processing. Hartung-Gorre. http://www-sigproc.eng.cam.ac.uk/˜js851/papers/ thesisA4.pdf. 16 / 16
Podobné dokumenty
Minor v oboru matematika Bakalárské studium OI
Anotace: Předmět seznamuje studenty s matematickými
základy komprese informace a metodami jejího spolehlivého
přenosu. Jsou vyloženy základní Shannonovy výsledky o
možnostech efektivního kódován...
Celkové pořadí
Boomerang Sport - Skyline - Blueye
Boomerang 4 L-Zuchna-Abwassertechnik
Omega Proto 25 - Advance
ADVA
Magus 25 - www.macpara.com - www.airaile.org
GIN BOOMERANG 4 SM-Cousin Lines-Morzine-EAS Energy...
Inteligentní hlidkovani v namornim provozu
V vztahu (2.3) je k > 0 tvarový parametr a λ > 0 představuje měřítko. Právě díky
parametru k může weibullovo rozložení nabývat rozličných tvarů. Pro potřeby této
práce byl použit parametr k = 1.5.
...