Einführung in die Programmierung für Studierende der Physik

(Introduction to Programming for Physicists)

Vorlesung gehalten an der J.W.Goethe-Universität in Frankfurt am Main

(Sommersemester 2022)

von Dr.phil.nat. Dr.rer.pol. Matthias Hanauske

Frankfurt am Main 05.05.2022

Das Computeralgebrasystem: Python Jupyter + SymPy

In diesem Jupyter Notebook wird die Programmiersprache Python, in Verbindung mit der Python-Bibliothek SymPy benutzt, um symbolische Berechnungen durchzuführen (Matrix-Berechnungen, Differentiation, Integration, analytisches Lösen von Differentialgleichungen). In diesem Sinne agiert das Jupyter Notebook somit als ein Computeralgebrasystem - ein Computerprogramm, das der Bearbeitung algebraischer Ausdrücke dient. Es löst nicht nur mathematische Aufgaben mit festen Zahlenwerten, sondern auch solche mit symbolischen Ausdrücken (Gleichungen von Variablen, Funktionen, Polynomen und Matrizen) und ist dadurch im Erscheinungsbild den kommerziellen Software-Produkten Mathematica oder Maple sehr ähnlich.

Zunächst wird das Python Modul "sympy" eingebunden. Falls Sie das "sympy" Modul das erste Mal verwenden, müssen Sie es zunächst in Ihrer Python 3 Umgebung installieren (z.B. in einem Linux Terminal mit "pip3 install sympy").

In [1]:
from sympy import *
init_printing()

Berechnungen mit Matrizen

Wir definieren uns eine (2x3)-Matrix $\hat{\bf {A}}$ und eine (3x3)-Matrix $\hat{\bf {B}}$:

In [2]:
A = Matrix([[1, 2, 3, 4, 5],[21,22,23,24,25],[51,52,53,54,55]])
A
Out[2]:
$$\left[\begin{matrix}1 & 2 & 3 & 4 & 5\\21 & 22 & 23 & 24 & 25\\51 & 52 & 53 & 54 & 55\end{matrix}\right]$$
In [3]:
B = Matrix([[1, 2, 3],[4, 5, 6],[7, 8, 9],[10,11,12],[13,14,15]])
B
Out[3]:
$$\left[\begin{matrix}1 & 2 & 3\\4 & 5 & 6\\7 & 8 & 9\\10 & 11 & 12\\13 & 14 & 15\end{matrix}\right]$$

Das Produkt der Matrizen $\hat{\bf {A}}$ und $\hat{\bf {B}}$ berechnet sich zu

In [4]:
C = A*B
C
Out[4]:
$$\left[\begin{matrix}135 & 150 & 165\\835 & 950 & 1065\\1885 & 2150 & 2415\end{matrix}\right]$$

, die transponierte Matrix $(\hat{\bf {A}})^T$

In [5]:
transpose(A)
Out[5]:
$$\left[\begin{matrix}1 & 21 & 51\\2 & 22 & 52\\3 & 23 & 53\\4 & 24 & 54\\5 & 25 & 55\end{matrix}\right]$$

Man kann die einzelnen Elemente der Matrix auch mittels symbolischer Variablen benennen und dann allgemeine Ausdrücke erhalten.

In [6]:
a,b,c,d = symbols('a,b,c,d')
F = Matrix([[a, b],[c,d]])
F
Out[6]:
$$\left[\begin{matrix}a & b\\c & d\end{matrix}\right]$$

Z.B. ergibt sich für die Determinante der Matrix $\hat{\bf {F}}$

In [7]:
det(F)
Out[7]:
$$a d - b c$$

Berechnungen mit Vektoren können in gleicher Weise durchgeführt werden und die Operationen des Skalar- und Kreuzproduktes sind ebenfalls in SymPy schon vordefiniert. Nehmen wir z.B. die folgenden Vektoren $\vec{a}$ und $\vec{b}$ und berechnen das Skalar- und Kreuzprodukt:

$$ \begin{equation} \vec{a} =\left( \begin{array}{ccc} 4 \\ 7 \\ 9 \end{array} \right) \quad , \quad \vec{b} =\left( \begin{array}{ccc} -3 \\ 5 \\ -7 \end{array} \right) \qquad , \quad \hbox{Skalarprodukt:} \,\, s = \vec{a} \cdot \vec{b} \quad , \quad \hbox{Kreuzprodukt:} \,\, \vec{c} = \vec{a} \times \vec{b} \end{equation} $$
In [8]:
va = Matrix([4, 7, 9])
vb = Matrix([-3, 5, -7])

Das Skalarprodukt ($s = \vec{a} \cdot \vec{b} = \sum_{i=1}^3 a_i \, b_i $) ergibt sich mittels dem Befehl $\vec{a}$.dot( $\vec{b}$ ):

