Textkompression: Burrows-Wheeler-Transformation

Ähnliche Dokumente
Dynamisches Huffman-Verfahren

Wann sind Codes eindeutig entschlüsselbar?

Textkompression: Burrows-Wheeler-Transformation

Praktikum BKSPP: Blatt 2

Die Burrows-Wheeler-Transformation

Datenkompression. 1 Allgemeines. 2 Verlustlose Kompression. Holger Rauhut

2. Woche Eindeutige Entschlüsselbarleit, Sätze von Kraft und McMillan, Huffmancodierung

Einleitung. Kapitel 1

4.4 Anwendungen von Suffixbäumen und Suffix-Arrays

Übrigens: um den Algorithmus im Unterricht einzuführen, sind keine Formeln notwendig! Warum reicht die normale ASCII-Codierung nicht aus?

Freiwillige Übung zum Thema: Adaptive Huffman-Kodierung

Universität Trier. Fachbereich IV. Wintersemester 2004/2005. Wavelets made easy. Kapitel 2 Mehrdimensionale Wavelets und Anwendungen

21. Greedy Algorithmen. Aktivitätenauswahl, Fractional Knapsack Problem, Huffman Coding Cormen et al, Kap. 16.1, 16.3

Algorithmen und Komplexität Lösungsvorschlag zu Übungsblatt 8

Technische Informatik - Eine Einführung

Algorithmen und Datenstrukturen 2

Übungsblatt 5 - Musterlösung

Algorithmus zur komprimierten Übertragung von Textdaten an mobile Endgeräte

Referat zum Thema Huffman-Codes

Informatik II, SS 2016

Häufige Mengen ohne Kandidatengenerierung. FP-Tree: Transaktionen. Konstruktion eines FP-Trees. FP-Tree: Items

Kapitel 7: Optimalcodierung und Huffman Coding

Seminar über Algorithmen, SS2004. Textkompression. von Christian Grümme und Robert Hartmann

Häufige Mengen ohne Kandidatengenerierung

6. Übungsblatt zu Algorithmen II im WS 2016/2017

ADS: Algorithmen und Datenstrukturen 2

Datenkompression. Vortrag von Markus Durzinsky Student der Otto-von-Guericke-Universität Magdeburg

3 Codierung diskreter Quellen. Quelle Quellcodierer Kanalcodierer reduziert die benötigte Datenmenge. fügt Daten zur Fehlerkorrektur ein.

Informatik II, SS 2018

Praktikum BKSPP. Aufgabenblatt Nr. 2

Übersicht. Aktivitäten-Auswahl-Problem. Greedy Algorithmen. Aktivitäten-Auswahl-Problem. Aktivitäten-Auswahl-Problem. Datenstrukturen & Algorithmen

Wie muss der Eingabetext beschaffen sein, damit er sich gut komprimieren lässt?

Informatik-Seminar Thema 6: Bäume

Beispiel: Zeigen Sie, dass H(x) = H 0 = I gilt, wenn alle Zeichen gleichwahrscheinlich sind.

2.7 Der Shannon-Fano-Elias Code

Proseminar WS 2002/2003

Eike Müller. Kompression-Algorithmen für Bilder. 3. Juli 2013

Bäume 1. Thomas Röfer

21. Dynamic Programming III

Datenstrukturen und Algorithmen (SS 2013)

Satz 172 Jedes vergleichsbasierte Sortierverfahren benötigt im worst-case mindestens n ld n + O(n) Vergleiche und hat damit Laufzeit Ω(n log n).

Gierige Algorithmen Interval Scheduling

Strings. Stringsuche, Boyer-Moore, Textkompression, Huffman Codes.

6. Komprimierung. (Text)komprimierung ist ein Wechsel der Repräsentation von Daten, so daß sie weniger

a) Fügen Sie die Zahlen 39, 38, 37 und 36 in folgenden (2, 3)-Baum ein:

Kapitel 2. Suche nach endlich vielen Wörtern. R. Stiebe: Textalgorithmen, Winter 2005/06 113

12 (2-4)-Bäume Implementierbare Funktionen. (2-4)-Bäume sind durch folgende Eigenschaften deniert: 1. Alle Äste sind gleich lang

Effiziente Algorithmen und Komplexitätstheorie

Aufgaben zur Klausurvorbereitung

Kapitel 2: Sortier- und Selektionsverfahren Gliederung

Datenstrukturen & Algorithmen

Datenstrukturen Kurzanleitung

Proseminar Datenkompression Suchstrategien und Präfixcodes

