finale Version des Vorlesungsskripts - ZIB
finale Version des Vorlesungsskripts - ZIB finale Version des Vorlesungsskripts - ZIB
4 Komplexitätstheorie und Speicherung von Graphen In diesem Kapitel führen wir einige der Grundbegriffe der Komplexitätstheorie ein, die für die algorithmische Graphentheorie und die kombinatorische Optimierung von Bedeutung sind. Wir behandeln insbesondere die Klassen P und N P und das Konzept der N P-Vollständigkeit. Die Darstellung erfolgt auf informellem Niveau. Gute Bücher zur Einführung in die Komplexitätstheorie sind Garey and Johnson (1979), Papadimitriou (1994) und Wegener (2003), weiterführende Aspekte werden unter anderem in Wagner and Wechsung (1986) und van Leeuwen (1990) behandelt. Shmoys and Tardos (1995) ist ein guter Übersichtsartikel. Einen detaillierten Überblick über Komplexitätsklassen gibt Johnson (1990), noch mehr Komplexitätsklassen findet man unter der URL: http://qwiki.caltech.edu/wiki/Complexity_Zoo. Komplexitätstheorie kann man nicht ohne Grundkenntnisse in Kodierungstechniken betreiben. Noch wichtiger aber sind Datenstrukturen beim Entwurf effizienter Algorithmen. Diesen Themenkreis streifen wir kurz in Abschnitt 4.3. Zur Vertiefung dieses Gebietes empfehlen wir Aho et al. (1974), Cormen et al. (2001), Mehlhorn (1984), Meinel (1991), Ottmann and Widmayer (2012) und Tarjan (1983). Ein Handbuch zu Datenstrukturen mit breiten Übersichtsartikeln ist Mehta and Sahni (2004). 4.1 Probleme, Komplexitätsmaße, Laufzeiten In der Mathematik (und nicht nur hier) kann das Wort „Problem“ sehr verschiedene Bedeutungen haben. Für unsere Zwecke benötigen wir eine (einigermaßen) präzise Definition. Ein Problem ist eine allgemeine Fragestellung, bei der mehrere Parameter offen gelassen sind und für die eine Lösung oder Antwort gesucht wird. Ein Problem ist dadurch definiert, dass alle seine Parameter beschrieben werden und dass genau angegeben wird, welche Eigenschaften eine Antwort (Lösung) haben soll. Sind alle Parameter eines Problems mit expliziten Daten belegt, dann spricht man im Englischen von einem „problem instance“. Im Deutschen hat sich hierfür bisher kein Standardbegriff ausgeprägt. Es sind u. a. die Wörter Einzelfall, Fallbeispiel, Problembeispiel, Probleminstanz oder Problemausprägung gebräuchlich. Ebenso wird auch das (allgemeine) Problem manchmal als Problemtyp oder Problemklasse bezeichnet. In diesem Skript werden wir keiner starren Regel folgen. Aus dem Kontext heraus dürfte i. a. klar sein, was gemeint ist. Das Travelling-Salesman-Problem ist in diesem Sinne ein Problem. Seine offenen Parameter sind die Anzahl der Städte und die Entfernungen zwischen diesen Städten. Eine 59
4 Komplexitätstheorie und Speicherung von Graphen Entfernungstabelle in einem Autoatlas definiert ein konkretes Beispiel für das Travelling- Salesman-Problem. Aus mathematischer Sicht kann man es sich einfach machen: Ein Problem ist die Menge aller Problembeispiele. Das Travelling-Salesman-Problem ist also die Menge aller TSP-Instanzen. Das ist natürlich nicht sonderlich tiefsinnig, vereinfacht aber die mathematische Notation. Wir sagen, dass ein Algorithmus Problem Π löst, wenn er für jedes Problembeispiel I ∈ Π eine Lösung findet. Das Ziel des Entwurfs von Algorithmen ist natürlich, möglichst „effiziente“ Verfahren zur Lösung von Problemen zu finden. Um dieses Ziel mit Inhalt zu füllen, müssen wir den Begriff „Effizienz“ meßbar machen. Mathematiker und Informatiker haben hierzu verschiedene Komplexitätsmaße definiert. Wir werden uns hier nur mit den beiden für uns wichtigsten Begriffen Zeit- und Speicherkomplexität beschäftigen. Hauptsächlich werden wir über Zeitkomplexität reden. Es ist trivial, dass die Laufzeit eines Algorithmus abhängt von der „Größe“ eines Problembeispiels, d. h. vom Umfang der Eingabedaten. Bevor wir also Laufzeitanalysen anstellen können, müssen wir beschreiben, wie wir unsere Problembeispiele darstellen, bzw. kodieren wollen. Allgemein kann man das durch die Angabe von Kodierungsschemata bewerkstelligen. Da wir uns jedoch ausschließlich mit Problemen beschäftigen, die mathematisch darstellbare Strukturen haben, reicht es für unsere Zwecke aus, Kodierungsvorschriften für die uns interessierenden Strukturen anzugeben. Natürlich gibt es für jede Struktur beliebig viele Kodierungsmöglichkeiten. Wir werden die geläufigsten benutzen und merken an, dass auf diesen oder dazu (in einem spezifizierbaren Sinn) äquivalenten Kodierungsvorschriften die gesamte derzeitige Komplexitätstheorie aufbaut. Ganze Zahlen kodieren wir binär. Die binäre Darstellung einer nicht-negativen ganzen Zahl n benötigt ⌈log2(|n|+1)⌉ Bits (oder Zellen). Hinzu kommt ein Bit für das Vorzeichen. Die Kodierungslänge 〈n〉 einer ganzen Zahl n ist die Anzahl der zu ihrer Darstellung notwendigen Bits, d. h. 〈n〉 := ⌈log2(|n| + 1)⌉ + 1. (4.1) Jede rationale Zahl r hat eine Darstellung r = p mit p, q ∈ Z, p und q teilerfremd und q > 0. Wir nehmen an, dass jede rationale Zahl so dargestellt ist, und können daher gegeben ist durch sagen, dass die Kodierungslänge von r = p q q 〈r〉 := 〈p〉 + 〈q〉. Wir werden im Weiteren auch sagen, dass wir eine ganze oder rationale Zahl r in einem Speicherplatz (oder Register) speichern, und wir gehen davon aus, dass der Speicherplatz für r die benötigten 〈r〉 Zellen besitzt. Die Kodierungslänge eines Vektors x = (x1, . . . , xn) T ∈ Q n ist 〈x〉 := n 〈xi〉, i=1 und die Kodierungslänge einer Matrix A ∈ Q (m,n) ist m n 〈A〉 := 〈aij〉. 60 i=1 j=1
- Seite 14 und 15: 1.2 Optimierungsprobleme Theorie al
- Seite 16 und 17: 2 Grundlagen und Notation 2.1 Graph
- Seite 18 und 19: 2.1 Graphen und Digraphen: Wichtige
- Seite 20 und 21: 2.1 Graphen und Digraphen: Wichtige
- Seite 22 und 23: (a) (c) 2.1 Graphen und Digraphen:
- Seite 24 und 25: 2.1 Graphen und Digraphen: Wichtige
- Seite 26 und 27: 2.2 Lineare Algebra uns auf Q oder
- Seite 28 und 29: und meinen damit, dass A die folgen
- Seite 30 und 31: 2.2 Lineare Algebra wie in der line
- Seite 32 und 33: 2.3 Polyeder und lineare Programme
- Seite 34 und 35: (2.4) Bemerkung. Die Lösungsmenge
- Seite 36 und 37: 2.3 Polyeder und lineare Programme
- Seite 38 und 39: 2.3 Polyeder und lineare Programme
- Seite 40 und 41: V. Chvátal. Linear Programming. Fr
- Seite 42 und 43: 3 Diskrete Optimierungsprobleme Die
- Seite 44 und 45: 3.2 Klassische Fragestellungen der
- Seite 46 und 47: (a) (b) 3.2 Klassische Fragestellun
- Seite 48 und 49: 3.3 Graphentheoretische Optimierung
- Seite 50 und 51: 3.3 Graphentheoretische Optimierung
- Seite 52 und 53: 3.3 Graphentheoretische Optimierung
- Seite 54 und 55: 3.3 Graphentheoretische Optimierung
- Seite 56 und 57: • Schaltkreisentwurf • Standort
- Seite 58 und 59: 3.3 Graphentheoretische Optimierung
- Seite 60 und 61: 3.3 Graphentheoretische Optimierung
- Seite 62 und 63: Literaturverzeichnis T. L. Gertzen
- Seite 66 und 67: 4.1 Probleme, Komplexitätsmaße, L
- Seite 68 und 69: 4.2 Die Klassen P und N P, N P-Voll
- Seite 70 und 71: 4.2 Die Klassen P und N P, N P-Voll
- Seite 72 und 73: 4.2 Die Klassen P und N P, N P-Voll
- Seite 74 und 75: 4 4.3 Datenstrukturen zur Speicheru
- Seite 76 und 77: 4.3 Datenstrukturen zur Speicherung
- Seite 78 und 79: 4.3 Datenstrukturen zur Speicherung
- Seite 80: R. E. Tarjan. Data structures and n
- Seite 83 und 84: 5 Bäume und Wege Der Beweis ist et
- Seite 85 und 86: 5 Bäume und Wege (2) =⇒ (3) Ist
- Seite 87 und 88: 5 Bäume und Wege Haben wir einen A
- Seite 89 und 90: 5 Bäume und Wege Falls T \ {ei} zu
- Seite 91 und 92: 5 Bäume und Wege /****************
- Seite 93 und 94: 5 Bäume und Wege THEN w[dope[i]+j]
- Seite 95 und 96: 5 Bäume und Wege Wie Beispiel (5.1
- Seite 97 und 98: 5 Bäume und Wege (a) F. Schiller.
- Seite 99 und 100: 5 Bäume und Wege DISTk(u) die Län
- Seite 101 und 102: 5 Bäume und Wege VOR(3) = 2. Wir s
- Seite 103 und 104: 5 Bäume und Wege 4. DO u = 1 TO v
- Seite 105 und 106: 5 Bäume und Wege Sei nun P ein kü
- Seite 107 und 108: 5 Bäume und Wege (b) D enthält ge
- Seite 109 und 110: 5 Bäume und Wege C2 C1 s 4 C3 C4 2
- Seite 111 und 112: 5 Bäume und Wege ders vorgehen: z.
- Seite 113 und 114: 5 Bäume und Wege ist ein System vo
4 Komplexitätstheorie und Speicherung von Graphen<br />
Entfernungstabelle in einem Autoatlas definiert ein konkretes Beispiel für das Travelling-<br />
Salesman-Problem.<br />
Aus mathematischer Sicht kann man es sich einfach machen: Ein Problem ist die<br />
Menge aller Problembeispiele. Das Travelling-Salesman-Problem ist also die Menge aller<br />
TSP-Instanzen. Das ist natürlich nicht sonderlich tiefsinnig, vereinfacht aber die mathematische<br />
Notation.<br />
Wir sagen, dass ein Algorithmus Problem Π löst, wenn er für je<strong>des</strong> Problembeispiel<br />
I ∈ Π eine Lösung findet. Das Ziel <strong>des</strong> Entwurfs von Algorithmen ist natürlich, möglichst<br />
„effiziente“ Verfahren zur Lösung von Problemen zu finden.<br />
Um dieses Ziel mit Inhalt zu füllen, müssen wir den Begriff „Effizienz“ meßbar machen.<br />
Mathematiker und Informatiker haben hierzu verschiedene Komplexitätsmaße definiert.<br />
Wir werden uns hier nur mit den beiden für uns wichtigsten Begriffen Zeit- und Speicherkomplexität<br />
beschäftigen. Hauptsächlich werden wir über Zeitkomplexität reden.<br />
Es ist trivial, dass die Laufzeit eines Algorithmus abhängt von der „Größe“ eines Problembeispiels,<br />
d. h. vom Umfang der Eingabedaten. Bevor wir also Laufzeitanalysen anstellen<br />
können, müssen wir beschreiben, wie wir unsere Problembeispiele darstellen, bzw.<br />
kodieren wollen. Allgemein kann man das durch die Angabe von Kodierungsschemata<br />
bewerkstelligen. Da wir uns jedoch ausschließlich mit Problemen beschäftigen, die mathematisch<br />
darstellbare Strukturen haben, reicht es für unsere Zwecke aus, Kodierungsvorschriften<br />
für die uns interessierenden Strukturen anzugeben. Natürlich gibt es für jede<br />
Struktur beliebig viele Kodierungsmöglichkeiten. Wir werden die geläufigsten benutzen<br />
und merken an, dass auf diesen oder dazu (in einem spezifizierbaren Sinn) äquivalenten<br />
Kodierungsvorschriften die gesamte derzeitige Komplexitätstheorie aufbaut.<br />
Ganze Zahlen kodieren wir binär. Die binäre Darstellung einer nicht-negativen ganzen<br />
Zahl n benötigt ⌈log2(|n|+1)⌉ Bits (oder Zellen). Hinzu kommt ein Bit für das Vorzeichen.<br />
Die Kodierungslänge 〈n〉 einer ganzen Zahl n ist die Anzahl der zu ihrer Darstellung<br />
notwendigen Bits, d. h.<br />
〈n〉 := ⌈log2(|n| + 1)⌉ + 1. (4.1)<br />
Jede rationale Zahl r hat eine Darstellung r = p<br />
mit p, q ∈ Z, p und q teilerfremd und<br />
q > 0. Wir nehmen an, dass jede rationale Zahl so dargestellt ist, und können daher<br />
gegeben ist durch<br />
sagen, dass die Kodierungslänge von r = p<br />
q<br />
q<br />
〈r〉 := 〈p〉 + 〈q〉.<br />
Wir werden im Weiteren auch sagen, dass wir eine ganze oder rationale Zahl r in einem<br />
Speicherplatz (oder Register) speichern, und wir gehen davon aus, dass der Speicherplatz<br />
für r die benötigten 〈r〉 Zellen besitzt.<br />
Die Kodierungslänge eines Vektors x = (x1, . . . , xn) T ∈ Q n ist<br />
〈x〉 :=<br />
n<br />
〈xi〉,<br />
i=1<br />
und die Kodierungslänge einer Matrix A ∈ Q (m,n) ist<br />
m n<br />
〈A〉 := 〈aij〉.<br />
60<br />
i=1 j=1