250 likes | 394 Views
Web Algorithmics. Dictionary-based compressors. LZ77. Algorithm’s step: Output <dist, len, next-char> Advance by len + 1 A buffer “window” has fixed length and moves. a. a. c. a. a. c. a. b. c. a. a. a. a. a. a. a. c. <6,3,a>. Dictionary (all substrings starting here). a.
E N D
Web Algorithmics Dictionary-based compressors
LZ77 Algorithm’s step: • Output <dist, len, next-char> • Advance by len + 1 A buffer “window” has fixed length and moves a a c a a c a b c a a a a a a a c <6,3,a> Dictionary(all substrings starting here) a c a a c a a c a b c a a a a a a c <3,4,c>
LZ77 Decoding Decoder keeps same dictionary window as encoder. • Finds substring and inserts a copy of it What if l > d? (overlap with text to be compressed) • E.g. seen = abcd, next codeword is (2,9,e) • Simply copy starting at the cursor for (i = 0; i < len; i++) out[cursor+i] = out[cursor-d+i] • Output is correct: abcdcdcdcdcdce
Lempel-Ziv Algorithms Keep a “dictionary” of recently-seen strings. The differences are: • How the dictionary is stored • How it is extended • How it is indexed • How elements are removed LZ-algos are asymptotically optimal, i.e. their compression ratio goes to H(S) for n !! No explicit frequency estimation
LZ77 Optimizations used by gzip LZSS: Output one of the following formats (0, position, length)or(1,char) Typically uses the second format if length < 3. Special greedy: possibly use shorter match so that next match is better Hash Table for speed-up searches on triplets Triples are coded with Huffman’s code
Web Algorithmics Some special compressors Spatial vs Temporal Locality
g-code for integer encoding Length-1 • x > 0 and Length = log2 x +1 e.g., 9 represented as <000,1001>. • g-code for x takes 2 log2 x +1 bits (ie. factor of 2 from optimal) • Optimal for Pr(x) = 1/2x2, and i.i.d integers
It is a prefix-free encoding… • Given the following sequence of g-coded integers, reconstruct the original sequence: 0001000001100110000011101100111 8 59 7 6 3
Streaming compression Still you need to determine and sort all terms…. Can we do everything in one pass ? • Move-to-Front (MTF): • As a freq-sorting approximator • As a caching strategy • As a compressor • Run-Length-Encoding (RLE): • FAX compression
Move to Front Coding Transforms a char sequence into an integersequence, that can then be var-length coded • Start with the list of symbols L=[a,b,c,d,…] • For each input symbol s • output the position of s in L • move s to the front of L Properties: • Exploit temporal locality, and it is dynamic • X = 1n 2n 3n… nn Huff = O(n2 log n), MTF = O(n log n) + n2 There is a memory
No much worse than Huffman ...but it may be far better MTF: how good is it ? Encode the integers via d-coding: |g(i)| ≤ 2 * log i + 1 Put S in the front and consider the cost of encoding: By Jensen’s:
Run Length Encoding (RLE) If spatial locality is very high, then abbbaacccca => (a,1),(b,3),(a,2),(c,4),(a,1) In case of binary strings just numbers and one bit Properties: • Exploit spatial locality, and it is a dynamic code • X = 1n 2n 3n… nn Huff(X) = O(n2 log n) > Rle(X) = O( n (1+log n) ) There is a memory
Web Algorithmics Burrows-Wheeler Transform
# mississipp i i #mississipp i ppi#mississ i ssippi#miss i ssissippi# m Sort the rows m ississippi# T p i#mississi p p pi#mississ i s ippi#missi s s issippi#mi s s sippi#miss i s sissippi#m i The Burrows-Wheeler Transform (1994) Let us given a text T = mississippi# F L mississippi# ississippi#m ssissippi#mi sissippi#mis issippi#miss ssippi#missi sippi#missis ippi#mississ ppi#mississi pi#mississip i#mississipp #mississippi
A famous example Much longer...
L is highly compressible Algorithm Bzip : • Move-to-Front coding of L • Run-Length coding • Statistical coder Compressing L seems promising... Key observation: • L is locally homogeneous • Bzip vs. Gzip: 20% vs. 33%, but it is slower in (de)compression !
SA L BWT matrix 12 11 8 5 2 1 10 9 7 4 6 3 #mississipp i#mississip ippi#missis issippi#mis ississippi# mississippi pi#mississi ppi#mississ sippi#missi sissippi#mi ssippi#miss ssissippi#m i p s s m # p i s s i i Given SA and T, we have L[i] = T[SA[i]-1] How to compute the BWT ? We said that: L[i] precedes F[i] in T #mississipp i#mississip ippi#missis issippi#mis ississippi# mississippi pi#mississi ppi#mississ sippi#missi sissippi#mi ssippi#miss ssissippi#m L[3] = T[ 7 ]
SA 12 11 8 5 2 1 10 9 7 4 6 3 Elegant but inefficient How to construct SA from T ? # i# ippi# issippi# ississippi# mississippi pi# ppi# sippi# sissippi# ssippi# ssissippi# • Obvious inefficiencies: • Q(n2 log n) time in the worst-case • Q(n log n)cache misses or I/O faults Input: T = mississippi#
i ssippi#miss How do we map L’s onto F’s chars ? i ssissippi# m ... Need to distinguishequal chars in F... m ississippi# p i#mississi p p pi#mississ i s ippi#missi s s issippi#mi s s sippi#miss i s sissippi#m i Take two equal L’s chars Rotate rightward their rows Same relative order !! A useful tool: L F mapping F L unknown # mississipp i i #mississipp i ppi#mississ
Two key properties: 1. LF-array maps L’s to F’s chars 2. L[ i ] precedes F[ i ] in T i ssippi#miss i ssissippi# m m ississippi# p p i T = .... # i p i#mississi p p pi#mississ i s ippi#missi s s issippi#mi s s sippi#miss i s sissippi#m i InvertBWT(L) Compute LF[0,n-1]; r = 0; i = n; while (i>0) { T[i] = L[r]; r = LF[r]; i--; } The BWT is invertible F L unknown # mississipp i i #mississipp i ppi#mississ Reconstruct T backward:
# at 16 Mtf = [i,m,p,s] Alphabet |S|+1 An encoding example T = mississippimississippimississippi L = ipppssssssmmmii#pppiiissssssiiiiii Mtf = 020030000030030200300300000100000 Mtf = 030040000040040300400400000200000 Bin(6)=110, Wheeler’s code RLE0 = 03141041403141410210 Bzip2-output = Arithmetic/Huffman on |S|+1 symbols... ... plus g(16), plus the original Mtf-list (i,m,p,s)