Stabiles Sortieren. Dieses Prinzip lässt sich natürlich auf beliebiege andere Zahlensystem oder auch komplett anders gestaltete Mengen übertragen.

Informatik II, SS 2018

ADS: Algorithmen und Datenstrukturen 2

Kapitel 3: Sortierverfahren Gliederung

10. Sortieren III. Untere Schranken für das vergleichsbasierte Sortieren, Radix- und Bucketsort

Übung Algorithmen und Datenstrukturen

Graphen. Definitionen

Lemma 185 Mit den zusätzlichen Festlegungen

3.3 Optimale binäre Suchbäume

Binäre Suchbäume. Mengen, Funktionalität, Binäre Suchbäume, Heaps, Treaps

Effiziente Algorithmen und Komplexitätstheorie

Textkompression. Komprimierung von Daten. Runlength Komprimierung (2) Runlength Komprimierung (1) Herkömmliche Kodierung. Runlength Komprimierung (3)

13 (2-4)-Bäume Implementierbare Funktionen. (2-4)-Bäume sind durch folgende Eigenschaften deniert: 1. Alle Äste sind gleich lang

3.2. Divide-and-Conquer-Methoden

JPEG Kompression technische Realisierung

Effizienter Planaritätstest Vorlesung am

Optimalcodierung. Thema: Optimalcodierung. Ziele

Praktikum Algorithmische Anwendungen WS 2006/07 Sortieren in linearer Laufzeit

Stud.-Nummer: Datenstrukturen & Algorithmen Seite 1

Algorithmen und Datenstrukturen

Vorlesung Datenstrukturen

Kompressionsverfahren

Algorithmen und Datenstrukturen. D1.1 Motivation. Algorithmen und Datenstrukturen. D1.2 Strings. D1.3 Sortieren von Strings. D1.4 LSD-Sortierverfahren

Algorithmische Bioinformatik 1

Alle bislang betrachteten Sortieralgorithmen hatten (worst-case) Laufzeit Ω(nlog(n)).

Algorithmen und Datenstrukturen

Isomorphie von Bäumen

Sortieren und Suchen. Jens Wächtler Hallo Welt! -Seminar LS 2

Seminar Kompressionsalgorithmen Huffman-Codierung, arithmetische Codierung

Datenstrukturen und Algorithmen. Christian Sohler FG Algorithmen & Komplexität

Kompression. Tim Kilian

Algorithmen auf Sequenzen

TU München. Hauptseminar: WS 2002 / Einführung in Suffix - Bäume

Proseminar Kodierverfahren bei Dr. Ulrich Tamm Sommersemester 2003 Thema: Codierung von Bäumen (Prüfer Codes...)

7. Sortieren Lernziele. 7. Sortieren

Algorithmen und Datenstrukturen

Heapsort / 1 A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

Seminar: Aktuelle Themen aus der Programmierung

Informationstheorie und Codierung

2. Klausur zur Vorlesung Theoretische Grundlagen der Informatik Wintersemester 2014/2015

Algorithmen und Datenstrukturen II

Zeichenketten Benedikt Straßner. Programming Systems Group Martensstr Erlangen Germany

ADS: Algorithmen und Datenstrukturen

Kompressionsverfahren für Texte

Erinnerung Blockchiffre

Transkript:

Proseminar Algorithmen der Bioinformatik WS 2010/11 Textkompression: Burrows-Wheeler-Transformation Johann Hawe Johann Hawe, WS 2010/11 1

Gliederung 1. Einleitung 2. BWT Kompressionstransformation 2.1 Prinzip der Transformation 2.2 Eigenschaften des Outputs 2.3 Implementierung 3. BWT Dekompressionstransformation 4. Move-To-Front-Kodierung und -Dekodierung 5. Huffman-Kodierung und -Dekodierung 6. Fazit Johann Hawe, WS 2010/11 2

