Rewrite doc introduction

This commit is contained in:
arnekeller 2019-04-14 13:57:38 +02:00
parent 484c06dbd2
commit d1c14227d8

View File

@ -19,7 +19,8 @@
\cfoot{}
% Für mathematische Befehle und Symbole
\usepackage{amsmath,amsthm,amssymb,gensymb}
\usepackage{textcomp}
\usepackage{amsmath,amsthm,gensymb}
% Für Bilder
\usepackage{graphicx,subcaption,float}
@ -65,7 +66,7 @@
\tableofcontents
\section{Lösungsidee}
Zunächst kann man feststellen, dass jeder Abschnitt einer Route immer exakt gerade sein muss. In einer Kurve würde Lisa länger laufen, ohne am Ende weiter zu kommen. 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:
Lisas Haus und die Ecken der Hindernisse kann man als Graph darstellen. 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}).
\begin{figure}[H]
\centering
@ -144,9 +145,7 @@ Zunächst kann man feststellen, dass jeder Abschnitt einer Route immer exakt ger
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.
Natürlich wäre ein Konstruktionsalgorithmus, der eine optimale Route schnell aufstellt, sehr praktisch, aber ich konnte so einen Algorithmus nicht bestimmen. Mit einigen Modifizierungen sollte es aber möglich sein, eine optimale Route mittels A* oder einem ähnlichen Algorithmus zu finden. Allerdings wäre es nicht leicht, für A* eine Heuristik aufzustellen. Daher sind Suchalgorithmen ohne Heuristiken, wie z. B. Tiefen- oder Breitensuchen, für diese Aufgabe besser geeignet. Außerdem kann nicht nur die Strecke der Route berücksichtigt werden, da Lisa nicht eine möglichst kurze Strecke, sondern möglichst spät aufstehen will.
Der letzte Abschnitt ihrer Route trifft die y-Achse immer in einem 60\degree-Winkel (siehe Abb. \ref{fig:winkel}). Dieser Winkel ist vom Verhältnis der Geschwindigkeiten von Lisa und dem Bus abhängig: $cos(60\degree) = \frac{15}{30}$.
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.
\begin{figure}[H]
\centering
@ -225,12 +224,12 @@ Der letzte Abschnitt ihrer Route trifft die y-Achse immer in einem 60\degree-Win
\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}
Das vorgegebene Eingabeformat ist mühsam zu schreiben. Daher kann das Programm auch SVG-Dateien einlesen. Punkte werden als Startpunkte interpretiert, sonstige Pfade als Hindernisse. Interessanterweise ist die y-Achse in SVGs umgedreht, was vom Programm ausgeglichen wird. So sehen das Original-SVG und die Lösung gleich aus.
SVG-Dateien können auch als Eingabe verwendet werden, weil das vorgegebene Eingabeformat mühsam zu schreiben ist. Punkte werden als Startpunkte interpretiert, sonstige Pfade als Hindernisse. Interessanterweise ist die y-Achse in SVGs umgedreht, was vom Programm ausgeglichen wird. So sehen das Original-SVG und die Lösung gleich aus.
\section{Umsetzung}
Das Programm benutzt den Dijkstra-Algorithmus, um die beste Route für Lisa zu finden. Lisas Haus und die Ecken aller Polygone kann als Graph darstellen. Die Kanten des Graphen haben 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. Die Distanz zwischen zwei Punkten wäre definitv eine falsche Gewichtung, weil Lisa die y-Achse in einem bestimmten Winkel treffen sollte. Der kürzeste Weg würde höchstwahrscheinlich relativ direkt zur y-Achse führen, was nicht optimal ist. Um die Route abzuschließen, probiert das Programm danach immer, auf direktem Weg die y-Achse zu erreichen. Die Route, bei dem Lisa sich am meisten Zeit lassen kann, wird gespeichert und beschrieben.
Das Programm benutzt den Dijkstra-Algorithmus, um die beste Route für Lisa zu finden. Der schon beschriebene Graphen wird aus der Eingabedatei konstruiert, wobei die Kantenbestimmung aus Performanzgründen bei Bedarf erfolgt. Um die Route abzuschließen, probiert das Programm danach immer, auf direktem Weg die y-Achse zu erreichen. Die Route, bei dem Lisa sich am meisten Zeit lassen kann, wird gespeichert und ausgegeben.
Der Weg von Lisa und dem Bus wird animiert ausgegeben. Zusätzlich zu den unbedingt benötigten Ausgaben wie z.B. der Start- und Zielzeit gibt das Programm auch noch die theoretisch (ohne Hindernisse) beste Startzeit aus. Nützlich sind auch die Debug-Ausgaben, die Statistiken zur Eingabedatei und der Performanz (Zeit pro Iteration, Gesamtzeit) enthalten.
Der Weg von Lisa und dem Bus wird im SVG-Dokument animiert angezeigt. Zusätzlich zu den unbedingt benötigten Ausgaben wie z.B. der Start- und Zielzeit gibt das Programm auch noch die theoretisch (ohne Hindernisse) beste Startzeit aus. Nützlich sind auch die Debug-Ausgaben, die Statistiken zur Eingabedatei und der Performanz (Zeit pro Iteration, Gesamtzeit) enthalten.
\subsection{Laufzeitanalyse}
Da programmintern der Dijkstra-Algorithmus verwendet wird, entspricht die Laufzeit in etwa diesem. Somit ist die Zeitkomplexität ca. $O(n^2)$, wobei $n$ die Anzahl der Ecken aller Polygone ist. Effektiv können allerdings in jedem Schritt nur eine kleine Anzahl anderer Ecken erreicht werden, was den Algorithmus beschleunigen könnte. In Abschnitt \ref{performance} werden diese theoretischen Werte überprüft.