Kapitel 8: Graphalgorithmen 8.1 Grundlagen 8.2 Tiefen- und Breitensuche 8.3 Prim- und Kruskal-Algorithmus 8.4 Kürzeste Wege in Graphen 8.5 Eulersche und Hamiltonsche Graphen 1 Coding Information If we want to code n symbols with the same number of bits we have to use log2n bits. For example, A...Z, = 26 chars log2 26 = 5 For example A=00000 Z = 11001 (25) This means, for a message of m characters we need m*5 bits 2 A better way • Give to the more frequent letter a representation with less bits and for the not so frequent a representation with more • So the expected length of a message of m characters will be m*∑ P(ci)*length(ci) • The Morse code tries to do this E= . A= .- L= .-.. S= … 3 The codification tree 4 Code and decode • How to find the meaning of .- .-.. --. --- .-. .. - …. .. . -. A L G O R I T H M E N The problem is, we have to introduce a sepcial simbol to separate each coded character SOS and IAMS have the same codification if no special character is provided 5 Präfix codes • a code in which no simbol code is the prefix of another one 6 Huffmancode Gegeben: eine Quelle/ein Alphabet A. Präfixcode: Abbildung von A auf die Menge aller Binärwörter mit: kein Codewort (=Element der Bildmenge) ist Präfix eines anderen Codewortes. Ein Präfixcode kann durch einen Binärbaum dargestellt werden: die Codewörter entsprechen den Blättern und sind durch den Weg von der Wurzel zum jeweiligen Blatt gegeben: nach links = 0, nach rechts = 1. Ein Präfixcode ermöglicht eine eindeutige Decodierung. 7 Präfix code Baum 000100100111 ? 0 0 0 0 0 8 Jetzt: Quelle/Alphabet A mit Häufigkeitsverteilung, d.h. mit Funktion f:A [0,1] mit {a in A} f(a) = 1. Optimaler Präfixcode zu (A,f): Präfixcode zu A mit minimaler Durchschnittslänge der Codewörter: {a in A} f(a) l(a) = min! ( l(a):= die Länge des Codewortes für a). dafür: oft vorkommende Zeichen: kurze Codewörter, selten vorkommende Zeichen: längere Codewörter. 9 Buchstabenhäufigkeit a) alphabetisch sortiert ohne Leerzeichen b) nach Häufigkeit sortiert 10 Buchstabenhäufigkeit 2 11 Greedy-Algorithmus zur Erstellung eines optimalen Präfixcodes: Huffmancode Erzeuge für jedes Zeichen aus dem Alphabet (für jede Häufigkeit) einen Knoten. Starte mit den beiden Zeichen x und y mit den kleinsten Häufigkeiten f(x) und f(y), ersetze x und y durch ein neues Zeichen z mit der Häufigkeit f(z)=f(x)+f(y), erzeuge einen neuen Knoten für z und füge an diesen die beiden Knoten für x und y an. Wiederhole dies mit dem Alphabet A´ := A \ {x,y} U {z}. Iteriere dies, bis nur noch ein Zeichen (automatisch mit Häufigkeit =1) übrig ist. Der Binärbaum kann nun so angeordnet werden, dass die Häufigkeiten auf jeder Ebene von links nach rechts fallen 12 oder gleich bleiben. Konstruktion eines optimalen Präfixcodes zu: Alphabet a1 a2 a3 a4 a5 a6 Häufigkeit 0.5 0.2 0.1 0.1 0.06 0.04 13 Korrektheit des Verfahrens Erste Hilfsaussage: In jedem optimalen Präfixcodebaum mit mind. zwei Codewörtern gibt es zwei tiefste Blätter (= längste Codewörter), die Brüder sind. 14 Korrektheit des Verfahrens (2) Dann zeigt man: Seien x und y zwei Zeichen in A geringster Häufigkeit f(x) und f(y). Dann gibt es zu A einen optimalen Präfixcode, in dem x und y durch zwei gleich lange, längste Codewörter (=zwei tiefste Bruderblätter) codiert werden. Denn wenn x und y nicht in zwei solchen Blättern stehen, kann man sie mit den Zeichen dort vertauschen und dadurch ein besseres Ergebnis haben. 15 Korrektheit des Verfahrens (3) Dann zeigt man: Sei A´ := A \ {x,y} U {z} mit einem neuen Zeichen z mit Häufigkeit f(z) = f(x)+f(y). Man erhält durch Weglassen der Blätter x und y einen optimalen Präfix-Code zu A´. Insbesondere ist MCL(A) – MCL(A´) = f(x) + f(y). Dabei sei MCL(A) := mittlere Codewortlänge eines optimalen Präfixcodes zu A. 16 Optimalitätsbeweis Nun Beweis dafür, dass das Verfahren wirklich einen optimalen Präfixcode liefert: durch Induktion über die Zahl der Zeichen im Alphabet. Induktionsanfang: klar für Alphabet mit einem Zeichen. Induktionsschluss: Sei A ein Alphabet mit mindestens zwei Zeichen und A´ := A \ {x,y} U {z} wie oben. Nach Induktionsannahme liefert das Verfahren einen optimalen Präfixcode für A´. Anhängen zweier Blätter für x und y an z liefert einen Präfixcode für A, dessen mittlere Codewortlänge nur um f(x) + f(y) größer ist. Also ist es ein optimaler Präfixcode für A. 17 Anwendungen Anwendungsbereiche der Huffmankodierung: z.B. • Textkompression, • Bildkompression, z.B. in JPEG. • Faxkodierung, CCITT Standard 18 8.4 Kürzeste Wege in Graphen „Single source shortest path problem“ Gegeben: • Gerichteter, gewichteter (alle Gewichte 0) Graph, • Ein Knoten („Quelle“, „Startknoten“) v0 in dem Graphen. Gesucht: kürzeste Wege von v0 zu allen anderen Knoten (sofern es überhaupt jeweils einen Weg gibt). 19 Dijkstra-Algorithmus Algorithmus Dijkstra (v0,G) // vereinfacht: berechnet Länge der kürzesten Wege in G von v0 aus für alle u { dist(u) := maxint }; gruen :=leer; gelb:= {v0}; dist(v0):=0; While gelb != leer do { wähle w aus gelb, so dass dist(w) minimal; färbe w grün; für jedes u aus succ(w) do { falls u aus V\(gruen oder gelb) { färbe u gelb; dist(u):= dist(w)+ cost(w,u);} falls u aus gelb { wenn dist (u) > dist(w)+cost(w,u) dann dist(u):=dist(w)+cost(w,u) } } } end; 20 Beispiel C D 40 30 40 10 A B 30 10 100 90 F E 20 Kürzester Wegebaum von A gesucht 21 Beschreibung: Idee: Lasse Teilbaum mit bereits ermittelten kürzesten Wegen wachsen. Grüne Knoten: die Knoten, deren Nachfolger schon betrachtet wurden. = die Knoten, zu denen schon ein kürzester Weg ermittelt ist. Gelbe Knoten: die Nachfolger von grünen Knoten, die nicht selbst grün sind. Rote Kanten: Kanten, die auf mindestens einem zur Zeit optimal erscheinenden Weg liegen. Gelbe Kanten: Kanten, die als nicht optimal erkannt wurden. 22 Schleife Eine Schleife des Algorithmus: • Färbe den v0 nächsten gelben Knoten w grün. • Färbe alle seine ungefärbten Nachfolger gelb. • Trage ein/korrigiere die kürzesten Wege von v0 zu jedem der Nachfolger von w, ebenso ihre jeweilige Länge (dadurch werden ungefärbte Kanten evtl. rot, und rote Kanten evtl. gelb). Korrektheit: siehe vereinfachter Algorithmus. 23 Beispiel (2) C D C D 30 A B A 100 B 100 90 E 40 10 30 F 90 E F 24 Beispiel (3) C 40 40 D 40 10 C 40 30 D 40 10 30 A B A B 10 100 10 100 90 E 40 F 90 F E 50 20 25 Beispiel (4) C 40 D C 40 D 70 40 70 40 10 40 30 30 A 30 30 B B 30 A 10 100 40 10 10 100 90 90 F E 50 20 70 F E 20 70 26 50 Computing „on the paper“ Gegeben sei der folgende bewertete ungerichtete Graph A, bei dem bereits ein minimaler Spannbaum in roten Kanten ausgegeben ist. A 5 B 7 5 6 D 2 F 3 2 E 4 3 1 2 5 C 3 G 27 Computing „on the paper“ A 5 B 7 5 6 D 2 F 2 2 E 3 1 G 3 4 3 Wir wollen in einer Array-Implementation den kürzesten Wegebaum von A aus berechnen. Hier werden die Entfernungen von A in die erste Zeile eingetragen. Sodann wird das Minimum 5 gewählt. Dieser Abstand und der neue Punkt B werden in die zweite Zeile eingetragen, die Abstände upgedatet. Sodann wählen wir das nächste Minimum in der Tabelle mit 6 und den zugehörigen Punkt D. Auch jetzt werden die Abstände angepasst. In der ersten Spalte stehen die Abstände im Nächste-Wege-Baum von A. 28 5 C 8.4.2 Implementierung des Algorithmus a) Implementierung mit einer Adjazenzmatrix Sei V={1,...,n} und sei cost(i,j) die Kostenmatrix mit Einträgen unendlich in Elementen, in denen keine Kante vorhanden ist. Man benutzt dann: Type node = 1..n; var dist : array[node] of real; var father: array[node] of node; var grün: array [node] of boolean; Der Array father stellt den Baum der roten Kanten dar, in dem zu jedem Knoten sein Vaterknoten festgehalten wird. Die gelben Knoten werden nicht explizit dargestellt. 29 Jeder Schleifendurchlauf besteht dann aus folgenden Teilschritten: • Der gesamte Array dist wird durchlaufen, um den gelben Knoten w mit minimalem Abstand zu finden. Aufwand: O(n). • Die Zeile cost(w,*) der Matrix wird durchlaufen, um für alle Nachfolger von w ggf. den Abstand (dist) und den Vater (father) zu korrigieren. Aufwand: O(n). Gesamtaufwand: O(n²), da n Schleifendurchläufe. Ineffizient, außer wenn n sehr klein oder e nahe n² ! 30 b) Implementierung mit Adjazenzlisten und Heap Graph: gegeben durch durch Adjazenzliste mit Kosteneinträgen. Wie eben: • Array dist • Array father Außerdem: • Heap (als Array implementiert) aller gelben Knoten, geordnet nach Abstand vom Ausgangsknoten, • Array heapaddress, der für jeden gelben Knoten die Heapposition enthält. 31 Schleifendurchlauf Jeder Schleifendurchlauf besteht dann aus folgenden Teilschritten: 1. Entnimm den gelben Knoten w mit minimalem Abstand aus dem Heap Aufwand: O(log n). 2. Finde in der Adjazenzliste die m(w) Nachfolger von w. Aufwand: O(m(w)). (i) Für jeden ,,neuen" gelben Nachfolger erzeuge einen Eintrag im Heap (ii) Für jeden ,,alten" gelben Nachfolger korrigiere ggf. seinen Eintrag im Heap. Seine Position dort ist über heapaddress zu finden. Da sein Abstandswert bei der Korrektur sinkt, kann der Eintrag im Heap ein Stück nach oben wandern. Die Heap-Adressen der vertauschten Einträge können in O(1) Zeit geändert werden. Aufwand für (i) und (ii): insgesamt O(m(w) log n). Aufwand für (2) insges.: O( log n • {Knoten w} m(w)) = O( e log n). Aufwand für (1) insges.: O(min{n,e} log n), da ein Element nur aus dem Heap entnommen werden kann, wenn es vorher eingefügt wurde. Gesamtaufwand: O(e log n) (Gesamter Platzbedarf: O(n+e)) 32 Korrektheitsnachweis: Behauptung: zu jedem Zeitpunkt gilt für jeden grünen Knoten u: • Es gibt einen kürzesten Weg von v0 nach u, der nur grüne Knoten enthält. • Seine Länge ist dist(u). Beweis: durch Induktion. Man muss die Behauptung jeweils für den Knoten zeigen, der von gelb nach grün umgefärbt wird. Aus dieser Behauptung folgt die Korrektheit des Algorithmus. 33 Lempel-Ziv codification • In the Huffmann codification mechanism it is necessary to first build the frequency table and after that is the coding possible • Two times passing over all the data • Lempel-Ziv allows the construction AND codification at the same time, in just one pass • It also allows to code sequences of characters that appear frequently 34 Principles of Lempel-Ziv • Lets take for example the following text: aaabbaabaa we can obtain greater efficiency if we consider also encoding the aa sequence beside encoding a and b alone. • A generalization of this idea is the Lempel-Ziv algorithm. This algorithm separates the input string into blocks or strings of various lengths, maintaining a dictionary of blocks already seen. • Applying the Huffman algorithm for these blocks and their probabilities, we can take advantage of the sequences that appear more frequently in the text. 35 The encoding algoritm 1 .- Initialize the dictionary with all blocks of length 1 (the basic alphabet) (for example, if the messages uses the common alphabet a=1, b=2 … z=26) 2 .- Select the longest prefix of the message that matches a sequence W in the dictionary and delete the message W 3 .- Encode W with its index in the dictionary 4 .- Add W followed by the first next symbol to the dictionary. 5 .- Repeat from step 2. 36 Example For the message : abbaabbaababbaaaabaabba We start with the dictionary having a-1 and b-2 We will have following process : (x-n) = recognized block x and its codification n X-n = entry added to the dictionary (a-1)ab-3 (b-2)bb-4 (b-2)ba-5 (a-1)aa-6 (ab-3)abb-7 (ba-5)baa-8 (ab-3)aba-9 (abb-7)abba-10(aa-6)aaa-11 (aa-6)aab-12 (baa-8)baab-13 (bb-4)bba-14 (a) 37 8.5 Eulersche und Hamiltonsche Graphen Ein zusammenhängender Graph G=(V,E) mit |E| 0 heißt Eulerscher Graph, wenn es einen geschlossenen Kantenzug gibt, der jede Kante von G einmal enthält; ein solcher Kantenzug heißt geschlossener Eulerscher Kantenzug oder Eulertour. Satz: Ein zusammenhängender Graph G mit |E| 0 ist genau dann eulersch, wenn der Grad jeder Ecke gerade ist. 38 Beweis des Satzes: Erste Richtung: Besitzt der Graph eine Eulertour, so wird jede Ecke bei einem Durchlauf von einer ankommenden und einer ausgehenden Kante getroffen. Alle diese Kanten sind verschieden, und damit ist der Eckengrad in jeder Ecke gerade. Umgekehrte Richtung: (der Grad jeder E ist gerade) Laufe von einer Ecke los, bis eine Ecke zum zweiten Mal erreicht wird. Dann eliminiere diesen Zyklus (d.h. seine Kanten). Man erhält einen oder mehr kleinere zusammenhängende Graphen mit geradem Eckengrad in jeder Ecke. Nach Induktionsannahme haben diese je eine Eulertour. Aus diesen kann mit dem eliminierten Zyklus eine GesamtEulertour konstruiert werden (verklebe die einzelnen Zyklen in gemeinsamen Ecken). 39 Beispiel: Königsberger Brückenproblem: gibt es einen Rundweg, der genau einmal über jede Brücke führt? 40 Hamiltonkreisproblem Ein zusammenhängender Graph G = (V,E) heißt Hamiltonscher Graph, wenn es einen geschlossenen Weg gibt, der durch jede Ecke von G führt. Ein derartiger Weg heißt Hamiltonkreis. 8.5.2 Satz (Ore 1960) Sei G = (V, E) ein Graph ohne Schlingen und Mehrfachkanten mit |V| >2. Gilt für die Eckengrade g aller nicht adjazenten Ecken a und b die Ungleichung g(a) + g(b) > |V| -1, so ist G hamiltonscher Graph. 41 Problem: Gegeben: • ein gewichteter Graph und • eine Zahl L >0. Frage: gibt es einen Hamiltonkreis mit Gesamtlänge L ? Mögliche Lösungsstrategie: alle Wege ausprobieren (Backtracking) exponentieller Aufwand. Ein deterministischer Algorithmus, der das Problem in besserer als exponentieller Zeit löst, ist nicht bekannt! Dieses Problem ist NP-vollständig! 42 Jetzt: Möglichst kurzen Hamiltonkreis berechnen. Annahmen: • Der Graph ist vollständig: alle knoten direkt verbunden • Die Kantenbewertung erfüllt die Dreiecksungleichung. Selbst dann: Greedy-Verfahren (wähle billigste nächste Kante) liefert nicht immer eine optimale Lösung. Der von dem Greedy-Verfahren produzierte Hamiltonkreis kann sogar um einen Faktor log(|V|) von einer optimalen Lösung entfernt sein! 43 Bessere Strategien Bessere Strategie (unter den obigen Annahmen): • Ermittle zunächst einen minimalen Spannbaum. • Durch Duplizieren der Kanten erhält man eine Eulertour. Dabei werden die Doppel-Kanten im Baum einmal, jeder Knoten jedoch zweimal durchlaufen. • Aus dieser Tour kann man jedoch einen Hamiltonkreis konstruieren, indem man im Kurzschlussverfahren zur nächsten noch nicht benutzten Ecke springt, bzw. falls es keine mehr gibt, zum Ausgangspunkt. Dann ist der konstruierte Hamiltonkreis höchstens doppelt so lang wie ein kürzester Hamiltonkreis. 44 Beispiel: In diesem Beispiel ist der Spannbaum durch die fetten Kanten gegeben. Wir duplizieren sie, starten im unteren rechten Knoten D und durchlaufen die Kanten 2 nach C , 1 nach F, 1 nach B, 2 nach E, überspringen den Rückweg nach B und wählen die gestrichelte Kante 2 nach A, schließen dann mit der gestrichelten Kante 3 ab zum Anfangsknoten D mit Gesamtgewicht des Kreises 11. 45 8.6 Bipartite Graphen, Heiratssatz Definition Bipartite Graphen Sei G = (V, E) ein Graph ohne Schlingen. Existiert eine Zerlegung der Ecken in zwei nichtleere disjunkte Teilmengen V1 und V2, so dass für beliebige a und b aus Vi dann a und b nicht adjazent sind, so heißt G bipartiter Graph mit der Zerlegung (V1, V2). Ist G zusätzlich ohne Doppelkanten und sind alle Ecken a und b aus verschiedenen Teilmengen adjazent, so heißt G vollständig bipartit. 46 Heiratssatz (König, Hall) Genau dann gibt es für einen bipartiten Graph G mit der Zerlegung V1 , V2 eine Menge von Verbindungskanten von allen Elementen aus V1 nach V2, wenn für alle Teilmengen V ' aus V1 die Kardinalzahl |N(V ')| der Menge der Nachbarn N(V ') nicht kleiner ist als |V '|. Jedes Element aus V1 findet somit einen Partner aus V2. 47 Exkurs: Das P-NP-Problem Entscheidungsprobleme: algorithmische Probleme mit einer Ja/Nein-Antwort. Sei f: N N eine Zahlenfunktion. TIME(f) := {jedes Entscheidungsproblem derart, dass es einen Algorithmus gibt, der bei einer Eingabe der Größe n die Antwort in höchstens f(n) Schritten berechnet.} P := {p Polynom} TIME(p) (P enthält die „(deterministisch) in Polynomzeit lösbaren Probleme“). 48 Klasse NP Sei f: N N eine Zahlenfunktion. NTIME(f) := {jedes Entscheidungsproblem derart, dass es einen „ratenden“ Algorithmus gibt, der bei einer Eingabe der Größe n die Antwort in höchstens f(n) Schritten berechnet.} NP := {p Polynom} NTIME(p) (NP enthält die „nichtdeterministisch in Polynomzeit lösbaren Probleme“). 49 NP-Klasse Erläuterung Eine „ratender“ Algorithmus darf während der Berechnung etwas „raten“, z.B. ein Binärwort, und zur weiteren Berechnung verwenden. Er „löst“ ein Entscheidungsproblem, wenn er • durch Raten zur Antwort JA gelangen kann, wenn JA stimmt, und • bei jedem Raten zur Antwort NEIN gelangt, wenn NEIN stimmt. 50 Problem des Handlungsreisenden (Traveling Salesman): Gegeben: • ein gewichteter Graph und • eine Zahl L >0. Frage: gibt es einen Hamiltonkreis mit Gesamtlänge L ? Mögliche Lösungsstrategie: alle Wege ausprobieren (Backtracking) -> exponentieller Aufwand. Ein deterministischer Algorithmus, der das Problem in besserer als exponentieller Zeit löst, ist nicht bekannt! Also offene Frage: ist das Problem des Handlungsreisenden in P? 51 Handlungsreisenden-Problem Das Problem des Handlungsreisenden ist in NP: Ein ratender, in Polynomzeit arbeitender Algorithmus für das Problem ist z.B: 1. Rate eine Reiseroute. 2. Prüfe, ob sie jede Stadt genau einmal enthält und nicht länger als die Schranke L ist. 52 P-NP-Problem Klar: P ist eine Teilmenge von NP. Das P-NP-Problem: ist P eine echte Teilmenge von NP oder sind P und NP gleich? Siehe dazu: http://www.claymath.org/millennium 53 Reduktion eines Problems auf eine anderes Problem Seien P1 und P2 zwei Entscheidungsprobleme. Dann ist P1 polynomiell auf P2 reduzierbar, wenn es eine in Polynomzeit berechenbare Funktion f: {Eingaben für P1} {Eingaben für P2} gibt mit P1(w) =JA P2(w) = JA für alle Eingaben w für P1. 54 NP-vollständig Ein Entscheidungsproblem P2 heißt NPvollständig, wenn 1. es in NP ist, und 2. jedes Problem P1 in NP auf P2 polynomiell reduzierbar ist. . Beispiel: das Problem des Handlungsreisenden ist NP-vollständig. 55 Bedeutung der NP-vollständigen Probleme Sei P1 ein beliebiges NP-vollständiges Problem. Dann ist: P = NP P1 ist in P. 56 NP-vollständige Probleme 57 Auszug: Schöning Theoretische Informatik 58