Winfried Auzinger Klaus Felsenstein Dirk Praetorius SS 2008 (3. April 2008) Übungen zur Vorlesung Computermathematik Serie 2 Die Aufgaben mit Stern (*) sind bis zur Übung in der kommenden Woche vorzubereiten und werden dort abgeprüft. Die übrigen Aufgaben dienen nur Ihrer Übung. Kopieren Sie bitte Ihre Worksheets auf Ihren Account auf cad.zserv.tuwien.ac.at. Überprüfen Sie vor der Übung, ob Ihre Codes unter Maple auf cad einwandfrei funktionieren. Es wird empfohlen, für jedes Beispiel im Verzeichnis serie02 ein eigenes Worksheet mit dem Namen aufgabeyy.mws anzulegen. Alle zu verfassenden Prozeduren sind zu kommentieren und – je nach Angabe – mit verschiedenen Werten für die Parameter auszutesten. Verwenden Sie konsequent die Online-Hilfe – das ist wichtig für den erfolgreichen praktischen Umgang mit Maple und für die eigenständige Erweiterung des einschlägigen Wissens. Insbesondere kann es vorkommen, dass etwas in der Vorlesung aus Zeitgründen nicht genau besprochen wurde – dann muss man sich zu helfen wissen. Die Beispiele dienen zum Teil auch der Erweiterung des in der Vorlesung behandelten Stoffes (beachten Sie die Hinweise). Nicht für jedes Beispiel gibt es eine ‘eindeutig definierte Lösung’ – manches bleibt der individuellen Kreativität überlassen. Es ist nicht immer a priori klar, welche Art von ‘Vereinfachung’ (z.B. ? eval, ? simplify, ? normal, ? expand, ? convert) die gewünschte Darstellung des Ergebnisses liefert – hier ist man manchmal auf experimentelle Überprüfung angewiesen. ‘Perfekte’ Maple-Prozeduren arbeiten mit konsequenter Überprüfung der Zulässigkeit der Eingangsparameter, insbesondere mittels type. Bei den meisten für die Übung zu implementierenden Prozeduren verzichten wir jedoch darauf, es sei denn es wird explizit verlangt. Für Standardsituationen kann man jedoch automatische Typprüfung aktivieren, indem man den zulässigen Argumenttyp spezifiziert, z.B. proc p(x::posint). Anmerkung: Auf das Katze / Maus / Käselaib (vulgo Wolf / Schaf / Kohlkopf ) - Problem aus Serie 1 kommen wir später nochmals zurück. Wir werden davon ausgehend einen kleinen Programmierwettbewerb veranstalten. Aufgabe 11∗ . Der Maple-Befehl convert dient für verschiedenartigste Umwandlungen von Maple-Objekten in eine andere Gestalt. Studieren Sie die Online-Hilfe (? convert) und erstellen Sie ein Worksheet, in dem einige wichtige Anwendungen dokumentiert sind. Aufgabe 12∗ . Schreiben Sie eine Maple-Prozdur DezimalStelle(n::posint,k::nonnegint) die die k - te Dezimalstelle (Koeffizient bei 10k ) einer natürlichen Zahl n zurückliefert. Verwenden Sie diese für eine grafische Darstellung der relativen Häufigkeiten des Auftretens der Ziffern 0,1,. . . ,9 in der Dezimaldarstellung von Pi = 3.14159. . . (N Dezimalstellen) für wachsendes N . Verwenden Sie Farben und gestalten Sie einen optisch ansprechenden plot. Aufgabe 13∗ . Schreiben Sie drei Maple-Prozeduren symmdiff(A::set,B::set)::set; cartprod(A::set,B::set)::set; auzprod(A::set,B::set)::set; die die symmetrische Differenz A 4 B := (A \ B) ∪ (B \ A), das kartesische Produkt A × B und das Auzinger-Produkt2 zweier Mengen A, B zurückgeben. Anmerkung: Die symmetrische Differenz ist die Menge aller Elemente, die genau in einer der beiden Mengen liegen (‘ausschließendes oder’, xor). Elemente des kartesischen Produktes werden als geordnete Paare (a,b), in Form von Listen der Länge 2 dargestellt. (? listlist) Mit dem ‘Auzinger-Produkt’ ist die Menge Z(A, B) := { (x, y) : x ∈ A, y ∈ B xor x ∈ B, y ∈ A} = Z(B, A) gemeint. (Beispiel: Z({1, 2}, {2}) = {(1, 2), (2, 1)}.) Aufgabe 14∗ . Kann man Maple-Prozeduren differenzieren (? diff), die nicht ‘inline’ in der Form f:=x->Formelausdruck gegeben sind, sondern als Prozedur f:=proc() ...end proc ? Probieren Sie es an einfachen Beispielen aus. Dann betrachten Sie z.B. folgende Funktion: p:=proc(x) if x<0 then cos(x) else cos(x)**2 end if end proc; Maple kann diese Funktion nicht differenzieren. Formulieren Sie die Prozedur um mittels des piecewise - Konstruktes – dann funktioniert es (ausprobieren). Testen Sie auch das Verhalten des plot-Befehles. (Ggf. quotes ’...’ verwenden!) Nun die eigentliche Aufgabenstellung: Angenommen, Sie haben irgendeine reelle, stückweise differenzierbare definierte Funktion als Prozedur p = p(x) vor sich, die mittels eines piecewiseKonstruktes (ev. auch mit mehrfachen Verzweigungen) definiert ist. Schreiben Sie eine Prozedur checkdiff(p,x[0]), die überprüft, ob p an der Stelle x[0] differenzierbar ist. Falls ja, ist der Wert der Ableitung an x[0] zurückzugeben. Falls nein, geben Sie zurück, was Sie für angemessen halten, z.B. einfach nur undefined. Aufgabe 15∗ . Schreiben Sie eine Maple-Prozedur invtable(t), die überprüft, ob die mittels einer gegebenen table t als assoziatives Array definierte Abbildung arg 7→ t[arg] injektiv ist (z.B. t[ich]:=Müller, t[du]:=Kuh, t[sie]:=Kuh). Falls ja, ist die inverse Abbildung als table zurückzugeben. Falls nein, ist eine ‘komprimierte’ Tabelle zurückzugeben, die zu jedem auftretenden Wert des Bildes alle zugehörigen Argumentwerte enthält, z.B. table([(Müller)=[ich],(Kuh)=[du,sie]]) (Siehe ? table, ? op, ? indices). Aufgabe 16∗ . Man schreibe eine Maple-Prozedur interpol2(f,x,xi::list), die eine gegebene reelle Funktion3 f an drei verschiedenen Stellen xi[1], xi[2], xi[3] durch ein Polynom 2 Copyright (c) W. Auzinger, 2008. All rights reserved. Die Funktion f selbst ist hier eigentlich irrelevant. Man kann auch einfach nur drei Werte f[1], f[2] ,f[3] vorgeben, die interpoliert werden. 3 p vom Grad 2 interpoliert (punktweise Übereinstimmung) und den Wert p(x) zurückliefert. Analog für Grad 1 (lineare Interpolation), interpol1(f,x,xi::list). Seien f, xi[] und die Auswertungsstelle x beliebig. Man vergleiche zunächst den erhaltenen Formelausdruck für p1..3 := interpol2(f,x,xi[1..3]) mit den erhaltenen Formeln für p1..2 := interpol1(f,x,xi[1..2]) und p2..3 := interpol1(f,x,xi[2..3]). Dies legt nahe, dass gilt p1..3 = α1,2 p1..2 + α2,3 p2..3 mit Koeffizienten α1,2 und α2,3 , die von x und xi[], aber nicht von f abhängig sind (ein Spezialfall des Lemmas von Aitken). Man berechne die Formelausdrücke für diese Koeffizienten. Aufgabe 17. Verallgemeinerung der vorhergehenden Aufgabe: Fabrizieren Sie einen Computergestützten ‘Beweis’ für das Lemma von Aitken, p1..n+1 = α1,n p1..n + α2,n+1 p2..n+1 , sinngemäß wie oben zu interpretieren, wobei an n + 1 Stellen xi[] mit Grad n (bzw. zweimal mit Grad n − 1) interpoliert wird. Die Koeffizienten α1,n und α2,n+1 sind gesucht! Anmerkung: Was hier unter ‘Beweis’ zu verstehen ist, darüber kann man debattieren. Ein rigoroser Beweis des Lemmas von Aitken erfolgt mittels vollständiger Induktion; derartige Induktionsbeweise sind meist einfach, wenn man die zu beweisende Identität bereits kennt (oder sich ihrer schon ziemlich sicher ist). In der Praxis hat man oft eine Vermutung, die z.B. durch Ausprobieren für kleine Werte von n entsteht. Dann schreibt man eine Prozedur, die dem Test dieser Vermutung für beliebige konkrete Werte von n dient – darauf läuft diese Aufgabe im wesentlichen hinaus. Aufgabe 18. Schreiben Sie eine Maple-Prozedur Lagrangepoly := proc(ty::listlist,t) description "Lagrange-Interpolation"; ... (vgl. ? listlist, ? Describe), die zu einer gegebenen Liste ty von Wertepaaren ty[k] = [tk , yk ] (Länge n, tk paarweise verschieden angenommen) das zugehörige Lagrange-Interpolationspolynom p(t) vom Grad ≤ n − 1 mit der Eigenschaft p(tk ) = yk , k = 1...n als Formelausdruck in der Variablen t zurückgibt. Man verwende folgende Darstellung für p (‘Lagrange-Darstellung’): p(t) = n X yk Lk (t) k=1 mit den sogenannten Lagrange-Polynomen Lk (t) vom Grad n − 1, die durch die Eigenschaft Lk (tj ) = δkj eindeutig festgelegt sind. (Man überlege, wie die Lk (t) darzustellen sind.) Was passiert, wenn eines der tk in der übergebenen Liste ty irrtümlich öfters auftritt? Man kann die Prozedur auch mit symbolischen Werten füttern und erhält dann das Polynom als Ausdruck in den betreffenden Parametern. Aufgabe 19. Schreiben Sie eine Maple-Prozedur convertlA(l), die eine Liste l, die aus Listen von Maple-Objekten besteht (z.B. [[a,b],[1,2,oops]]), in ein zweidimensionales Array konvertiert (? Array) und dieses zurückgibt. Beide Dimensionen des arrays sollen dabei nicht von 1 sondern von 0 weg indiziert werden. Falls die gegebenen Teil-Listen nicht gleich lang sind, sollen die jeweils ‘fehlenden’ Elemente mit 0 aufgefüllt werden. Im Beispiel ist das Ergebnis also Array(0..1,0..2,[[a,b,0],[1,2,oops]]) Aufgabe 20. Verwenden Sie Ihre Implementierung eines Stacks aus Serie 1, um eine Art Taschenrechner zu schreiben: Wir gehen davon aus, dass ein arithmetischer Ausdruck gegeben ist, z.B. als String, f := "(((4+13)*(22+2))-(1+8))" Als Operanden lassen wir der Einfachheit halber nur natürliche Zahlen zu; erlaubte Operationen sind +, − und *. Außerdem wird angenommen, dass jeder sich bei der Auswertung ergebende Teilausdruck in Klammern eingeschlossen ist (siehe Beispiel; auf eine Überprüfung dieser Voraussetzungen darf verzichtet werden). Damit ist auch der übliche ‘Vorrang’ einzelner Operanden (* vor +, −) hier kein Thema. Die Maple-Prozedur myeval(f) schreibt diesen Ausdruck der Reihe nach auf den Stack S, und zwar so lange, bis das oberste Element auf dem Stack eine schließende Klammer ) ist. (Zahlen werden als Zahlen auf den Stack gelegt; Klammern und Operationssymbole z.B. als Strings der Länge 1 oder als Namen (‘+‘) ). Dann werden die obersten 5 Elemente vom Stack entnommen; diese stellen genau einen Teilausdruck (inklusive öffnende und schließende Klammer) dar. Dieser wird nun ausgewertet und sein Ergebnis wird als Zahl auf den Stack zurückgeschrieben. Dann setzt man mit dem Scannen des Eingabestrings fort. Falls es sich um einen korrekten String gehandelt hat, besteht der Stack am Ende nur aus einem einzigen Element (ohne Klammern) – genau die Zahl, die dem Resultat des ausgewerteten Ausdruckes entspricht. Dieser Wert wird auch von myeval zurückgegeben. Man benötigt dazu auch eine Hilfsprozedur, die eine Folge von gescannten Zeichen, z.B. "1" gefolgt von "4" und "3" in eine Zahl umwandelt (143) – auf den Stack kommt das Ergebnis dieser Umwandlung. In obigem Beispiel entstehen z.B. folgende Zwischenzustände, ausgehend vom leeren Stack (nicht alle Zustände sind angegeben): (((4+13) 7→ ((17*(22+2) ((17*24) 7→ 7→ (408-(1+8) (408-9) ((17 7→ ((17*24 (408 7→ (408-9 399 . . . fertig. Bemerkung: Die richtige Abarbeitung der Vorrangregeln ist im Eingabestring durch eine entsprechende Klammerung sicherzustellen.