\subsubsection{Monombasis}

\fancytheorem{Eindeutigkeit} $p(x) \in \mathcal(P)_k$ ist durch $k+1$ Punkte $y_i = p(x_i)$ eindeutig bestimmt.

Dieser Satz kann direkt angewendet werden zur Interpolation, in dem man $p(x)$ als Gleichungssystem schreibt.
% FIXME: It'd probably be better to use align* environment in general, it's much more flexible
% FIXME: Having a new line before $$ (or align* environment for that matter) makes the space between text and math env larger!
$$
	p_n(x) = \alpha_n x^n + \cdots + \alpha_0 x^0 \quad \iff \quad
	\underbrace{
		\begin{bmatrix}
			1      & x_0    & \cdots & x_0^n  \\
			1      & x_1    & \cdots & x_1^n  \\
			\vdots & \vdots & \ddots & \vdots \\
			1      & x_n    & \cdots & x_n^n  \\
		\end{bmatrix}
	}_\text{Vandermonde Matrix}
	\begin{bmatrix}
		\alpha_0 \\
		\alpha_1 \\
		\vdots   \\
		\alpha_n
	\end{bmatrix}
	=
	\begin{bmatrix}
		y_0    \\
		y_1    \\
		\vdots \\
		y_n
	\end{bmatrix}
$$

\begin{code}{python}
def coeffs_monomial(x: np.ndarray, y: np.ndarray):
    """ Solve Vandermonde matrix for monomial coeffs (very unstable) """
    A = np.vander(x)
    coeffs = np.linalg.solve(A, y)
    return coeffs
\end{code}

Um $\alpha_i$ zu finden ist die Vandermonde Matrix unbrauchbar, da die Matrix schlecht konditioniert ist.

\newpage

Zur Auswertung von $p(x)$ kann man direkt die Matrix-darstellung nutzen, oder effizienter:

\fancydef{Horner Schema} $p(x) = (x \ldots x ( x (\alpha_n x + \alpha_{n-1}) + \ldots + \alpha_1) + \alpha_0)$

\begin{code}{python}
def eval_horner(coeffs: np.ndarray, vals: np.ndarray):
    """ Evaluate polynomial using Horner scheme """
    h = coeffs[0]
    for i in range(1, len(coeffs)): h = vals * h + coeffs[i]
    return h
\end{code}

\innumpy liefert \verb|polyfit| die direkte Auswertung, \verb|polyval| wertet Polynome via Horner-Schema aus. (Gemäss Script, in der Praxis sind diese Funktionen \verb|deprecated|)
