computational analysis - math.uni-luebeck.de · programmiert man in java rekursiv, so hat man immer...

8
Computational Analysis Computergestützte Mathematik am Beispiel Mathematica Im Rahmen der Veranstaltung Analysis II im Sommersemster 2012 Ronny Bergmann Institut für Mathematik, Universität zu Lübeck zuletzt geändert 17. April 2013 Homepage: math.uni-luebeck.de/mitarbeiter/bergmann/comp-ana-ss13.php Anmelden an den Rechnern: Login: mathestudenten, Passwort: ******** Anmerkungen und Bedienung von Mathematica Statt vor der Abgabe: (1) Evaluation -> Quit Kernel -> Local. (2) Evaluation Evaluate Notebook durchzuführen, kann auch statt (1) Quit[] verwendet werden. Bis auf einige kleine Fehler waren die Abgaben super. denkt dran, Variablennamen nicht für Funktionen zu verwenden In[2]:= mywert = 4; In[3]:= mywert@x_D := 8x SetDelayed::write : Tag Integer in 4@x_D is Protected. Out[3]= $Failed Denkt an := bei den Funktionsdefinitionen Funktionen immer mit Argument in [] - auch bei bekannten Funktionen wie Cosinus. Funktionsname, die Mathematica bereits implementiert hat, beginnen mit einem großen Buchstaben. Was also formell cos(3x) heißt, schreibt man in Mathematica Cos[3x]. Teil II: Funktionen, private Variablen, Kontrollstrukturen und Rekursion Motivationsbeispiel: Zwei verschiedene Arten zu Programmieren Wir beginnen heute mal mit einem kleinen Experiment, dass die Vorteile von Mathematica darstellt. Wir mö chten folgendes berechnen: Gegeben sei d HnL = i=1 n j=1 n i * j, n ˛ N. Wie bestimmt man den Wert von d für ein gegebenes n mö glichst effizient?

Upload: duongdat

Post on 25-Aug-2019

214 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Computational Analysis - math.uni-luebeck.de · Programmiert man in Java rekursiv, so hat man immer eine If-Abfrage, ob man bereits am Ende ist. Dies geht in Mathematica schöner

Computational AnalysisComputergestützte Mathematik am Beispiel Mathematica

Im Rahmen der Veranstaltung Analysis II im Sommersemster 2012

Ronny Bergmann

Institut für Mathematik, Universität zu Lübeck

zuletzt geändert 17. April 2013

Homepage: math.uni-luebeck.de/mitarbeiter/bergmann/comp-ana-ss13.php

� Anmelden an den Rechnern: Login: mathestudenten, Passwort: ********

Anmerkungen und Bedienung von Mathematica

� Statt vor der Abgabe: (1) Evaluation -> Quit Kernel -> Local. (2) Evaluation Evaluate Notebook

durchzuführen, kann auch statt (1) Quit[] verwendet werden.

� Bis auf einige kleine Fehler waren die Abgaben super.

� denkt dran, Variablennamen nicht für Funktionen zu verwenden

In[2]:= mywert = 4;

In[3]:= mywert@x_D := 8 x

SetDelayed::write : Tag Integer in 4@x_D is Protected. �

Out[3]= $Failed

� Denkt an := bei den Funktionsdefinitionen

� Funktionen immer mit Argument in [] - auch bei bekannten Funktionen wie Cosinus.

Funktionsname, die Mathematica bereits implementiert hat, beginnen mit einem großen

Buchstaben. Was also formell cos(3x) heißt, schreibt man in Mathematica Cos[3x].

Teil II: Funktionen, private Variablen, Kontrollstrukturen

und Rekursion

Motivationsbeispiel: Zwei verschiedene Arten zu Programmieren

Wir beginnen heute mal mit einem kleinen Experiment, dass die Vorteile von Mathematica darstellt.

Wir möchten folgendes berechnen:

Gegeben sei

d HnL = âi=1

n

âj=1

n

i*j , n Î N.

Wie bestimmt man den Wert von d für ein gegebenes n möglichst effizient?

