Übung III zur Vorlesung Informatik III Prof. Dr. Nikolaus Wulff Zum 11. November 2010 1 Konvergenz von Cauchy-Folgen Sie werden häufig vor der Aufgabe stehen einen iterativen Algorithmus zu entwickeln, der eine numerische Nährungslösung zu einem gegebenem Problem berechnet. Meist wissen Sie weder eine analytische Lösung noch kennen Sie einen direkten Weg zur deren Berechnung. Der Computer kann Ihnen jedoch sehr effizient eine Nährung mit gewünschter Genauigkeit liefern. Dies geschieht häufig in Form einer Folge von Werten (ak )k∈N die (hoffentlich) gegen die gesuchte exakte Lösung a konvergiert. Eine Folge (ak )k∈N heißt Cauchy-Folge, falls es zu einem beliebig vorgegebenen ε > 0 ein n0 (ε) ∈ N gibt mit der Eigenschaft |an − am | < ε ∀ n, m > n0 (ε). (1) Diese Folge konvergiert dann gegen den Grenzwert a, d.h. |an − a| < ε ∀ n > n0 (ε) (2) Bemerkung: n0 ist keine Konstante, sonderen hängt ab von der Wahl von ε, meist wird dies jedoch nicht explizit ausgeschrieben. Entscheidend für unsere Fragstellung ist jetzt, was bedeutet dies für eine numerische Auswertung einer solchen Folge, welches n0 ist zu wählen oder kann man auf dessen Bestimmung unter geeigneten Bedingungen eventuell ganz verzichten? Wie lässt sich ein geeigneter algorithmischer Rahmen – quasi als Blaupause – zur Berechnung solcher Folgen, wie sie in vielen numerischen Anwendungen vorkommen, beschreiben? Aufgabe Formulieren Sie den Kern des Algorithmus zur Bestimmung ob die Konvergenz einer Folge (ak )k∈N zu vorgegebenem ε erreicht ist oder nicht und ermitteln Sie deren Grenzwert a. Berücksichtigen Sie ferner, dass unter Umständen die Folge gar keine Cauchy-Folge ist, d.h. dass diese divergiert. Auch dies muss erkannt werden, so dass sich der Algorithmus nicht in einer Endlosschleife verfängt. 1 Tip Konkreter Hintergrund dieser Fragestellung ist z.B. die numerische Integration und Differentiation, das numerische Lösen von Differentialgleichungen, das Ermitteln von Eigenwerten von Matrizen mit iterativen Verfahren etc. Um z.B. das bestimmte Integral Z x f (u) du (3) I(x) := 0 numerisch zu bestimmen, wird im einfachsten Fall der Rechteckintegration eine Folge Sn∈N (x) von Summen der Art n−1 Sn (x) := xX x f ( j) n n (4) j=0 zur Approximation des Integrals wiederholt mit wachsendem n ausgewertet, bis die gewünschte Genauigkeit erreicht ist. Für stetige beschränkte Funktionen f wird die Folge (Sn ) gegen das Riemannsche Integral (3) konvergieren, so dass I(x) = lim Sn (x) (5) n→∞ gilt. Bis zu welchem n muss iteriert werden, um sicherzustellen, dass der gemachte Fehler kleiner ε ist? Denn n = ∞ ist nicht definiert, macht numerisch keinen Sinn und dauert “ewig”... 2 2 Problematische Rekursion Zur Berechnung der Fakultätet n! wird häufig ein rekursiver Algorithmus verwendet, der genau n rekursive Aufrufe benötigt. Eine solche Verkettung von rekursiven Aufrufen kann jedoch unter Umständen ungünstig sein, wie das folgende Beispiel der Fibonacci Zahlen Fn zeigt. Diese sind ähnlich zur Fakultät rekursiv definiert F1 ≡ F2 ≡ 1 (6) Fn := Fn−1 + Fn−2 ∀ n ∈ N\{1, 2}. (7) Machen Sie sich Gedanken zum Laufzeitverhalten eines rekursiven Algorithmus fib(n)≡ Fn . Überlegen Sie wie die Anzahl an rekursiven Aufrufen von fib – bezeichnet als R(n) – ansteigt, um Fn für ein beliebiges n > 2 zu berechnen. Anbei zur Illustration des exponentiellen Verhaltens eine Tabelle mit einigen Fibonacci Zahlen Fn und der Anzahl R(n) an notwendigen Rekursionen zu deren Berechnung. n 3 4 5 10 20 30 F(n) 2 3 5 55 6765 832040 R(n) 3 5 9 109 13529 1664079 Aufgabe • Entwickeln Sie einen rekursiven Algorithmus fib(int n) zur Berechnung der Fibonacci Zahlen. • Wie lautet das Bildungsgesetz von R(n)? • Wie kann der Algorithmus verbessert werden, so dass er lineares Verhalten zeigt? D.h. entwickeln Sie einen nicht rekursiven Algorithmus. Tip Das Bildungsgesetz R(n) kann selbst rekursiv definiert werden und besitzt auch eine Darstellung mit Hilfe der Fibonacci Zahlen. Skizzieren Sie den Aufrufgraphen (⇒ Baumstruktur) für die Berechnung von F5 , um sich klar zu machen, weshalb hierzu 9 Aufrufe von fib benötigt werden. 3 3 Speicherverwaltung Sie entwickeln einen MemoryManager, der ähnlich zu den C Funktionen malloc und free Speicher zur Verfügung stellt. Sie designen hierzu zwei Funktionen allocate und deallocate zum Anfordern und Freigeben von Speicher, wie in der Headerdatei (1) abgebildet. 1 2 #ifndef MEMORY H #define MEMORY H 3 4 5 6 7 /∗∗ allocate size bytes of memory ∗/ void ∗allocate(unsigned int size); /∗∗ free allocated memory ∗/ void deallocate(void∗); 8 9 #endif /∗MEMORY H ∗/ Listing 1: Prototypen des MemoryManagers. Aufgabe Berücksichtigen Sie bei Ihrem Design die folgenden Anforderungen 1. Speicherbereich, der mit allocate angefordert wurde, darf nicht zweimal vergeben werden, 2. bzw. ein Speicherbereich darf erst nach einer Freigabe wieder weiter verwendet werden. 3. Speicher darf nicht mehrmals freigegeben werden. 4. Freigeben von ”falschen Speicherblöcken”, die gar nicht angefordert wurden, führt zu einer entsprechenden Assertion. 5. Es soll möglich sein eine Statusabfrage des augenblicklichen Auslastungszustands vom MemoryManager zu erhalten. Insbesondere um in der Entwicklungsphase zu sehen, ob alle alloziierten Speicherblöcke wieder frei gegeben wurden. 6. Stellen Sie beim Freigeben eines Speicherbereiches fest, ob ”über die Ränder” des Speicherbereichs geschrieben wurde. 7. Soll ein freigegebener Speicherbereich wieder verwendet werden, so muss er ”groß genug” für die neue allocate Anforderungen sein. 8. Es soll möglich sein freie fragmentierte Speicherblöcke zu größeren zusammenzufassen. 4 Tip Die Anforderungen sind nach Schwierigkeitsgrad absteigend sortiert. Lösen Sie also Top-Down ein Problem nach dem anderen. Bei der deallocate Methode wird nur der Zeiger auf den Speicherbereich zurückgegeben, Sie müssen trotzdem sicherstellen, dass Sie wissen wie groß dieser Speicherblock war, und ob er überhaupt vorher angefordert wurde. Es könnte eine falsche Speicheraddresse oder ein NullPointer sein. Es gibt mehrere Lösungen, überlegen und begründen Sie weshalb Sie sich für die eine oder andere Variante entschieden haben. Es ist sinnvoll die Lösung tatsächlich auszuimplementieren und zu testen, ansonsten wird die Diskussion an der Tafel nicht all zu zielführend... 5