In [9]:
va.dot(vb)
Out[9]:
$$-40$$

Das Kreuzprodukt ( $\vec{c} = \vec{a} \times \vec{b} = \sum_{i,j,k=1}^3 \epsilon_{ijk} \, a_i \, b_j \, \vec{e}_k$ ) ergibt sich mittels dem Befehl $\vec{a}$.cross( $\vec{b}$ ), wobei $\epsilon_{ijk}$ der total antisymmetrischer Tensor (auch Epsilon-Tensor bzw. Levi-Civita-Symbol) ist.

In [10]:
va.cross(vb)
Out[10]:
$$\left[\begin{matrix}-94\\1\\41\end{matrix}\right]$$

Weitere Matrix Operationen finden Sie unter http://docs.sympy.org/latest/tutorial/matrices.html

Symbolische Berechnungen von Gleichungen

Das Modul sympy ist auch dafür gemacht, symbolische Berechnungen durchzuführen. Betrachten wir z.B. die folgende Gleichung $0=x^2 + p \, x + q$. Zunächst definieren wir die symbolischen Variablen der Gleichung und geben der Gleichung den Variablennamen "Gl".

In [11]:
x = symbols('x')
p,q = symbols('p,q')
Gl = Eq(x**2 + p*x + q, 0)
Gl
Out[11]:
$$p x + q + x^{2} = 0$$

Die Lösungen erhält man mittels des SymPy-Befehls "solve(...)"

In [12]:
Loes_Gl=solve(Gl,x)
Loes_Gl
Out[12]:
$$\left [ - \frac{p}{2} - \frac{\sqrt{p^{2} - 4 q}}{2}, \quad - \frac{p}{2} + \frac{\sqrt{p^{2} - 4 q}}{2}\right ]$$

Wir legen nun die symbolischen Variablen $p$ und $q$ auf die folgenden Werte fest (SymPy-Befehl "subs(...)", $0=x^2-3x+9$)

In [13]:
Gl_1=Gl.subs(p,-3).subs(q,9)
Gl_1
Out[13]:
$$x^{2} - 3 x + 9 = 0$$

und lösen die Gleichung erneut:

In [14]:
Loes_Gl_1=solve(Gl_1)
Loes_Gl_1
Out[14]:
$$\left [ \frac{3}{2} - \frac{3 \sqrt{3} i}{2}, \quad \frac{3}{2} + \frac{3 \sqrt{3} i}{2}\right ]$$

Die Gleichung besitzt keine reellwertige Lösung, wie man auch anhand der folgenden Abbildung erkennt.

In [15]:
plot(Gl_1.lhs,xlim=(-5,7),ylim=(-2,50));
<Figure size 640x480 with 1 Axes>

Differentation und Integration

Die erste Ableitung einer Funktion $f(x)$:

hier speziell $f(x)=10 \cdot e^{-x/5} \cdot \hbox{sin}(3 x)$

In [16]:
f= 10 * exp(-x/5) * sin(3*x)
f
Out[16]:
$$10 e^{- \frac{x}{5}} \sin{\left (3 x \right )}$$

Erste Ableitung: $f^\prime(x)$=

In [17]:
f.diff(x)
Out[17]:
$$- 2 e^{- \frac{x}{5}} \sin{\left (3 x \right )} + 30 e^{- \frac{x}{5}} \cos{\left (3 x \right )}$$

Zweite Ableitung: $f^{\prime \prime}(x)$=

In [18]:
f.diff(x,x)
Out[18]:
$$- 4 \left(\frac{112 \sin{\left (3 x \right )}}{5} + 3 \cos{\left (3 x \right )}\right) e^{- \frac{x}{5}}$$

Dritte Ableitung: $f^{\prime \prime \prime}(x)$=

In [19]:
f.diff(x,3)
Out[19]:
$$\frac{4 \left(337 \sin{\left (3 x \right )} - 1665 \cos{\left (3 x \right )}\right) e^{- \frac{x}{5}}}{25}$$

Das unbestimmte Integral einer Funktion $f(x)$: $\int f(x) \, dx$

In [20]:
f.integrate(x)
Out[20]:
$$- \frac{25 e^{- \frac{x}{5}} \sin{\left (3 x \right )}}{113} - \frac{375 e^{- \frac{x}{5}} \cos{\left (3 x \right )}}{113}$$

Das bestimmte Integral einer Funktion $f(x)$: $\int_a^b f(x) \, dx$

In [21]:
f.integrate((x, a, b))
Out[21]:
$$- \frac{25 e^{- \frac{b}{5}} \sin{\left (3 b \right )}}{113} - \frac{375 e^{- \frac{b}{5}} \cos{\left (3 b \right )}}{113} + \frac{25 e^{- \frac{a}{5}} \sin{\left (3 a \right )}}{113} + \frac{375 e^{- \frac{a}{5}} \cos{\left (3 a \right )}}{113}$$

