diff --git a/sose2020/num/uebungen/4-root-polynomial.pdf b/sose2020/num/uebungen/4-root-polynomial.pdf new file mode 100644 index 0000000..f2e8c75 Binary files /dev/null and b/sose2020/num/uebungen/4-root-polynomial.pdf differ diff --git a/sose2020/num/uebungen/num8.pdf b/sose2020/num/uebungen/num8.pdf new file mode 100644 index 0000000..232da27 Binary files /dev/null and b/sose2020/num/uebungen/num8.pdf differ diff --git a/sose2020/num/uebungen/num8.tex b/sose2020/num/uebungen/num8.tex new file mode 100644 index 0000000..cc6efab --- /dev/null +++ b/sose2020/num/uebungen/num8.tex @@ -0,0 +1,214 @@ +\documentclass[uebung]{../../../lecture} + +\title{Einführung in die Numerik: Übungsblatt 8} +\author{Leon Burgard, Christian Merten} + +\begin{document} + +\punkte + +\begin{aufgabe} + Sei $A \in \R^{n \times n}$ symmetrisch und positiv definit. Betrachte + \[ + F\colon \R^{n} \to \R, \quad F(x) = \frac{1}{2} (Ax,x)_2 - (b,x)_2 + .\] + \begin{enumerate}[1.] + \item Beh.: $\nabla F(x) = Ax - b$. + \begin{proof} + Es ist + \begin{salign*} + F(x) &= \frac{1}{2} \sum_{i,j=1}^{n} a_{ij}x_j x_i - \sum_{i=1}^{n} b_i x_i + \intertext{Damit folgt} + \frac{\partial F}{\partial x_i} &= \frac{1}{2} \left(2 \sum_{j=1, i\neq j}^{n} a_{ij}x_j + + 2 a_{ii} x_i \right) - b_i \\ + &= \sum_{j=1}^{n} a_{ij} x_j - b_i \\ + &= (Ax)_i - b_i + \intertext{Also folgt} + \nabla F(x) &= Ax - b + .\end{salign*} + \end{proof} + \item Beh.: $x^{*}$ löst $Ax = b$ g.d. wenn $x^{*}$ das eindeutige Minimum von $F$ ist. + \begin{proof} + ,,$\implies$``: Sei $x^{*}$ Lösung von $Ax = b$. Dann ist + $\nabla F(x^{*}) = Ax^{*} -b = b - b = 0$. Außerdem gilt da $A$ symmetrisch + \[ + H_f(x) = \left( \frac{\partial^2F}{\partial x_i \partial x_j} \right)_{i,j=1}^{n} = A^{T} = A + .\] Da $A$ positiv definit, ist $x^{*}$ Minimum von $F$. Da $A$ symmetrisch + und positiv definit, ist $A$ regulär, also hat $\nabla F(x)$ keine weiteren Nullstellen. + $x^{*}$ ist also eindeutiges Minimum. + + ,,$\impliedby$``: Sei $x^{*}$ Minimum von $F$. Dann gilt $\nabla F(x^{*}) = 0$, also + $Ax^{*} - b = 0$, d.h. $Ax^{*} = b$. + \end{proof} + \item Seien $x, p \in \R^{n}$ mit $p \neq 0$. Beh.: $g(\alpha) = F(x + \alpha p)$ nimmt + bei + \[ + \alpha = \frac{(p, b-Ax)_2}{(p,Ap)_2} + \] sein Minimum an. + \begin{proof} + Es ist + \[ + g'(\alpha) = (\nabla F(x + \alpha p), p)_2 = (Ax, p)_2 + \alpha (Ap, p)_2 - (b,p)_2 + .\] Eingesetzt ergibt sich + \begin{salign*} + g'\left( \frac{(p, b-Ax)_2}{(p,Ap)_2} \right) &= + (Ax,p)_2 + (p,b-Ax)_2 - (b,p)_2 \\ + &= (Ax - b, p)_2 + (b - Ax, p)_2 \\ + &= (0,p)_2 \\ + &= 0 + .\end{salign*} + Weiter gilt da $A$ positiv definit und $p \neq 0$: + \[ + g''(\alpha) = (Ap, p)_2 > 0 + .\] Also ist $\alpha$ Minimum von $g$. + \end{proof} + \end{enumerate} +\end{aufgabe} + +\begin{aufgabe} + Sei $\R \ni a \neq 0$ und + \[ + f(x) = x^2 - a + .\] + \begin{enumerate}[1.] + \item + \begin{enumerate}[(a)] + \item $g_R'(x) = 1 - \frac{2x}{a} \implies 0 = 1 - \frac{2x}{a} \implies x = \frac{a}{2}$, + $g_R''(x) = - \frac{2}{a} < 0$. Also ist $x = \frac{a}{2}$ Maximum und + einziges Extremum von $g_R$, + inbes. auf $[0, a]$. Weiter ist $g\left( \frac{a}{2} \right) = \frac{a}{4} + 1$. + + Wegen $g(0) = 1 = g(a)$ folgt $g([0,a]) = [1, 1 + \frac{a}{4}]$. + \item Für $a > $, $\sigma = \frac{1}{a}$ und $0 < x,y < a$ gilt + \begin{salign*} + |g(x) - g(y)| &= | x - \frac{x^2}{a} + 1 - (y - \frac{y^2}{a} + 1)| \\ + &= |x-y + \frac{1}{a}(y^2 - x^2)| \\ + &= |x-y - \frac{1}{a}(x-y)(y+x)| \\ + &= |x-y| |1 - \underbrace{\frac{1}{a}(y+x)}_{< 2a}| \\ + &< |x-y| |-1| \\ + &= |x-y| + .\end{salign*} + \item Aus (b) folgt + \[ + q \coloneqq |1 - \frac{1}{a} (\underbrace{x^{k+1} + x^{k}}_{\to 2\sqrt{a}}) | + \xrightarrow{x^{k} \to \sqrt{a}} 1 - \frac{2 \sqrt{a} }{a} + .\] + \end{enumerate} + \item Sei nun + \[ + g_N(x) = x - \frac{x^2 - a}{2x} + .\] + Sei $z \in \R$ beliebig. Dann ex. mit Taylor ein $\eta_x$ zwischen $x$ und $z$ und + ein $\eta_y$ zwischen $y$ und $z$, s.d. + \begin{salign*} + g_N(x) &= g_N'(z)(x - z) + \underbrace{g_N''(\eta_x)(x - z)^2}_{\text{Restglied}} \\ + g_N(y) &= g_N'(z)(y - z) + \underbrace{g_N''(\eta_y)(y - z)^2}_{\text{Restglied}} \\ + \intertext{Damit folgt} + g_N(y) - g_N(y) &= g_N'(z)(y-y) + g_N''(\eta_y)(y - z)^2 + g_N''(\eta_y)(y - z)^2 + .\end{salign*} + Es gilt weiter + \begin{align*} + g_N'(x) &= 1 - \frac{4x^2 - 2x^2 + 2a}{4x^2} = 1 - \frac{x^2 + a}{2x^2} = \frac{1}{2} - \frac{a}{2x^2} \\ + g_N''(x) &= \frac{a}{x^{3}} + .\end{align*} + Mit $z = \frac{x+y}{2}$ folgt + \begin{salign*} + |g(x) - g(y)| &= \left| \left( \frac{1}{2} - \frac{2a}{(x+y)^2} \right) (x-y) + \frac{a(x-y)^2}{4} \left( \frac{1}{\eta_x^{3}} + \frac{1}{\eta_{y}^{3}} \right) \right| \\ + &= |x - y| \left| \frac{1}{2} - \frac{2a}{(x+y)^2} + \frac{a|x-y|}{4} \left( \frac{1}{\eta_{x}^{3}} + \frac{1}{\eta_y^{3}} \right) \right| + .\end{salign*} + Z.z.: $\exists \epsilon > 0$, s.d. für $|x - \sqrt{a}|, |y - \sqrt{a}| < \epsilon$, $\left| \frac{1}{2} - \frac{2a}{(x+y)^2} + \frac{a|x-y|}{4} \left( \frac{1}{\eta_{x}^{3}} + \frac{1}{\eta_y^{3}} \right) \right| < 1$ gilt. + + Für $x \to \sqrt{a} $ und $y \to \sqrt{a}$ folgt $\eta_x \to \sqrt{a} $ und $\eta_y \to \sqrt{a} $. + Damit folgt + \begin{salign*} + \left| \frac{1}{2} - \frac{2a}{\underbrace{(x+y)^2}_{\to 4 \sqrt{a} }} + \frac{a\overbrace{|x-y|}^{\to 0}}{4} + \underbrace{\left( \frac{1}{\eta_{x}^{3}} + \frac{1}{\eta_y^{3}} \right)}_{\to \frac{1}{2 \sqrt{a}^{3}}} \right| \longrightarrow 0 + .\end{salign*} + Also für $\epsilon$ klein genug, folgt $|g(x) - g(y)| < |x-y|$ für + $|x - \sqrt{a}|, |y - \sqrt{a}| < \epsilon$. + + \item Es gilt für $0 < x^{k} \neq \sqrt{a}$: + \[ + x^{k+1} = g_N(x^{k}) = x^{k} - \frac{(x^{k})^2 - a}{2x^{k}} + .\] + Es gilt damit + \begin{alignat*}{3} + &&0 &< (\underbrace{x^{k})^{2} - a}_{\neq 0})^2 + = (x^{k})^{4} - 2(x^{k})^2 a + a^2 \\ + &\implies& 4 (x^{k})^2 a &< (x^{k})^{4} + 2(x^{k})^2a + a^2 \\ + &\implies& 2 x^{k} \sqrt{a} &< (x^{k})^2 + a + = 2 (x^{k})^2 - (x^{k})^2 + a\\ + &\implies& \sqrt{a} &< x^{k} - \frac{(x^{k})^2 - a}{2x^{k}} + = x^{k+1} \qquad (*) + .\end{alignat*} + Für $x^{k} > \sqrt{a} $ gilt zudem + \begin{align*} + x^{k+1} &= x^{k} - \underbrace{\frac{(x^{k})^2 - a}{2 x^{k}}}_{> 0} \\ + &< x^{k} + .\end{align*} + + Damit folgt für $x^{k} > \sqrt{a} $ konvergiert $x^{k+1}$ monoton gegen $\sqrt{a} $. Falls + $x^{k} < \sqrt{a} $, dann ist wegen ($*$) $x^{k+1} > \sqrt{a} $. Dann tritt wieder der erste + Fall ein und es liegt ebenfalls Konvergenz vor. + \end{enumerate} +\end{aufgabe} + +\begin{aufgabe} + Sei $f\colon \R^{n} \to \R^{n}$. Betrachte + \[ + F(x) = \Vert f(x) \Vert_2^2 + \] und + \[ + H(\alpha) = \Vert f(x^{k}) + \alpha J_f(x^{k})p^{k}\Vert_2^2 + .\] Es gilt + \begin{align*} + H'(\alpha) &= 2 \left[ f(x^{k}) + \alpha J_f(x^{k})p^{k} \right]^{T} J_f(x^{k})p^{k} \\ + &= 2 \left[ (fx^{k}, J_f(x^{k})p^{k})_2 + \alpha (J_f(x^{k}) p^{k}, J_f(x^{k}) p^{k})_2 \right] + \intertext{$\alpha_{opt}$ eingesetzt ergibt} + H'(\alpha_{opt}) &= 2 \left[ (f(x^{k}, J_f(x^{k})p^{k})_2 - (f(x^{k}), J_f(x^{k}) p^{k})_2 \right] \\ + &= 0 + \intertext{Weiter ist wegen $p^{k} \neq 0$} + H''(\alpha) &= (J_f(x^{k})p^{k}, J_f(x^{k})p^{k})_2 \\ + &> 0 + .\end{align*} + Also hat $H$ bei $\alpha_{opt}$ ein Minimum. + + Iterationen: + \begin{enumerate}[1.] + \item Relaxation: + \[ + x^{k+1} = x^{k} + \alpha_{opt} f(x^{k}) + .\] + \item Gradientenverfahren: Es gilt + \[ + \frac{\partial F}{\partial x_j} = \sum_{i=1}^{n} 2 f_i(x) \frac{\partial f_i}{\partial x_j} + = 2 \left( f(x), (J_f(x))_{j-\text{te Spalte}} \right)_2 + \implies \nabla F = 2 J_f(x^{k}) f(x^{k}) + .\] Damit folgt + \[ + x^{k+1} = x^{k} - 2 \alpha_{opt} J_f(x^{k}) f(x^{k}) + .\] + \item Newton-Verfahren: + \[ + x^{k+1} = x^{k} + \alpha_{opt} J_f^{-1}(x^{k}) f(x^{k}) + .\] + \end{enumerate} +\end{aufgabe} + +\newpage +\begin{aufgabe} + Siehe \textit{prog\_nonlinear\_solvers\_methods.cc} und \textit{prog\_nonlinear\_solvers\_fractal.cc}. + + Nullstellen mit Newtonverfahren sie Programmcode. + Gewählte Parameter für Relaxationsverfahren: + Startpunkt $(2,1)^{T}$, $\sigma = 0.35$. + Damit konvergiert das Verfahren in $49$ Iterationsschritten mit einer Abweichung von + $\Vert f(x_i) \Vert_2 < 10^{-15}$. + \begin{figure}[h!] + \includegraphics[width=.5\textwidth]{raster_changed.pdf} + \includegraphics[width=.5\textwidth]{4-root-polynomial.pdf} + \caption{Links: Verändertes Raster, Rechts: Polynom $x^{4} - 3x^{3} + 5x + 3$} + \end{figure} +\end{aufgabe} + +\end{document} diff --git a/sose2020/num/uebungen/prog_nonlinear_solvers_fractal.cc b/sose2020/num/uebungen/prog_nonlinear_solvers_fractal.cc new file mode 100644 index 0000000..649e7af --- /dev/null +++ b/sose2020/num/uebungen/prog_nonlinear_solvers_fractal.cc @@ -0,0 +1,91 @@ +#include +#include +#include "hdnum.hh" + + +template +class PolynomialProblem +{ +public: + // Exportiere Größentyp + typedef std::size_t size_type; + + // Exportiere Zahlentyp + typedef N number_type; + + // Dimension der untenstehenden Funktion + std::size_t size () const + { + return 1; + } + + // Funktionsauswertung + void F (const hdnum::Vector& x, hdnum::Vector& result) const + { + result[0] = pow(x[0], 4) - 3.0*pow(x[0], 3) + 5.0*x[0] + 3.0; + } + + // Jacobimatrix + void F_x (const hdnum::Vector& x, hdnum::DenseMatrix& result) const + { + result[0][0] = 4.0*pow(x[0], 3) - 9.0*pow(x[0], 2) + 5.0; + } +}; + + +int main () +{ + typedef std::complex Number; // Der Zahlentyp soll hier komplex sein + + typedef PolynomialProblem Problem; + Problem problem; + + + // Wir schauen Startpunkte auf einem Raster an, das später in ein Bild umgesetzt werden soll + for (double start_value_i = -5.0; start_value_i <= 5.0; start_value_i += 1e-2) { + + for (double start_value = -5.0; start_value <= 5.0; start_value += 1e-2) { + + hdnum::Vector u(problem.size()); // Vektor für Startpunkt bzw Lösung + u[0] = Number(start_value, start_value_i); // Startpunkt + + hdnum::Newton newton; + newton.set_maxit(20); + newton.set_verbosity(0); + newton.set_reduction(1e-10); + newton.set_abslimit(1e-20); + newton.set_linesearchsteps(3); + + newton.solve(problem,u); // Lösen + + double id = 0; + if(newton.has_converged()) { + + // Falls unser Newton-Löser konvergiert ist, stellen wir fest welche Nullstelle + // Nullstelle wir getroffen haben und legen einen Index für jede Nullstelle fest. + + if (u[0].real() < 0 && u[0].imag() < 0) + id = 1; + else if (u[0].real() < 0 && u[0].imag() > 0) + id = 2; + else if (u[0].real() > 0 && u[0].imag() < 0) + id = 3; + else if (u[0].real() > 0 && u[0].imag() > 0) + id = 4; + else + std::cout << "Unbekannte Nullstelle!" << std::endl; + + // Damit auch der "Abstand" zur Nullstelle (im Sinne von benötigten Iterationen + // um sie zu erreichen) sichtbar wird, addieren wir noch die Iterationszahl + // um einen Faktor abgeschwächt + id += .1 * (double)newton.iterations(); + } + + std::cout << id << ","; + } + + std::cout << std::endl; + } + + return 0; +} diff --git a/sose2020/num/uebungen/prog_nonlinear_solvers_fractal.py b/sose2020/num/uebungen/prog_nonlinear_solvers_fractal.py new file mode 100644 index 0000000..832bf0e --- /dev/null +++ b/sose2020/num/uebungen/prog_nonlinear_solvers_fractal.py @@ -0,0 +1,7 @@ +import numpy as np +import matplotlib.pyplot as plt + +data = np.genfromtxt('out', delimiter=",") + +plt.imshow(data, interpolation='nearest', cmap='viridis') +plt.savefig('out.pdf') diff --git a/sose2020/num/uebungen/prog_nonlinear_solvers_fractal2.cc b/sose2020/num/uebungen/prog_nonlinear_solvers_fractal2.cc new file mode 100644 index 0000000..ddc8958 --- /dev/null +++ b/sose2020/num/uebungen/prog_nonlinear_solvers_fractal2.cc @@ -0,0 +1,89 @@ +#include +#include +#include "hdnum.hh" + + +template +class PolynomialProblem +{ +public: + // Exportiere Größentyp + typedef std::size_t size_type; + + // Exportiere Zahlentyp + typedef N number_type; + + // Dimension der untenstehenden Funktion + std::size_t size () const + { + return 1; + } + + // Funktionsauswertung + void F (const hdnum::Vector& x, hdnum::Vector& result) const + { + result[0] = x[0]*x[0]*x[0] - 2.0*x[0] + 2.0; + } + + // Jacobimatrix + void F_x (const hdnum::Vector& x, hdnum::DenseMatrix& result) const + { + result[0][0] = 3.0*x[0]*x[0] - 2.0; + } +}; + + +int main () +{ + typedef std::complex Number; // Der Zahlentyp soll hier komplex sein + + typedef PolynomialProblem Problem; + Problem problem; + + + // Wir schauen Startpunkte auf einem Raster an, das später in ein Bild umgesetzt werden soll + for (double start_value_i = -5.0; start_value_i <= 5.0; start_value_i += 1e-3) { + + for (double start_value = -5.0; start_value <= 5.0; start_value += 1e-3) { + + hdnum::Vector u(problem.size()); // Vektor für Startpunkt bzw Lösung + u[0] = Number(start_value, start_value_i); // Startpunkt + + hdnum::Newton newton; + newton.set_maxit(20); + newton.set_verbosity(0); + newton.set_reduction(1e-10); + newton.set_abslimit(1e-20); + newton.set_linesearchsteps(3); + + newton.solve(problem,u); // Lösen + + double id = 0; + if(newton.has_converged()) { + + // Falls unser Newton-Löser konvertiert ist, stellen wir fest welche Nullstelle + // Nullstelle wir getroffen haben und legen einen Index für jede Nullstelle fest. + + if (u[0].real() < 0) + id = 1; + else if (u[0].imag() < 0) + id = 2; + else if (u[0].imag() > 0) + id = 3; + else + std::cout << "Unbekannte Nullstelle!" << std::endl; + + // Damit auch der "Abstand" zur Nullstelle (im Sinne von benötigten Iterationen + // um sie zu erreichen) sichtbar wird, addieren wir noch die Iterationszahl + // um einen Faktor abgeschwächt + id += .1 * (double)newton.iterations(); + } + + std::cout << id << ","; + } + + std::cout << std::endl; + } + + return 0; +} diff --git a/sose2020/num/uebungen/prog_nonlinear_solvers_methods.cc b/sose2020/num/uebungen/prog_nonlinear_solvers_methods.cc new file mode 100644 index 0000000..c48edc7 --- /dev/null +++ b/sose2020/num/uebungen/prog_nonlinear_solvers_methods.cc @@ -0,0 +1,98 @@ +#include +#include +#include "hdnum.hh" + +template +class EllipseProblem +{ +public: + // Exportiere Größentyp + typedef std::size_t size_type; + + // Exportiere Zahlentyp + typedef N number_type; + + // Dimension der untenstehenden Funktion + std::size_t size () const + { + return 2; + } + + // Funktionsauswertung + void F (const hdnum::Vector& x, hdnum::Vector& result) const + { + result[0] = pow(x[0], 2) + pow(x[1], 2) - 4; + result[1] = pow(x[0], 2)/9 + pow(x[1], 2) - 1; + } + + // Jacobimatrix + void F_x (const hdnum::Vector& x, hdnum::DenseMatrix& result) const + { + result[0][0] = 2*x[0]; result[0][1] = 2*x[1]; + result[1][0] = 2*x[0]/9; result[1][1] = 2*x[1]; + } +}; + +int main () +{ + typedef double Number; // Zahlentyp + + + typedef EllipseProblem Problem; + Problem problem; + + + hdnum::Vector u(problem.size()); // Vektor für Startpunkt bzw Lösung + hdnum::Vector result(problem.size()); // Vektor für Funktionswerte + + // Newton + hdnum::Newton newton; + newton.set_maxit(20); + newton.set_verbosity(2); + newton.set_reduction(1e-10); + newton.set_abslimit(1e-20); + newton.set_linesearchsteps(3); + + // 1. Quadrant + u[0] = 2.0; u[1] = 1.0; + newton.solve(problem,u); + std::cout << "Nullstelle im 1. Quadrant: " << std::setprecision(15) << u << std::endl; + problem.F(u, result); + std::cout << "Funktionswert: " << std::setprecision(15) << result << std::endl; + + // 2. Quadrant + u[0] = -2.0; u[1] = 1.0; + newton.solve(problem,u); + std::cout << "Nullstelle im 2. Quadrant: " << std::setprecision(15) << u << std::endl; + problem.F(u, result); + std::cout << "Funktionswert: " << std::setprecision(15) << result << std::endl; + + // 3. Quadrant + u[0] = -2.0; u[1] = -1.0; + newton.solve(problem,u); + std::cout << "Nullstelle im 3. Quadrant: " << std::setprecision(15) << u << std::endl; + problem.F(u, result); + std::cout << "Funktionswert: " << std::setprecision(15) << result << std::endl; + + // 4. Quadrant + u[0] = 2.0; u[1] = -1.0; + newton.solve(problem,u); + std::cout << "Nullstelle im 4. Quadrant: " << std::setprecision(15) << u << std::endl; + problem.F(u, result); + std::cout << "Funktionswert: " << std::setprecision(15) << result << std::endl; + + // Relaxation + hdnum::Banach banach; + banach.set_maxit(5000); // set parameters + banach.set_verbosity(2); + banach.set_reduction(1e-15); + banach.set_abslimit(1e-20); + banach.set_sigma(0.375); + + u[0] = 2.0; u[1] = 1.0; // Startwert + banach.solve(problem,u); + + std::cout << "Ergebnis: " << std::setprecision(15) << u << std::endl; + + return 0; +} diff --git a/sose2020/num/uebungen/raster_changed.pdf b/sose2020/num/uebungen/raster_changed.pdf new file mode 100644 index 0000000..0e666b1 Binary files /dev/null and b/sose2020/num/uebungen/raster_changed.pdf differ