sin(x) = P∞ n x2n+1 n=0 (−1) (2n+1)! Da Polynome stark oszillieren, nimmt man auch gern Polynomstückchen zur Funktionsinterpolation, und setzt die Gesamtfunktion daraus zusammen: Ein Spline n-ten Grades ist eine stückweise aus Polynomen mit maximalem Grad n zusammengesetzte Funktion. An die Stellen, an denen zwei Polynomstücke zusammenstoßen werden dabei noch bestimmte Bedingungen z.B. bezüglich der Differenzierbarkeit gestellt. Was macht Funktionsapproximationen eigentlich interessant? • Manchmal hat man gar keine Funktionen, sonder nur Messwerte. Zu gegebenen Paaren (x, p(x)) kann man ein geeignetes Polynom p recht einfach berechnen. • Manchmal sind die Approximationen gutmütiger, und hinreichend für die Modellierung eines Problems. Der Algorithmus von Strassen und Schönhage macht sich eine Umwandlung des Problems in einen andere Struktur zunutze, er benutzt die schnelle diskrete Fourier-Transormation (DFT). Die prinzipielle Idee dabei ist folgende: • Man kann eine Funktion, z.B. ein Polynom, durch eine Funktionalgleichung angeben. • Viele Funktionen kann man aber auch eindeutig dadurch bestimmen, das man geeignete Paare von Werten und Funktionswerten (SStützstellen") angibt. • Insbesondere Polynome vom Grad n sind eindeutig bestimmt, wenn man n solcher Paare angibt. • Bei der FFT sind die Stützstellen idR Einheitswurzeln. • Die Eindeutigkeit erlaubt auch eine Rücktransformation der Darstellung in die ursprüngliche Form. Nützlich ist das dann, wenn man zu einer schwierigen Operation o auf der Originaldarstellung eine aequivalente, effiziente Operation o′ auf der Transformierten findet. Dann kann man statt Aufgabe −→o Lösung folgenden Weg realisieren: Aufgabe →DF T DFT(Aufgabe) →o′ DFT(Lösung) →IDF T Lösung Damit läßt sich z.B die Multiplikation zweier Polynome vom Grad n in O(nlog(n)) Zeit berechnen. Die FFT wird auch sehr erfolgreich in der Signalverarbeitung und anderen Bereichen verwendet. Definition 185. Für n ∈ N heissen die n verschiedenen komplexen Nullstellen 1, ω, ω 2 , ..., ω n−1 der Polynome xn −1 n-te Einheitswurzeln, ω heisst dann n-te Einheitswurzel Satz 186. In C ist für jedes n = 0, 1, 2, ... ω = exp(2πi/n) eine n-te Einheitswurzel. Beweis. exp(2πi/n)n = exp(2πi) = 1 57 4.5 CRC Eine vorrangig in der Datenübertragung eingesetzte Korrektheitsprüfung durch (binäre) Polynomdivision mit einem Generatorpoynoms ist das Verfahren hinter dem Begriff zyklischen Redundanzprüfung (Cyclic Redundancy Check). Das Verfahren muss effizient sein, damit es eine Datenübertragung nicht verlangsamt, sondern parallel dazu ohne wesentliche Mehrlast berechnet werden kann. Bei der binären Datenübertragung ist der Zahlkörper aber der F2 , in dem Polynomdivision im wesentlichen eine einfache xor-Operation ist. Bei der Polynomdivision kommt nun zum tragen, das im Ergebnis eine 1 den Divisor kopiert, eine 0 nur (eine 2erPotzenz) shiftet. Dieses Verfahren lässt sich effizient mit Schieberegistern realisieren, die auch in Hardware realisiert werden können. Das ist - schnell! Die Qualität der Prüfung hängt vom gewählten CRC-Polynom ab. Ethernet, FDDI, ZIP und PNG benutzen z.B das Polynom CRC-32 = 0x04C11DB7 = 0000 0100 1100 0001 0001 1101 1011 0111 (Die führende 1 an der 33. Bitposition wird nicht gespeichert.) • CRC-32 = x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 (V.42, MPEG-2, PNG [14], POSIX cksum) • CRC-1 = x + 1 (Parity Bit) • CRC-5-USB = x5 + x2 + 1 (USB token packets) • CRC-24-Radix-64 = x24 + x23 + x18 + x17 + x14 + x11 + x10 + x7 + x6 + x5 + x4 + x3 + x + 1 (OpenPGP) http://en.wikipedia.org/wiki/Cyclic_redundancy_check#Commonly_used_and_standardised_CRCs Nachricht= 1101011011, Generatorpolynom = 10011 11010110110000 10011 ----10011 10011 ----000010110 10011 ----010100 10011 ----1110 (Rest) Nachricht wird um (Länge des G-Polynoms)-1 Nullen aufgestockt Übertragen wird nun die Nachricht+Rest: 11010110111110 Beim Empfang wird nun wieder durch das CRC-Polynom dividiert: 11010110111110 10011 ----10011 10011 ----000010111 10011 ----010011 10011 ----00000 Geht das wie hier ohne Rest auf, ist die Übertragung mit hoher Wahrscheinlichkeit korrekt 58 4.6 Rechnen mit grossen Zahlen Unter grossen Zahlen verstehen wir Zahlen, die - dargestellt zur Basis 2 - nicht mehr in die Register der verfügbaren Rechner passen. Aktuell haben Rechner Register mit 32 oder 64 bits, wir meinen also Zahlen, die grösser als 4294967296 bzw. 18446744073709551616 sind. Additionen von Zahlen in dieser Grössenordnung ergeben wieder diese Grössenordnung, lassen sich also mit einem Maschinenbefehl erledigen. Mutliplikationen können ja leicht die Stellenzahl verdoppeln, für ein korrektes Ergebnis in einem Maschinenbefehl dürfen also die beteiligten Zahlen sogar nur halb so viele Stellen haben. Man kann jede Zahl zu einer geeigneten Basis b darstellen. Unsere übliches System ist die Darstellung zur Basis 10, die dezimale Darstellung: a= ∞ X ak 10k k=0 Für ein festes a sind ab einem gewisse k die ak+l , l > 0 natürlich alle Null. Dann nennt man k + 1 die Stelligkeit von a. Wir schreiben a dann statt als Summe als Reihe der Koeffizienten, beginnend mit dem höchsten Index: a = an an−1 an−2 ...a0 Beispiele: • 123 = 1 ∗ 102 + 2 ∗ 101 + 3 ∗ 100 a2 = 1, a1 = 2, a0 = 3, a = 123, Stelligkeit 3, • 123 = 1 ∗ 26 + 1 ∗ 25 + 1 ∗ 24 + 1 ∗ 23 + 0 ∗ 22 + 1 ∗ 21 + 1 ∗ 20 , a = (1111011)2 , Stelligkeit 7, • 123 = 1 ∗ 82 + 7 ∗ 81 + 3 ∗ 80 , a = (173)8 Stelligkeit 3 Die verwendete Basis notieren wir falls es nicht eindeutig ist wie oben in Form einer Klammer mit Index: (...)Basis Für die Berechnung grosser Zahlen wählen wir eine Darstellung zu einer Basis, die der noch handhabbaren Registergrösse (als 2er-Potenz) entspricht, also für 32 Bits die Basis b = 232 , etc. Wenn wir also von einem (hypothetischen) 3-Bit-Rechner ausgehen, wäre die Basis 23 = 8 angemessen. Jedes der Produkte in der Summendarstellung im letzen Beispiel wäre also auf der Maschine in einer Operation berechenbar, die Gesamtsumme aber nicht mehr. In dieser Darstellung können wir zwei grosse Zahlen natürlich addieren (und subtrahieren), indem wir jeweils die jeweils gleichen Koeffizienten summieren. Fehlende Koeffizienten werden auf 0 gesetzt, und Überträge, also das Verlassen des Zahlbereichs, müssen wir berücksichtigen: Sei x = (xn ...x0 )b , y = (ym ...y0 )b , und sei k := max(n, m). Dann berechnet sich z = (x + y) = (zk ...z0 )b aus z0 := (x0 + y0 ) mod b, r0 := (x0 + y0 ) ÷ b z1 := (x1 + y1 + r0 ) mod b, r1 := (x1 + y1 + r0 ) ÷ b, ... zl := (xl + yl + rl−1 ) mod b, l ist dabei k oder k + 1, je nach Übertrag der höchsten Stelle. Beispiel 187. x = 123 = (173)8 , y = 87 = (127)8 , z = x + y z0 = (7 + 3) mod 8 = 2, r0 = 1 z1 = (7 + 2 + 1) mod 8 = 2, r1 = 1 z2 = (1 + 1 + 1) mod 8 = 3, r2 = 0 x + y = (322)8 = 3 ∗ 64 + 2 ∗ 8 + 2 = 210 59 Die Subtraktion behandelt man analog. Hier fällt sogar der Übertrag weg. Insgesamt reichen für Addition und Subtraktion O(max(n, m)) Standardoperationen aus. Kanonisch würde man die Darstellung von oben verwenden, Faktor für Faktor ausmultipizieren und wieder summieren: Sei x = (xn ...x0 )b , und y = (ym ...y0 )b , Dann ist x∗y =x∗ m X y k bk = k=0 m X k=0 (x ∗ yk ∗ bk ) Jedes der Produkte x ∗ yk ist wieder eine Summe yk ∗ x = yk ∗ n X xj bj = j=0 n X j=0 (yk ∗ xj ∗ bj ) Der bei der einfachen Multiplikation entstehende Übertrag von rj = ⌊yk ∗ xj /b⌋ ist natürlich auch noch geeignet in die Summation aufzunehmen. Das ist, etwas kompliziert formuliert, das Schema des schriftlichen Multiplizierens: Beispiel 188. x = 123 = (173)8 , y = 87 = (127)8 , z = x ∗ y 173 * 127 -----------173 366 1535 -----------24715 14=1*8+6 21=2*8+5, 49+2=6*8+3, 7+6=1*8+5 (24715)8 = 5 + 7 ∗ 8 + 6 ∗ 82 + 4 ∗ 83 + 2 ∗ 84 = 10701 = 123 ∗ 87 Insgesamt erfordert also auf diesem Wege die Multiplikation zweier (zur Basis b) n-stelliger Zahlen O(n2 ) Operationen. Mit geschickterer Zusammenstellung kann man bessere Werte erreichen, das Verfahren von Schönhage und Strassen (1971) benötigt O(n ∗ log(n) ∗ log(log(n))) Schritte. http://de.wikipedia.org/wiki/Sch%C3%B6nhage-Strassen-Algorithmus Die Division lässt sich auf die Multiplikation zurückführen, der Berechnungsaufwand liegt also auch in dieser Grössenordnung. 4.6.1 Anwendungen von Poynomen in der Kryptographie Den RSA-Algrorithmus haben wir ja schon gesehen, hier sei nur auf interessante Darstellungen von Nutzung von Polynomen bei Krypthographie im Web verwiesen: • http://www.gnupg.org/gph/de/manual/ • http://www.openssh.com/manual.html • http://de.wikipedia.org/wiki/RSA-Kryptosystem • http://www.matheprisma.uni-wuppertal.de/Module/RSA/ • http://de.wikipedia.org/wiki/Digital_Signature_Algorithm 60 5 Algorithmenanalyse und Rekursion 5.1 Rekursionsgleichungen In den vergangenen Kapiteln sind uns ja wiederholt induktiive Definitionen begegnet, bei denen die Begriffe ausgehend von Anfangswerten dann durch eine Rekursionsgleichung definiert wurden. Für viele Zwecke ist das auch sehr praktisch, etwa bei der algorithmischen Behandlung von Graphen (insbes. Bäumen), bei denen jeder Knoten besucht werden muss. Bei rekursiv definnierten Funktionen dagegen, wo uns eigentlich nur der Funktionswert interessiert, ist es wesentlich effizienter die Rekursionsgleichung aufzulösen und durch eine Funktion zu ersetzen, deren Wert nicht mehr auf den Vorgängerwerten basiert, sondern nur noch vom Index n und den Anfangswerten abhängt, und natürlich auch keine von n abhängigen Summen oder Produkte enthält. Hat man solch eine nicht-rekursive Darastellung der Funktion gefunden, spricht man auch von einem geschlossenem Ausdruck und von einer Lösung der Rekursionsgleichung. Ein Beispiel: Definition 189. Die Folge f ib(n), die definiert ist durch 1. f ib(0) := 0, f ib(1) := 1 2. ∀n > 1 : f ib(n) := f ib(n − 1) + f ib(n − 2) heisst Fibonacci-Folge Wenn man die Folge ganz einfach rekursiv nach der Definitionsgleichung programmiert, wächst der Berechungsaufwand enorm (A = Additionen): f ib(2) = 1A f ib(3) = 1A + 0A + 1A = 2A f ib(4) = 2A + 1A + 1A = 4A f ib(5) = 4A + 2A + 1A = 7A f ib(6) = (7 + 4 + 1)A = 12A f ib(7) = 20A, f ib(8) = 33A, f ib(9) = 54A, f ib(10) = 88A, ... Genauer betrachtet ist das auch eine Rekursionsgleichung: 1. Additionen(f ib(0)) = Additionen(f ib(1)) = 0 2. ∀n > 1 : Additionen(f ib(n)) = Additionen(f ib(n − 1)) + Additionen(f ib(n − 2)) + 1 Berechnet man f ib(n) schlauer, indem man die Zwischenergebnisse speichert und nicht immer neu berechnet, benötigt man immer noch (n − 1) Additionen für die Berechnung von f ib(n), und natürlich mehr, genauer O(n) Zellen Speicherplatz. √ √ n n Es ist aber auch f ib(n) = √15 1+2 5 − √15 1−2 5 Auch die Analyse die Kombinatorik führen oft zu Rekursionsgleichungen, als Beispiel etwa Kombinatorisches Zählen: Wir bestimmen die Anzahl Wörter an der Länge n über dem Alphabet {a, b}, die keine zwei aufeinander folgenden a’s enthalten. Es gilt: a1 = 2 und a2 = 3. Für n ≥ 3 gilt: an = an−1 + an−2 . Begründung: Wir unterscheiden die Wörter der Länge n nach ihrem letzten Buchstaben. ·|· {z · · ·}· b oder n−1 ·|· {z · · ·}· ba n−2 • Ist dies ein b, so darf das vorangehende Teilwort ein beliebiges Wort der Länge n − 1 sein, das keine zwei aufeinander folgenden a’s enthält (davon gibt es an−1 ). 61 • Ist das letzte Zeichen a, so muss unmittelbar davor ein b stehen. Das davor stehende Teilwort kann dann wiederum ein beliebiges Wort der Länge n − 2 sein, das keine zwei aufeinander folgenden a’s enthält (davon gibt es an−2 ). Das ist nur eine leicht verschobene Fibonacci-Rekursion: a0 := 0, und für n ≥ 1 : an = f ib(n + 2)! Um uns dem Problem, eine Lösung der Rekursionsgleichung zu finden, verallgemeinern und formalisieren wir zunächst, um dann über Spezialfälle ggf. zum Einzelproblem zu finden. Definition 190. Eine Rekursionsgleichung ist eine Gleichung der Form f (n) := g(n, f (n − 1), f (n − 2), ..., f (n − k)) mit Funktionen f : N → W und g : N × W k → W für eine Wertemenge W . Damit eine Rekursionsgleichung der o.a. Form eindeutig bestimmt ist, werden k Anfangswerte benötigt. Beispiel 191. Bei f ib ist k = 2, W = N, f = f ib, und g(n, a, b) = a + b für n > 1, g(1, a, b) = 1, g(0, a, b) = 0 Strategien zum Lösen von Rekursionsgleichungen: • Iterationsmethode Hierbei wird die Funktion auf der rechten Seite immer wieder durch die Rekursionsgleichung ersetzt. Dann wird versucht, die rechte Seite in eine geschlossene Form zu bringen. • Verwendung bekannter Lösungen für spezielle Klassen von Rekursionsgleichungen • Erzeugende Funktionen Beispiel: Iterationsmethode für f (n) = n + 3f (n/4) f (n) = n + 3f (n/4) = n + 3(n/4 + 3f (n/16)) = n + 3n/4 + 9(n/16 + 3f (n/64)) ≤ n + 3n/4 + 9n/16 + · · · X n· (3/4)i = i≥0 = n· 1 = 4n(∈ Θ(n)) 1 − 3/4 (Die Anfangswertbedingung f (1) = a wirkt sich nur auf die in der Θ-Notation verborgenen Konstanten aus.) Lineare Rekursionsgleichungen stellen eine wichtigen Spezialfall dar, für den in einigen Fällen allgemeine Lösungen angegeben werden können. Definition 192. Eine Rekursionsgleichung der o.a. Form, bei der g eine lineare Funktion in f ist, heisst lineare Rekursionsgleichung k-ter Ordnung. Es ist dann für n > (k − 1) f (n) = a1 f (n − 1) + a2 f (n − 2) + ... + ak f (n − k) + b0 mit den Anfangsbedingungen f (i) = bi für i = 1, ..., k − 1. Ist b0 = 0, so heisst die Rekursionsgleichung homogen 62 Die Unterscheidung zwischen homogener und inhomogener Form ist für den Fall nicht eindeutiger Lösungen spannend. dann kann man aus Lösungen der homogenen Form weitere Lösungen zusammensetzen, etc. http://de.wikipedia.org/wiki/Lineare_Differenzengleichung#Rechenregeln Lineare Rekursionsgleichungen 1. Ordnung sind einfach zu lösen Homogener Fall: Ist f (n) = af (n − 1), und f (0) gegeben, dann ist f (1) = af (0), f (2) = aaf (0), f (3) = aaaf (0), insgesamt f (n) = an f (0). Beweis: Durch Induktion nach n Beispiel 193. Wenn sich Bakterienkulturen in Nährlösung jede Minute teilen, bedeutet das für ihre Anzahl nach n Minuten: Anzahl(n) = 2 ∗ Anzahl(n − 1). Fangen wir mit einem Bakterium an, also f (0) = 1, dann ist Anzahl(n) = 2n . Nach 60 Minuten haben wir also 1.152.921.504.606.846.976 Stück. Und wenn sie sich nur alle 5 Minuten teilen? Allgemein gilt im inhomogenern Fall: Ist f (n) = af (n − 1) + b, und f (0) gegeben, dann ist f (1) = af (0) + b, f (2) = aaf (0) + ab + b, f (3) = aaaf (0) + aab + ab + b = a3 f (0) + b(a2 + a + 1), insgesamt ergibt sich: Satz 194. Für die inhomoge lineare Rekursionsgleichung f (n) = af (n − 1) + b mit Anfangswert f (0) ist die geschlossene Form f (0) + n ∗ b falls a = 1 f (n) = an f (0) + b(an − 1)/(a − 1) sonst Beweis. Induktion nach n Beispiel 195. Wenn eine Bank für 4% Zinsen Geld verleiht, und man immer 6% zurückzahlt, ergibt das bei 100 EUR einen Restbetrag(n) = 1, 04 ∗ Restbetrag(n − 1) − 6. Mit f (0) = 100 ist Restbetrag(n) = 1, 04n ∗ 100 − 6 ∗ (1, 04n − 1)/0, 04. Restbetrag=0 ergibt sich dann für 1, 04n ∗ 100 = 6 ∗ (1, 04n − 1)/0, 04. Umformen ergibt 3 = 1, 04n , mithin n = log(3)/log(1, 04). Das ergibt 28, 011022757 Rückzahlungen, ehe die Summe abgetragen ist. Auch für homogene lineare Rekursionsgleichungen 2. Ordnung finden sich noch eine bekannte geschlossene Form. Satz 196. (1. Fall) Seien f (0), f (1), a1 und a2 Konstanten, a1 und a2 nicht beide Null, und f (n) = a1 f (n − 1) + a2 f (n − 2) für n > 1. Seien weiter b1 und b2 reelle Lösungen der Gleichung x2 − a1 x − a2 = 0, und b1 = b2 : Dann ist f (n) = (nA + B)bn1 mit A := f (1)−b1 ∗f (0) , b1 und B := f (0) Satz 197. (2. Fall) Seien f (0), f (1), a1 und a2 Konstanten, a1 und a2 nicht beide Null, und f (n) = a1 f (n − 1) + a2 f (n − 2) für n > 1. Seien weiter b1 und b2 reelle Lösungen der Gleichung x2 − a1 x − a2 = 0, und b1 6= b2 . Dann ist mit A := f (1)−f (0)b2 , b1 −b2 B := f (1)−f (0)b1 b1 −b2 f (n) = bn1 A − bn2 B 63 Bew: Induktion nach n Beispiel 198. Für die Fibonacci-Rekursion ist der Satz anwendbar. Wir erhalten f (0) = 0, f (1) = 1, a1 = a2 = 1. √ p 1± 5 2 Lösungen für x − x − 1 = 0 sind 1/2 ± 1/4 + 1 = 2 , also A=B= √ 2 √ (1+ 5)−(1− 5) = √1 , 5 und 1 f ib(n) = √ 5 Die Zahl √ 1+ 5 2 √ !n 1+ 5 1 −√ 2 5 √ !n 1− 5 2 ist auch als Goldener Schnitt bekannt. Betrachten wir ein Rechteck mit Seitenlängen s und r ≤ s. Schneiden wir von diesem Rechteck ein Quadrat ab, so verbleibt ein Rechteck r×(s−r). Bestimmt man s und r so, dass die beiden Rechtecke dasselbe Seitenverhältnis haben, also s/r = r/(s − r), so folgt √ s 1+ 5 = r 2 http://de.wikipedia.org/wiki/Goldener_Schnitt 5.1.1 Erzeugende Funktionen Vorbemerkung zur Schreibweise: Bei Folgen und Reihen wird statt an auch oft a(n) geschrieben. Gemeint ist dasselbe: Der Wert von a(n) hängt von n ab, a ist also eine Funktion von n. Ich habe mich wegen der Lesbarkeit hier meist für die Funktionsschreibweise entschieden. Bislang haben wir Lösungen von Rekursionsgleichungen mehr oder minder geraten, und dann unsere Vermutung bewiesen. Man kann aber auch versuchen, Lösungen von Rekursionsgleichungen konstruktiv zu finden. Die Rekusionsgleichung liefert uns ja eine Folge (a(n))n∈N Die Folgenglieder kann man auch als Koeffizienten einer Potenzreihe ansehen, um dann durch Umwandeln der Gleichung und Koeffzientenvergleich eine geschlossenen Form zu finden. Definition 199. Ein Ausdruck A(x) := X a(n)xn n≥0 heisst formale Potenzreihe. Die formale Potenzreihe ist die erzeugende Funktion zur unendlichen Folge (a(n))n≥0 . Formal deshalb, weil die Reihen nicht unbedingt überall konvergieren müssen. Für formale Potzenzreihen in diesem Zusammenhang reicht die Konvergenz für sehr kleine Werte von x, weil wir im wesentlichen an den Koeffizienten interessiert sind, und die Werte der Reihen keine grosse Rolle spielt. Die Idee ist nun, zu einer Rekursionsgleichung eine passende erzeugende Funktion zu finden, diese in die Gleichung einzusetzen und danach aufzulösen, um dann letzlich über einen Koeffizientenvergleich eine nichtrekursive Darstellung der a(n) zu bekommen. Das geht allgemein in 6 Schritten. P 1. Aufstellen der erzeugenden Funktion A(x) := n≥0 a(n)xn 2. Umformen der rechten Seite, so dass Anfangswerte und Rekursionsgleichung eingesetzt werden können. 3. Unendliche Summen (meist über Index-shifts) so weiter umformen, dass sie durch A(x) ersetzt werden können. 64 4. Auflösen nach A(x). Man erhält A(x) = f (x) mit einer - hoffentlich einfachen - Funktion f . 5. Umschreiben von f (x) als formale Potenzreihe. Das kann durch Partialbruchzerlegung und Zurückgreifen auf bekannte Potenzreihen geschehen. 6. Der Koeffizientenvergleich liefert dann eine explizite Darstellung für a(n). Ein einfaches Beispiel: Beispiel 200. a(n) = 2a(n − 1), a(0) = 1 P 1. Aufstellen der erzeugenden Funktion A(x) := n≥0 a(n)xn 2. Umformen der rechten Seite, so dass Anfangswerte und Rekursionsgleichung eingesetzt werden können. Hier kann a(n) ersetzen: P P P man direkt n a(n)xn = 1 + n≥1 2a(n − 1)xn = a(0) + n≥1 P n≥0 a(n)x P n ergibt n≥0 a(n)x = 1 + n≥1 2a(n − 1)xn 3. Unendliche Summen (meist über Index-shifts) so weiter umformen, das sie durch A(x) ersetzt werden können: P A(x) = 1 + n≥0 2a(n)xn+1 P n+1 =1+2 P n≥0 a(n)x = 1 + 2x n≥0 a(n)xn = 1 + 2xA(x) P ergibt A(x) = 1 + n≥0 2a(n)xn+1 = 1 + 2xA(x) 4. Auflösen nach A(x): A(x) = 1 + 2xA(x) A(x) − 2xA(x) = 1 A(x)(1 − 2x) = 1 1 A(x) = 1−2x 1 ergibt A(x) = 1−2x =: f (x) 5. Umschreiben von f (x) als formale Potenzreihe. P Bei den bekannten Funktionen mit Potenzreihenentwicklung findet man 1/(1 − ux) = n≥0 un xn für ein festes u, hier u = 2: A(x) = X 1 2n xn = 1 − 2x n≥0 6. Koeffizientenvergleich liefert dann eine explizite Darstellung für a(n): A(x) = P n≥0 also a(n) = 2n . 5.1.2 a(n)xn = P n≥0 2n xn Bekannte Potenzreihen Bekannte Potenzreihen findet man viele, z.B bei http://de.wikipedia.org/wiki/Erzeugende_Funktion#Explizite_Formeln_f.C3.BCr_einige_wichtige_Potenzreihen. Sehr bekannt ist z.B. die geometrische Reihe X xn = n≥0 1 1−x Sie konvergiert für |x| < 1. Um zu weiteren Funktionen zu kommen, kann man sie z.B. ableiten: ′ ′ X 1 n = x 1−x n≥0 65 X nxn−1 = n≥1 entsprechend 2. Ableitung: X n≥2 X (n + 1)xn = n≥0 (n − 1)nxn−2 = X 1 (1 − x)2 (n + 2)(n + 1)xn = n≥0 2 (1 − x)3 und für k>=1 die k-te Ableitung: X n≥k n(n − 1) · · · (n − k + 1)xn−k = X n≥0 (n + k) · · · (n + 1)xn = k! (1 − x)k+1 Dividiert man durch k!, findet man für k > 0 als erzeugende Funktionen: X n+k 1 xn = k (1 − x)k+1 n≥0 Die erzeugende Funktion der Folge 0, 1, 2, 3, . . . ist X nxn = x (1−x)2 : X n≥0 n≥0 = = (n + 1)xn − X xn n≥0 1 1 − (1 − x)2 1−x x (1 − x)2 Durch Substituieren von y := ax in der geometrischen Reihe: X n≥0 erhalten wir X n≥0 yn = 1 + y + y2 + · · · + yk + · · · = 1 1−y an xn = 1 + ax + a2 x2 + · · · + ak xk + · · · = 1 Die erzeugende Funktion der Folge 1, a, a2 , a3 , . . . ist also 1−ax . an Folge Potenzreihe erz. Fkt. P 1 1 1, 1, 1, 1, . . . xn 1−x Pn≥0 1 n n+1 1, 2, 3, 4, . . . + 1)x n≥0 (n (1−x)2 P n+k n+k 1 1, k + 1, . . . xn (1−x) k+1 n≥0 k k P x n n 0, 1, 2, 3, . . . nx (1−x)2 Pn≥0 n n 1 n 2 3 a 1, a, a , a , . . . n≥0 a x 1−ax P x(1+x) 2 n 2 n x n 0, 1, 4, 9, . . . (1−x)3 Pn≥0 1 n 1 1 1 1 , , . . . x 0, 1, ln n≥1 n n 2 3 1−x P 1 n 1 1, 1, 12 , 16 , . . . ex n≥0 n! x n! Beispiel 201. an = 3an−1 + n für n ≥ 1 mit a0 = 1 • 1. Schritt: Aufstellen der erzeugenden Funktion A(x) := 66 P n≥0 an xn 1 1 − ax • 2./3. Schritt: Anwendung der Rekursionsgleichung und Umformungen X X X nxn an−1 xn−1 + (3an−1 + n)xn = 1 + 3x A(x) = 1 + X = 1 + 3x n≥1 n≥1 n≥1 n an x + X n nx = 1 + 3x · A(x) + n≥0 n≥0 x (1 − x)2 • 4. Schritt: Auflösen nach A(x) A(x) = (1 − x)2 + x x2 − x + 1 = =: f (x) 2 (1 − 3x)(1 − x) (1 − 3x)(1 − x)2 • 5. Schritt: Umschreiben von f (x) durch Partialbruchzerlegung A Bx + C x2 − x + 1 = + (1 − 3x)(1 − x)2 1 − 3x (1 − x)2 A(x) = führt zum linearen Gleichungssystem: A − 3B = 1 −2A + B − 3C = −1 A+C =1 mit der Lösung: A = X an xn = A(x) = n≥0 = 7 , 4 1 B = − , 4 3 4 7 1 1 x 3 1 · − · − · 4 1 − 3x 4 (1 − x)2 4 (1 − x)2 7 X n n 1 X n 3 X 3 x − · nx − · (n + 1)xn · 4 4 4 n≥0 = C = − n≥0 n≥0 X 7 1 3 ( 3n − n − )xn 4 2 4 n≥0 • 6. Schritt: Koeffizientenvergleich liefert an = 74 3n − 12 n − 3 4 Mit dem Ansatz der linearen Rekursion 2. Grades kann so auch der Satz mit der allgemeinen Formel dazu hergeleitet werden, oder spezieller die geschlossenen Form für die Fibionacci-Rekursion. Herleitungen finden sich in der Literatur. Beispiel 202. Gegeben ist hier ein System von Rekursionsgleichungen an = 2an−1 + bn−1 , bn = an−1 + bn−1 , mit a0 = 1, b0 = 0 • 1. Schritt: Aufstellen der erzeugenden Funktionen A(x) = X an xn ; B(x) = X n≥0 n≥0 67 bn xn • 2./3. Schritt: Anwendung der Rekursionsgleichung und Umformungen A(x) = 1 + X (2an−1 + bn−1 )xn n≥1 = 1 + 2x X an−1 xn−1 + x = 1 + 2x bn−1 xn−1 n≥1 n≥1 X X n an x + x X n≥0 n≥0 bn xn = 1 + 2x · A(x) + x · B(x) • und für B(x): B(x) = X (an−1 + bn−1 )xn n≥1 = x X an−1 xn−1 + x = x bn−1 xn−1 n≥1 n≥1 X X n an x + x X n≥0 n≥0 bn xn = x · A(x) + x · B(x) • 4. Schritt: Auflösen nach A(x) und B(x) Das lineare Gleichungssystem (2x − 1) · A(x) + x · B(x) = −1 x · A(x) + (x − 1) · B(x) = 0 führt zur Lösung: A(x) = x2 1−x , − 3x + 1 B(x) = x2 x − 3x + 1 • 5. Schritt: Umschreiben durch Partialbruchzerlegung A(x) = A B 1−x = + , x2 − 3x + 1 1 − αx 1 − βx x A′ B′ = + x2 − 3x + 1 1 − α′ x 1 − β ′ x B(x) = √ 3− 5 , α = α = 2 ′ A = √ 5+ 5 , 10 B = √ 5− 5 , 10 68 √ 3+ 5 β = β = 2 ′ A′ = − √ 5 , 5 B′ = √ 5 5 1 1 +B· 1 − αx 1 − βx X X β n xn αn xn + B · = A· A(x) = A · n≥0 n≥0 = X n n n (Aα + Bβ )x n≥0 1 1 + B′ · 1 − αx 1 − βx X X β n xn αn xn + B ′ · = A′ · B(x) = A′ · n≥0 n≥0 = X ′ n ′ n n (A α + B β )x n≥0 • 6. Schritt: Koeffizientenvergleich liefert an = Aαn + Bβ n , bzw. an √ 5+ 5 = 10 bn 5.2 bn = A′ αn + B ′ β n √ !n √ !n √ 3− 5 5− 5 3+ 5 + 2 10 2 √ !n √ √ !n √ 5 3− 5 5 3+ 5 + = − 5 2 5 2 Algorithmenanalyse Ein Grund, sich mit dem Auflösen von Rekursionsgleichungen zu beschäftigen, ist die Analyse von Laufzeit und Speicherverbrauch bei Algorithmen. Der Bereich ist von ganz praktischen Erwägungen (Knacken von Codes) über praktische erreichbare Grenzen bis zur Theorie der Berechenbarkeit überhaupt sehr interessant. Im einfachen Fall zählt man Operationen bzw. Speicherzellen, und berechnet den Aufwand (abhängig von der Größe der Eingabe) nicht exakt, sondern in der Größenordnung - z.B. O(n2 ), Θ(nlog n), ... Verschiedene Analysen sind von Interesse: • bester Fall (best case) • mittlerer Fall (average case) • schlimmster Fall (worst case) Für den eigentlich interessantesten mittleren Fall wären auch noch Annahmen über die zu erwartende Eingabeverteilung sinnvoll. Meistens beschränkt man sich bei der Analyse auf den schlimmsten Fall. Beispiel: Lineare Suche im Array i = 0; while (a[i] != x) i++ ; • Bestenfalls 1 Schritt ⇒ Θ(1) 69