Page 2: Computational Analysis - math.uni-luebeck.de · Programmiert man in Java rekursiv, so hat man immer eine If-Abfrage, ob man bereits am Ende ist. Dies geht in Mathematica schöner

In[4]:=

Aus Java kennt man bereits die For - Schleife, nur dass sie hier wieder wie eine Funktion

geschrieben wird, in der die Argumente mit , getrennt werden:

In[5]:= ? For

For@start, test, incr, bodyD executes start, then repeatedly evaluates body and incr until test fails to give True. �

Bereiche für lokale Variablen (die werden dann ebenso grün gesetzt) ermöglicht die Funktion

Module

In[6]:= ? Module

Module@8x, y, … <, exprD specifies that occurrences of the symbols x, y, … in expr should be treated as local.

Module@8x = x0, … <, exprD defines initial values for x, … . �

Damit können wir einmal – nach den Gedanken eines Informatikers – die oben genannte Summe

berechnen, denn das ist ja lediglich eine Ineinanderschachtelung zweier For-Schleifen:

In[7]:= doppelsumme@n_D := Module@8summe, i, j<,summe = 0;

For@i = 1, i £ n, i++,

For@j = 1, j £ n, j++,

summe += i * j;

D;D;Return@summeD;

D;

In[8]:= doppelsumme@1000D

Out[8]= 250500250000

Der Mathematiker kommt vielleicht auf die Idee, den Term vorher einmal zu vereinfachen, vor allem

kennt er aber (und ihr ja nun auch bald) die vielen Möglichkeiten von Mathematica, zum Beispiel

den ersten und vorletzten Ausdruck in der Hilfe

In[9]:= ? Sum

Sum@ f , 8i, imax<D evaluates the sum âi=1

imax

f .

Sum@ f , 8i, imin, imax<D starts with i = imin.

Sum@ f , 8i, imin, imax, di<D uses steps di.

Sum@ f , 8i, 8i1, i2, … <<D uses successive values i1, i2, … .

Sum@ f , 8i, imin, imax<, 8 j, jmin, jmax<, … D evaluates the multiple sum âi=imin

imax

âj= jmin

jmax

… f .

Sum@ f , iD gives the indefinite sum âi

f . �

In[10]:= doppelsumme2@n_D := Sum@ Sum@i * j, 8j, 1, n<D, 8i, 1, n<D

Oder noch kürzer

2 2-Funktionen.nb

Page 3: Computational Analysis - math.uni-luebeck.de · Programmiert man in Java rekursiv, so hat man immer eine If-Abfrage, ob man bereits am Ende ist. Dies geht in Mathematica schöner

In[11]:= doppelsumme3@n_D := Sum@i * j, 8j, 1, n<, 8i, 1, n<D

Und wir vergleichen einmal die Laufzeiten indem wir den Befehl Timing betrachten

In[12]:= ? Timing

Timing@exprD evaluates expr, and returns a list of the time in seconds used, together with the result obtained. �

In[13]:= Timing@doppelsumme@1000DD

Out[13]= 83.879936, 250500250000<

In[14]:= Timing@doppelsumme2@1000DD

Out[14]= 80.137774, 250500250000<

In[15]:= Timing@doppelsumme3@1000DD

Out[15]= 80.033694, 250500250000<

In[16]:= doppelsumme@nD

Out[16]= 0

In[17]:= doppelsumme3@nD

Out[17]=

1

4

n2 H1 + nL2

Und die schnellste Lösung?

weitere Kontrollstrukturen I – bekannt aus Java

In[20]:= ? If

If@condition, t, f D gives t if condition evaluates to True, and f if it evaluates to False.

If@condition, t, f , uD gives u if condition evaluates to neither True nor False. �

In[21]:= ? Do

Do@expr, 8imax<D evaluates expr imax times.

Do@expr, 8i, imax<D evaluates expr with the

variable i successively taking on the values 1 through imax Hin steps of 1L.Do@expr, 8i, imin, imax<D starts with i = imin.

Do@expr, 8i, imin, imax, di<D uses steps di.