Das bestimmte Integral einer Funktion $f(x)$: $\int_1^2 f(x) \, dx$

In [22]:
f.integrate((x, 1, 2))
Out[22]:
$$\frac{375 \cos{\left (3 \right )}}{113 e^{\frac{1}{5}}} - \frac{375 \cos{\left (6 \right )}}{113 e^{\frac{2}{5}}} + \frac{25 \sin{\left (3 \right )}}{113 e^{\frac{1}{5}}} - \frac{25 \sin{\left (6 \right )}}{113 e^{\frac{2}{5}}}$$
In [23]:
f.integrate((x, 1, 2)).evalf()
Out[23]:
$$-4.75874851668195$$

Analytisches Lösen von Differentialgleichungen

Zusätzlich ist es in sympy auch möglich Differentialgleichungen (DGLs) zu lösen (falls eine analytische Lösung existiert). Betrachten wir z.B. die folgende DGL zweiter Ordnung: $\frac{d^2y(x)}{dx^2}=-3y(x)$

In [24]:
y = Function('y')(x)
DGL = Eq(y.diff(x,x), -3*y)
DGL
Out[24]:
$$\frac{d^{2}}{d x^{2}} y{\left (x \right )} = - 3 y{\left (x \right )}$$

Die allgemeine Lösung lautet:

In [25]:
dsolve(DGL)
Out[25]:
$$y{\left (x \right )} = C_{1} \sin{\left (\sqrt{3} x \right )} + C_{2} \cos{\left (\sqrt{3} x \right )}$$

Die allgemeine Lösung hängt von den zwei Parametern $C_1$ und $C_2$ ab, die durch eine Wahl der Anfangs/Randbedingungen festgelegt werden können. Wir wählen z.B.

In [26]:
Eq(y.subs(x,0),3)
Out[26]:
$$y{\left (0 \right )} = 3$$
In [27]:
Eq(y.diff(x).subs(x, 0),2)
Out[27]:
$$\left. \frac{d}{d x} y{\left (x \right )} \right|_{\substack{ x=0 }} = 2$$
In [28]:
Loes = dsolve(DGL,ics={y.subs(x,0):3,y.diff(x).subs(x, 0): 2})
Loes
Out[28]:
$$y{\left (x \right )} = \frac{2 \sqrt{3} \sin{\left (\sqrt{3} x \right )}}{3} + 3 \cos{\left (\sqrt{3} x \right )}$$

Die Lösung können wir dann wie folgt visualisieren:

In [29]:
plot(Loes.rhs)
Out[29]:
<sympy.plotting.plot.Plot at 0x7f4f582938d0>

Die Lösung können wir uns auch mittels "matplotlib" visualisieren:

In [30]:
import matplotlib.pyplot as plt 
import numpy as np

xvals = np.linspace(-10, 10, 300)
func = lambdify(x, Loes.rhs)
plt.ylabel('y(x)')
plt.xlabel('x')
plt.plot(xvals,func(xvals));
In [31]:
func(xvals[:10])
Out[31]:
array([ 1.27890346,  0.92941137,  0.56745804,  0.19789642, -0.17431852,
       -0.54419626, -0.90677761, -1.25720118, -1.59076863, -1.90300758])

Anwendungsbeispiel: Taylorreihen Entwicklung

Wir möchten nun die Funktion $f(x)=\frac{1}{x}$ um die Stelle $x_0=1$ in eine Taylorreihe entwickeln. Hierzu definieren wir zunächst die Funktion:

In [32]:
f = 1/x

Das N-te Taylorpolynom $P_N(x)$ der Taylorreihe einer Funktion um eine Stelle $x_0$ ist wie folgt definiert:

$$ \begin{equation} P_N(x) = \sum_{k=0}^N \frac{f^{(k)}(x_0)}{k!}\cdot(x-x_0)^k \quad, \end{equation} $$

wobei $f^{(k)}(x_0)$ die k-te Ableitung der Funktion $f(x)$ an der Stelle $x=x_0$ darstellt: $f^{(k)}(x_0):=\left. \frac{d^k f(x)}{dx^k} \right|_{x=x_0}$

Das 4-te Taylorpolynom $P_4(x)$ der Taylorreihe der Funktion $f(x)=\frac{1}{x}$ um eine Stelle $x_0$ lautet z.B.:

In [33]:
x_0 = Symbol('x_0')
sum(f.diff(x, k).subs(x,x_0)/factorial(k)*(x - x_0)**k  for k in range(5))
Out[33]:
$$\frac{1}{x_{0}} - \frac{x - x_{0}}{x_{0}^{2}} + \frac{\left(x - x_{0}\right)^{2}}{x_{0}^{3}} - \frac{\left(x - x_{0}\right)^{3}}{x_{0}^{4}} + \frac{\left(x - x_{0}\right)^{4}}{x_{0}^{5}}$$

