#!/usr/bin/env python
# coding: utf-8
# # Python Kurzeinführung
#
# [Python](http://www.python.org) ([Wikipedia](http://en.wikipedia.org/wiki/Python_%28programming_language%29))
# ist eine
# [multiparadigmatische](http://en.wikipedia.org/wiki/Programming_paradigm#Multi-paradigm)
# ([imperativ](http://en.wikipedia.org/wiki/Imperative_programming),
# [prozedural](http://en.wikipedia.org/wiki/Procedural_programming),
# [funktional](http://en.wikipedia.org/wiki/Functional_programming),
# und
# [objektorientierte](http://en.wikipedia.org/wiki/Object-oriented_programming)) Programmiersprache.
# Sie wurde 1991 von [Guido van Rossum](http://en.wikipedia.org/wiki/Guido_van_Rossum) veröffentlicht
# und wurde von [ABC](http://en.wikipedia.org/wiki/ABC_%28programming_language%29),
# Java, Haskell und anderen Sprachen maßgeblich beeinflusst.
# Seit bald 10 Jahren gehört sie zu den am weitesten verbreiteten und flexiblesten Programmiersprachen weltweit.
# Aus der Sicht der Mathematik ist die große Sammlung an mathematischen, statistischen und wissenschaftlichen
# [Programmbibliotheken](http://en.wikipedia.org/wiki/Library_%28computing%29) hervorzuheben,
# und darauf aufbauende Tools wie Sage erwähnenswert.
# Außerdem ist Python eine exzellente Sprache zum funktionellen Kombinieren diverser Programme, Utilities und Systeme.
# Der beste Weg Python kennen zu lernen ist ein Sprung ins kalte Wasser.
# Ein Programm zu programmieren folgt keinen kochrezeptartigen Regeln,
# sondern bedarf des kreativen Kombinierens von Konzepten, Regeln und Ideen.
# Daher ist kreatives Denken und ein Schatz an Erfahrungen wichtig --
# ganz ähnlich wie das Führen von Beweisen in der Mathematik.
#
# Die Funktionsweise der hier vorliegenden Worksheets ist die folgende:
# Die mit `In[]` gekennzeichneten Boxen sind die Eingabezellen.
# In ihnen stehen in oder mehrere Zeilen Code.
# Durch betätigen des Buttons oder der + Tasten wird die aktive Zelle ausgeführt.
# Die Ausgabe steht darunter und ist mit `Out[n]` gekennzeichnet.
#
# Die folgenden Beispiele zeigen anschauliche Beispiele,
# die einen ersten groben Umriss um die Funktionalität Python's liefert.
# Davon neugierig gemacht, werden in der Folge die darin vorkommenden Grundprinzipien erklärt.
# Keine Scheu, kopiere einzelne Zellen in ein neues IPython Notebook und fange an zu experimentieren!
# ## Einfache Rechenbeispiele
# In[1]:
14 + 3 * (8 - 1)
# Achtung, potenziert wird mit `**`!
# In[2]:
banane = 3**2 + 1
print(banane)
# Hierbei ist `banane` eine Variable, die auf den Wert `10` gesetzt wurde.
# Das ist das Ergebnis der Auswertung des Ausdrucks `3**2 + 1`.
# Abgerufen kann der Wert von `banane`, wenn es an letzter Stelle einer Code-Zelle steht,
# oder durch den `print` Befehl.
# In[3]:
print(banane)
# In[4]:
banane
# Für "mathematisches" Dividieren muss mindestens ein Argument eine Flißekommazahl sein;
# Ganzzahldivisionen werden abgerundet!
# (Ausnahme: entweder es ist Python in Version 3 **oder** mittels `from __future__ import division` wurde das modernere Verhalten importiert)
# In[5]:
(2.2 * 9.81) / 2
# Beide Zahlen sind Ganzzahlen, daher striktes Abrunden:
# In[6]:
51 / 10
# Ist mindestens eine der beiden Zahlen eine Fließkommazahl (sichtbar an dem kleinen `.` nach der `51`),
# so wird eine Fließkommadivision durchgeführt.
# In[7]:
51. / 10
# Aktivieren des alternativen Verhaltens für Divisionen.
# In[8]:
from __future__ import division
51 / 10
# Das IPython Notebook merkt sich derweilen weiter oben definierte Variable `banane`,
# solange die "Session" aktiv ist.
# Kernel > Restart bzw. starten die Session neu.
# `print` kann in Python 2 als Statement verwendet werden,
# es geht aber auch die in Python 3 gebräuchliche Variante als Funktion.
# Damit können jederzeit Zwischenergebnisse, die während des Ablaufs des Programmes passieren, ausgegeben werden.
# Ansonsten wird immer nur der Wert des letzten Ausdrucks ausgegeben.
# In[9]:
apfel = 8.76
print(3 * banane + 2 * apfel)
apfel = 9.81
print(2 * banane + apfel)
# Brüche können mit `Fraction` angegeben werden
# In[10]:
from fractions import Fraction
a = Fraction("33/31003100")
b = Fraction("-9/100000100001")
a * b ** 4
# Liste von Zahlen von 0 bis 9. Es ist außerdem und ganz generell so, dass bei `0` zu zählen begonnen wird und Intervalle auf der linken Seite geschlossen und auf der rechten Seite offen sind.
# In[11]:
range(10)
# Jede dritte Zahl in $-10 \leq x < 10,\; x \in \mathbb{Z}$
# In[12]:
range(-10, 10, 3)
# Eine `for`-Schleife iteriert -- das heißt, sie wiederholt den darin vorhandenen Codeblock -- für alle angegebenen Werte:
# In[13]:
for x in range(-10, 10, 4):
y = 3 * x + 1
print("x ist %3d und y ist %3d" % (x, y))
# `if`-Verzweigungen erlauben, Codeblöcke nur unter bestimmten Bedingungen auszuführen.
# Das Wort `else` kann optional dazu verwendet werden, einen Codeblock bei nichterfüllung der Bedingung auszuführen.
# In[14]:
k = -4
if k >= 0:
print("k ist positiv")
else:
print("k ist negativ")
# Eine `for`-Schleife mit einer darin enthaltenen `if`-Bedingung.
# Sie summiert alle Zahlen bis 100, die durch 3 und 7 teilbar sind, auf:
# In[15]:
summe = 0
for i in range(100):
if i % 3 == 0 and i % 7 == 0:
summe += i
print(summe)
# Das `import` Statement dient dazu, Funktionalitäten aus diversen Programmbibliotheken zu importieren.
#
# Beispiel: Die Sinusfunktion `sin` aus der `math`-Bibliothek importieren und mit Standardgenauigkeit berechnen.
# In[16]:
from math import sin
sin(3.1415926535)
# Hier wird die `sin`-Funktion mit 100 Stellen Genauigkeit durch dessen Version in der `mpmath`-Bibliothek in Sympy berechnet.
# Beachte, dass `mpm` vorangestellt wird, um Vermischungen mit der schon importieren `sin` zu vermeiden.
# In[17]:
import sympy.mpmath as mpm
mpm.mp.dps = 100
mpm.sin(mpm.mpf("3.1415926535"))
# ## Symbolische Ausdrücke, Funktionen, Differenzieren
#
# Symbolische Ausdrücke können mit der Programmbibliothek `SymPy` erzeugt werden.
# Hierfür importieren wir z.B. in einem ersten Schritt die Variable $x$ und den Operator $\sin$,
# mit der die Ausdrücke aufgebaut werden.
# In[18]:
from sympy import sin, pi
from sympy.abc import x
# $f(x) := \frac{2 x}{x - \sin(x)}$
# In[19]:
f = 2 * x / (x - sin(x))
f
# Differenzieren nach $x$ mit `.diff(x)` und anschließendes Vereinfachen des Ausdrucks durch `.simplify()`.
# In[20]:
f_prime = f.diff(x).simplify()
f_prime
# ## Auswertung von symbolischen Ausdrücken
# Hier wird das `x` in dem zuvor definierten symbolischen Ausdruck `f` mittels der Methode `.subs(, )` ersetzt.
# $f(x)\Big\rvert_{x=1}=\dots$
# In[21]:
f.subs(x, 1)
# pi wurde weiter oben via `from sympy import pi` definiert.
#
# $f(x)\Big\rvert_{x=\pi}=\dots$
# In[22]:
f.subs(x, pi)
# Numerische Auswertung nach der Substitution durch `.evalf()`
# In[23]:
f.subs(x, 1).evalf()
# In[24]:
f.subs(x, 1).evalf(100)
# ## $\LaTeX{}$-Formatierung mittels SymPy:
# In[25]:
from IPython.display import Math
from sympy import latex
# In[26]:
Math(latex(f))
# In[27]:
Math(latex(f_prime))
# ## Listen und Listenverarbeitung
# Eine "Liste" ist eine geordnete Sammlung von Objekten.
# Sie ist so ziemlich die zentralste *Datenstruktur* überhaupt.
# In[28]:
l1 = ["Haus", 99]
l1
# In[29]:
l2 = ["a", 0, "x"]
l2
# In[30]:
l1 + l2
# Verarbeiten von Listen mittels
#
# `[ for in ]`
#
# (genannt "list-comprehension")
# In[31]:
ll = [2., 2.5, 3., 5., 8.1, 10., 22.]
k1 = [2*i-2 for i in ll]
k1
# In[32]:
[k**2 + 2*k + 1 for k in range(10)]
# Zugriff auf Elemente in einer Liste -- achtung, wie schon erwähnt wird ab `0` indiziert.
# In[33]:
p = ["P", "y", "t", "h", "o", "n"]
p[3]
# Das zweit-letzte Element mittels `-2`
# In[34]:
p[-2]
# ## Grafische Darstellungen
#
# Dies geschieht mittels der `matplotlib`-Bibliothek. Sie muss zur Ausgabe von Grafiken aktiviert werden:
# In[35]:
get_ipython().run_line_magic('matplotlib', 'inline')
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (10,6)
# ### Plotten paarweiser Punkte
#
# `xx` und `yy` beinhalten jeweils die x- und y-Koordinaten.
# In[36]:
xx = [20, 15, 11, 7.57, 9.6, 13, 21, 24, 28, 23, 20]
yy = [3, 2.5, 2.3, 2.66, 3, 3.1, 2.3, 2.5, 2.8, 3, 3]
plt.plot(xx, yy, "o-")
plt.xlim(5, 30)
plt.ylim(2, 3.3)
# ### Funktionen und deren Graph
# Definieren einer Funktionen mit `SymPy` und zeichnen ihres Graphen:
# In[37]:
from sympy import sin
from sympy.abc import x
sin_square = sin(x) * x**2
# In[38]:
sin_square.subs(x, -2).evalf()
# In[39]:
sin_square.subs(x, 15).evalf()
# In[40]:
from sympy.plotting import plot
plot(sin_square, (x, -3, 15))
# ### Interaktive Funktionen
#
# `@interact` führt eine Funktion mit interaktiven Argumenten (`a` und `b`) aus.
# `a = (0, 20, .1)` definiert, dass der Slider von `0` bis `20` mit Schrittweite `0.1` gehen soll.
# Das `a = 10` in der Funktion `damped_oscillation` selbst ist der initiale default Wert,
# den der Slider am Anfang bekommen soll.
# In[41]:
from IPython.html.widgets import interact
from sympy.abc import x
from sympy import exp, cos
from sympy.plotting import plot
@interact(a = (0, 20, .1), b = (0, 3, .1))
def damped_oscillation(a = 10, b = .5):
f2 = a * exp(-b * x) * cos(a * x) / a
plot(f2, (x, 0, 10), ylim=(-1, 1))
# ### Parametrischer Plot
# Die Matrix $\bigl(\begin{smallmatrix}a&b\\ c&d\end{smallmatrix} \bigr)$ beinhaltet die Parameter,
# und wird mit dem von $\phi$ abhängigen Vektor multipliziert.
# $$f(\phi) :=
# \begin{pmatrix}
# a & b \\ c & d
# \end{pmatrix}
# \cdot \log(1+\phi)
# \begin{pmatrix}
# \sin(\phi) \\ \cos(\phi)
# \end{pmatrix}
# \qquad \phi \in [0,\,8 \pi]$$
# In[42]:
from IPython.html.widgets import interact
import numpy as np
@interact(a=(-2, 2, .1), b =(-2, 2, .1), c=(-2, 2, .1), d=(-2, 2, .1))
def elliptic_plot(a = 1., b = 0, c = 0, d = -1):
phi = np.linspace(0, 8 * np.pi, 1000)
m = np.array([[a, b],
[c, d]])
v = np.c_[np.sin(phi),
np.cos(phi)].T
r = np.log1p(phi)
xx, yy = m.dot(r * v)
plt.plot(xx, yy)
plt.grid()
plt.ylim(-4, 4)
plt.xlim(-4, 4)
# ### Histogram
# [Gauss](https://docs.python.org/2/library/random.html#random.gauss)-Glocke für $\mu = 2$ und $\sigma = .5$
# In[43]:
from random import gauss
data = [gauss(2, .5) for i in range(10000)]
# In[44]:
_ = plt.hist(data, 20, color="grey")