Do@expr, 8i, 8i1, i2, … <<D uses the successive values i1, i2, … .

Do@expr, 8i, imin, imax<, 8 j, jmin, jmax<, … D evaluates expr looping over different values of j, etc. for each i. �

Wobei Do eine wirklich nette Eigenschaft mit sich bringt, wenn man mal die vorletzte Beschreibung

betrachtet, so können wir eine Menge definieren, indem wir einen Vektor bauen

2-Funktionen.nb 3

Page 4: Computational Analysis - math.uni-luebeck.de · Programmiert man in Java rekursiv, so hat man immer eine If-Abfrage, ob man bereits am Ende ist. Dies geht in Mathematica schöner

In[22]:= ? Table

Table@expr, 8imax<D generates a list of imax copies of expr.

Table@expr, 8i, imax<D generates a list of the values of expr when i runs from 1 to imax.

Table@expr, 8i, imin, imax<D starts with i = imin.

Table@expr, 8i, imin, imax, di<D uses steps di.

Table@expr, 8i, 8i1, i2, … <<D uses the successive values i1, i2, … .

Table@expr, 8i, imin, imax<, 8 j, jmin, jmax<, … D gives a nested list. The list associated with i is outermost. �

In[23]:= S = Table@Prime@nD, 8n, 1, 20<D

Out[23]= 82, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71<

Dabei funktioniert Table fast wie Do, nur dass es einen Vektor an Werten zurückgibt, in diesem Fall

die ersten 20 Primzahlen. Dann können wir mit Do etwas für alle Elemente aus S ausrechnen :

In[24]:= Do@Print@"Die Wurzel der Zahl ", x,

" ist ", Sqrt@xD, " Hnumerisch: ", N@Sqrt@xDD, "L."D;, 8x, S<

D

Die Wurzel der Zahl 2 ist 2 Hnumerisch: 1.41421L.

Die Wurzel der Zahl 3 ist 3 Hnumerisch: 1.73205L.

Die Wurzel der Zahl 5 ist 5 Hnumerisch: 2.23607L.

Die Wurzel der Zahl 7 ist 7 Hnumerisch: 2.64575L.

Die Wurzel der Zahl 11 ist 11 Hnumerisch: 3.31662L.

Die Wurzel der Zahl 13 ist 13 Hnumerisch: 3.60555L.

Die Wurzel der Zahl 17 ist 17 Hnumerisch: 4.12311L.

Die Wurzel der Zahl 19 ist 19 Hnumerisch: 4.3589L.

Die Wurzel der Zahl 23 ist 23 Hnumerisch: 4.79583L.

Die Wurzel der Zahl 29 ist 29 Hnumerisch: 5.38516L.

Die Wurzel der Zahl 31 ist 31 Hnumerisch: 5.56776L.

Die Wurzel der Zahl 37 ist 37 Hnumerisch: 6.08276L.

Die Wurzel der Zahl 41 ist 41 Hnumerisch: 6.40312L.

Die Wurzel der Zahl 43 ist 43 Hnumerisch: 6.55744L.

Die Wurzel der Zahl 47 ist 47 Hnumerisch: 6.85565L.

Die Wurzel der Zahl 53 ist 53 Hnumerisch: 7.28011L.

Die Wurzel der Zahl 59 ist 59 Hnumerisch: 7.68115L.

Die Wurzel der Zahl 61 ist 61 Hnumerisch: 7.81025L.

Die Wurzel der Zahl 67 ist 67 Hnumerisch: 8.18535L.

Die Wurzel der Zahl 71 ist 71 Hnumerisch: 8.42615L.

In[25]:= ? While

While@test, bodyD evaluates test, then body, repetitively, until test first fails to give True. �

weitere Kontrollstrukturen II – der funktionale Anteil von Mathematica

Programmiert man in Java rekursiv, so hat man immer eine If-Abfrage, ob man bereits am Ende

ist. Dies geht in Mathematica schöner. Beispiel: Die Fibonacci - Zahlen

4 2-Funktionen.nb