Wir stellen uns im Folgenden die ersten drei Taylorpolynome $P_1(x), P_2(x)$ und $P_3(x)$ der Funktion $f(x)=\frac{1}{x}$ mit $x_0=1$ grafisch dar und vergleichen diese mit der ursprünglichen Funktion $f(x)$.

In [34]:
P_1=sum(f.diff(x, k).subs(x,1)/factorial(k)*(x - 1)**k  for k in range(2))
P_2=sum(f.diff(x, k).subs(x,1)/factorial(k)*(x - 1)**k  for k in range(3))
P_3=sum(f.diff(x, k).subs(x,1)/factorial(k)*(x - 1)**k  for k in range(4))
In [35]:
x_min=0.4
x_max=2.25
pf = plot(f, P_1, P_2, P_3, (x,x_min,x_max), line_color='black', legend = True, show=False)
pf[1].line_color='red'
pf[2].line_color='blue'
pf[3].line_color='green'
pf.show()

Wir stellen uns nun das 30-te Taylorpolynom $P_{30}(x)$ der Funktion $f(x)=\frac{1}{x}$ mit $x_0=1$ grafisch dar und vergleichen es wieder mit der ursprünglichen Funktion $f(x)$.

In [36]:
P_30=sum(f.diff(x, k).subs(x,1)/factorial(k)*(x - 1)**k  for k in range(31))
P_30
Out[36]:
$$- x + \left(x - 1\right)^{30} - \left(x - 1\right)^{29} + \left(x - 1\right)^{28} - \left(x - 1\right)^{27} + \left(x - 1\right)^{26} - \left(x - 1\right)^{25} + \left(x - 1\right)^{24} - \left(x - 1\right)^{23} + \left(x - 1\right)^{22} - \left(x - 1\right)^{21} + \left(x - 1\right)^{20} - \left(x - 1\right)^{19} + \left(x - 1\right)^{18} - \left(x - 1\right)^{17} + \left(x - 1\right)^{16} - \left(x - 1\right)^{15} + \left(x - 1\right)^{14} - \left(x - 1\right)^{13} + \left(x - 1\right)^{12} - \left(x - 1\right)^{11} + \left(x - 1\right)^{10} - \left(x - 1\right)^{9} + \left(x - 1\right)^{8} - \left(x - 1\right)^{7} + \left(x - 1\right)^{6} - \left(x - 1\right)^{5} + \left(x - 1\right)^{4} - \left(x - 1\right)^{3} + \left(x - 1\right)^{2} + 2$$
In [37]:
x_min=0.05
x_max=2.1
pf = plot(f, P_30, (x,x_min,x_max), line_color='black', show=False)
pf[1].line_color='red'
pf.show()

Anwendungsbeispiel: Herleitung der Differentiationregeln mittels der Methode der Lagrange Polynome

Die Ableitung (Differentiation) einer Funktion $f(x)$ stellt ein fundamentales Konzept der Mathematik dar, welches bei der Formulierung von physikalischen Bewegungsgleichungen essenziell ist. Die mathematische Definition der Ableitung einer Funktion, der sogenannte Differentialquotient, benutzt dabei eine Grenzwert-Formulierung ($h \to 0$), wobei in der numerischen Mathematik hingegen mehrere Differentiationregeln formuliert werden, die den wirklichen Wert der Ableitung approximieren. Die analytische Herleitung dieser Regeln benutzt die Methode der Lagrange Polynome (siehe Anwendungsbeispiel: Interpolation und Polynomapproximation). In diesem Anwendungsbeispiel wird die Herleitung der Differentiationregeln behandelt.

Die mathematische Definition der Ableitung einer Funktion $f(x)$ an der Stelle $x_0$ lautet

$$ \begin{equation} f^\prime(x_0) = \lim \limits_{h \to 0} \frac{f(x_0+h) - f(x_0)}{h} \quad. \end{equation} $$

Zur Approximation dieser Zahl werden wir nun die Funktion $f(x)$ in ein Lagrange Polynom entwickeln und diesen Ausdruck dann Differenzieren. Wir möchten jetzt die Funktion $f(x)$ mittels ($n+1$) vorgegebener Punkte ($(x_0,f(x_0)), (x_1,f(x_1)), ..., (x_n,f(x_n)) $) in ein Lagrange Polynom vom Grade N entwickeln, wobei wir annehmen, dass $x_0 \in [a,b]$ und $x_n = x_0 + n \cdot h$. Der Wert von $h$ sollte hierbei hinreichend klein sein um sicherzustellen, dass $x_n \in [a,b]$ gilt.

Das n-te Lagrange Polynom $P_n(x)$ einer Funktion ist wie folgt definiert:

