Datakompression fö 5 p.1 Shannon-Fano-Elias-kodning Antag att vi har en minnesfri källa X i som tar värden i {1, 2,...,L}. Antag att sannolikheterna för alla symboler är strikt positiva: p(i) > 0, i. Fördelningsfunktionen F (i) definieras som F (i) = k i p(k) F (i) är en trappstegsfunktion där steget i k har höjden p(k). Betraktaäven den modifierade fördelningsfunktionen F (i) F (i) = k<i p(k)+ 1 2 p(i) Värdet av F (i) är mittpunktet på steget för i.
Datakompression fö 5 p.2 Shannon-Fano-Elias-kodning Eftersom alla sannolikheter är positiva är F (i) F (j) för i j. Alltså kan vi bestämma i om vi vet F (i). Värdet på F (i) kan användas som kodord för i. I allmänhet är dock F (i) ett reellt tal med en oändlig antal bitar i sin binärutveckling, så vi kan inte använda det exakta värdet som kodord. Om vi istället använder ett närmevärde med ändlig binärutveckling, hur stor noggrannhet måste vi använda, dvs hur många bitar måste vi ha i kodordet? Antag att vi trunkerar binärutvecklingen för F (i) till l i bitar (betecknat med F (i) li. Då gäller att F (i) F (i) li < 1 2 l i Om vi låter l i = log p(i) +1så är 1 2 l =2 l i =2 log p(i) 1 2 log p(i) 1 = p(i) i 2 = F (i) F (i 1)
Datakompression fö 5 p.3 Shannon-Fano-Elias-kodning Alltså ligger talet F (i) li i steget som motsvarar i och därför räcker det med l i = log p(i) +1bitar för att beskriva i. Är den konstruerade koden prefixfri? Antag att ett kodord är b 1 b 2...b l. Dessa bitar representerar intervallet [0.b 1 b 2...b l 0.b 1 b 2...b l + 1 ) För att koden ska vara prefixfri måste alla 2 l intervall vara disjunkta. Intervallet för kodordet till symbol i har längden 2 l i vilket är mindre än halva längden av motsvarande steg. Startpunkten på intervallet ligger i nedre halvan av steget. Detta betyder att slutpunkten på intervallet ligger under toppen av steget. Alltså är alla intervall disjunkta och koden är prefixfri.
Datakompression fö 5 p.4 Shannon-Fano-Elias-kodning Vad har koden för datatakt? Kodordsmedellängden blir l = p(i) l i = p(i) ( log p(i) +1) i i p(i) ( log p(i)+2)= p(i) log p(i)+2 p(i) i i i = H(X i )+2 Vi kodar bara en symbol i taget, så datatakten R = l. Koden är alltså lite sämre än t.ex. en huffmankod. Prestanda kan förbättras genom att man kodar flera symboler i taget. Detta leder oss till aritmetisk kodning.
Datakompression fö 5 p.5 Aritmetisk kodning Aritmetisk kodning är i princip en generalisering av Shannon-Fano-Elias-kodning till att koda symbolsekvenser istället för enstaka symboler. Antag att vi vill koda en sekvens x = x 1,x 2,...,x n. Man börjar med hela sannolikhetsintervallet [0, 1). I varje steg delar man in sitt intervall proportionellt enligt fördelningsfunktionen F (i) och väljer just det delintervall som motsvarar den symbol som kodas. Har vi en minneskälla gör man intervalluppdelningen enligt den betingade fördelningsfunktionen. Varje symbolsekvens av längd n identifierar unikt ett delintervall. Kodordet för sekvensen är ett tal i intervallet. Antal bitar i kodordet beror av intervallets storlek, så ett stort intervall (dvs en sekvens med hög sannolikhet) får ett kort kodord, medan ett litet intervall ger ett längre kodord.
Datakompression fö 5 p.6 Iterativ algoritm Antag att vi vill koda en sekvens x = x 1,x 2,...,x n. Vi betecknar den undre gränsen i motsvarande intervall med l (n) och den övre gränsen med u (n). Intervallgenereringen ges då iterativt av { l (n) = l (n 1) +(u (n 1) l (n 1) ) F (x n 1) u (n) = l (n 1) +(u (n 1) l (n 1) ) F (x n ) Startvärden är l (0) =0och u (0) =1. F (0) = 0 Intervallstorleken är förstås lika med sannolikheten för sekvensen u (n) l (n) = p(x)
Datakompression fö 5 p.7 Kodord Kodordet för ett intervall är den kortaste bitsekvens b 1 b 2...b k sådan att det binära talet 0.b 1 b 2...b k ligger i intervallet och att även alla andra tal som börjar med samma k bitar också ligger i intervallet. Givet ett binärt tal a i intervallet [0, 1) med k bitar 0.b 1 b 2...b k. Alla tal vars k första bitar är samma som för a ligger i intervallet [a, a + 1 ). 2 k Ett nödvändigt villlkor för att hela detta intervall ska ligga inom intervallet som hör till symbolsekvensen, är att det är mindre än eller lika stort som symbolsekvensintervallet, dvs p(x) 1 2 k k log p(x) Vi kan inte vara säkra på att det verkligen räcker med log p(x) bitar, eftersom vi inte kan placera ut dessa intervall på godtyckliga platser. Däremot kan man inse att det maximalt krävs en bit extra om man har otur. Kodordslängden l(x) för en sekvens x ges alltså av l(x) = log p(x) eller l(x) = log p(x) +1
Datakompression fö 5 p.8 Kodordsmedellängd l = p(x) l(x) x x x p(x) ( log p(x) +1) p(x) ( log p(x)+2)= x p(x) log p(x)+2 p(x) = H(X 1 X 2...X n )+2 Och den resulterande datatakten begränsas alltså uppåt av x R 1 n H(X 1X 2...X n )+ 2 n Detta är visserligen lite sämre än man skulle få med en utvidgad huffmankod, men huffmankoder är inte praktiskt användbara för stora n. Komplexiteten för en aritmetisk kod är å andra sidan oberoende av hur många symboler n som man kodar i taget.
Datakompression fö 5 p.9 Praktiska problem Vi har begränsad precision och kan inte lagra intervallgränser och sannolikheter med godtycklig noggrannhet. Vi vill kunna börja skicka bitar utan att vänta på att hela sekvensen med n symboler kodats. En lösning är att skicka bitar så snart vi är säkra på dem och att när detta görs skala om intervallet, så att vi maximalt utnyttjar den tillgängliga precisionen. Om den första biten i både den lägre och den övre gränsen är den samma måste även den biten i kodordet vara densamma. Då kan man skicka den biten och därefter skifta gränserna en bit, dvs skala om intervallstorleken med en faktor 2.
Datakompression fö 5 p.10 Fixpunktsaritmetik Aritmetisk kodning implementeras oftast med fixpunktsaritmetik. Antag att intervallgränserna l (n) och u (n) lagras som heltal med m bitars noggrannhet och att fördelningsfunktionen F (i) lagras som heltal med k bitars noggrannhet. Algoritmen kan då modifieras till l (n) = l (n 1) + (u(n 1) l (n 1) +1)F (x n 1) 2 k u (n) = l (n 1) + (u(n 1) l (n 1) +1)F (x n ) 2 k 1 Startvärden blir l (0) =0och u (0) =2 m 1.
Datakompression fö 5 p.11 Intervallskalning Fallen när vi ska göra intervallskalning blir: 1. Intervallet ligger helt inom [0, 2 m 1 1], dvs den mest signifikanta biten i både l (n) och u (n) är 0. Skifta ut mest signifikant bit ur l (n) och u (n) och skicka den. Skifta in 0 i l (n) och 1 i u (n). 2. Intervallet ligger helt inom [2 m 1, 2 m 1], dvs den mest signifikanta biten i både l (n) och u (n) är 1. Samma operationer som i fall 1. När vi har kodat våra n symboler avslutas kodordet genom att vi skickar alla m bitar i l (n). Koden kan visserligen bli en prefixkod även med färre bitar, men implementationen av avkodaren blir enklare om hela l skickas. För stora n blir de extra bitarna försumbara, dessutom måste man förmodligen ända packa bitarna i ett jämnt antal bytes.
Datakompression fö 5 p.12 Mer problem Tyvärr kan vi i vår algoritm hamna i problem, om den första biten i l hela tiden är 0 och den första biten i u är 1. I värsta fall hamnar vi i situationen att l = 011...11 och u = 100...00. Då kommer vår algoritm inte att fungera. Lyckligtvis kan vi komma runt detta problem. Om de två första bitarna i l blir 01 och de två första i u blir 10, kan vi göra ett bitskift, utan att skicka några bitar i kodordet. När sen de första bitarna i l och u blir detsamma kan vi förutom den biten även skicka en extra, inverterad bit, dvs vi är då säkra på om kodordet ska ha 01 eller 10.
Datakompression fö 5 p.13 Intervallskalning Vi får nu tre fall 1. Intervallet ligger helt inom [0, 2 m 1 1], dvs den mest signifikanta biten i både l (n) och u (n) är 0. Skifta ut mest signifikant bit ur l (n) och u (n) och skicka den. Skifta in 0 i l (n) och 1 i u (n). 2. Intervallet ligger helt inom [2 m 1, 2 m 1], dvs den mest signifikanta biten i både l (n) och u (n) är 1. Samma operationer som i fall 1. 3. Vi har inte fall 1 eller 2, men intervallet ligger helt inom [2 m 2, 2 m 1 +2 m 2 1], dvs de två mest signifikanta bitarna är 01 i l (n) och 10 i u (n). Skifta ut mest signifikant bit ur l (n) och u (n). Skifta in 0 i l (n) och 1 i u (n). Invertera de nya mest signifikanta bitarna i l (n) och u (n). Skicka inga bitar, men håll reda på hur många gånger vi gör omskalningar av den här typen. Nästa gång vi gör en omskalning av typen 1, skicka lika många 1:or extra som antalet omskalningar av typ 3. På samma sätt, nästa gång vi gör en omskalning av typ 2 så skickas lika många extra 0:or som antalet omskalningar av typ 3.
Datakompression fö 5 p.14 Krav på precisionen Vi måste använda en datatyp med minst m + k bitar för att få plats med delresultaten i beräkningarna. Vi ser också att det minsta intervall vi kan ha utan att någon omskalning görs har storleken 2 m 2 +1, vilket till exempel händer när l (n) =2 m 2 1 och u (n) =2 m 1. För att algoritmen ska fungera får aldrig u (n) bli mindre än l (n) (samma värde är tillåtet, när man skiftar ut bitar skiftas ju nollor in i l ochettoriniu). För att detta ska gälla måste alltså alla intervall i fördelningsfunktionen uppfylla (med en lätt överskattning) F (i) F (i 1) 2 k m+2 ; i =1,...,L Till exempel så måste m k +2om vi har något intervall av storlek 1.
Datakompression fö 5 p.15 Avkodning Starta avkodaren i samma tillstånd (dvs l =0och u =2 m 1) som kodaren. Inför t som de m första bitarna i bitströmmen (kodordet). I varje steg räknar vi ut talet (t l +1) 2k 1 u l +1 Jämför detta tal med F för att se vilket intervall detta motsvarar. Detta ger en avkodad symbol. Uppdatera l och u på samma sätt som i kodaren. Vi gör eventuellt ett antal skift (omskalningar). Varje gång vi skalar om l och u ska vi även uppdatera t på samma sätt (skifta ut den mest signifikanta biten, skifta in en ny bit från kodströmmen som minst signifikant bit samt, om det är en om skalning av typ 3, invertera den nya mest signifikanta biten.) Repetera tills hela sekvensen är avkodad. Observera att kodaren kan behöva skicka antalet symboler som sidoinformation, så att avkodaren vet när den ska sluta avkoda. Alternativt kan man införa en extra symbol i sitt alfabet, med lägsta möjliga sannolikhet, som används för att markera när sekvensen tar slut.