1. Einleitung Die Burrows-Wheeler-Transformation, kurz BWT, entspricht einer reversiblen Transformation eines zu komprimierenden Textes. Diese Permutation des Textes erlaubt es bestimmten Kompressionsverfahren, wie z.b. die kombinierte Anwendung von Huffman- und Move-to-Front- Kodierung, diesen effizienter zu komprimieren. Eine gute und performante Kompression von Daten wird in vielen Gebieten rund um Medien und Daten im Allgemeinen benötigt, nicht zuletzt auch in der Bioinformatik. Hier ist es unter anderem wichtig, große Datensätze, wie vollständige Genome oder Proteome, effizient zu speichern und schnellen Zugriff darauf zu gewährleisten. Gerade die Tatsache, dass derzeit eine wahre Datenflut von verschiedenen Forschungseinrichtungen generiert wird, macht gute Kompressionsverfahren unabdinglich. 2. Die Kompressions-Transformation 2.1 Prinzip der Transformation Betrachten wir zuerst die Hintransformation, deren Ziel es ist, eine Inputseqeuenz S der Länge N so zu permutieren, dass die entstehende Sequenz L sich zum einen in S zurück transformieren und zum anderen besser komprimieren lässt. Hierzu erstellt man zunächst eine Matrix M, welche in jeder Zeile i die Sequenz S um i Positionen zyklisch nach rechts rotiert enthält. Die Zeilen der Matrix werden anschließend lexikographisch aufsteigend sortiert. Abb.1: Input S: artanaa Matrix M: aaartan aartana anaaart Index I = 3: artanaa naaarta rtanaaa tanaaar Johann Hawe, WS 2010/11 3

In Abb.1 fällt auf, dass in jeder Spalte von M eine Permutation von S steht. Das Ergebnis der Transformation gestaltet sich nun zum einen aus dem Index I, welcher das erste Vorkommen von S innerhalb der Matrix beschreibt (Es ist durchaus möglich, dass S in mehreren Zeilen von M vorkommt). Der zweite Teil ist eine Permutation L von S, welche durch die letzte Spalte von M beschrieben wird, also L := M[0][N-1] + + M[N-1][N-1] Somit entspricht das Ergebnis dem Tupel (L, I). In obigem Beispiel: (nataaar, 3) 2.2 Eigenschaften des Outputs Warum lässt sich diese Permutation von L nun besser komprimieren als z.b. der ursprüngliche Input S? Betrachtet man alle Wörter der deutschen Sprache, so fällt auf, dass viele Suffixe oft nur von einigen wenigen Präfixen angeführt werden können, wie z.b. das Suffix ett. Hierfür kommen als Präfixe u.a. nur Br oder B in Frage. Dieses Phänomen ist dafür verantwortlich, dass sich in der letzten Spalte von M gleiche Buchstaben in einer lokalen Umgebung anhäufen, da diese ja die Präfixe der Anfänge der Zeilen darstellen und diese lexikographisch sortiert sind. Diese Eigenschaft, dass lange Folgen gleicher Buchstaben in einer Sequenz vorkommen, sorgt dafür, dass sich diese einfach durch eine Kombination aus Move-to-Front-Kodierer und einem sog. entropy-coder, wie z.b. dem Huffman-Kodierer, komprimieren lässt. 2.3 Implementierung Das größte Problem bei der Implementierung dieses Algorithmus stellt die Sortierung aller Zeilen der Matrix dar. Das Anlegen der Matrix selbst geschieht intuitiv, wobei man darauf achten muss, nicht in jeder Zeile die komplette Sequenz abzuspeichern, sondern jeweils nur einen Zeiger auf die entsprechende Startposition in der Sequenz. Ansonsten kann es, gerade bei längeren Input-Sequenzen, zu Speicherproblemen kommen. In der Praxis ist auch eine blockweise Verarbeitung des Inputs sinnvoll, z.b. zu Blöcken von ein paar hundert kbyte bis zu einem MByte. Johann Hawe, WS 2010/11 4