$$ \begin{equation} P_n(x) = \sum_{k=0}^n f(x_k) \cdot L_{n,k}(x) \quad, \end{equation} $$

mit

$$ \begin{equation} L_{n,k}(x) = \prod_{i=0 , \, i \neq k}^n \frac{(x-x_i)}{(x_k-x_i)} \quad. \end{equation} $$

Wir approximieren nun die Funktion $f(x)$ durch das n-te Lagrange Polynom $P_n(x)$

$$ \begin{equation} f(x) = P_n(x) + \underbrace{ \frac{f^{(n+1)}(\xi(x))}{(n+1)!} \prod_{i=0}^n (x-x_i) }_{\hbox{Fehler}} \,\, , \,\, \forall \,\, \xi(x) \in [x_0,x_n] \quad, \end{equation} $$

wobei $f^{(n+1)(x)}$ die $(n+1)$-te Ableitung der Funktion darstellt und $\xi(x)$ ein x-Wert im Bereich der Stützstellen ist.

Vernachlässigt man den Fehlerterm und leitet den Ausdruck ab, erhält man:

$$ \begin{equation} f^\prime(x) \approx \frac{d}{dx} P_n(x) = \frac{d}{dx} \left( \sum_{k=0}^n f(x_k) \cdot L_{n,k}(x) \right) = \sum_{k=0}^n f(x_k) \cdot \frac{d}{dx} L_{n,k}(x) = \sum_{k=0}^n f(x_k) \cdot L^\prime_{n,k}(x) \end{equation} $$

Wir definieren zunächst eine allgemeine SymPy-Funktion $f(x)$.

In [38]:
f = Function('f')(x)

Zweipunkteformel (n=1)

Wir betrachten nun den Fall $n=1$ und approximieren die Funktion mittels des ersten Lagrange Polynoms $P_1(x)$: $f(x) \approx P_1(x)$

In [39]:
x0,h = symbols('x_0,h')
points=[x0,x0+h]
f_points=[f.subs(x,points[0]), f.subs(x,points[1])]
In [40]:
points, f_points
Out[40]:
$$\left ( \left [ x_{0}, \quad h + x_{0}\right ], \quad \left [ f{\left (x_{0} \right )}, \quad f{\left (h + x_{0} \right )}\right ]\right )$$

Mit den oben angegebenen zwei Punkten erhält man das folgende Lagrange Polynom $P_1(x)$:

In [41]:
List_ranges=[]
for i in range(len(points)):
    List_range=list(range(len(points)))
    List_range.pop(i)
    List_ranges.append(List_range)
List_ranges
P_1=sum(f_points[k] * prod((x - points[i])/(points[k] - points[i])  for i in List_ranges[k]) for k in range(len(points)))
P_1.simplify()
Out[41]:
$$\frac{\left(x - x_{0}\right) f{\left (h + x_{0} \right )} + \left(h - x + x_{0}\right) f{\left (x_{0} \right )}}{h}$$

Leitet man diesen Ausdruck nach $x$ ab, so erhält man $f^\prime(x_0) \approx P_1^\prime(x_0)$

In [42]:
P_1.diff(x).simplify()
Out[42]:
$$\frac{- f{\left (x_{0} \right )} + f{\left (h + x_{0} \right )}}{h}$$

Der obere Ausdruck stellt die sogenannte Zweipunkte-Differentiationsregel dar.

Dreipunkte-Endpunkt-Formel (n=2)

Wir betrachten nun den Fall $n=2$ und approximieren die Funktion mittels des zweiten Lagrange Polynoms $P_2(x)$: $f(x) \approx P_2(x)$, wobei wir hierbei die folgenden drei Punkte verwenden: ($(x_0,f(x_0)), (x_0 + h,f(x_0 + h)), (x_0 + 2h,f(x_0 + 2h)) $).

In [43]:
points=[x0,x0+h,x0+2*h]
f_points=[f.subs(x,points[0]), f.subs(x,points[1]), f.subs(x,points[2])]
In [44]:
points, f_points
Out[44]:
$$\left ( \left [ x_{0}, \quad h + x_{0}, \quad 2 h + x_{0}\right ], \quad \left [ f{\left (x_{0} \right )}, \quad f{\left (h + x_{0} \right )}, \quad f{\left (2 h + x_{0} \right )}\right ]\right )$$

Mit den oben angegebenen zwei Punkten erhält man das folgende Lagrange Polynom $P_2(x)$:

In [45]:
List_ranges=[]
for i in range(len(points)):
    List_range=list(range(len(points)))
    List_range.pop(i)
    List_ranges.append(List_range)
