[NumCS] Add more notes and tricks

They came up while solving the utter mess and clusterf of exercises of
this subject and are trying to make future us's live easier
This commit is contained in:
2025-10-03 16:16:46 +02:00
parent 885d9990c8
commit 3664961747
3 changed files with 64 additions and 1 deletions

Binary file not shown.

View File

@@ -5,6 +5,7 @@
\newsection \newsection
\subsection{Lagrange- und Baryzentrische Interpolationsformeln} \subsection{Lagrange- und Baryzentrische Interpolationsformeln}
% Session: Gemäss TA sehr gut beschrieben im alten Script % Session: Gemäss TA sehr gut beschrieben im alten Script
\label{sec:barycentric-interpolation}
\begin{definition}[]{Lagrange Polynome} \begin{definition}[]{Lagrange Polynome}
Für Knoten (auch gennannt Stützstellen) $x_0, x_1, \ldots, x_n \in \R$ definieren wir die Lagrange-Polynome: Für Knoten (auch gennannt Stützstellen) $x_0, x_1, \ldots, x_n \in \R$ definieren wir die Lagrange-Polynome:
@@ -42,8 +43,34 @@ Falls $j = i$ im Produkt, so überspringt $j$ diese Zahl.
\end{multicols} \end{multicols}
Da eine Implementation, welche direkt auf den Lagrange-Polynomen basiert, eine Laufzeit von $\tco{n^3}$ hätte, suchte man nach einer besseren Methode. Da eine Implementation, welche direkt auf den Lagrange-Polynomen basiert, eine Laufzeit von $\tco{n^3}$ hätte, suchte man nach einer besseren Methode.
Mit der \bi{baryzentrischen Interpolationsformel} wird zuerst ein Pre-Computing auf Teilen der Lagrange-Polynome durchgeführt, was dann dazu führt, dass die Laufzeit auf $\tco{n^2}$ sinkt ($\tco{n}$ für die Auswertung der Formel und $\tco{n^2}$ für die Berechnung der $\lambda_k$): Mit der \bi{baryzentrischen Interpolationsformel} wird zuerst ein Pre-Computing auf Teilen der Lagrange-Polynome durchgeführt, was dann dazu führt, dass die Laufzeit auf $\tco{n^2}$ sinkt ($\tco{n}$ für die Auswertung der Formel und $\tco{n^2}$ für die Berechnung der $\lambda_k$).
Man berechnet die baryzentrischen Gewichte $\lambda_k$ folgendermassen:
\rmvspace
\begin{align*}
\lambda_k = \prod_{j \neq k} \frac{1}{x_k - x_j}
\end{align*}
oder das ganze mithilfe von Numpy:
\begin{code}{python}
def barycentric_weights(x: np.ndarray) -> np.ndarray:
n = len(x)
# Initialize to zeros
barweight = np.ones(n)
for k in range(n):
# Vectorized differences between $x_k$ and all $x$s
differences = x[k] - x
# Remove the $k$-th element (and handle edge cases for $k = 0$ and $k = n - 1$)
if k < n - 1 and k > 0:
diff_processed = np.concatenate((differences[:k], differences[(k + 1) :]))
barweight[k] = 1 / np.prod(diff_processed)
elif k == 0:
barweight[k] = 1 / np.prod(differences[1:])
else:
barweight[k] = 1 / np.prod(differences[:k])
return barweight
\end{code}
Mit dem können wir dann ein Polynom mit der baryzentrischen Interpolationsformel interpolieren:
\setcounter{numberingConfig}{0} \setcounter{numberingConfig}{0}
\begin{formula}[]{Baryzentrische Interpolationsformel} \begin{formula}[]{Baryzentrische Interpolationsformel}
\vspace{-1.5pc} \vspace{-1.5pc}
@@ -60,6 +87,40 @@ Mit anderen $\lambda_k$ eröffnet die baryzentrische Formel einen Weg zur Verall
Eine weitere Anwendung der Formel ist als Ausganspunkt für die Spektralmethode für Differenzialgleichungen. Eine weitere Anwendung der Formel ist als Ausganspunkt für die Spektralmethode für Differenzialgleichungen.
\begin{code}{python}
def interp_barycentric(
data_point_x: np.ndarray,
data_point_y: np.ndarray,
barweight: np.ndarray,
x: np.ndarray
):
"""Compute an Interpolation polynomial p(x) using the barycentric interpolation formula
Args:
data_point_x: The data points' x-coordinate from which to interpolate (Stützstellen)
data_point_y: The data points' y-coordinates (Stützwerte)
barweight: Barycentric weights
x: The argument of the polynomial (the x in p(x))
Returns:
The Interpolation polynomial evaluated at each x
"""
p_x = np.zeros_like(x)
n = data_point_x.shape[0]
for i in range(x.shape[0]):
# Separate sums to divide in the end
upper_sum = 0
lower_sum = 0
for k in range(n):
frac = barweight[k] / (x[i] - data_point_x[k])
upper_sum += frac * data_point_y[k]
lower_sum += frac
p_x[i] = upper_sum / lower_sum
return p_x
\end{code}
% ──────────────────────────────────────────────────────────────────── % ────────────────────────────────────────────────────────────────────
\newpage \newpage

View File

@@ -53,6 +53,8 @@ Das $n$-te Chebyshev-Polynom ist ein Polynom von Grad $n$ und für $x \in [-1, 1
\fancydef{Chebyshev-Abszissen} Die $(n - 1)$ Chebyshev-Abszissen $x_0, \ldots, x_{n - 2}$ im Intervall $[-1, 1]$ sind die Extrema des Chebyshev-Polynoms $T_n(x)$ und zeitgleich die Nullstellen von $U_{n - 1}(x)$. \fancydef{Chebyshev-Abszissen} Die $(n - 1)$ Chebyshev-Abszissen $x_0, \ldots, x_{n - 2}$ im Intervall $[-1, 1]$ sind die Extrema des Chebyshev-Polynoms $T_n(x)$ und zeitgleich die Nullstellen von $U_{n - 1}(x)$.
Je nach Kontext nimmt man noch die Grenzen des Intervalls ($1$ und $-1$) hinzu und hat dann $(n + 1)$ Abszissen. Je nach Kontext nimmt man noch die Grenzen des Intervalls ($1$ und $-1$) hinzu und hat dann $(n + 1)$ Abszissen.
Die Baryzentrischen Gewichte sind dann viel einfacher zu berechnen: $\lambda_k = (-1)^k$ (siehe Bemerkung unterhalb der Baryzentrischen Interpolationsformel, Kapitel \ref{sec:barycentric-interpolation})
\fancyremark{Chebyshev-Abszissen für beliebiges Intervall} Für $I = [a, b]$ sind die Chebyshev-Abszissen: \fancyremark{Chebyshev-Abszissen für beliebiges Intervall} Für $I = [a, b]$ sind die Chebyshev-Abszissen:
\rmvspace \rmvspace
\begin{align*} \begin{align*}