From c3312086206a4b3cf0c955f306db9b98c7333a8f Mon Sep 17 00:00:00 2001 From: joachimschmidt557 Date: Mon, 25 Mar 2019 19:07:35 +0100 Subject: [PATCH] Fix GraphAlgorithm (hopefully) --- .../src/base/GraphAlgorithm.java | 23 ++++--- .../student/GraphAlgoComplexityTest.java | 32 +++++++++- doc/Dokumentation.tex | 60 ++++++++++++++++--- 3 files changed, 98 insertions(+), 17 deletions(-) diff --git a/Projektgruppe_175/src/base/GraphAlgorithm.java b/Projektgruppe_175/src/base/GraphAlgorithm.java index 2c5be16..b7def6c 100644 --- a/Projektgruppe_175/src/base/GraphAlgorithm.java +++ b/Projektgruppe_175/src/base/GraphAlgorithm.java @@ -70,7 +70,7 @@ public abstract class GraphAlgorithm { * @return Der nächste abzuarbeitende Knoten oder null */ private AlgorithmNode getSmallestNode() { - + if (DEBUG_2) System.out.println("Enter gSN"); @@ -79,13 +79,15 @@ public abstract class GraphAlgorithm { } Iterator> iter = availableNodes.iterator(); - AlgorithmNode MinElem; + Iterator> minElemIter = availableNodes.iterator(); + AlgorithmNode minElem; AlgorithmNode tempElem; if (iter.hasNext()) { - // Set minimum to first elements - MinElem = algorithmNodes.get(iter.next()); + // Set minimum to first element + minElem = algorithmNodes.get(iter.next()); + minElemIter.next(); while (iter.hasNext()) { @@ -99,15 +101,18 @@ public abstract class GraphAlgorithm { tempElem = algorithmNodes.get(iter.next()); if (tempElem.value > 0) { - if (tempElem.value < MinElem.value) { - MinElem = tempElem; + if (tempElem.value < minElem.value) { + + // New minimum + minElem = tempElem; + minElemIter = iter; } } } - iter.remove(); + minElemIter.remove(); - return MinElem; + return minElem; } @@ -192,7 +197,7 @@ public abstract class GraphAlgorithm { if (prevNode == null) return null; - while (!prevNode.node.equals(destination)) { + while (!(prevNode.value == 0)) { AlgorithmNode prevPrevNode = prevNode.previous; diff --git a/Projektgruppe_175/src/tests/student/GraphAlgoComplexityTest.java b/Projektgruppe_175/src/tests/student/GraphAlgoComplexityTest.java index b54a30c..977fc42 100644 --- a/Projektgruppe_175/src/tests/student/GraphAlgoComplexityTest.java +++ b/Projektgruppe_175/src/tests/student/GraphAlgoComplexityTest.java @@ -15,7 +15,7 @@ public class GraphAlgoComplexityTest { @Test public void test() { - for (int i = 1; i < 1000; i+=10) { + for (int i = 30; i < 50; i+=1) { Graph g = generateGraph(i); DumbGraphAlgorithm ga = new DumbGraphAlgorithm(g, g.getNodes().get(0)); @@ -27,6 +27,19 @@ public class GraphAlgoComplexityTest { double divN3 = (double)ga.getN() / ((double)i*i*i); System.out.println(i + "," + ga.getN() + "," + divN + "," + divN2 + "," + divN3); + + ///////////// + + Graph g2 = generateGraph2(i); + DumbGraphAlgorithm ga2 = new DumbGraphAlgorithm(g2, g2.getNodes().get(4)); + + ga2.run(); + + List> path = ga2.getPath(g2.getNodes().get(12)); + for (Edge edge : path) { + System.out.println(edge.getNodeA().getValue().toString() + " " + edge.getNodeB().getValue().toString()); + } + //System.out.println(); } @@ -53,6 +66,23 @@ public class GraphAlgoComplexityTest { } + public Graph generateGraph2(int n) { + + Graph g = new Graph(); + + List> nodes = new ArrayList<>(); + + for (int i = 0; i < n; i++) + nodes.add(g.addNode(i)); + + for (int i = 0; i < n - 1; i++) { + g.addEdge(nodes.get(i), nodes.get(i+1)); + } + + return g; + + } + public class DumbGraphAlgorithm extends GraphAlgorithm { public DumbGraphAlgorithm(Graph graph, Node sourceNode) { diff --git a/doc/Dokumentation.tex b/doc/Dokumentation.tex index ac80561..0b49e91 100644 --- a/doc/Dokumentation.tex +++ b/doc/Dokumentation.tex @@ -145,7 +145,7 @@ Eine pseudocode-Darstellung des Algorithmus: \If{edge is passable} \State $n \gets$ otherNode \State $a \gets$ v.value + edge.value - \If{n.value = -1 or n.value > a} + \If{n.value $= -1$ or n.value $> a$} \State n.value $\gets$ a \State n.previous $\gets$ v \EndIf @@ -182,9 +182,8 @@ Knoten eine Kante mit sich selber haben kann. \subsubsection{Teil (b)} Anstelle einer \texttt{LinkedList} braucht man eine -Datenstruktur, die bereits nach der Größe sortiert ist, -damit bei dem Zugriff auf das kleinste Element nur ein -Schritt erforderlich ist. +Datenstruktur, die den Zugriff auf das kleinste Element +effektiver gestaltet. Ein Beispiel dafür ist die \texttt{PriorityQueue}, die wir in Hausübung 8 implementiert haben. Dort werden @@ -192,8 +191,26 @@ Elemente beim Einfügen bereits sortiert, sodass der Zugriff auf das (in diesem Fall) kleinste Element in $O(1)$, also konstanter Zeit, gemacht werden kann. +Die algorithmische Komplexität mit dieser Änderung +beträgt dann im worst case + $$O(n)$$ +Für einen allgemeine Datentyp \texttt{T} kann man +folgendes feststellen: + +Sei $x$ die algorithmische Komplexität für das +Suchen vom kleinsten Element (z.B. $x = O(n)$ bei +\texttt{LinkedList}). + +Sei $y$ die algorithmische Komplexität für das +Entfernen vom kleinsten Element (bei einer normalen +\texttt{LinkedList} $O(1)$). + +Dann beträgt die algorithmische Komplexität + +$$O(n \cdot x \cdot y)$$ + \subsubsection{Teil (c)} Sei $n$ die Anzahl an Knoten. @@ -210,18 +227,37 @@ $n - h$ Elemente wurden noch nicht abgearbeitet. Für alle abgearbeiteten Knoten gilt: $h$ Knoten sind schon abgearbeitet worden. +Die zu den Knoten zugehörigen \texttt{AlgorithmNodes}-Objekte +beinhalten die insgesamte Länge zu dem Startknoten. \subsection{Kürzester Pfad zu allen Knoten} \subsubsection{Teil (a)} -Wenn ein negativer Zyklus auftaucht, +Wenn ein Zykel auftaucht, dann bedeutet +das, dass eine Menge $K$ an Knoten gibt, sodass +$K = \{k_1 ... k_n\}$ und Kanten zwischen $k_1$ +und $k_2$ usw. bis $k_n$ und $k_1$ existieren. + +Ein negativer Zykel ist dann vorhanden, wenn +$M^0(k_1, k_2) + ... + M^0(k_n, k_1) < 0$. +Oder mathematischer aufgeschrieben: + +$$\sum_{l=1}^{n-1} {M^0(k_l, k_{l+1})} + M^0(k_n, k_1) < 0$$ + +Laut der Schleifeninvariante gilt, dass nach $h \geq 0$ +Schritten $M^h$ die Längen von den Pfaden enthält, +die am kürzesten sind und dabei nicht mehr als +$h + 1$ Kanten besuchen. + +%Für die Graphmatrix $M$ gilt außerdem +%$M(k_1, k_2) < 0$ usw. bis $M(k_n, k_1) < 0$. \subsubsection{Teil (b)} -Best case: +Best case: $\Theta()$ -Worst case: +Worst case: $\Theta()$ \section{Weitergestaltung des Spiels} @@ -231,6 +267,12 @@ Worst case: \subsubsection{Begrenzte Rundenanzahl} +Wenn man diese Mission wählt, gilt es, nach einer +festgelegten Anzahl an Runden die meisten Burgen +zu besitzen. Sollten zwei oder mehr Spieler +gleich viele Burgen zu diesem Zeitpunkt in Besitz haben, +gibt es ein Unentschieden. + \subsubsection{Capture the Flag} In dieser Mission werden wichtige Burgen, sogenannte @@ -257,6 +299,10 @@ wenn die Mission aktiv ist und die Burgen verteilt wurden. \subsubsection{Bevölkerung} +Das Ziel der Spieler, die diese Mission ausgewählt haben, +ist es, vor allen anderen Spielern eine bestimmte Anzahl +an Truppen auf verschiedenen Burgen stationiert zu haben. + \subsection{Joker} \end{document}