Für die Sortierung der Zeilen kann man verschiedene Verfahren verwenden, wie zum Beispiel Quicksort oder ein gemischtes Verfahren aus Bucketsort und Quicksort. Da das worst-case Laufzeitverhalten bei Quicksort allerdings mit O(n 2 ) nicht zufriedenstellend ist, ist es sinnvoll effizientere bzw. passendere Sortierverfahren zu implementieren, z.b. auf Basis von Suffixtrees oder Suffixarrays (weniger Platzbedarf). Mit Hilfe solcher Suffixtrees kann die Implementierung sogar ein Laufzeitverhalten von O(n) generieren. 3. Dekompressions-Transformation Das Ziel dieses Schrittes ist es, den ursprünglichen Output der Kompressionstransformation, (L, I), in die Input-Sequenz S zurückzuführen. Zuerst bemerken wird, dass wir durch L auch die erste Spalte F der ursprünglichen Matrix M gegeben haben. Denn zum einen sind alle Spalten von M Permutationen von S, also sind auch L und F jeweils Permutationen von S. Weiterhin ist M zeilenweise lexikographisch sortiert, also ist F sortiert. Somit erhalten wir F aus L durch einfaches sortieren aller Zeichen. Nun ist es uns möglich, anhand von F und L eine neue Permutation π zu beschreiben, durch welche sich die ursprüngliche Sequenz S wiederherstellen lässt. Zur besseren Erklärung der Permutation betrachten wir zunächst noch die Matrix M', welche sich von der ursprünglichen Matrix M durch rotieren aller Zeilen um eine Position nach rechts ergibt. Es gilt also: M'[i][j] = M[i][(j-i) mod N] Da M lexikographisch aufsteigend sortiert ist, ist M' lexikographisch aufsteigend ab der zweiten Position sortiert (aufgrund der zykl. Rotation nach rechts). Ebenso gilt für M', dass jede Spalte einer Permutation von S entspricht und dass jede Zeile aus M eine äquivalente Zeile in M' besitzt. Betrachten wir nun alle Zeilen welche mit einem gemeinsamen Zeichen c beginnen. Es fällt auf, dass die relative Ordnung der Zeilen in M und M' jeweils gleich ist, da ja entsprechend die Anfangsbuchstaben gleich sind und M' ab der zweite Spalte aufsteigend sortiert ist. D. h., das erste Vorkommen von z.b. 'b' in L entspricht dem ersten Vorkommen von 'b' in F. Johann Hawe, WS 2010/11 5

Nun nehmen wir uns der Permutation π an. Mit dem jetzigen Wissen ist sie einfach zu berechnen, denn sie beschreibt im Wesentlichen in welcher Zeile von M man eine Zeile aus M' finden kann, also: M'[i][j] = M[π(i)][j] für i,j є [0: n-1] Anhand dieser Permutation, den beiden Spalten F und L sowie dem Index I kann man schließlich S bestimmen. Für jeden Index i wissen wir, dass L[i] direkt vor F[i] steht (zyklische Rotation der Zeilen). Ebenso wissen wir, dass F[π(i)] = L[i] und somit L[π(i)] direkt vor L[i] steht. Da wir zusätzlich wissen, dass L[I] = S[N-1] also das letzte Zeichen von S darstellt, bekommen wir S durch folgende Vorschrift: S[n-1-k] = L[π k(i) ] wobei π 0 (i) = i und π k+1 (i) = π(π k (i)). S wird hier von hinten nach vorne generiert. Hierbei ist nochmals zu betonen, dass für die Generierung von S im Endeffekt nur L und I benötigt werden. Die Dekompressions- Transformation kann unmittelbar intuitiv implementiert werden. 4. Move-To-Front-Kodierung Die nächsten beiden Abschnitte befassen sich der Vollständigkeit halber mit der eigentlichen Kompression des Outputs (L, I) der BWT. Die Sequenz S wird hier zuerst mit Hilfe eines Move-to-Front-Kodierers kodiert, um diese anschließend durch die Huffman-Kodierung zu komprimiert. Bei der Move-to-Front-Kodierung wird jeder Character aus L durch einen Integer kodiert, indem zunächst eine Liste R aller Charactere des zugrunde liegenden Alphabets nach einer bestimmten Reihenfolge, z.b. aufsteigend lexikographisch, generiert wird. Zusätzlich wird eine Liste K der Länge N (= Länge von L) initalisiert. Am Ende der Kodierung enthält K[i] den Code des Characters von L an der Stelle i. Nun wird L analysiert, und bei jedem Vorkommen eines Characters c in L, wird der Index von c aus R in K geschrieben. Anschließend wird R reorganisiert, indem c aus R gelöscht und am Anfang von R wieder angefügt wird. Dies führt dazu, dass lokal häufig vorkommende Zeichen in L nach vorne wandern und somit durch kleine Integer Werte kodiert Johann Hawe, WS 2010/11 6

