Einführung in numerische Simulation mit Python

Werbung
Einleitung
Sprachelemente
Nützliches
Einführung in numerische Simulation mit Python
Alexander Schlemmer, Jan Schumann-Bischoff, Tariq Baig
Max-Planck-Institut für Dynamik und Selbstorganisation,
Biomedizinische Physik
Nichtlineare Dynamik Praktikum
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Inhaltsverzeichnis
1
Einleitung
2
Sprachelemente
Numerik mit Numpy
Plots mit matplotlib
Scipy
3
Nützliches
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Python
Universelle Skriptsprache, meistens interpretiert
Fokus auf gute Lesbarkeit von Sourcecode
Open Source (Python Software Foundation License)
Existiert seit 1991
Wird gepflegt und weiter entwickelt von der Python Software
Foundation
Aktuell zwei (z.T. inkompatible) Hauptversionen:
Python 2.7 und Python 3.4
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Python: Merkmale
Große Anzahl an (frei) verfügbaren Bibliotheken
Im wissenschaftlichen Bereich: numpy, scipy, matplotlib
Dynamische Typisierung
Objektorientierung
Reduzierte, übersichtliche Syntax, wenige Schlüsselwörter
⇒ Leicht zu lernen
Als interpretierte Sprache eher langsam
→ Höhere Geschwindigkeit durch Vektorisierung von numerischen
Operationen
Schlechte Unterstützung von Threads (Multithreading)
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Python ausführen
Python-Interpreter ausführen:
p y t h o n # Python 2 ( a u f den m e i s t e n R e c h n e r n )
python3
Skript / Programm ausführen:
p y t h o n s k r i p t . py
Äußerst praktische interaktive Shell:
ipython
Interaktives (Web-)Notebook:
ipython notebook
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Einfache Beispiele
Erstes Beispiel
>>> print("Hello World!")
Hello World!
>>> # Das ist ein Kommentar
>>> a = 42
# Variablendeklaration
>>> print(a * 527 + abs(-0.1))
22134.1
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Variablendeklaration
>>> v = 1
>>> type(v)
<type ’int’>
>>> y = 17 + 4j
>>> type(y)
<type ’complex’>
>>> st = "str"
>>> type(st)
<type ’str’>
>>> tr = True
>>> type(tr)
<type ’bool’>
>>> x = 0.025
>>> type(x)
<type ’float’>
Mehr zu Typen unter:
https://docs.python.org/2/library/types.html
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Mathematische Operationen (1)
>>> # Einfache Ausdrücke:
>>> 42 * 5 + 8 - 2 / (17 + 4) + a
260
>>> # Division:
>>> 43.0 / 3
14.333333333333334
>>> 43 / 3 # Unterschied zw. Python 2 und 3!
14
>>> 43 // 3 # Ganzzahl-Division
14
>>> 43 % 3 # Modulo
1
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Weitere Operatoren
>>> # Potenzieren:
>>> # Komplexe Zahlen:
>>> 8**3
>>> c = 2 + 3j
512
>>> c.real
>>> 9**(-2)
2.0
0.012345679012345678
>>> c.imag
>>> # Vergleichen:
3.0
>>> 4 < 3
>>> c.conjugate()
False
(2-3j)
>>> "str" == "str"
>>> abs(c)
True
3.605551275463989
>>> 68 >= 17*4
True
>>> (not True == True) or (4 > 3 and 8 != 99)
True
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Mathematische Standardfunktionen
>>> from math import sqrt, exp
>>> from math import pi,sin,acos
>>> sqrt(2)
1.4142135623730951
>>> exp(a*-7)
2.0769322043867094e-128
>>> sin(0.5*pi)
1.0
>>> acos(1)
0.0
>>> import cmath
>>> cmath.exp(-1/2*pi*1j)
(-1-1.2246467991473532e-16j)
>>> cmath.log(32, 2)
(5+0j)
>>> cmath.log(-2).imag
3.141592653589793
https://docs.python.org/3/library/math.html
https://docs.python.org/3/library/cmath.html
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Listen
>>>
>>>
>>>
>>>
>>>
[3,
>>>
>>>
[1,
>>>
>>>
>>>
[1,
liste = [1, 3, 4, 5]
liste.append(7)
liste.extend([2, 3])
liste.reverse()
liste
2, 7, 5, 4, 3, 1]
liste.sort()
liste
2, 3, 3, 4, 5, 7]
liste.append("str")
liste.append([1, 3])
liste
2, 3, 3, 4, 5, 7, ’str’, [1,
>>>
1
>>>
[7,
>>>
5
>>>
[7,
>>>
216
liste[0]
liste[6:8]
’str’]
liste[-4]
liste[-3:]
’str’, [1, 3]]
liste[-1][1] * 72
3]]
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Bedingungen
if-elif-else-Block
>>> if a < 7:
...
b = 17
...
print(a*7)
... elif a > 7:
...
print(a/7)
... else:
...
print(a)
...
6
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Schleifen (1)
for-Loop über Liste
>>> for l in liste[0:2]:
...
print(l)
...
1
2
for-Loop über Range
>>> for l in range(-2,2):
...
if l % 2 == 0:
...
print(l)
...
-2
0
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Schleifen (2)
while-Loop
>>> i = 0
>>> while(i < 7):
...
i += 2 # i = i + 2
...
>>> print(i)
8
Mehr zu Control-Flow:
https://docs.python.org/3/tutorial/controlflow.html
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Funktionen
Funktionen definieren
>>> def f(x, y):
...
print("Funktionsaufruf")
...
b = a * x + y
...
return(b)
...
Funktionen aufrufen
>>> f(23, -2) * 4
Funktionsaufruf
3856
Mehr zu Funktionen: https://docs.python.org/3/tutorial/
controlflow.html#defining-functions
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Numerik mit Numpy
Numpy ist elementares Python Paket für numerische
Berechnungen in Python
Numpy bietet:
→ N-dimensionales Array Objekt
→ Indizierung ganzer Array Bereiche
→ Sehr schnelle Berechnung elementweiser Operationen
(Vektorisierung)
→ Viele Lineare Algebra Routinen wie Matrix Multiplikation,
SVD, Eigewertberechnungen, Invertierung,
Zufallszahlengeneratoren, Foiurier-Transformation, ...
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Indizierung von Python Arrays
Indizierung in Python ist Null-basiert (wie C)!
Numpy Arrays sind keine Listen oder Listen von Listen
Listen können zu Numpy Arrays konvertiert werden.
Eindimensionales Array (1)
>>> import numpy as np
>>> a = np.array([1., 4.5, 6.3, 4.1, 0.3, 9.4, 7.1])
>>> a
array([ 1. , 4.5, 6.3, 4.1, 0.3, 9.4, 7.1])
>>> a[2]
6.2999999999999998
>>> a.shape
(7,)
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Index ’von : bis : Schrittweite’ gibt Bereich im Array an
Eindimensionales Array (2)
>>> a = np.array([1., 4.5, 6.3, 4.1, 0.3, 9.4, 7.1])
>>> a[:3] # Das dritte Element ist NICHT enthalten!
array([ 1. , 4.5, 6.3])
>>> a[3:] # Das dritte Element IST enthalten!
array([ 4.1, 0.3, 9.4, 7.1])
>>> a[1:-2] # Indizierung bis vorvorletztem Element
array([ 4.5, 6.3, 4.1, 0.3])
>>> a[::2] # Indizierung mit Schrittweite 2
array([ 1. , 6.3, 0.3, 7.1])
>>> a[1:5:2]
array([ 4.5, 4.1])
>>> a[::-1] # Reihenfolge umdrehen
array([ 7.1, 9.4, 0.3, 4.1, 6.3, 4.5, 1. ])
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Zweidimensionale Arrays
>>> a = np.array([[4.2, 8.1, 7.9], [2.3, -7.6, 0.3]])
>>> a
array([[ 4.2, 8.1, 7.9],
[ 2.3, -7.6, 0.3]])
>>> a.shape
(2, 3)
>>> a[:,2]
array([ 7.9, 0.3])
>>> a[1,1:]
array([-7.6, 0.3])
>>> a.T
# transponieren
array([[ 4.2, 2.3],
[ 8.1, -7.6],
[ 7.9, 0.3]])
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Verändern von Elementen in Arrays
>>> a = np.array([[4.2, 8.1, 7.9], [2.3, -7.6, 0.3]])
>>> a[0,2] = 1
>>> a
array([[ 4.2, 8.1, 1. ],
[ 2.3, -7.6, 0.3]])
>>> a[:,1] = [8, 9]
>>> a
array([[ 4.2, 8. , 1. ],
[ 2.3, 9. , 0.3]])
>>> a[-1,:] = 3
>>> a
array([[ 4.2, 8. , 1. ],
[ 3. , 3. , 3. ]])
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Rechnen mit Arrays
Elementweises Rechnen in Numpy deutlich schneller als mit
eigenen Schleifen (wie in C, Fortran, ... üblich).
Quellcode sollte also vektorisiert sein.
>>> a = np.array([[4, 8, 7], [2., -7, 0]])
>>> a + 3
array([[ 7., 11., 10.],
[ 5., -4.,
3.]])
>>> np.sin(a)
array([[-0.7568025 , 0.98935825, 0.6569866 ],
[ 0.90929743, -0.6569866 , 0.
]])
>>> b = np.array([[1, 4, 3], [5, 2, 4.1]])
>>> a * b
# Achtung: elementweise Multiplikation!
array([[ 4., 32., 21.],
[ 10., -14.,
0.]])
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Spezielle Funktionen zum erzeugen von Arrays
>>> a = np.zeros((4,3)) # Array mit Nullen
>>> a = np.ones((4,3)) # Array mit Nullen
>>> np.arange(3, 9, 2) # Werte mit gleichem Abstand
array([3, 5, 7])
>>> np.diag([1, 2, 3]) # Diagonalmatrix
array([[1, 0, 0],
[0, 2, 0],
[0, 0, 3]])
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Lineare Algebra mit numpy
Lineare Algebra Routinen befinden sich in np.linalg
>>> a = np.array([[2, 1], [3, 4]])
>>> b = np.array([[4, 8, 7], [2., -7, 0]])
>>> np.dot(a,b) # Matrixmultiplikation
array([[ 10.,
9., 14.],
[ 20., -4., 21.]])
U, S, V = np.linalg.svd(a)
w, v
= np.linalg.eig(a)
# Singulärwertzerlegung
# Eigenwertberechnung
http://docs.scipy.org/doc/numpy/reference/routines.
linalg.html
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Kopieren und Referenzieren von Arrays
>>> a = np.array([4.2, 8.1, 7.9, 2.3, -7.6, 0.3])
>>> b = a
# Referenz auf gleichen Speicherbereich von a
>>> a[1:4] = 4
>>> a
array([ 4.2, 4. , 4. , 4. , -7.6, 0.3])
>>> b
array([ 4.2, 4. , 4. , 4. , -7.6, 0.3])
>>> b = np.copy(a) # Kopie von a
>>> a[-2:] = 3
>>> a
array([ 4.2, 4. , 4. , 4. , 3. , 3. ])
>>> b
array([ 4.2, 4. , 4. , 4. , -7.6, 0.3])
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Plots mit matplotlib
Matplotlib ist quasi Standard zum graphischen darstellen von
Daten
Beherrscht 2D und 3D Plots, Histogramme und vieles mehr
Gallery: http://www.matplotlib.org/gallery.html
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
1.0
2D Matplotlib - einzelner Plot (1)
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,10,0.01)
y = np.sin(x)
plt.plot(x,y)
0.0
plt.show()
1.00
0.5
0.5
2
Num. Sim. mit Python
4
6
8
10
2D Matplotlib - einzelner Plot (2)
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,10,0.01)
y = np.sin(x)
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.plot(x,y)
ax.set_xlabel(’$x$’)
ax.set_ylabel(’y’)
plt.savefig(’sinusx2.pdf’)
Numerik mit Numpy
Plots mit matplotlib
Scipy
1.0
0.5
y
Einleitung
Sprachelemente
Nützliches
0.0
0.5
1.00
2
Num. Sim. mit Python
4
x
6
8
10
Einleitung
Sprachelemente
Nützliches
2D Matplotlib - Histogramm
import matplotlib.pyplot as plt
import numpy as np
x = np.random.randn(10000)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.hist(x, 20)
ax.set_xlabel(’$x$’)
plt.savefig(’histogramm.pdf’)
Numerik mit Numpy
Plots mit matplotlib
Scipy
1600
1400
1200
1000
800
600
400
200
04
3
Num. Sim. mit Python
2
1
0
x
1
2
3
4
y
2D Matplotlib - subplots
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,10,0.01)
y = np.sin(x)
z = np.cos(x)
fig = plt.figure()
ax = fig.add_subplot(2,1,1)
ax.plot(x,y)
ax.set_ylabel(’y’)
ax = fig.add_subplot(2,1,2)
ax.plot(x,z,’--r’)
ax.set_ylabel(’z’)
ax.set_xlabel(’x’)
plt.savefig(’sincosx.pdf’)
Numerik mit Numpy
Plots mit matplotlib
Scipy
z
Einleitung
Sprachelemente
Nützliches
1.0
0.5
0.0
0.5
1.00
1.0
0.5
0.0
0.5
1.00
2
4
2
4
Num. Sim. mit Python
x
6
8
10
6
8
10
Einleitung
Sprachelemente
Nützliches
3D Matplotlib
from mpl_toolkits.mplot3d \
import Axes3D
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,50,0.1)
y = np.sin(x)
z = np.cos(x)
fig = plt.figure()
ax = fig.add_subplot(1,1,1,
projection=’3d’)
ax.plot(x,y,z,’.’)
ax.set_xlabel(’x’)
ax.set_ylabel(’y’)
ax.set_zlabel(’z’)
plt.savefig(’sincosx3d.pdf’)
Numerik mit Numpy
Plots mit matplotlib
Scipy
1.0
0.5
0 10
0.0y
20 30
0.5
x
40 50 1.0
Num. Sim. mit Python
0.5
0.0 z
0.5
1.0
1.0
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Scipy
Enthält weitere numerische Funktionen
Basiert auf Numpy
Beispiele:
→ Integrationsmethoden scipy.integrate
→ Minimierung von Funktionen scipy.optimize
→ Nächste Nachbarn Suche: scipy.spatial
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
DGL Integration
Numerische Integratoren für gewöhnliche
Differenzialgleichungen (DGLen) befinden sich im Paket
scipy
Gutes und genaues Integrationsverfahren ist Runge-Kutta45
(’dopri5’ in scipy)
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Beispiel: Lorenz63 model
Definition der Modell Gleichungen
def lorenz63(t,x):
x1 = x[0]
x2 = x[1]
x3 = x[2]
sigma
= 10
rho
= 28
beta
= 8./3
F = np.zeros(3)
F[0] = sigma*(x2-x1)
F[1] = x1*(rho-x3)-x2
F[2] = x1*x2-beta*x3
return F
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Beispiel: Lorenz63 model
Integration der Modell Gleichungen
from scipy.integrate import ode
N
= 2000
dt = 0.01
x
= np.zeros((N,3))
t
= np.arange(0,2000*dt,dt)
x[0,:] = [-4.70, 0.10, 29.10]
r = ode(lorenz63).set_integrator(’dopri5’)
r.set_initial_value(x[0,:], 0)
i = 0
while r.successful() and r.t < (N-1)*dt:
r.integrate(r.t+dt)
i = i + 1
x[i,:]
= r.y
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Numerik mit Numpy
Plots mit matplotlib
Scipy
Attraktor des Lorenz63 Modells
20 15 10
45
40
35
30x3
25
20
15
10
5
30
20
10
0
10 x2
50 5
x1 10 15 3020
20
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Dictionaries
Dictionary: Datenstruktur, um Key-Value-Paare zu speichern
Erzeugung
>>> d1 = {}
# Erzeugt ein leeres Dictionary
>>> # Dictionary mit einigen Key-Value-Paaren:
>>> d2 = {"key1": "value1", "key2": 728,
...
"key3": [2, 3, 8]}
Zugriff
>>> d2["key1"]
’value1’
>>> d2["key2"] = 17
Mehr zu Dictionaries: https://docs.python.org/2/tutorial/
datastructures.html#dictionaries
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Serialisierung: Das Pickle-Modul
... stellt Funktionen bereit, um (fast) beliebige komplexe
Datenstrukturen auf der Festplatte zu speichern und von dort
wiederherzustellen.
Erzeugung
>>> import pickle
>>> pickle.dump(d2, open("pickled_d2.dat", "wb"))
>>> new_d = pickle.load(open("pickled_d2.dat", "rb"))
>>> print(new_d)
{’key3’: [2, 3, 8], ’key2’: 17, ’key1’: ’value1’}
Num. Sim. mit Python
Einleitung
Sprachelemente
Nützliches
Weiteres Dokumentationsmaterial
Offizielles Python-Tutorial:
https://docs.python.org/3/tutorial/index.html
Stackoverflow:
http://stackoverflow.com/questions/tagged/python
Offizielles Numpy-Tutorial:
http://wiki.scipy.org/Tentative_NumPy_Tutorial
Scipy-Cookbook:
http://wiki.scipy.org/Cookbook
Offizielles SciPy-Tutorial:
http://docs.scipy.org/doc/scipy/reference/
tutorial/index.html
Num. Sim. mit Python
Herunterladen