Page 5: Computational Analysis - math.uni-luebeck.de · Programmiert man in Java rekursiv, so hat man immer eine If-Abfrage, ob man bereits am Ende ist. Dies geht in Mathematica schöner

Programmiert man in Java rekursiv, so hat man immer eine If-Abfrage, ob man bereits am Ende

ist. Dies geht in Mathematica schöner. Beispiel: Die Fibonacci - Zahlen

In[26]:= Fib@n_D := Fib@n - 1D + Fib@n - 2D;Fib@0D := 0;

Fib@1D := 1;

Also lassen wir uns mal die ersten 13 Zahlen ausgeben

In[29]:= Table@Fib@nD, 8n, 0, 12<D

Out[29]= 80, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144<

Diese Art zu programmieren ist funktional , die Definition dieser Funktion folgt der Idee des „Pattern

Matching“ - zu deutsch : musterbasierte Suche. Es wird diejenige Definition der 3 obigen gewählt,

die „am besten“ übereinstimmt, hier also für 0 und 1 die zweite bzw. dritte Zeile, sonst (weil nichts

besser passt) die erste.

Was man sich für größere und komplizierte Funktionen angewöhnen sollte ist eine Beschreibung

der Funktion. Diese kann man angeben mit ::usage

In[30]:= Fib::usage = "Fib@nD gibt die n-te Zahl der Fibonacci-Folge zurück.";

Dann hat man eine eigene Hilfe geschrieben :

In[31]:= ? Fib

Fib@nD gibt die n-te Zahl der Fibonacci-Folge zurück.

In Mathematica lassen sich weitere Forderungen an die Eingabe definieren, indem man statt mit ;

mit /; die Definition beendet und dann einen aussagenlogischen Ausdruck angibt. Beispiel : Eine

Funktion, die nur für Primzahlen definiert ist.

In[32]:= ? PrimeQ

PrimeQ@exprD yields True if expr is a prime number, and yields False otherwise. �

In[33]:= H*Der Dritte Fall betrifft uns*L ? /;

patt �; test is a pattern which matches only if the evaluation of test yields True.

lhs :> rhs �; test represents a rule which applies only if the evaluation of test yields True.

lhs := rhs �; test is a definition to be used only if test yields True. �

In[34]:= NumPrime@x_D := Module@8i<,i = 1;

While@Prime@iD ¹ x,

i++D;Return@iD;

D �; HPrimeQ@xDL H*Beim Aufruf wird geprüft,

ob x eine Primzahl ist, nur dann wird die Funktion ausgeführt*L

In[35]:= NumPrime::usage = "Gibt die Nummer zurück,

die eine Primzahl in der Folge der Primzahlen einimmt.";

Dann gibt die Funktion einen Wert zurück, falls die Eingabe eine Primzahl ist :

In[36]:= NumPrime@17D

Out[36]= 7

Und ist für andere Zahlen nicht definiert, was so aussieht :

2-Funktionen.nb 5

Page 6: Computational Analysis - math.uni-luebeck.de · Programmiert man in Java rekursiv, so hat man immer eine If-Abfrage, ob man bereits am Ende ist. Dies geht in Mathematica schöner

In[37]:= NumPrime@8D

Out[37]= NumPrime@8D

Eine andere Möglichkeit eine Funktion zu definieren ist der Befehl Function. Hier wird eine reine

Funktion erzeugt, ohne dass sie einen Namen bekommt. So kann man beispielsweise eine Funktion

zurückgeben:

In[38]:= ? Function

Function@bodyD or body & is a pure function. The formal parameters are ð Hor ð1L, ð2, etc.

Function@x, bodyD is a pure function with a single formal parameter x.

Function@8x1, x2, … <, bodyD is a pure function with a list of formal parameters. �

In[39]:= generateFunction@a_, b_, c_D := Function@x, a * x^2 + b * x + cD

Erzeugt Funktionen, die eine Unbekannte haben und gibt diese zurück :

In[40]:= generateFunction@2, 2, 2D

Out[40]= FunctionAx$, 2 x$2