werden können. Insbesondere das vorherige Anwenden des BWT führt häufig zu einer langen Folge von Nullen in K. Die generiert Liste K kann aufgrund der asymmetrischen Verteilung der Integer Werte anschließend gut mittels der Huffman-Kodierung komprimiert werden. Die inverse Operation der Move-to-Front-Kodierung kann einfach implementiert werden. Es genügt hier die Liste R auf die gleiche Weise wie bei der Kodierung zu generieren und für jeden Integer i in K den Character an der Stelle R[i] in L zu schreiben. Anschließend muss R wieder durch Entfernen und vorne Anfügen von c in R reorganisiert werden. 5. Huffman-Kodierung Für die Huffman-Kodierung sehen wir uns zunächst einen normalen Text in deutscher Sprache an. Typischerweise kann jedes Zeichen des Textes als 8- Bit-Code bzw. ASCII-Code ausgedrückt werden. Dies wäre eine optimale Codierung, würden alle Zeichen in dem Text mit der gleichen Wahrscheinlichkeit auftreten. Das dies aber nicht der Fall ist, ist intuitiv zu erkennen, da z.b. der Buchstaben 'e' bei weitem häufiger Auftritt wie z.b. 'x' oder 'z' oder auch Satzzeichen wie '!'. Deshalb setzt man zur Kodierung eines solchen Textes mit asymmetrischen Auftrittswahrscheinlichkeiten der einzelnen Zeichen u.a. die Huffman-Kodierung ein, da diese einen Code in Abhängigkeit der Wahrscheinlichkeiten berechnet. Ziel der Huffman-Kodierung ist es also, eine Input-Sequenz anhand der Wahrscheinlichkeit der einzelnen Zeichen in einen optimalen Präfix- Code zu übersetzen. Diesem Code liegen zwei Bedingungen zu Grunde: 1) es gibt keinen anderen Code mit kürzerer, mittlerer Codewortlänge 2) kein Codewort ist Präfix eines anderen Codeworts (Fanobedingung) Die Wahrscheinlichkeit für ein bestimmtes Zeichen ist im allgemeinen, z.b. für einen deutschen Text, nicht bekannt. Deshalb behilft man sich hier mit der relativen Häufigkeit eines Zeichens in dem zu kodierenden, festen Text, welche genau dessen Wahrscheinlichkeit widerspiegelt. Die Kodierung wird im Prinzip durch einen binären Baum dargestellt, dessen Blätter alle Zeichen des Alphabetes des zu kodierenden Textes Johann Hawe, WS 2010/11 7

darstellen. Dieser kann einfach konstruiert werden, indem man jeweils die beiden Zeichen mit den geringsten Wahrscheinlichkeiten in einem neuen Knoten K vereinigt. Die Wahrscheinlichkeit für K ist dann die Summe der Einzelwahrscheinlichkeiten der beiden Zeichen. K dient dann als Basis für die weitere Konstruktion des Baumes, solange bis alle Buchstaben des Alphabetes hinzugefügt wurden. Abb.2: Huffman-Baum mit dazugehörigem Code Der Code für ein bestimmtes Zeichen kann dann einfach an dem erstellten Baum abgelesen werden, indem man den Pfad von der Wurzel bis zu dem Blatt betrachtet. Wird hier ein Knoten nach links verlassen, notiert man eine '0', wird er nach rechts verlassen notiert man eine '1' (s. Abb. 2). Auf diese Weise entsteht für einen gegebenen Text ein optimaler Präfix-Code (ohne Beweis). Zur Dekodierung kann der kodierte Text zusammen mit dem generierten Baum oder mit einer Vorschrift zur Erstellung des Baumes übertragen werden. Letzteres ist dann nötig, wenn z.b. zwei Zeichen die gleiche Auftrittswahrscheinlichkeit besitzen. Johann Hawe, WS 2010/11 8

6. Fazit Mit der Burrows-Wheeler-Transformation haben wir ein Verfahren kennen gelernt, welches in Kombination mit z.b. der Move-To-Front-Kodierung und der Huffman-Kodierung eine schnelle und effiziente Kompression verschiedener Texte ermöglicht. Ist die Implementierung der Dekompressions-Transformation noch einfach zu bewerkstelligen, so muss man bei der Kompressions-Transformation ein besonderes Augenmerk darauf legen, die Sortierung der Zeilen effizient zu implementieren, da sonst die Laufzeit des Algorithmus stark anwachsen kann. Johann Hawe, WS 2010/11 9

Literatur [1] M. Burrows, D.J. Wheeler: A Block-Sorting Lossless Data Compression Algorithm, Digital SRC Research Report No. 124, 1994. [2] V. Heun: Grundlegende Algorithmen, Vieweg-Verlag, 2003, Abschnitt 6.5. [3] Burrows-Wheeler transform, http://en.wikipedia.org/wiki/bwt, vom 6.11.2010, letzter Besuch: 15.11.2010 [4] Mark Nelson: Data Compression with the Burrows-Wheeler-Transform, Dr. Dobb's Journal, online version, http://marknelson.us/1996/09/01/bwt/ vom 1.09.1996, letzter Besuch: 15.11.2010, Johann Hawe, WS 2010/11 10