List_ranges
P_2=sum(f_points[k] * prod((x - points[i])/(points[k] - points[i]) for i in List_ranges[k]) for k in range(len(points)))
P_2.expand()
Out[45]:
$$f{\left (x_{0} \right )} - \frac{3 x f{\left (x_{0} \right )}}{2 h} + \frac{2 x f{\left (h + x_{0} \right )}}{h} - \frac{x f{\left (2 h + x_{0} \right )}}{2 h} + \frac{3 x_{0} f{\left (x_{0} \right )}}{2 h} - \frac{2 x_{0} f{\left (h + x_{0} \right )}}{h} + \frac{x_{0} f{\left (2 h + x_{0} \right )}}{2 h} + \frac{x^{2} f{\left (x_{0} \right )}}{2 h^{2}} - \frac{x^{2} f{\left (h + x_{0} \right )}}{h^{2}} + \frac{x^{2} f{\left (2 h + x_{0} \right )}}{2 h^{2}} - \frac{x x_{0} f{\left (x_{0} \right )}}{h^{2}} + \frac{2 x x_{0} f{\left (h + x_{0} \right )}}{h^{2}} - \frac{x x_{0} f{\left (2 h + x_{0} \right )}}{h^{2}} + \frac{x_{0}^{2} f{\left (x_{0} \right )}}{2 h^{2}} - \frac{x_{0}^{2} f{\left (h + x_{0} \right )}}{h^{2}} + \frac{x_{0}^{2} f{\left (2 h + x_{0} \right )}}{2 h^{2}}$$

Leitet man diesen Ausdruck nach $x$ ab, so erhält man $f^\prime(x) \approx P_2^\prime(x)$

In [46]:
P_2.diff(x).expand()
Out[46]:
$$- \frac{3 f{\left (x_{0} \right )}}{2 h} + \frac{2 f{\left (h + x_{0} \right )}}{h} - \frac{f{\left (2 h + x_{0} \right )}}{2 h} + \frac{x f{\left (x_{0} \right )}}{h^{2}} - \frac{2 x f{\left (h + x_{0} \right )}}{h^{2}} + \frac{x f{\left (2 h + x_{0} \right )}}{h^{2}} - \frac{x_{0} f{\left (x_{0} \right )}}{h^{2}} + \frac{2 x_{0} f{\left (h + x_{0} \right )}}{h^{2}} - \frac{x_{0} f{\left (2 h + x_{0} \right )}}{h^{2}}$$

Betrachtet man nun speziell die Ableitung bei $f^\prime(x_0) \approx P_2^\prime(x_0)$, so erhält man die Dreipunkte-Endpunkt-Formel:

$$ \begin{equation} f^\prime(x_0) \approx \frac{1}{2h} \left[ - 3\,f(x_0) + 4 \, f(x_0 + h) - f(x_0 + 2 \, h) \right] \end{equation} $$
In [47]:
P_2.diff(x).subs(x,x_0).simplify()
Out[47]:
$$\frac{- 3 f{\left (x_{0} \right )} + 4 f{\left (h + x_{0} \right )} - f{\left (2 h + x_{0} \right )}}{2 h}$$

Dreipunkte-Mittelpunkt-Formel (n=2)

Wir betrachten nun abermals den Fall $n=2$ und approximieren die Funktion mittels des zweiten Lagrange Polynoms $P_2(x)$: $f(x) \approx P_2(x)$, wobei wir nun die folgenden drei Punkte verwenden: ($(x_0 -h,f(x_0 -h)), (x_0 ,f(x_0)), (x_0 + h,f(x_0 + h)) $).

In [48]:
points=[x0 -h,x0,x0+h]
f_points=[f.subs(x,points[0]), f.subs(x,points[1]), f.subs(x,points[2])]
In [49]:
points, f_points
Out[49]:
$$\left ( \left [ - h + x_{0}, \quad x_{0}, \quad h + x_{0}\right ], \quad \left [ f{\left (- h + x_{0} \right )}, \quad f{\left (x_{0} \right )}, \quad f{\left (h + x_{0} \right )}\right ]\right )$$
In [50]:
List_ranges=[]
for i in range(len(points)):
    List_range=list(range(len(points)))
    List_range.pop(i)
    List_ranges.append(List_range)
List_ranges
P_2_M=sum(f_points[k] * prod((x - points[i])/(points[k] - points[i]) for i in List_ranges[k]) for k in range(len(points)))
P_2_M.simplify()
Out[50]:
$$\frac{- \left(x - x_{0}\right) \left(h - x + x_{0}\right) f{\left (- h + x_{0} \right )} + \left(x - x_{0}\right) \left(h + x - x_{0}\right) f{\left (h + x_{0} \right )} + 2 \left(h - x + x_{0}\right) \left(h + x - x_{0}\right) f{\left (x_{0} \right )}}{2 h^{2}}$$

Leitet man diesen Ausdruck nach $x$ ab, so erhält man $f^\prime(x) \approx P_2^\prime(x)$

