495 19. Dynamic Programming I Fibonacci, Längste aufsteigende Teilfolge, längste gemeinsame Teilfolge, Editierdistanz, Matrixkettenmultiplikation, Matrixmultiplikation nach Strassen [Ottman/Widmayer, Kap. 1.2.3, 7.1, 7.4, Cormen et al, Kap. 15]
Fibonacci Zahlen 496 (schon wieder) F n := { 1 wenn n < 2 F n 1 + F n 2 wenn n 3. Analyse: warum ist der rekursive Algorithmus so langsam.
Algorithmus FibonacciRecursive(n) 497 Input : n 0 Output : n-te Fibonacci Zahl if n 2 then f 1 else f FibonacciRecursive(n 1) + FibonacciRecursive(n 2) return f
Analyse 498 T (n): Anzahl der ausgeführten Operationen. n = 1, 2: T (n) = Θ(1) n 3: T (n) = T (n 2) + T (n 1) + c. T (n) = T (n 2) + T (n 1) + c 2T (n 2) + c 2 n/2 c = ( 2) n c Algorithmus ist exponentiell (!) in n.
Grund, visualisiert 499 F 47 F 46 F 45 F 45 F 44 F 44 F 43 F 44 F 43 F 43 F 42 F 43 F 42 F 42 F 41 Knoten mit denselben Werten werden oft ausgewertet.
500 Memoization Memoization (sic) Abspeichern von Zwischenergebnissen. Bevor ein Teilproblem gelöst wird, wird Existenz eines entsprechenden Zwischenergebnis geprüft. Existiert ein gespeichertes Zwischenergebnis bereits, so wird dieses verwendet. Andernfalls wird der Algorithmus ausgeführt und das Ergebnis wird entsprechend gespeichert.
Memoization bei Fibonacci 501 F 47 F 46 F 45 F 45 F 44 F 44 F 43 Rechteckige Knoten wurden bereits ausgewertet.
Algorithmus FibonacciMemoization(n) 502 Input : n 0 Output : n-te Fibonacci Zahl if n 2 then f 1 else if memo[n] then f memo[n] else f FibonacciMemoization(n 1) + FibonacciMemoization(n 2) memo[n] f return f
Analyse Berechnungsaufwand: T (n) = T (n 1) + c =... = O(n). Algorithmus benötigt Θ(n) Speicher. 24 24 Allerdings benötigt der naive Algorithmus auch Θ(n) Speicher für die Rekursionsverwaltung. 503
Genauer hingesehen... 504... berechnet der Algorithmus der Reihe nach die Werte F 1, F 2, F 3,... verkleidet im Top-Down Ansatz der Rekursion. Kann den Algorithmus auch gleich Bottom-Up hinschreiben. Man spricht dann auch von dynamischer Programmierung.
505 Algorithmus FibonacciDynamicProgram(n) Input : n 0 Output : n-te Fibonacci Zahl F [1] 1 F [2] 1 for i 3,..., n do F [i] F [i 1] + F [i 2] return F [n]
506 Dynamic Programming: Vorgehen 1 Verwalte DP-Tabelle mit Information zu den Teilproblemen. Dimension der Tabelle? Bedeutung der Einträge? 2 Berechnung der Randfälle. Welche Einträge hängen nicht von anderen ab? 3 Berechnungsreihenfolge bestimen. In welcher Reihenfolge können Einträge berechnet werden, so dass benötigte Einträge jeweils vorhanden sind? 4 Auslesen der Lösung. Wie kann sich Lösung aus der Tabelle konstruieren lassen? Laufzeit (typisch) = Anzahl Einträge der Tabelle mal Aufwand pro Eintrag.
507 Dynamic Programming: Vorgehen am Beispiel 1 Dimension der Tabelle? Bedeutung der Einträge? Tabelle der Grösse n 1. n-ter Eintrag enthält n-te Fibonacci Zahl. 2 Welche Einträge hängen nicht von anderen ab? Werte F 1 und F 2 sind unabhängig einfach berechenbar. 3 In welcher Reihenfolge können Einträge berechnet werden, so dass benötigte Einträge jeweils vorhanden sind? F i mit aufsteigenden i. 4 Wie kann sich Lösung aus der Tabelle konstruieren lassen? F n ist die n-te Fibonacci-Zahl.
Längste aufsteigende Teilfolge (LAT) 508 1 2 3 4 5 6 7 1 2 3 4 5 6 7 3 2 4 6 5 7 1 3 2 4 6 5 7 1 Verbinde so viele passende Anschlüsse wie möglich, ohne dass sich die Anschlüsse kreuzen.
509 Formalisieren Betrachte Folge A = (a 1,..., a n ). Suche eine längste aufsteigende Teilfolge von A. Beispiele aufsteigender Teilfolgen: (3, 4, 5), (2, 4, 5, 7), (3, 4, 5, 7), (3, 7). A 1 2 3 4 5 6 7 3 2 4 6 5 7 1 Verallgemeinerung: Lasse Zahlen ausserhalb von 1,..., n zu, auch mit Mehrfacheinträgen. Lasse nur strikt aufsteigende Teilfolgen zu. Beispiel: (2,3,3,3,5,1) mit aufsteigender Teilfolge (2,3,5).
510 Erster Entwurf Annahme: LAT L k für k bekannt. Wollen nun LAT L k+1 für k + 1 berechnen. Wenn a k+1 zu L k passt, dann L k+1 = L k a k+1 Gegenbeispiel: A 5 = (1, 2, 5, 3, 4). Sei A 3 = (1, 2, 5) mit L 3 = A. Bestimme L 4 aus L 3? So kommen wir nicht weiter: können nicht von L k auf L k+1 schliessen.
Zweiter Entwurf 511 Annahme: eine LAT L j für alle j k bekannt. Wollen nun LAT L k+1 für k + 1 berechnen. Betrachte alle passenden L k+1 = L j a k+1 (j k) und wähle eine längste solche Folge. Gegenbeispiel: A 5 = (1, 2, 5, 3, 4). Sei A 4 = (1, 2, 5, 3) mit L 1 = (1), L 2 = (1, 2), L 3 = (1, 2, 5), L 4 = (1, 2, 5). Bestimme L 5 aus L 1,..., L 4? So kommen wir nicht weiter: können nicht von jeweils nur einer beliebigen Lösung L j auf L k+1 schliessen. Wir müssten alle möglichen LAT betrachten. Zu viel!
Dritter Entwurf Annahme: die LAT L j, welche mit kleinstem Element endet sei für alle Längen 1 j k bekannt. Betrachte nun alle passenden L j a k+1 (j k) und aktualisiere die Tabelle der längsten aufsteigenden Folgen, welche mit kleinstem Element enden. Beispiel: A = (1, 1000, 1001, 2, 3, 4,..., 999) A LAT (1) (1) (1, 1000) (1), (1, 1000) (1, 1000, 1001) (1), (1, 1000), (1, 1000, 1001) (1, 1000, 1001, 2) (1), (1, 2), (1, 1000, 1001) (1, 1000, 1001, 2, 3) (1), (1, 2), (1, 2, 3) 512
513 DP Table Idee: speichere jeweils nur das letzte Element der aufsteigenden Folge am Slot j. Beispielfolge: 3 2 5 1 6 4 Problem: Tabelle enthält zum Schluss nicht die Folge, nur den letzten Wert. Lösung: Zweite Tabelle mit den Vorgängern. Index 1 2 3 4 5 6 Wert 3 2 5 1 6 4 Vorgänger 2 5 1 0 1 2 3 4... - - 3-2 - 2 5-1 5-1 5 6-1 4 6
514 Dynamic Programming Algorithmus LAT 1 Dimension der Tabelle? Bedeutung der Einträge? Zwei Tabellen T [0,..., n] und V [1,..., n]. Zu Beginn T [0], T [i] i > 1 2 Berechnung eines Eintrags Einträge in T aufsteigend sortiert. Für jeden Neueintrag a k+1 binäre Suche nach l, so dass T [l] < a k < T [l + 1]. Setze T [l + 1] a k+1. Setze V [k] = T [l].
515 Dynamic Programming Algorithmus LAT 3 Berechnungsreihenfolge Beim Traversieren der Liste werden die Einträge T [k] und V [k] mit aufsteigendem k berechnet. 4 Wie kann sich Lösung aus der Tabelle konstruieren lassen? Suche das grösste l mit T [l] <. l ist der letzte Index der LAT. Suche von l ausgehend den Index i < l, so dass V [l] = A[i], i ist der Vorgänger von l. Repetiere mit l i bis T [l] =
Analyse 516 Berechnung Tabelle: Initialisierung: Θ(n) Operationen Berechnung k-ter Eintrag: Binäre Suche auf Positionen {1,..., k} plus konstante Anzahl Zuweisungen. n (log k + O(1)) = O(n) + k=1 n log(k) = Θ(n log n). k=1 Rekonstruktion: Traversiere A von rechts nach links: O(n). Somit Gesamtlaufzeit Θ(n log n).
517 Längste Gemeiname Teilfolge Teilfolgen einer Zeichenkette: Problem: Teilfolgen(KUH): (), (K), (U), (H), (KU), (KH), (UH), (KUH) Eingabe: Zwei Zeichenketten A = (a 1,..., a m ), B = (b 1,..., b n ) der Längen m > 0 und n > 0. Gesucht: Eine längste gemeinsame Teilfolge (LGT) von A und B. Sinnvolle Anwendung: Ähnlichkeit von DNA-Sequenzen in der Biologie.
Längste Gemeiname Teilfolge 518 Beispiele: LGT(IGEL,KATZE)=E, LGT(TIGER,ZIEGE)=IGE Ideen zur Lösung? T I G E R Z I E G E
Rekursives Vorgehen Annahme: Lösungen L(i, j) bekannt für A[1,..., i] und B[1,..., j] für alle 1 i m und 1 j n, jedoch nicht für i = m und j = n. T I G E R Z I E G E Betrachten Zeichen a m, b n. Drei Möglichkeiten: 1 A wird um ein Leerzeichen erweitert. L(m, n) = L(m, n 1) 2 B wird um ein Leerzeichen erweitert. L(m, n) = L(m 1, n) 3 L(m, n) = L(m 1, n 1) + δ mn mit δ mn = 1 wenn a m = b n und δ mn = 0 sonst 519
Rekursion 520 L(m, n) max {L(m 1, n 1) + δ mn, L(m, n 1), L(m 1, n)} für m, n > 0 und Randfälle L(, 0) = 0, L(0, ) = 0. Z I E G E 0 0 0 0 0 0 T 0 0 0 0 0 0 I 0 0 1 1 1 1 G 0 0 1 1 2 2 E 0 0 1 2 2 3 R 0 0 1 2 2 3
521 Dynamic Programming Algorithmus LGT 1 Dimension der Tabelle? Bedeutung der Einträge? Tabelle L[0,..., m][0,..., n]. L[i, j]: Länge einer LGT der Zeichenketten (a 1,..., a i ) und (b 1,..., b j ) 2 Berechnung eines Eintrags L[0, i] 0 0 i m, L[j, 0] 0 0 j n. Berechnung von L[i, j] sonst mit L[i, j] = max(l[i 1, j 1] + δ ij, L[i, j 1], L[i 1, j]).
522 Dynamic Programming Algorithmus LGT 3 Berechnungsreihenfolge Abhängigkeiten berücksichtigen: z.b. Zeilen aufsteigend und innerhalb von Zeilen Spalten aufsteigend. 4 Wie kann sich Lösung aus der Tabelle konstruieren lassen? Beginne bei j = m, i = n. Falls a i = b j gilt, gib a i aus, sonst falls L[i, j] = L[i, j 1] fahre mit j j 1 fort, sonst falls L[i, j] = L[i 1, j] fahre mit i i 1 fort. Terminiere für i = 0 oder j = 0.
523 Analyse LGT Anzahl Tabelleneinträge: (m + 1) (n + 1). Berechnung jeweils mit konstanter Anzahl Zuweisungen und Vergleichen. Anzahl Schritte O(mn) Bestimmen der Lösung: jeweils Verringerung von i oder j. Maximal O(n + m) Schritte. Laufzeit insgesamt: O(mn).
Editierdistanz Editierdistanz von zwei Zeichenketten A = (a 1,..., a m ), B = (b 1,..., b m ). Editieroperationen: Einfügen eines Zeichens Löschen eines Zeichens Änderung eines Zeichens Frage: Wie viele Editieroperationen sind mindestens nötig, um eine gegebene Zeichenkette A in eine Zeichenkette B zu überführen. TIGER ZIGER ZIEGER ZIEGE Editierdistanz= Levenshtein Distanz 524
Vorgehen? Zweidimensionale Tabelle E[0,..., m][0,..., n] mit Editierdistanzen E[i, j] zwischen Worten A i = (a 1,..., a i ) und B j = (b 1,..., b j ). Betrachte die jeweils letzten Zeichen von A i und B j. Drei mögliche Fälle: 1 Lösche letztes Zeichen von A i : 25 E[i 1, j] + 1. 2 Füge Zeichen zu A i hinzu: 26 E[i, j 1] + 1. 3 Ersetze A i durch B j : E[i 1, j 1] + 1 δ ij. E[i, j] min { E[i 1, j]+1, E[i, j 1]+1, E[i 1, j 1]+1 δ ij } 25 oder füge Zeichen zu B j hinzu 26 oder lösche letztes Zeichen von B j 525
DP Tabelle E[i, j] min { E[i 1, j] + 1, E[i, j 1] + 1, E[i 1, j 1] + 1 δ ij } Z I E G E 0 1 2 3 4 5 T 1 1 2 3 4 5 I 2 2 1 2 3 4 G 3 3 2 2 2 3 E 4 4 3 2 3 2 R 5 5 4 3 3 3 Algorithmus: Übung! 526
Matrix-Kettenmultiplikation 527 Aufgabe: Berechnung des Produktes A 1 A 2... A n von Matrizen A 1,..., A n. Matrizenmultiplikation ist assoziativ, d.h. Klammerung kann beliebig gewählt. Ziel: möglichst effiziente Berechnung des Produktes. Annahme: Multiplikation einer (r s)-matrix mit einer (s u)-matrix hat Kosten r s u.
Macht das einen Unterschied? 528 1 1 k k 1 k = = A 1 A 2 A 3 A 1 A 2 A 3 k 2 Operationen! A 1 A 2 A 3 1 1 k Operationen! k k 1 k = = A 1 A 2 A 3 A 1 A 2 A 3 A 1 A 2 A 3
529 Rekursion Annahme, dass die bestmögliche Berechnung von (A 1 A 2 A i ) und (A i+1 A i+2 A n ) für jedes i bereits bekannt ist. Bestimme bestes i, fertig. n n-tabelle M. Eintrag M[p, q] enthält Kosten der besten Klammerung von (A p A p+1 A q ). M[p, q] min (M[p, i] + M[i + 1, q] + Kosten letzte Multiplikation) p i<p
530 Berechnung der DP-Tabelle Randfälle: M[p, p] 0 für alle 1 p n. Berechnung von M[p, q] hängt ab von M[i, j] mit p i j q, (i, j) (p, q). Insbesondere hängt M[p, q] höchstens ab von Einträgen M[i, j] mit i j < q p. Folgerung: Fülle die Tabelle von der Diagonale ausgehend.
Analyse 531 DP-Tabelle hat n 2 Einträge. Berechung eines Eintrages bedingt Betrachten von bis zu n 1 anderen Einträgen. Gesamtlaufzeit O(n 3 ). Auslesen der Reihenfolge aus M: Übung!
Exkurs: Matrixmultiplikation Betrachten Multiplikation zweier n n-matrizen. Seien dann A = (a ij ) 1 i,j n, B = (b ij ) 1 i,j n, C = (c ij ) 1 i,j n, C = A B c ij = n a ik b kj. k=1 Naiver Algorithmus benötigt Θ(n 3 ) elementare Multiplikationen. 532
Divide and Conquer 533 B a c b d e f ea + fc eb + fd A C = AB g h ga + hc gb + hd
534 Divide and Conquer Annahme n = 2 k. a b Anzahl elementare Multiplikationen: M(n) = 8M(n/2), M(1) = 1. c d Ergibt M(n) = 8 log 2 n = n log 2 8 = n 3. Kein Gewinn e g f h ea + fc ga + hc eb + fd gb + hd
535 Strassens Matrixmultiplikation Nichttriviale Beobachtung von Strassen (1969): Es genügt die Berechnung der sieben Produkte A = (e + h) (a + d), B = (g + h) a, C = e (b d), D = h (c a), E = (e + f) d, F = (g e) (a + b), G = (f h) (c + d). Denn: ea + fc = A + D E + G, eb + fd = C + E, ga + hc = B + D, gb + hd = A B + C + F. Damit ergibt sich M (n) = 7M(n/2), M (1) = 1. Also M (n) = 7 log 2 n = n log 2 7 n 2.807. e g f h a c ea + fc ga + hc b d eb + fd gb + hd Schnellster bekannter Algorithmus: O(n 2.37 )