Reorder docs and add image

This commit is contained in:
arnekeller 2019-04-18 13:58:21 +02:00
parent 6f46467b78
commit 4cb06640bc

View File

@ -67,58 +67,21 @@
\tableofcontents
\section{Lösungsidee}
Lisas Haus und die Ecken der Hindernisse kann man als Graph darstellen (siehe Abb. \ref{fig:graph}). Eine Kante zwischen zwei Ecken ist nur dann vorhanden, wenn Lisa direkt vom einen zum anderen Punkt laufen kann. Mögliche Wege, die nicht geradlinig sind, sind immer suboptimal, da diese immer einem Hindernis ausweichen würden. Stattdessen wäre es besser, zuerst zu diesem Hindernis zu gehen und dann weiterzugehen. Die Gewichtung der Kanten kann nicht einfach nur der euklidische Abstand der beiden Punkte sein, da Lisa nicht den kürzesten Weg finden will, sondern möglichst lange schlafen will. Daher haben diese ein Gewicht, das der Zeit entspricht, die Lisa früher aufstehen müsste, wenn sie zu einem bestimmten Punkt geht, statt direkt zum Bus zu gehen. Es gibt viele Suchalgorithmen für Graphen, die einen kürzesten Weg bestimmen. Allerdings ist es nicht einfach, eine Heuristik, die z.B. von A* benötigt wird, aufzustellen. Sowohl die Distanz zur y-Achse auch als die Anzahl der Hindernisse auf direktem Weg zum Bus können nicht in das Einheitensystem der Kantengewichte übertragen werden. Daher sind Suchalgorithmen ohne solche Heuristikfunktionen besser geeignet. Eine Breiten- oder Tiefensuche wäre allerdings nicht besonders performant, da diese entweder zu langsam vorwärtskommen (Breitensuche) oder sich zuerst auf eine suboptimal Route fokussieren können (Tiefensuche). Da die Kantengewichte immer nicht-negativ sind, kann auch der Dijkstra-Algorithmus verwendet werden. Wenn Lisa am Ende der Route zum Bus läuft, gibt es keinen, einen oder zwei Treffpunkte, bei denen Lisa (ohne zu warten) den Bus erwischt (siehe Abb. \ref{fig:treffpunkte}).
Der einfachste Fall ist der, in dem Lisa keine Hindernisse berücksichtigen muss. Würde der Bus zudem die gleiche Geschwindigkeit wie Lisa haben, müsste Lisa die Route vom Bus (die y-Achse) in einem 90\degree-Winkel treffen. So kann sie möglichst spät loslaufen. Generell tritt dieser Fall immer im letzten Abschnitt von Lisas Route auf. Nachdem sie eventuelle Hindernisse passiert hat, läuft sie danach immer direkt zur y-Achse. Wenn sie so am Ende der Route zum Bus läuft, gibt es theoretisch gesehen keinen, einen oder zwei Treffpunkte, bei denen Lisa (ohne zu warten) den Bus erwischt (siehe Abb. \ref{fig:treffpunkte}).
Ein weiteres Problem ist die Bestimmung der Kanten. Um sicher alle möglichen Wege zu finden, müssen $\frac{n*(n-1)}{2}+n$ Überprüfungen durchgeführt werden, wobei $n$ die Anzahl der Wegpunkte ist. Wegpunkte sind Lisas Haus und die Ecken der Hindernisse. Da die Anzahl der benötigten Überprüfungen ca. quadratisch anwächst, sollten diese möglichst schnell durchgeführt werden. Um für jeden Wegabschnitt zu überprüfen, ob er eins der Hindernisse schneidet (nicht nur berührt), kann man für jedes Hindernis ausrechnen, ob die Gerade das entsprechende Polygon schneidet. Allerdings würde die Rechenzeit dann kubisch wachsen.
Zudem ist die Anzahl der möglichen Routen sehr groß: ca. $n!$. In einem Suchalgorithmus sollten also zuerst die Routen ausprobiert werden, die wahrscheinlich zu einer guten Lösung führen. Unvollständige Routen, die schlechter als während der Suche gefundene Lösungen sind, können auch verworfen werden.
\begin{figure}[H]
\centering
\begin{subfigure}{.48\textwidth}
\centering
\begin{tikzpicture}
\tkzInit[xmax=5,ymax=2.5]
\tkzAxeXY
\tkzGrid
\tkzDefPoints{0.75/0.75/P0_0,2.25/0.75/P0_1,1.75/2/P0_2,1.25/2/P0_3}
\tkzDrawPolygon[fill=black,line width=1pt,opacity=0.5](P0_0,P0_1,P0_2,P0_3)
\tkzDefPoint(3,1){R0}
\tkzDrawPoint[fill=red,color=black,size=13](R0)
\end{tikzpicture}
\caption{Eingabe}
\label{abb:eingabe}
\end{subfigure}%
\begin{subfigure}{.48\textwidth}
\centering
\begin{tikzpicture}
\SetGraphUnit{1.5}
\GraphInit[vstyle=Normal]
\SetVertexSimple[Shape=circle,FillColor=green!50]
\Vertex{L}
\SetVertexSimple[Shape=rectangle,FillColor=blue!50]
\WE(L){P0E0}
\WE(P0E0){P0E1}
\NO(P0E1){P0E2}
\EA(P0E2){P0E3}
\SetVertexSimple[Shape=circle,FillColor=yellow!50]
\NOWE(P0E2){B}
\Edge(L)(P0E0)
\Edge(L)(P0E3)
\Edge(P0E0)(P0E1)
\Edge(P0E0)(P0E3)
\Edge(P0E1)(P0E2)
\Edge(P0E2)(P0E3)
\Edge(P0E1)(B)
\Edge(P0E2)(B)
\Edge(P0E3)(B)
\end{tikzpicture}
\caption{Graph}
\label{abb:graph-eingabe}
\end{subfigure}
\caption{Konvertierung der Eingabe zu einem Graphen}
\label{fig:graph}
\end{figure}
\begin{proof}
Sei Lisa bei $L(x_{L},y_{L})$ und der Bus bei $B(x_{B},y_{B})$. $M(x_{M},y_{M})$ sei der Treffpunkt von Lisa mit dem Bus. $d$ sei der Weg, den Lisa zu diesem Punkt geht.
\begin{align*}
d &= \sqrt{(x_{L}-x_{M})^2 + (y_{L}-y_{M})^2} &&\text{(Satz des Pythagoras)} \\
&= \sqrt{x_{L}^2 + (y_{L}-y_{M})^2} &&\text{($x_{B} = x_{M} = 0$)} \\
d^2 &= x_{L}^2 + (y_{L}-y_{M})^2 \\
&= x_{L}^2 + (y_{L}-y_{B}-2d)^2 &&\text{($y_{M} = y_{B} + 2d$)} \\
&= x_{L}^2 + y_{L}^2 + y_{B}^2 + 4d^2 - 2y_{B}y_{L} - 4dy_{L} + 4dy_{B} \\
0 &= x_{L}^2 + y_{L}^2 + y_{B}^2 + 3d^2 - 2y_{B}y_{L} - 4dy_{L} + 4dy_{B} \\
d &= \frac{-b\pm\sqrt{b^2 - 12\cdot{}(x_{L}^2 + y_{L}^2 + y_{B}^2 - 2y_{B}y_{L})}}{6} &&\text{($b = 4\cdot(y_{B}-y_{L})$)}
\end{align*}
Für diese Gleichung gibt es maximal zwei nicht-negative Lösungen.\qedhere
\end{proof}
\begin{figure}[H]
\centering
@ -181,23 +144,7 @@ Zudem ist die Anzahl der möglichen Routen sehr groß: ca. $n!$. In einem Suchal
\label{fig:treffpunkte}
\end{figure}
\begin{proof}
Sei Lisa bei $L(x_{L},y_{L})$ und der Bus bei $B(x_{B},y_{B})$. $M(x_{M},y_{M})$ sei der Treffpunkt von Lisa mit dem Bus. $d$ sei der Weg, den Lisa zu diesem Punkt geht.
\begin{align*}
d &= \sqrt{(x_{L}-x_{M})^2 + (y_{L}-y_{M})^2} &&\text{(Satz des Pythagoras)} \\
&= \sqrt{x_{L}^2 + (y_{L}-y_{M})^2} &&\text{($x_{B} = x_{M} = 0$)} \\
d^2 &= x_{L}^2 + (y_{L}-y_{M})^2 \\
&= x_{L}^2 + (y_{L}-y_{B}-2d)^2 &&\text{($y_{M} = y_{B} + 2d$)} \\
&= x_{L}^2 + y_{L}^2 + y_{B}^2 + 4d^2 - 2y_{B}y_{L} - 4dy_{L} + 4dy_{B} \\
0 &= x_{L}^2 + y_{L}^2 + y_{B}^2 + 3d^2 - 2y_{B}y_{L} - 4dy_{L} + 4dy_{B} \\
d &= \frac{-b\pm\sqrt{b^2 - 12\cdot{}(x_{L}^2 + y_{L}^2 + y_{B}^2 - 2y_{B}y_{L})}}{6} &&\text{($b = 4\cdot(y_{B}-y_{L})$)}
\end{align*}
Für diese Gleichung gibt es maximal zwei nicht-negative Lösungen.\qedhere
\end{proof}
Um den letzten Zeitpunkt, bei dem sie den Bus gerade noch erwischt, zu bestimmen, kann man die Wurzel in der letzen Gleichung gleich Null setzen. Wenn man nach $y_{B}$ auflöst, erhält man die Position des Busses, bei dessen Durchquerung Lisa anfangen sollte zu laufen. So kann man für jeden Startpunkt berechnen, wann Lisa spätestens von dort loslaufen müsste.
Indem Lisa früher oder später losläuft kann sie im letzten Abschnitt ihrer Route die y-Achse immer in einem 60\degree-Winkel (siehe Abb. \ref{fig:winkel}) treffen. Dieser Winkel ist vom Verhältnis der Geschwindigkeiten von Lisa und dem Bus abhängig: $cos(60\degree) = \frac{15}{30}$. Für andere Winkel müsste Lisa früher loslaufen. In der linken und rechten Abbildung ist der Bus dementsprechend noch weiter unten auf der y-Achse.
Wenn zwei Treffpunkte möglich sind, kann die y-Startkoordinate des Busses erhöht werden. Dabei konvergieren die beiden Treffpunkte zu einem Punkt. Um die diesem Punkt entsprechende Position des Busses zu ermitteln, kann man die Wurzel in der letzten Gleichung gleich Null setzen. Löst man nach $y_{B}$ auf, erhält man die Position des Busses, bei dessen Durchquerung Lisa anfangen sollte zu laufen. So kann man für jede Position berechnen, wann Lisa spätestens von dieser loslaufen müsste. Der Winkel, in dem Lisa die y-Achse trifft, ist vom Verhältnis der Geschwindigkeiten von Lisa und dem Bus abhängig: $cos(60\degree) = \frac{15}{30}$. Für andere Winkel müsste Lisa früher loslaufen. In der linken und rechten Abbildung ist der Bus dementsprechend noch weiter unten auf der y-Achse:
\begin{figure}[H]
\centering
@ -273,6 +220,90 @@ Indem Lisa früher oder später losläuft kann sie im letzten Abschnitt ihrer Ro
\label{fig:winkel}
\end{figure}
Lisas Haus und die Ecken der Hindernisse kann man als Graph darstellen (siehe Abb. \ref{fig:graph}). Eine Kante zwischen zwei Ecken ist nur dann vorhanden, wenn Lisa geradlinig vom einen zum anderen Punkt laufen kann. Mögliche Wege, die nicht geradlinig sind, sind immer suboptimal, da diese immer einem Hindernis ausweichen würden. Stattdessen ist es besser, zuerst zu einer Ecke des Hindernisses zu gehen und dann weiterzugehen (siehe Abb. \ref{fig:gewicht}). Die Gewichtung der Kanten kann nicht einfach nur der euklidische Abstand der beiden Punkte sein, da Lisa nicht den kürzesten Weg finden will, sondern möglichst lange schlafen will. Daher haben diese ein Gewicht, das proportional zur Zeit ist, die Lisa früher aufstehen müsste, wenn sie zu einem bestimmten Punkt geht, statt direkt zum Bus zu gehen ($x$ in Abb. \ref{fig:gewicht}).
\begin{figure}[H]
\centering
\begin{tikzpicture}
\tkzInit[xmax=5.2,ymax=5.2]
\tkzAxeXY
\tkzGrid
\tkzDefPoints{3.8214/2.6286/P0_0,4.357/0.2/P0_1,3.2857/0.2/P0_2,3.8214/2.6286/P0_3}
\tkzDrawPolygon[fill=black,line width=1pt,opacity=0.5](P0_0,P0_1,P0_2,P0_3)
\tkzDefPoint(0,0.9017){B0}
\tkzDefPoint(0,2.4755){B1}
\tkzDefPoint(4.5214,1.05){R0}
\tkzDefPoint(3.8214,2.6286){R1}
\tkzDefPoint(0,4.8348){R2}
\tkzDrawSegment(R0,R1)
\tkzDrawSegment(R1,R2)
\tkzDrawSegment(B0,R2)
\draw [dashed] (R0) -- (R2);
\draw [decorate,decoration={brace,mirror,amplitude=10pt,raise=4pt},yshift=0pt]
(B0) -- (B1) node [black,midway,xshift=0.7cm] {$x$};
\tkzDrawPoint[fill=yellow,color=black,size=13](B0)
\tkzDrawPoint[fill=green,color=black,size=13](B1)
\tkzDrawPoint[fill=red,color=black,size=13](R0)
\tkzDrawPoint[fill=yellow,color=black,size=13](R1)
\tkzDrawPoint[fill=red,color=black,size=13](R2)
\end{tikzpicture}
\caption{Kantengewicht}
\label{fig:gewicht}
\end{figure}
Es gibt viele Suchalgorithmen für Graphen, die einen kürzesten Weg bestimmen. Allerdings ist es nicht einfach, eine Heuristik, die z.B. von A* benötigt wird, aufzustellen. Sowohl die Distanz zur y-Achse auch als die Anzahl der Hindernisse auf direktem Weg zum Bus können nicht in das Einheitensystem der Kantengewichte übertragen werden. Daher sind Suchalgorithmen ohne solche Heuristikfunktionen besser geeignet. Eine Breiten- oder Tiefensuche wäre allerdings nicht besonders performant, da diese entweder zu langsam vorwärtskommen (Breitensuche) oder sich zuerst auf eine suboptimale Route fokussieren können (Tiefensuche). Da die Kantengewichte immer nicht-negativ sind, kann auch der Dijkstra-Algorithmus verwendet werden.
Ein weiteres Problem ist die Bestimmung der Kanten. Um sicher alle möglichen Wege zu finden, müssen $\frac{n*(n-1)}{2}+n$ Überprüfungen durchgeführt werden, wobei $n$ die Anzahl der Wegpunkte ist. Wegpunkte sind Lisas Haus und die Ecken der Hindernisse. Da die Anzahl der benötigten Überprüfungen ca. quadratisch anwächst, sollten diese möglichst schnell durchgeführt werden. Um für jeden Wegabschnitt zu überprüfen, ob er eins der Hindernisse schneidet (nicht nur berührt), kann man für jedes Hindernis ausrechnen, ob die Gerade das entsprechende Polygon schneidet. Allerdings würde die Rechenzeit dann kubisch wachsen.
Zudem ist die Anzahl der möglichen Routen sehr groß: ca. $n!$. In einem Suchalgorithmus sollten also zuerst die Routen ausprobiert werden, die wahrscheinlich zu einer guten Lösung führen. Unvollständige Routen, die schlechter als während der Suche gefundene Lösungen sind, können auch verworfen werden.
\begin{figure}[H]
\centering
\begin{subfigure}{.48\textwidth}
\centering
\begin{tikzpicture}
\tkzInit[xmax=5,ymax=2.5]
\tkzAxeXY
\tkzGrid
\tkzDefPoints{0.75/0.75/P0_0,2.25/0.75/P0_1,1.75/2/P0_2,1.25/2/P0_3}
\tkzDrawPolygon[fill=black,line width=1pt,opacity=0.5](P0_0,P0_1,P0_2,P0_3)
\tkzDefPoint(3,1){R0}
\tkzDrawPoint[fill=red,color=black,size=13](R0)
\end{tikzpicture}
\caption{Eingabe}
\label{abb:eingabe}
\end{subfigure}%
\begin{subfigure}{.48\textwidth}
\centering
\begin{tikzpicture}
\SetGraphUnit{1.5}
\GraphInit[vstyle=Normal]
\SetVertexSimple[Shape=circle,FillColor=green!50]
\Vertex{L}
\SetVertexSimple[Shape=rectangle,FillColor=blue!50]
\WE(L){P0E0}
\WE(P0E0){P0E1}
\NO(P0E1){P0E2}
\EA(P0E2){P0E3}
\SetVertexSimple[Shape=circle,FillColor=yellow!50]
\NOWE(P0E2){B}
\Edge(L)(P0E0)
\Edge(L)(P0E3)
\Edge(P0E0)(P0E1)
\Edge(P0E0)(P0E3)
\Edge(P0E1)(P0E2)
\Edge(P0E2)(P0E3)
\Edge(P0E1)(B)
\Edge(P0E2)(B)
\Edge(P0E3)(B)
\end{tikzpicture}
\caption{Graph}
\label{abb:graph-eingabe}
\end{subfigure}
\caption{Konvertierung der Eingabe zu einem Graphen}
\label{fig:graph}
\end{figure}
\section{Bedienung des Programms}
Das Programm liest die Problemstellung von der Standardeingabe ein. Die grafische Ausgabe wird in die Standardausgabe geschrieben. Wird $-t$ übergeben, kann die Ausgabe in einem \LaTeX-Dokument verwendet werden. Standardmäßig wird ein SVG-Dokument erzeugt. Falls man die Geschwindigkeit von Lisa oder dem Bus verändern will, kann man dies mit $-l$ bzw. $-b$ tun. Für zusätzliche Debug-Ausgaben kann man $-d$ verwenden. Die Standardoptionen $-h$ und $-V$ zeigen die Hilfe und die Version des Programms an.
\lstinputlisting[caption=Hilfetext des Programmes,frame=single,breaklines=true]{help.txt}