+ 2 x$ + 2E

Und man kann dort gleich einen Wert einsetzen oder sich das symbolisch anschauen, etwa

In[41]:= generateFunction@2, 2, 2D@4D

Out[41]= 42

In[42]:= generateFunction@2, 2, 2D@yD

Out[42]= 2 + 2 y + 2 y2

Oder selbst aus dem Ergebis eine Funktion erzeugen

In[43]:= g@x_D := generateFunction@2, 2, 2D@xD

In[44]:= g@4D

Out[44]= 42

Aufgaben

Wir beginnen mit den Aufgaben in dieser Veranstaltung, aber mailt mir bitte eure Ergebnisse an

[email protected] jeweils in Zweiergruppen mit Name/Matrikelnummer. Natürlich

gehe ich jetzt mit rum und helfe beim Bearbeiten.

Aufgabe 1

Schreibe die rekursive Funktion fakultaet[n], die n! berechnet. Und gebe 30! aus.

Aufgabe 2

Die Collatz-Folge ist definiert als:

Gegeben sei ein Startwert x0 = k. Dann ist

xn=

xn-1

2falls xn-1 gerade,

3 xn-1 + 1 falls xn-1 ungerade,für n Î N

Und sie endet, falls xn = 1. (denn danach würde eine sich immer wiederholende Folge

1,4,2,1,4,2,1,... ergeben).

Schreibe eine rekursive Funktion Collatz[k], welche die Collatz-Folge für einen Startwert k

zurückgibt.

Schreibe dafür eine rekursive Funktion CollatzRek[s], die an den Vektor s so lange Elemente

anfügt, bis der letzte Eintrag in s eine 1 ist. Starte in der Funktion Collatz[n] lediglich die Rekursion

mit einem geeigneten Vektor s.

Nützliche Befehle: Last für den Zugriff auf das letzte Element von s, Append zum Anfügen, sowie

EvenQ und OddQ für die Mustertests, beachte dabei, dass im ungeraden Fall zusätzlich dieses letzte

Element nicht 1 sein darf, denn dafür gibt es einen extra Fall.

Prüfe deine Funktion mit dem Startwert 7 und gib die Folge an.

Wie viele Folgenglieder haben die Folgen mit den Startwerten 1199,1200 und 1201 ?

6 2-Funktionen.nb

Page 7: Computational Analysis - math.uni-luebeck.de · Programmiert man in Java rekursiv, so hat man immer eine If-Abfrage, ob man bereits am Ende ist. Dies geht in Mathematica schöner

Die Collatz-Folge ist definiert als:

Gegeben sei ein Startwert x0 = k. Dann ist

xn=

xn-1

2falls xn-1 gerade,

3 xn-1 + 1 falls xn-1 ungerade,für n Î N

Und sie endet, falls xn = 1. (denn danach würde eine sich immer wiederholende Folge

1,4,2,1,4,2,1,... ergeben).

Schreibe eine rekursive Funktion Collatz[k], welche die Collatz-Folge für einen Startwert k

zurückgibt.

Schreibe dafür eine rekursive Funktion CollatzRek[s], die an den Vektor s so lange Elemente

anfügt, bis der letzte Eintrag in s eine 1 ist. Starte in der Funktion Collatz[n] lediglich die Rekursion

mit einem geeigneten Vektor s.

Nützliche Befehle: Last für den Zugriff auf das letzte Element von s, Append zum Anfügen, sowie

EvenQ und OddQ für die Mustertests, beachte dabei, dass im ungeraden Fall zusätzlich dieses letzte

Element nicht 1 sein darf, denn dafür gibt es einen extra Fall.

Prüfe deine Funktion mit dem Startwert 7 und gib die Folge an.

Wie viele Folgenglieder haben die Folgen mit den Startwerten 1199,1200 und 1201 ?

Tipps

Da Colatz[n] die Folge der Werte zurückgeben soll, muss in jedem Schritt ein Element angefügt

werden und wir beginnen mit, also wissen wir

In[45]:= Collatz@n_D := CollatzRek@8n<D

