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

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...

Více

Celkové pořadí

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...

Více

Results total

Results total Yigit YILDIRIM

Více

Inteligentní hlidkovani v namornim provozu

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. ...

Více