Mathematisches Praktikum — Sommersemester 2016 Prof. Dr. Wolfgang Dahmen — Felix Gruber, Michael Rom Zusatzaufgabe 1 für Informatiker Bearbeitungszeit: zwei Wochen (bis Freitag, 13. Mai 2016) Mathematischer Hintergrund: Eindimensionale adaptive Quadratur, Quadraturformeln Elemente von C++: Rekursion, Einbinden einer Grafikbibliothek, Makefiles Aufgabenstellung Gegeben seien π, π ∈ R, π < π und eine stetige Funktion π : [π, π] → R. Schreiben Sie ein Programm, welches ∫οΈ π das Integral πΌ(π₯) = π π (π₯) dπ₯ bis auf einen vorgegebenen Fehler π > 0 berechnet. Verwenden Sie dafür eine adaptive Unterteilung des Intervalls [π, π] und vergleichen Sie den benötigten Aufwand mit dem Aufwand im Falle einer äquidistanten Unterteilung von [π, π]. Quadraturformeln Da Integrale nur in den wenigsten Fällen analytisch geschlossen berechenbar sind, bemüht man numerische Methoden zur Berechnung von Integralen (Quadratur ). Die resultierenden Näherungsformeln werden als Quadraturformeln bezeichnet. Hierfür legt man π Stützstellen π₯π ∈ [π, π], 1 ≤ π ≤ π fest, an denen die Funktion π ausgewertet wird. In Abbildung 1 sind die drei einfachsten Quadraturformeln Mittelpunktsregel, Trapezregel und Simpson-Regel dargestellt. Diese drei Quadraturformeln sind allesamt sogenannte Newton-Cotes-Formeln, welche man erhält, indem man die Funktion π an den Stützstellen π₯π durch ein Polynom interpoliert und dieses anschließend exakt integriert. [2] y y y f (x) a a+b 2 f (x) b x a (a) Mittelpunktsregel f (x) b x (b) Trapezregel a a+b 2 b x (c) Simpson-Regel Abbildung 1: Einfache Newton-Cotes-Quadraturformeln Die entstehenden Newton-Cotes-Formeln kann man in allgemeiner Form als ∫οΈ π π (π₯) dπ₯ ≈ (π − π) π π ∑οΈ πΎπ π (π₯π ) π=1 schreiben, wobei die πΎπ ∈ R auch als Gewichte der Stützstellen bezeichnet werden. In Tabelle 1 stehen die Stützstellen und Gewichte der ersten Newton-Cotes-Quadraturformeln auf dem Intervall [π, π]. 1 Quadraturformel Mittelpunktsregel Trapezregel Simpson-Regel Stützstellen π₯π π+π 2 π, π π, π+π 2 ,π Gewichte πΎπ 1 1 1 2, 2 1 4 1 6, 6, 6 Tabelle 1: Newton-Cotes-Quadraturformeln auf dem Intervall [π, π] Exaktheitsgrad und Ordnung Man klassifiziert Quadraturformeln danach, bis zu welchem Grad sie Polynome exakt integrieren, d.h. bis zu welchem π ∈ N gilt ∫οΈ π π ∑οΈ π(π₯) dπ₯ = (π − π) πΎπ π(π₯π ) für alle π ∈ ππ , π π=1 wobei ππ die Menge der Polynome vom Grad kleinergleich π ∈ N bezeichne. Man sagt in diesem Fall auch, die Quadraturformel ist exakt vom Grade π. Die Mittelpunktsregel und die Trapezregel sind exakt vom Grade 1. Die Simpson-Regel ist sogar exakt vom Grade 3. [2] Ist eine Quadraturformel exakt vom Grade π und ist π eine (π + 1)-mal stetig differenzierbare Funktion, so kann man die Funktion π bei der Quadratur durch ihre Taylor-Entwicklung π (π₯) = π ∑οΈ π (π) (π₯0 ) π=0 π! (π₯ − π₯0 )π + πͺ((π₯ − π₯0 )π+1 ). ersetzen. Die Quadraturformel integriert dann das Taylor-Polynom π-ten Grades exakt. Der Fehler bei der Quadratur hängt dann von der Länge des Integrationsintervalls in (π+1)-ter Potenz ab, ist also von Ordnung π + 1. Summierte Quadraturformeln Zur Steigerung der Genauigkeit wendet man eine Quadraturformel meist nicht direkt auf das Intervall [π, π] an, sondern unterteilt [π, π] zunächst in Teilintervalle und wendet die Quadraturformel dann auf die Teilintervalle an. Auf diese Weise erhält man sogenannte summierte Quadraturformeln. Unterteilt man das Intervall [π, π] äquidistant in π Teilintervalle der Länge β := π−π π , so erhält man die Stützstellen ππ = π + πβ für 0 ≤ π ≤ π, d.h. π0 = π und ππ = π. Wendet man auf jedem Teilintervall [ππ , ππ+1 ] die Trapezregel πΌπ (π, [ππ , ππ+1 ]) := β 1 (ππ+1 − ππ ) [π (ππ ) + π (ππ+1 )] = [π (ππ ) + π (ππ+1 )] 2 2 an, so erhält man die summierte Trapezregel ππ,π (π, [π, π]) := π ∑οΈ πΌπ (π, [π + πβ, π + (π + 1)β]) π=0 = π [οΈ ∑οΈ β π=0 ]οΈ π−1 ∑οΈ β β β π (ππ ) + π (ππ+1 ) = π (π) + β π (π + πβ) + π (π). 2 2 2 2 π=1 2 Adaptivität In vielen Fällen ist es zum Erreichen der gewünschten Genauigkeit des Integrals nicht notwendig, das gesamte Intervall in kleine Teilintervalle zu zerlegen. Verhält sich die Funktion π z.B. auf einem großen Teilintervall wie eine Gerade, so wird sie hier bereits durch die Mittelpunktsregel exakt integriert. In einem anderen Abschnitt kann es jedoch nötig sein, das Intervall in viele Teilintervalle zu unterteilen. Liegt eine Möglichkeit vor, den Fehler der aktuellen Näherung auf einem Teilintervall zu schätzen, so kann man die weitere Unterteilung in Abhängigkeit dieser Fehlerschätzung steuern. Diese Fähigkeit eines Verfahrens, sich selbst an das gegebene Problem anzupassen, wird als Adaptivität bezeichnet. Einschluss der Lösung bei konvexen oder konkaven Funktionen Ist die gegebene Funktion π auf dem Intervall [π, π] differenzierbar und zudem konvex oder konkav, so schließen die durch die Mittelpunktsregel und Trapezregel numerisch bestimmten Näherungen des Integrals πΌπ und ∫οΈ π πΌπ den Wert des exakten Integrals πΌ = π π (π₯) dπ₯ ein, d.h. es ist min {πΌπ , πΌπ } ≤ πΌ ≤ max {πΌπ , πΌπ } . (1) Beweis: O.E. sei π konkav auf dem Intervall [π, π] (ansonsten ist π konvex und somit −π konkav und man betrachte −π , −πΌπ und −πΌπ ). Für die Sekante ∫οΈπ von π über∫οΈ dem Intervall [π, π] gilt aufgrund der Konkavität π (π₯) ≤ π (π₯) für alle π₯ ∈ [π, π]. Folglich ist πΌ = π (π₯) dπ₯ ≥ π (π₯) dπ₯ = πΌπ . y y A B f (x) f (x) a b x a (a) Trapezregel a+b 2 b x (b) Mittelpunktsregel Abbildung 2: Einschluss der Lösung bei konkaver Funktion π Es sei π‘ die Tangente an den Funktionsgraphen von π im Punkt π₯ = π+π 2 (siehe Abbildung 2(b)). Dann entspricht die Fläche unter π‘ über dem Intervall [π, π] der von der Mittelpunktsregel berechneten Fläche, da die Dreiecke π΄ und π΅ in Abbildung ∫οΈ2(b) gleich groß sind. Aufgrund der Konkavität kann π jedoch nicht ∫οΈ oberhalb von π‘ liegen und es gilt πΌ = π (π₯) dπ₯ ≤ π‘(π₯) dπ₯ = πΌπ . Die Abschätzung (1) kann man bei konvexen oder konkaven Funktionen nutzen und |πΌπ − πΌπ | als Schätzung des Quadraturfehlers verwenden. In der Praxis fällt diese Schätzung allerdings eher pessimistisch aus. Wurde die Funktion π bereits an den Stützstellen der Mittelpunkts- und der Trapezregel ausgewertet, so kann mithilfe der Simpson-Regel leicht die Approximation höheren Exaktheitsgrades bestimmt werden, da die Stützstellen der Simpson-Regel gerade die Stützstellen der Mittelpunkts- und der Trapezregel sind. 3 Umsetzung im Programm Für das Programm verfolgen wir folgende Strategie: Soll das Integral der Funktion π im Intervall [π, π] mit einem absoluten Fehler von höchstens π berechnet werden, so wenden wir zunächst die Mittelpunkts- und die Trapezregel an und berechnen den Fehlerschätzer |πΌπ − πΌπ |. Ist die gewünschte Genauigkeit erreicht, so geben wir das mit der Simpson-Regel berechnete Ergebnis zurück. Wurde die Genauigkeit π verfehlt, so wird das Intervall in zwei Teilintervalle gleicher Länge zerlegt und das Verfahren auf jedem Teilintervall wiederholt, wobei nun jeweils die Genauigkeit 2π verlangt wird. Der Aufwand einer Quadratur wird oft über die Anzahl der Funktionsauswertungen gemessen. Da eine Funktionsauswertung sehr aufwändig sein kann1 , sollten Sie vermeiden, die Funktion π mehrmals an der gleichen Stützstelle auszuwerten. Um die Vorzüge der adaptiven Rechnung beobachten zu können, vergleichen Sie die Anzahl der benötigten Funktionsauswertungen mit jener bei der summierten Trapezregel mit äquidistanter Schrittweite. Gehen Sie bei der summierten Trapezregel von der minimalen Schrittweite, welche im adaptiven Algorithmus nötig ist, aus. Rekursive Programmierung Benutzen Sie zur Implementierung Ihres Programms die Technik der rekursiven Programmierung. Diese soll anhand des folgenden Beispiels erläutert werden. Beispiel: Berechnung der Fakultät Im Zusammenhang mit kombinatorischen Überlegungen benötigt man gelegentlich die Fakultät π! := Πππ=1 π einer natürlichen Zahl π ∈ N. Diese lässt sich leicht über eine for-Schleife berechnen: 1 unsigned int f a k u l t a e t ( unsigned int n ) { 2 unsigned int f =1; 3 4 i f ( n>1) 5 f o r ( unsigned int i =2 ; i<=n ; ++i ) f *= i ; 6 7 8 return f ; 9 10 } Andererseits gilt für die Fakultät aber auch die Beziehung (π + 1)! = π!(π + 1). Dies legt eine weitere Möglichkeit der Umsetzung in ein Programm nahe: 1 unsigned int f a k u l t a e t ( unsigned int n ) { 2 i f ( n<=1) { return 1 ; } else { return n* f a k u l t a e t ( n−1) ; } 3 4 5 6 7 8 1 } Ist der gesuchte Funktionswert beispielsweise der Auftrieb einer Flugzeugtragfläche in Abhängigkeit eines Parameters, so kann zur Berechnung eine sehr komplexe Strömungssimulation notwendig sein. 4 Diese Programmiertechnik, bei der eine Funktion sich selbst rekursiv aufruft, heißt rekursive Programmierung. Die Rekursionstiefe gibt dabei an, wie oft sich die Funktion selbst aufgerufen hat. Bei rekursiver Programmierung muss vom Programmierer sichergestellt werden, dass die Rekursionstiefe beschränkt bleibt, d.h., dass die Funktion nach endlicher Anzahl von Selbstaufrufen endet, ohne sich selbst wieder aufzurufen. Anderenfalls liegt eine unterminierte Rekursion vor, welche solange fortgesetzt wird, bis alle zur Verfügung stehenden Ressourcen (z.B. Speicher) belegt sind. Funktionsauswertungen und Zielgenauigkeit Fragen Sie zu Beginn Ihres Programmes ab, welches Beispiel gerechnet werden soll. Fangen Sie mögliche Fehler bei der Eingabe ab. Rufen Sie anschließend die Routine void S t a r t ( int Bsp , double &a , double &b , double &e p s i l o n , bool G r a f i k=true , int Pause =300) ; auf, welche Ihnen die Grenzen des Intervalls [π, π] sowie die gewünschte Zielgenauigkeit des Ergebnisses epsilon zurückgibt. Die optionale Grafikausgabe können Sie mit Grafik aktivieren. Der Parameter Pause steuert die Ausgabegeschwindigkeit. Die zu integrierende Funktion können Sie anschließend durch einen Aufruf der Funktion double f ( double x ) ; auswerten. Geben Sie am Ende ihres Programmes das Resultat Ihrer numerischen Quadratur durch einen Aufruf von bool E r g e b n i s ( double I ) ; zurück. Es wird dann mit dem Wert des exakten Integrals verglichen und Ihr Ergebnis wird bewertet. Verwendung von Makefiles Programme, die aus mehreren Dateien bestehen, werden meist nicht „per Hand“ kompiliert. Stattdessen wird üblicherweise der Befehl make verwendet. Die Ausführung dieses Befehls wird durch die Datei Makefile (bzw. makefile) gesteuert. In ihr stehen sowohl die „Regeln“ (Befehlssequenzen), wie man beispielsweise quadratur.o aus quadratur.cpp erhält, als auch die Abhängigkeiten der verschiedenen Dateien. Die Befehlssequenz zur Erzeugung einer bestimmten Datei wird immer dann ausgeführt, wenn wenigstens eine der Dateien, von denen sie abhängt, jünger ist als sie selbst. Dies befreit den Programmierer von der Aufgabe, sich über die Reihenfolge der Kompilierung Gedanken zu machen, und vermeidet überflüssiges Kompilieren von Dateien, welche bereits auf dem neuesten Stand sind. Das Makefile zur Erzeugung des Programms quadratur der vorliegenden Aufgabe könnte zum Beispiel wie folgt aussehen (<Tab> steht für das Tab(ulator)-Zeichen): 1 2 CXXFLAGS = −O2 −Wall LIBS = −lGL −l p t h r e a d −lX11 3 4 5 quadratur : quadratur . o <Tab> $ (CXX) −o q u a d r a t u r q u a d r a t u r . o u n i t . o IGL . o $ ( LIBS ) 6 7 8 q u a d r a t u r . o : q u a d r a t u r . cpp <Tab> $ (CXX) $ (CXXFLAGS) −c q u a d r a t u r . cpp 9 10 11 clean : <Tab> rm −f q u a d r a t u r . o q u a d r a t u r 12 13 .PHONY: c l e a n Erstellen Sie ein Makefile, welches Ihnen Ihr Programm erzeugt. [1] 5 Literatur [1] Dokumentation zu GNU Make. http://www.gnu.org/software/make/. [2] Dahmen, W. und A. Reusken: Numerische Mathematik für Ingenieure und Naturwissenschaftler. Springer Verlag, Heidelberg, 2. Auflage, 2008. 6