Wir stellen uns vor, wir haben schon einige Elemente angefügt, haben also die Situation, dass die

Funktion CollatzRek[s_] aufgerufen wird mit einer Menge S={n, m1,m2,m3,...mk}. Wobei das Ganze

entstanden ist nach den obigen Regeln, also m1 ist n/2 falls n gerade oder 3n+1 falls n ungerade

usw. Wir müssen zunächst also einen Nachfolger bestimmen, den wir anfügen.

Welche Fälle gibt es?

Für die letzten beiden Fälle (ha! verraten, es gibt wohl drei oder mehr) haben wir eine neue Menge

S, was ist mit dieser zu tun?

Tipps zu den Befehlen:

Für eine Menge gibt uns der Befehl Last das letzte Element (genau das wollen wir ja immer betra-

chten), Beispielsweise

In[46]:= Last@8Π, E, 1, 2, 4, 1, 2<D

Out[46]= 2

Append fügt ein Element an, wenn wir den Nachfolger also bestimmt haben, hilft uns Append

In[47]:= Append@87, 22<, 11D

Out[47]= 87, 22, 11<

Naja und EvenQ[] und OddQ[] sind für die Abfragen in welchem der Fälle wir sind (wenn das letzte

Element nicht eh 1 ist)

In[48]:= a = 3;

If@EvenQ@aD, Print@"a ist gerade"D, Print@"a ist ungerade"DD

a ist ungerade

Aufgabe 3

Schreibe eine Funktion Taylor[n_, x0_, f_], die für eine univariate Funktion f(x) das n-te Taylor-

polynom als Funktion zurückgibt. Benutze dazu die Befehle Sum, Binomial, ! (Factorial) und D,

jedoch nicht Series.

Beachte dabei die Auswertungsreihenfolge (wie beim Integral brauchen wir also eventuell

Evaluate.)

1) Berechne zuerst die Summe

2) Baue eine implizite Funktion in x daraus und gebe dieses Ergebnis zurück.

Zusatzaufgabe: Gebe auch die Bedingungen an die Parameter an.

Gib dann die Taylorpolynome T4 und T5zu der Funktion f(x) = e2 x+Π

an der Stelle x0 = 0 an. Da Die

oben implementierte Funktion eine Funktion zurückgibt musst du natürlich noch einen symbolischen

Wert einsetzen, um das Polynom zu betrachten.

Zusatzaufgabe: Plotte beide Taylorpolynome zusammen mit f auf dem Intervall [-2,2]. Nutze dazu

den Befehl Plot und schau dir an, wie du mehrere Funktionen in einem Plot darstellen kannst.

2-Funktionen.nb 7

Page 8: Computational Analysis - math.uni-luebeck.de · Programmiert man in Java rekursiv, so hat man immer eine If-Abfrage, ob man bereits am Ende ist. Dies geht in Mathematica schöner

Schreibe eine Funktion Taylor[n_, x0_, f_], die für eine univariate Funktion f(x) das n-te Taylor-

polynom als Funktion zurückgibt. Benutze dazu die Befehle Sum, Binomial, ! (Factorial) und D,

jedoch nicht Series.

Beachte dabei die Auswertungsreihenfolge (wie beim Integral brauchen wir also eventuell

Evaluate.)

1) Berechne zuerst die Summe

2) Baue eine implizite Funktion in x daraus und gebe dieses Ergebnis zurück.

Zusatzaufgabe: Gebe auch die Bedingungen an die Parameter an.

Gib dann die Taylorpolynome T4 und T5zu der Funktion f(x) = e2 x+Π

an der Stelle x0 = 0 an. Da Die

oben implementierte Funktion eine Funktion zurückgibt musst du natürlich noch einen symbolischen

Wert einsetzen, um das Polynom zu betrachten.

Zusatzaufgabe: Plotte beide Taylorpolynome zusammen mit f auf dem Intervall [-2,2]. Nutze dazu

den Befehl Plot und schau dir an, wie du mehrere Funktionen in einem Plot darstellen kannst.

8 2-Funktionen.nb