In [51]:
P_2_M.diff(x).expand()
Out[51]:
$$- \frac{f{\left (- h + x_{0} \right )}}{2 h} + \frac{f{\left (h + x_{0} \right )}}{2 h} - \frac{2 x f{\left (x_{0} \right )}}{h^{2}} + \frac{x f{\left (- h + x_{0} \right )}}{h^{2}} + \frac{x f{\left (h + x_{0} \right )}}{h^{2}} + \frac{2 x_{0} f{\left (x_{0} \right )}}{h^{2}} - \frac{x_{0} f{\left (- h + x_{0} \right )}}{h^{2}} - \frac{x_{0} f{\left (h + x_{0} \right )}}{h^{2}}$$

Betrachtet man nun speziell die Ableitung bei $f^\prime(x_0) \approx P_2^\prime(x_0)$, so erhält man die Dreipunkte-Mittelpunkt-Formel:

$$ \begin{equation} f^\prime(x_0) \approx \frac{1}{2h} \left[ f(x_0 + h) - f(x_0 - h) \right] \end{equation} $$
In [52]:
P_2_M.diff(x).subs(x,x_0).simplify()
Out[52]:
$$\frac{- f{\left (- h + x_{0} \right )} + f{\left (h + x_{0} \right )}}{2 h}$$

Fünfpunkte-Mittelpunkt-Formel (n=4)

Wir betrachten nun den Fall $n=4$ und approximieren die Funktion mittels des vierten Lagrange Polynoms $P_4(x)$: $f(x) \approx P_4(x)$, wobei wir die folgenden fünf Punkte verwenden: ($(x_0 - 2 \, h,f(x_0 - 2 \, h)), (x_0 - h,f(x_0 - h)), (x_0 ,f(x_0)), (x_0 + h,f(x_0 + h)), (x_0 + 2 \, h,f(x_0 + 2 \, h)) $).

In [53]:
points=[x0-2*h, x0-h,x0,x0+h,x0+2*h]
f_points=[f.subs(x,points[0]), f.subs(x,points[1]), f.subs(x,points[2]), f.subs(x,points[3]), f.subs(x,points[4])]
In [54]:
points, f_points
Out[54]:
$$\left ( \left [ - 2 h + x_{0}, \quad - h + x_{0}, \quad x_{0}, \quad h + x_{0}, \quad 2 h + x_{0}\right ], \quad \left [ f{\left (- 2 h + x_{0} \right )}, \quad f{\left (- h + x_{0} \right )}, \quad f{\left (x_{0} \right )}, \quad f{\left (h + x_{0} \right )}, \quad f{\left (2 h + x_{0} \right )}\right ]\right )$$
In [55]:
List_ranges=[]
for i in range(len(points)):
    List_range=list(range(len(points)))
    List_range.pop(i)
    List_ranges.append(List_range)
List_ranges
P_4_M=sum(f_points[k] * prod((x - points[i])/(points[k] - points[i]) for i in List_ranges[k]) for k in range(len(points)))
P_4_M.simplify()
Out[55]:
$$\frac{\left(x - x_{0}\right) \left(h - x + x_{0}\right) \left(h + x - x_{0}\right) \left(2 h - x + x_{0}\right) f{\left (- 2 h + x_{0} \right )} - \left(x - x_{0}\right) \left(h - x + x_{0}\right) \left(h + x - x_{0}\right) \left(2 h + x - x_{0}\right) f{\left (2 h + x_{0} \right )} - 4 \left(x - x_{0}\right) \left(h - x + x_{0}\right) \left(2 h - x + x_{0}\right) \left(2 h + x - x_{0}\right) f{\left (- h + x_{0} \right )} + 4 \left(x - x_{0}\right) \left(h + x - x_{0}\right) \left(2 h - x + x_{0}\right) \left(2 h + x - x_{0}\right) f{\left (h + x_{0} \right )} + 6 \left(h - x + x_{0}\right) \left(h + x - x_{0}\right) \left(2 h - x + x_{0}\right) \left(2 h + x - x_{0}\right) f{\left (x_{0} \right )}}{24 h^{4}}$$

Leitet man diesen Ausdruck nach $x$ ab, so erhält man $f^\prime(x) \approx P_4^\prime(x)$

