Effiziente Algorithmen Lösen NP-vollständiger Probleme Abschätzung der Suchbaumgröße Der Schätzwert für die Suchbaumgröße war 3529. Lassen wir das Programm laufen, ergibt sich, daß 1830 gültige Positionen getestet werden. Insgesamt gibt es 92 Lösungen. 263 Effiziente Algorithmen Lösen NP-vollständiger Probleme Folgendes Programm schätzt die Suchbaumgröße automatisch: #includehstdio.hi #includehstdlib.hi #define N 8 int c[N ], d1 [2 ∗ N − 1], d2 [2 ∗ N − 1], t[N ]; int main(void) { int k = 0, i, z , r = 1, m = 1; while(1) { z = 0; for(i = 0; i < N ; i++) if (!c[i] && !d1 [k − i + N − 1] && !d2 [i + k ]) t[z ] = i, z ++; if (z == 0) break; m += r ∗= z ; i = t[random()%z ]; printf ("%2d %2d %d\n", i, z , m); c[i] = d1 [k − i + N − 1] = d2 [i + k ] = 1; k ++; } return 0; } 264 Effiziente Algorithmen Lösen NP-vollständiger Probleme Lassen wir dieses Programm laufen, ergibt sich folgende Ausgabe: 5 7 4 6 3 8 5 4 3 2 9 49 209 689 1649 Die mit Hand geschätzte Zahl war 1609 und die tatsächliche Suchbaumgröße 1830. 265 Effiziente Algorithmen Lösen NP-vollständiger Probleme 0Z0Z0L0Z 7 Z0Z0Z0ZQ 6 0Z0ZQZ0Z 5 Z0Z0Z0L0 4 0Z0L0Z0Z 3 Z0Z0Z0Z0 2 0Z0Z0Z0Z 1 Z0Z0Z0Z0 8 a b c d e f g h Dies ist die geratene Belegung des Programms. 266 Effiziente Algorithmen Lösen NP-vollständiger Probleme Für N = 16 ergibt sich diese Ausgabe: 13 1 10 4 15 0 12 9 6 8 14 16 13 10 10 7 5 7 3 3 3 1 17 225 2305 23105 168705 896705 5992705 21280705 67144705 204736705 342328705 267 Effiziente Algorithmen Lösung für N = 80: Lösen NP-vollständiger Probleme 268 Effiziente Algorithmen Lösen NP-vollständiger Probleme Erfüllbarkeitsproblem Die Lösung für N = 80 kann nicht mehr durch den normalen Backtracking-Algorithmus gefunden werden. Sie wurde tatsächlich durch Lösung eines Erfüllbarkeitsproblem gefunden. Die zugehörige Formel hat für jedes Feld eine Variable. Es gibt Klauseln die sicherstellen, daß jede Zeile mindestens eine Dame enthält. Es gibt Klauseln die verhindern, daß eine Spalte, Zeile oder Diagonale mehr als eine Dame enthält. 269 Effiziente Algorithmen Lösen NP-vollständiger Probleme 270 Erfüllbarkeitsproblem Diese Formel sieht so aus: n n ^ n n _ ^ ^ xij ∧ (¬xij ∨ ¬xkj )∧ i=1 j=1 i,j=1 k=i+1 n ^ (¬xij ∨ ¬xik )∧ k=j+1 min{n−i,n−j} ^ (¬xij ∨ ¬xi+k,j+k )∧ k=1 min{n−i,j−1} ^ (¬xij ∨ ¬xi+k,j−k ) k=1 Diese Formel ist in konjunktiver Normalform. Effiziente Algorithmen Lösen NP-vollständiger Probleme Literatur Dieses Buch behandelt eher die mathematische Theorie der Linearen und Ganzzahligen Programmierung und ist geeignet, sich in dieses Gebiet genauer einzuarbeiten. Alexander Schrijver: Theory of Linear and Integer Programming. John Wiley & Sons. Preis: US $60.90, Paperback. 271 Effiziente Algorithmen Lösen NP-vollständiger Probleme Literatur Dieses Buch ist anders aufgebaut als die meisten Algorithmenbücher. Es ist nach Lösungstechniken gegliedert. Insbesondere enthält es viel Information über das Lösen von NP -vollständigen Problemen. Horowitz, Sahni, Rajasekaran: Computer Algorithms. Computer Science Press. Preis: US $79.95, Hardcover (oder Rs 279 als Indian Edition). 272 Effiziente Algorithmen Lösen NP-vollständiger Probleme Branch-and-Bound Wir betrachten allgemein Probleme, deren Suchraum durch Bäume dargestellt werden kann. Innerhalb des Suchraums suchen wir 1. nach einer Lösung oder 2. nach einer Lösung mit minimalen Kosten. Beispiel: Beim N -Damen-Problem wird nach einer Lösung gesucht. Beispiel: Beim Problem des Handlungsreisenden wird nach der kürzesten Rundreise durch gegebene Orte gesucht. 273 Effiziente Algorithmen Lösen NP-vollständiger Probleme Branch-and-Bound Die Klasse der Branch-and-Bound-Algorithmen, die wir jetzt betrachten, haben folgendes gemeinsam: • Es gibt stets eine Menge von lebendigen Knoten des Suchraums, unter deren Unterbäumen noch nach Lösungen gesucht wird. • Zu Beginn ist genau die Wurzel lebendig. • Es wird stets ein lebendiger Knoten, der E-Knoten ausgesucht, und durch all seine Kinder zu den lebendigen Knoten hinzugefügt. • Lebendige Knoten können durch bounding functions entfernt werden. • Die lebendigen Knoten werden in einer geeigneten Datenstruktur gehalten. • Zur Auswahl des E-Knotens gibt es verschiedene Strategien. 274 Effiziente Algorithmen Lösen NP-vollständiger Probleme Branch-and-Bound Werden die lebendigen Knoten mit einer Warteschlange (FIFO-queue) implementiert, dann entspricht dies einer Breitensuche. Verwenden wir für die lebendigen Knoten dagegen einen Keller (LIFO-queue, stack), dann erhalten wir im wesentlichen eine Tiefensuche. Allgemeiner können wir jedem Knoten x einen Wert ĉ(x) zuordnen und als E-Knoten das lebendige x mit kleinstem ĉ(x) wählen. Diese Variante wird least-cost-search (LC-search) genannt. 275 Effiziente Algorithmen Lösen NP-vollständiger Probleme Terminierung Falls der Suchbaum endlich ist, dann terminieren alle Branch-and-Bound-Verfahren. Falls der Suchbaum unendlich ist, aber eine Lösung enthält, dann terminiert die Breitensuche. Die Tiefensuche muß nicht terminieren! Bei LC-Suche kommt es auf die Funktion ĉ(x) an. Wenn man den Aufwand x zu erreichen mit einbezieht, kann man Terminierung garantieren. 276 Effiziente Algorithmen Lösen NP-vollständiger Probleme Beispiel 277 Effiziente Algorithmen Lösen NP-vollständiger Probleme Beispiel: DFS 51 50 45 44 41 40 139 141 142 143 151 150 152 153 154 52 49 46 43 42 39 53 48 47 137 138 122 37 54 55 60 61 123 121 120 131 117 33 149 136 56 59 62 124 125 119 118 116 32 135 57 58 63 127 126 132 110 111 112 30 134 69 68 64 128 129 130 109 114 113 29 133 70 67 65 98 99 100 108 104 115 28 38 140 36 144 145 146 35 34 148 147 31 72 71 77 66 97 96 101 102 103 107 27 73 75 76 78 79 95 94 93 105 106 26 25 81 80 82 83 87 88 19 20 23 24 5 6 84 85 86 89 18 21 22 7 8 92 91 90 17 16 9 10 11 12 13 14 74 4 2 1 3 15 158 159 161 163 164 155 156 157 160 162 278 Effiziente Algorithmen Lösen NP-vollständiger Probleme 279 Beispiel: BFS 77 73 59 57 53 50 47 52 56 58 71 68 72 76 80 91 88 90 94 96 100 81 69 61 55 51 48 46 49 62 60 63 65 75 78 82 84 86 93 97 99 83 66 64 45 44 43 42 70 67 79 85 87 41 74 40 39 89 98 92 95 54 37 36 38 35 34 5 7 4 6 8 2 3 18 9 10 1 17 15 13 11 12 14 16 33 32 31 26 27 30 25 28 29 23 21 24 19 20 22 Effiziente Algorithmen Lösen NP-vollständiger Probleme 280 Beispiel: LC 42 44 41 43 40 39 45 46 47 38 50 48 49 37 36 35 33 32 31 34 30 29 5 4 2 1 3 6 7 8 9 10 11 12 13 28 27 26 21 22 25 20 23 24 19 16 17 14 15 18 51 52 53 54 57 55 56 58 59 60 61 Effiziente Algorithmen Lösen NP-vollständiger Probleme Beispiel 281 Effiziente Algorithmen Lösen NP-vollständiger Probleme Beispiel: DFS 282 Effiziente Algorithmen Lösen NP-vollständiger Probleme Beispiel: BFS 283 Effiziente Algorithmen Lösen NP-vollständiger Probleme Beispiel: LC 284