In [56]:
P_4_M.diff(x).expand()
Out[56]:
$$\frac{f{\left (- 2 h + x_{0} \right )}}{12 h} - \frac{2 f{\left (- h + x_{0} \right )}}{3 h} + \frac{2 f{\left (h + x_{0} \right )}}{3 h} - \frac{f{\left (2 h + x_{0} \right )}}{12 h} - \frac{5 x f{\left (x_{0} \right )}}{2 h^{2}} - \frac{x f{\left (- 2 h + x_{0} \right )}}{12 h^{2}} + \frac{4 x f{\left (- h + x_{0} \right )}}{3 h^{2}} + \frac{4 x f{\left (h + x_{0} \right )}}{3 h^{2}} - \frac{x f{\left (2 h + x_{0} \right )}}{12 h^{2}} + \frac{5 x_{0} f{\left (x_{0} \right )}}{2 h^{2}} + \frac{x_{0} f{\left (- 2 h + x_{0} \right )}}{12 h^{2}} - \frac{4 x_{0} f{\left (- h + x_{0} \right )}}{3 h^{2}} - \frac{4 x_{0} f{\left (h + x_{0} \right )}}{3 h^{2}} + \frac{x_{0} f{\left (2 h + x_{0} \right )}}{12 h^{2}} - \frac{x^{2} f{\left (- 2 h + x_{0} \right )}}{4 h^{3}} + \frac{x^{2} f{\left (- h + x_{0} \right )}}{2 h^{3}} - \frac{x^{2} f{\left (h + x_{0} \right )}}{2 h^{3}} + \frac{x^{2} f{\left (2 h + x_{0} \right )}}{4 h^{3}} + \frac{x x_{0} f{\left (- 2 h + x_{0} \right )}}{2 h^{3}} - \frac{x x_{0} f{\left (- h + x_{0} \right )}}{h^{3}} + \frac{x x_{0} f{\left (h + x_{0} \right )}}{h^{3}} - \frac{x x_{0} f{\left (2 h + x_{0} \right )}}{2 h^{3}} - \frac{x_{0}^{2} f{\left (- 2 h + x_{0} \right )}}{4 h^{3}} + \frac{x_{0}^{2} f{\left (- h + x_{0} \right )}}{2 h^{3}} - \frac{x_{0}^{2} f{\left (h + x_{0} \right )}}{2 h^{3}} + \frac{x_{0}^{2} f{\left (2 h + x_{0} \right )}}{4 h^{3}} + \frac{x^{3} f{\left (x_{0} \right )}}{h^{4}} + \frac{x^{3} f{\left (- 2 h + x_{0} \right )}}{6 h^{4}} - \frac{2 x^{3} f{\left (- h + x_{0} \right )}}{3 h^{4}} - \frac{2 x^{3} f{\left (h + x_{0} \right )}}{3 h^{4}} + \frac{x^{3} f{\left (2 h + x_{0} \right )}}{6 h^{4}} - \frac{3 x^{2} x_{0} f{\left (x_{0} \right )}}{h^{4}} - \frac{x^{2} x_{0} f{\left (- 2 h + x_{0} \right )}}{2 h^{4}} + \frac{2 x^{2} x_{0} f{\left (- h + x_{0} \right )}}{h^{4}} + \frac{2 x^{2} x_{0} f{\left (h + x_{0} \right )}}{h^{4}} - \frac{x^{2} x_{0} f{\left (2 h + x_{0} \right )}}{2 h^{4}} + \frac{3 x x_{0}^{2} f{\left (x_{0} \right )}}{h^{4}} + \frac{x x_{0}^{2} f{\left (- 2 h + x_{0} \right )}}{2 h^{4}} - \frac{2 x x_{0}^{2} f{\left (- h + x_{0} \right )}}{h^{4}} - \frac{2 x x_{0}^{2} f{\left (h + x_{0} \right )}}{h^{4}} + \frac{x x_{0}^{2} f{\left (2 h + x_{0} \right )}}{2 h^{4}} - \frac{x_{0}^{3} f{\left (x_{0} \right )}}{h^{4}} - \frac{x_{0}^{3} f{\left (- 2 h + x_{0} \right )}}{6 h^{4}} + \frac{2 x_{0}^{3} f{\left (- h + x_{0} \right )}}{3 h^{4}} + \frac{2 x_{0}^{3} f{\left (h + x_{0} \right )}}{3 h^{4}} - \frac{x_{0}^{3} f{\left (2 h + x_{0} \right )}}{6 h^{4}}$$

Betrachtet man nun speziell die Ableitung bei $f^\prime(x_0) \approx P_4^\prime(x_0)$, so erhält man die Fünfpunkte-Mittelpunkt-Formel:

$$ \begin{equation} f^\prime(x_0) \approx \frac{1}{12 \, h} \left[ f(x_0 - 2 \, h) - 8 \, f(x_0 - h) + 8 \, f(x_0 + h) - f(x_0 + 2 \, h) \right] \end{equation} $$
In [57]:
P_4_M.diff(x).subs(x,x_0).simplify()
Out[57]:
$$\frac{f{\left (- 2 h + x_{0} \right )} - 8 f{\left (- h + x_{0} \right )} + 8 f{\left (h + x_{0} \right )} - f{\left (2 h + x_{0} \right )}}{12 h}$$