Merge branch 'main' of https://gitea.hb.dhbw-stuttgart.de/i23024/ProjektGraph
# Conflicts: # .idea/workspace.xml # graph/ExampleGraphs.java
This commit is contained in:
commit
dc371da1f2
@ -43,13 +43,7 @@ public class OurApplication {
|
||||
*/
|
||||
public static void main(String[]args){
|
||||
|
||||
Random random = new Random();
|
||||
|
||||
DirectedGraph<VertexMarking, EdgeMarking> myGraph = new DirectedGraph<>();
|
||||
|
||||
ExampleGraphs temp = new ExampleGraphs();
|
||||
//myGraph = temp.example2();
|
||||
//sean: Ich wollte erst hier dann das ausgewählte Beispiel reinhauen, jedoch wird das hier nur einmal am Anfang aufgerufen
|
||||
System.out.println(myGraph.toString());
|
||||
|
||||
|
||||
@ -73,7 +67,7 @@ public class OurApplication {
|
||||
frame.pack();
|
||||
applet.init();
|
||||
applet.start();
|
||||
frame.setSize(1000,800);
|
||||
frame.setSize(1350,800);
|
||||
frame.setVisible(true);
|
||||
|
||||
}
|
||||
|
@ -349,18 +349,18 @@ public class DirectedGraph<T extends VertexMarking, U extends EdgeMarking> exten
|
||||
// Den nächsten Knoten, der am wenigsten kostet, besuchen
|
||||
WrapperElement<T> nextVertex = queue.poll();
|
||||
|
||||
// Knoten als besucht makieren
|
||||
visited.put(nextVertex.getElement(), true);
|
||||
|
||||
|
||||
// Logging
|
||||
textDescription = "Visit " + nextVertex.getElement().getName();
|
||||
System.out.println(textDescription);
|
||||
if (nextVertex.getElement().getScreenVertex().getColor() != Color.RED) {
|
||||
nextVertex.getElement().getScreenVertex().setColor(Color.BLUE);
|
||||
// Falls Knoten schon besucht
|
||||
if(!visited.get(nextVertex.getElement())){
|
||||
// Knoten als besucht makieren
|
||||
visited.put(nextVertex.getElement(), true);
|
||||
textDescription = "Visit " + nextVertex.getElement().getName();
|
||||
// Logging
|
||||
System.out.println(textDescription);
|
||||
if (nextVertex.getElement().getScreenVertex().getColor() != Color.RED) {
|
||||
nextVertex.getElement().getScreenVertex().setColor(Color.BLUE);
|
||||
}
|
||||
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
||||
}
|
||||
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
||||
|
||||
|
||||
// Wenn Weg gefunden, brich ab
|
||||
if (nextVertex.getElement() == n2) {
|
||||
@ -445,7 +445,7 @@ public class DirectedGraph<T extends VertexMarking, U extends EdgeMarking> exten
|
||||
* @param n2 the ending vertex
|
||||
* @return the shortest distance from n1 to n2, or -1 if no path is found
|
||||
*/
|
||||
public int getShortestPathAStar(MarkedVertex<T> n1, MarkedVertex<T> n2) {
|
||||
public double getShortestPathAStar(MarkedVertex<T> n1, MarkedVertex<T> n2) {
|
||||
|
||||
// Erstellt Hashmap um Distanz von Startnoten zu jedem Knoten auf dem Graph zu tracken
|
||||
// Erstellt Hashmap um zu tracken welche Knoten schon besucht wurden
|
||||
@ -453,11 +453,11 @@ public class DirectedGraph<T extends VertexMarking, U extends EdgeMarking> exten
|
||||
// Initialisierung aller Distanzen auf UNENDLICH (= -1)
|
||||
// Initialisierung, dass kein Knoten besucht wurde
|
||||
// Initialisierung aller Vorgänger auf null
|
||||
HashMap<MarkedVertex<T>, Integer> distance = new HashMap<>();
|
||||
HashMap<MarkedVertex<T>, Double> distance = new HashMap<>();
|
||||
HashMap<MarkedVertex<T>, Boolean> visited = new HashMap<>();
|
||||
HashMap<MarkedVertex<T>, MarkedVertex<T>> predecessors = new HashMap<>();
|
||||
for (MarkedVertex<T> i: this.getAllVertexes()) {
|
||||
distance.put(i, -1);
|
||||
distance.put(i, -1.0);
|
||||
visited.put(i, false);
|
||||
predecessors.put(i, null);
|
||||
}
|
||||
@ -467,15 +467,15 @@ public class DirectedGraph<T extends VertexMarking, U extends EdgeMarking> exten
|
||||
|
||||
// Distanz zu Startknoten auf 0
|
||||
// Weg zu Startknoten in die Schlange aufnehmen
|
||||
distance.put(n1, 0);
|
||||
distance.put(n1, 0.0);
|
||||
queue.add(new WrapperElement<>(n1, 0));
|
||||
|
||||
// Variable, die Distanz zwischen aktuellem Knoten und Nachfolger speichert
|
||||
int dist = 0;
|
||||
double dist = 0;
|
||||
// Variable, die Distanz zwischen dem potenziell nächsten Knoten und dem Zielknoten speichert
|
||||
int airDist = 0;
|
||||
double airDist = 0;
|
||||
// Variable, die Distanz zwischen dem aktuellen Knoten bis zum Endknoten speichert
|
||||
int distToFinish = 0;
|
||||
double distToFinish = 0;
|
||||
// Zähler für LogList
|
||||
int step = 0;
|
||||
// String für den Description Inhalt
|
||||
@ -492,17 +492,19 @@ public class DirectedGraph<T extends VertexMarking, U extends EdgeMarking> exten
|
||||
// Den nächsten Knoten, der am wenigsten kostet, besuchen
|
||||
WrapperElement<T> nextVertex = queue.poll();
|
||||
|
||||
// Knoten als besucht makieren
|
||||
visited.put(nextVertex.getElement(), true);
|
||||
|
||||
|
||||
// Logging
|
||||
textDescription = "Visit " + nextVertex.getElement().getName();
|
||||
System.out.println(textDescription);
|
||||
if (nextVertex.getElement().getScreenVertex().getColor() != Color.RED) {
|
||||
nextVertex.getElement().getScreenVertex().setColor(Color.BLUE);
|
||||
// Falls Knoten schon besucht
|
||||
if(!visited.get(nextVertex.getElement())){
|
||||
// Knoten als besucht makieren
|
||||
visited.put(nextVertex.getElement(), true);
|
||||
textDescription = "Visit " + nextVertex.getElement().getName();
|
||||
// Logging
|
||||
System.out.println(textDescription);
|
||||
if (nextVertex.getElement().getScreenVertex().getColor() != Color.RED) {
|
||||
nextVertex.getElement().getScreenVertex().setColor(Color.BLUE);
|
||||
}
|
||||
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
||||
}
|
||||
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
||||
|
||||
// Wenn Weg gefunden, brich ab
|
||||
if (nextVertex.getElement() == n2) {
|
||||
@ -531,8 +533,8 @@ public class DirectedGraph<T extends VertexMarking, U extends EdgeMarking> exten
|
||||
if (j.getSource() == nextVertex.getElement() && j.getDestination() == i) {
|
||||
|
||||
//Berechnung der Heuristik über die Luftdistanz des nächsten Knoten zum Zielknoten
|
||||
airDist = (int) Math.sqrt(Math.pow((i.getCords()[0] - n2.getCords()[0]), 2)
|
||||
+ Math.pow((i.getCords()[1] - n2.getCords()[1]), 2));
|
||||
airDist = Math.sqrt(Math.pow((i.getCords()[0] - n2.getCords()[0]), 2)
|
||||
+ Math.pow((i.getCords()[1] - n2.getCords()[1]), 2)) / 100;
|
||||
|
||||
// Berechne Distanz zu nächstem Knoten
|
||||
EdgeWeightMarking marking = (EdgeWeightMarking) j.getMarking();
|
||||
@ -554,7 +556,7 @@ public class DirectedGraph<T extends VertexMarking, U extends EdgeMarking> exten
|
||||
distance.put(i, dist);
|
||||
|
||||
// Logging
|
||||
textDescription = "Add " + i.getName() + " with " + dist + " weight to queue.";
|
||||
textDescription = "Add " + i.getName() + " with " + distToFinish + " weight to queue.";
|
||||
System.out.println(textDescription);
|
||||
if (i.getScreenVertex().getColor() != Color.RED) {
|
||||
i.getScreenVertex().setColor(Color.YELLOW);
|
||||
|
@ -1,29 +1,93 @@
|
||||
package graph;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class containing example graphs for demonstration purposes.
|
||||
*/
|
||||
public class ExampleGraphs {
|
||||
|
||||
/**
|
||||
* Creates an example graph suitable for demonstrating Dijkstra's and A* algorithms.
|
||||
* This graph contains multiple nodes connected by weighted edges, allowing efficient
|
||||
* calculation of shortest paths from a start node to an end node.
|
||||
*
|
||||
* @return Directed graph instance for example 1.
|
||||
*/
|
||||
public DirectedGraph<VertexMarking, EdgeMarking> example1() {
|
||||
|
||||
/**
|
||||
* Beispiel 1 zeigt ein Gitter aus Knoten und Kanten, bei dem jeder Knoten mit
|
||||
* seinen horizontal und vertikal benachbarten Knoten verbunden ist. Alle Kanten
|
||||
* haben die gleiche Gewichtung. Der Startknoten befindet sich in einer Ecke
|
||||
* des Gitters und der Zielknoten in der gegenüberliegenden Ecke.
|
||||
/*
|
||||
* Erstellt einen Beispielgraphen, der sich ideal für die Demonstration der Funktionsweise
|
||||
* des Dijkstra- und A*-Algorithmus eignet. Der Graph enthält eine Vielzahl von Knoten, die durch
|
||||
* gewichtete Kanten verbunden sind. Dies ermöglicht es, den kürzesten Weg von einem Startknoten zu einem
|
||||
* Zielknoten effizient zu berechnen und die Pfadfindung der beiden Algorithmen zu veranschaulichen.
|
||||
*
|
||||
* Ziel:
|
||||
* Demonstrieren, wie der A*-Algorithmus durch gezieltere Suche effizienter ist
|
||||
* als der Dijkstra-Algorithmus in einem strukturierten Gittergraphen.
|
||||
*
|
||||
* Startknoten: A
|
||||
* Endknoten: Y
|
||||
*/
|
||||
|
||||
DirectedGraph<VertexMarking, EdgeMarking> example1 = new DirectedGraph<>();
|
||||
|
||||
// Erstellung der Knoten mit Koordinaten
|
||||
MarkedVertex<VertexMarking> A = new MarkedVertex<>(50, 250, "Start", null, null);
|
||||
MarkedVertex<VertexMarking> B = new MarkedVertex<>(150, 150, "B", null, null);
|
||||
MarkedVertex<VertexMarking> C = new MarkedVertex<>(150, 350, "C", null, null);
|
||||
MarkedVertex<VertexMarking> D = new MarkedVertex<>(250, 100, "D", null, null);
|
||||
MarkedVertex<VertexMarking> E = new MarkedVertex<>(250, 250, "E", null, null);
|
||||
MarkedVertex<VertexMarking> F = new MarkedVertex<>(350, 200, "F", null, null);
|
||||
MarkedVertex<VertexMarking> G = new MarkedVertex<>(450, 300, "G", null, null);
|
||||
MarkedVertex<VertexMarking> H = new MarkedVertex<>(450, 100, "Ende", null, null);
|
||||
|
||||
|
||||
// Hinzufügen der Knoten zum Graphen
|
||||
example1.addVertex(A);
|
||||
example1.addVertex(B);
|
||||
example1.addVertex(C);
|
||||
example1.addVertex(D);
|
||||
example1.addVertex(E);
|
||||
example1.addVertex(F);
|
||||
example1.addVertex(G);
|
||||
example1.addVertex(H);
|
||||
|
||||
// Erstellung der Kanten mit Gewichtungen
|
||||
example1.addEdge(new MarkedEdge<>("AB", A, B, new EdgeWeightMarking(4)));
|
||||
example1.addEdge(new MarkedEdge<>("AC", A, C, new EdgeWeightMarking(2)));
|
||||
example1.addEdge(new MarkedEdge<>("BC", B, C, new EdgeWeightMarking(5)));
|
||||
example1.addEdge(new MarkedEdge<>("BD", B, D, new EdgeWeightMarking(10)));
|
||||
example1.addEdge(new MarkedEdge<>("CD", C, D, new EdgeWeightMarking(3)));
|
||||
example1.addEdge(new MarkedEdge<>("CE", C, E, new EdgeWeightMarking(7)));
|
||||
example1.addEdge(new MarkedEdge<>("DE", D, E, new EdgeWeightMarking(2)));
|
||||
example1.addEdge(new MarkedEdge<>("DF", D, F, new EdgeWeightMarking(2)));
|
||||
example1.addEdge(new MarkedEdge<>("EF", E, F, new EdgeWeightMarking(5)));
|
||||
example1.addEdge(new MarkedEdge<>("EG", E, G, new EdgeWeightMarking(10)));
|
||||
example1.addEdge(new MarkedEdge<>("FG", F, G, new EdgeWeightMarking(3)));
|
||||
example1.addEdge(new MarkedEdge<>("FH", F, H, new EdgeWeightMarking(6)));
|
||||
example1.addEdge(new MarkedEdge<>("GH", G, H, new EdgeWeightMarking(1)));
|
||||
|
||||
return example1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an example grid graph where each node is connected to its horizontal and vertical neighbors.
|
||||
* All edges have the same weight. The start node is in one corner of the grid, and the end node is
|
||||
* in the opposite corner, demonstrating the efficiency of the A* algorithm in structured grid graphs.
|
||||
*
|
||||
* @return Directed graph instance for example 2.
|
||||
*/
|
||||
public DirectedGraph<VertexMarking, EdgeMarking> example2() {
|
||||
|
||||
/*
|
||||
* Beispiel 2 zeigt ein Gitter aus Knoten und Kanten, bei dem jeder Knoten mit
|
||||
* seinen horizontal und vertikal benachbarten Knoten verbunden ist. Alle Kanten
|
||||
* haben die gleiche Gewichtung. Der Startknoten befindet sich in einer Ecke
|
||||
* des Gitters und der Zielknoten in der gegenüberliegenden Ecke. Dadurch wird gezeigt,
|
||||
* wie der A*-Algorithmus durch gezieltere Suche effizienter ist
|
||||
* als der Dijkstra-Algorithmus in einem strukturierten Gittergraphen.
|
||||
*
|
||||
*/
|
||||
|
||||
DirectedGraph<VertexMarking, EdgeMarking> example2 = new DirectedGraph<>();
|
||||
|
||||
int size = 5;
|
||||
MarkedVertex<VertexMarking>[][] vertices = new MarkedVertex[size][size];
|
||||
|
||||
@ -37,7 +101,7 @@ public class ExampleGraphs {
|
||||
name = "Ende";
|
||||
}
|
||||
vertices[row][col] = new MarkedVertex<>(50 + col * 100, 50 + row * 100, name, null, null);
|
||||
example1.addVertex(vertices[row][col]);
|
||||
example2.addVertex(vertices[row][col]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,38 +109,36 @@ public class ExampleGraphs {
|
||||
for (int row = 0; row < size; row++) {
|
||||
for (int col = 0; col < size; col++) {
|
||||
if (col < size - 1) {
|
||||
addBidirectionalEdge(example1, vertices[row][col], vertices[row][col + 1], new EdgeWeightMarking(1));
|
||||
addBidirectionalEdge(example2, vertices[row][col], vertices[row][col + 1], new EdgeWeightMarking(1));
|
||||
}
|
||||
if (row < size - 1) {
|
||||
addBidirectionalEdge(example1, vertices[row][col], vertices[row + 1][col], new EdgeWeightMarking(1));
|
||||
addBidirectionalEdge(example2, vertices[row][col], vertices[row + 1][col], new EdgeWeightMarking(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return example1;
|
||||
return example2;
|
||||
}
|
||||
|
||||
private void addBidirectionalEdge(DirectedGraph<VertexMarking, EdgeMarking> graph, MarkedVertex<VertexMarking> from, MarkedVertex<VertexMarking> to, EdgeWeightMarking weight) {
|
||||
MarkedEdge<EdgeMarking> forwardEdge = new MarkedEdge<>("edge" + from.getName() + "_" + to.getName(), from, to, weight);
|
||||
MarkedEdge<EdgeMarking> backwardEdge = new MarkedEdge<>("edge" + to.getName() + "_" + from.getName(), to, from, weight);
|
||||
graph.addEdge(forwardEdge);
|
||||
graph.addEdge(backwardEdge);
|
||||
}
|
||||
/**
|
||||
* Creates an example graph illustrating two paths from a start node to an end node with different characteristics:
|
||||
* one path with few nodes and mostly low-weight edges, and another path with more nodes and higher-weight edges.
|
||||
* The algorithms will alternate exploration between these paths.
|
||||
*
|
||||
* @return Directed graph instance for example 3.
|
||||
*/
|
||||
public DirectedGraph<VertexMarking, EdgeMarking> example3() {
|
||||
|
||||
public DirectedGraph<VertexMarking, EdgeMarking> example2() {
|
||||
DirectedGraph<VertexMarking, EdgeMarking> example2 = new DirectedGraph<>();
|
||||
|
||||
|
||||
/**
|
||||
* Beispiel 2 zeigt zwei Wege von einem Startknoten zu einem Zielknoten mit unterschiedlichen Eigenschaften:
|
||||
* Ein Weg (oben) hat wenige Knoten mit Kanten geringer Gewichtung, außer der letzten Kante, die hohe Gewichtung hat.
|
||||
* Der andere Weg (unten) hat mehr Knoten mit höherer Gewichtung der Kanten. Der Algorithmus sollte zuerst den oberen
|
||||
* Weg erkunden, bis er die hohe Gewichtung der letzten Kante des unteren Wegs berücksichtigt.
|
||||
/*
|
||||
* Beispiel 3 zeigt zwei Wege von einem Startknoten zu einem Zielknoten mit unterschiedlichen Eigenschaften:
|
||||
* Ein Weg (oben) hat wenige Knoten mit Kanten geringer Gewichtung, außer der vorletzten Kante, die hohe Gewichtung hat.
|
||||
* Der andere Weg (unten) hat mehr Knoten mit höherer Gewichtung der Kanten. Die Algorithmen wechseln also mit dem Erkunden
|
||||
* zwischen den beiden Pfaden.
|
||||
*
|
||||
* Startknoten: A
|
||||
* Endknoten: E
|
||||
*/
|
||||
|
||||
DirectedGraph<VertexMarking, EdgeMarking> example3 = new DirectedGraph<>();
|
||||
|
||||
MarkedVertex A = new MarkedVertex<>(100, 100, "Start", null, null);
|
||||
MarkedVertex B = new MarkedVertex<>(250, 50, "B", null, null);
|
||||
MarkedVertex C = new MarkedVertex<>(400, 100, "C", null, null);
|
||||
@ -85,40 +147,44 @@ public class ExampleGraphs {
|
||||
MarkedVertex F = new MarkedVertex<>(250, 200, "F", null, null);
|
||||
MarkedVertex G = new MarkedVertex<>(550, 200, "G", null, null);
|
||||
|
||||
example2.addVertex(A);
|
||||
example2.addVertex(B);
|
||||
example2.addVertex(C);
|
||||
example2.addVertex(D);
|
||||
example2.addVertex(E);
|
||||
example2.addVertex(F);
|
||||
example2.addVertex(G);
|
||||
example3.addVertex(A);
|
||||
example3.addVertex(B);
|
||||
example3.addVertex(C);
|
||||
example3.addVertex(D);
|
||||
example3.addVertex(E);
|
||||
example3.addVertex(F);
|
||||
example3.addVertex(G);
|
||||
|
||||
example2.addEdge(new MarkedEdge<>("AB", A, B, new EdgeWeightMarking(1)));
|
||||
example2.addEdge(new MarkedEdge<>("BC", B, C, new EdgeWeightMarking(1)));
|
||||
example2.addEdge(new MarkedEdge<>("CD", C, D, new EdgeWeightMarking(10)));
|
||||
example2.addEdge(new MarkedEdge<>("DE", D, E, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("AB", A, B, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("BC", B, C, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("CD", C, D, new EdgeWeightMarking(10)));
|
||||
example3.addEdge(new MarkedEdge<>("DE", D, E, new EdgeWeightMarking(1)));
|
||||
|
||||
example2.addEdge(new MarkedEdge<>("AF", A, F, new EdgeWeightMarking(5)));
|
||||
example2.addEdge(new MarkedEdge<>("FG", F, G, new EdgeWeightMarking(5)));
|
||||
example2.addEdge(new MarkedEdge<>("GE", G, E, new EdgeWeightMarking(5)));
|
||||
example3.addEdge(new MarkedEdge<>("AF", A, F, new EdgeWeightMarking(5)));
|
||||
example3.addEdge(new MarkedEdge<>("FG", F, G, new EdgeWeightMarking(5)));
|
||||
example3.addEdge(new MarkedEdge<>("GE", G, E, new EdgeWeightMarking(5)));
|
||||
|
||||
return example2;
|
||||
return example3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an example labyrinth graph with four horizontal paths, each consisting of four nodes.
|
||||
* Each path leads to a respective endpoint, demonstrating how algorithms may explore potentially incorrect paths
|
||||
* before finding the correct one, and showing the efficiency of A* in finding the correct path quickly.
|
||||
*
|
||||
* @return Directed graph instance for example 4.
|
||||
*/
|
||||
public DirectedGraph<VertexMarking, EdgeMarking> example4() {
|
||||
|
||||
|
||||
public DirectedGraph<VertexMarking, EdgeMarking> example3() {
|
||||
|
||||
/**
|
||||
* Beispiel 3 zeigt ein Labyrinth mit vier horizontalen Wegen, die jeweils aus vier Knoten bestehen.
|
||||
* Jeder Weg führt zum Endpunkt E1, E2, E3 bzw. E4. Ziel ist es zu zeigen, dass die Algorithmen auch
|
||||
* potenziell falsche Wege erkunden können, bevor sie den richtigen Endpunkt erreichen.
|
||||
/*
|
||||
* Beispiel 4 zeigt ein Labyrinth mit vier horizontalen Wegen, die jeweils aus vier Knoten bestehen.
|
||||
* Jeder Weg führt zum Endpunkt E1, E2, E3 bzw. Ende. Ziel ist es zu zeigen, dass die Algorithmen auch
|
||||
* potenziell falsche Wege erkunden können, bevor sie den Endknoten erreichen. Zudem wird gezeigt,
|
||||
* wie A* schnell den richtigen Weg findet, während Djkstra alle Wege durchsucht.
|
||||
*
|
||||
* Startknoten: A
|
||||
* Endknoten: E2
|
||||
*/
|
||||
|
||||
DirectedGraph<VertexMarking, EdgeMarking> example3 = new DirectedGraph<>();
|
||||
DirectedGraph<VertexMarking, EdgeMarking> example4 = new DirectedGraph<>();
|
||||
|
||||
// Startpunkt A in der Mitte der Y-Koordinate
|
||||
MarkedVertex A = new MarkedVertex<>(100, 250, "Start", null, null);
|
||||
@ -147,103 +213,59 @@ public class ExampleGraphs {
|
||||
MarkedVertex D4 = new MarkedVertex<>(400, 400, "D4", null, null);
|
||||
MarkedVertex E4 = new MarkedVertex<>(500, 400, "Ende", null, null); // Endpunkt des vierten Weges
|
||||
|
||||
example3.addVertex(A);
|
||||
example3.addVertex(B1);
|
||||
example3.addVertex(C1);
|
||||
example3.addVertex(D1);
|
||||
example3.addVertex(B2);
|
||||
example3.addVertex(C2);
|
||||
example3.addVertex(D2);
|
||||
example3.addVertex(B3);
|
||||
example3.addVertex(C3);
|
||||
example3.addVertex(D3);
|
||||
example3.addVertex(B4);
|
||||
example3.addVertex(C4);
|
||||
example3.addVertex(D4);
|
||||
example3.addVertex(E1);
|
||||
example3.addVertex(E2);
|
||||
example3.addVertex(E3);
|
||||
example3.addVertex(E4);
|
||||
|
||||
example3.addEdge(new MarkedEdge<>("AB1", A, B1, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("AB2", A, B2, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("AB3", A, B3, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("AB4", A, B4, new EdgeWeightMarking(1)));
|
||||
|
||||
example3.addEdge(new MarkedEdge<>("B1C1", B1, C1, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("B2C2", B2, C2, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("B3C3", B3, C3, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("B4C4", B4, C4, new EdgeWeightMarking(1)));
|
||||
|
||||
example3.addEdge(new MarkedEdge<>("C1D1", C1, D1, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("C2D2", C2, D2, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("C3D3", C3, D3, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("C4D4", C4, D4, new EdgeWeightMarking(1)));
|
||||
|
||||
example3.addEdge(new MarkedEdge<>("D1E1", D1, E1, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("D2E2", D2, E2, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("D3E3", D3, E3, new EdgeWeightMarking(1)));
|
||||
example3.addEdge(new MarkedEdge<>("D4E4", D4, E4, new EdgeWeightMarking(1)));
|
||||
|
||||
return example3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public DirectedGraph<VertexMarking, EdgeMarking> example4() {
|
||||
|
||||
/**
|
||||
* Erstellt einen Beispielgraphen (Beispiel 4), der sich ideal für die Demonstration der Funktionsweise
|
||||
* des Dijkstra- und A*-Algorithmus eignet. Der Graph enthält eine Vielzahl von Knoten, die durch
|
||||
* gewichtete Kanten verbunden sind. Dies ermöglicht es, den kürzesten Weg von einem Startknoten zu einem
|
||||
* Zielknoten effizient zu berechnen und die Unterschiede zwischen den beiden Algorithmen in der
|
||||
* Pfadfindung zu veranschaulichen.
|
||||
*
|
||||
* Startknoten: A
|
||||
* Zielknoten: H
|
||||
*
|
||||
*/
|
||||
|
||||
DirectedGraph<VertexMarking, EdgeMarking> example4 = new DirectedGraph<>();
|
||||
|
||||
// Erstellung der Knoten mit Koordinaten
|
||||
MarkedVertex<VertexMarking> A = new MarkedVertex<>(50, 250, "Start", null, null);
|
||||
MarkedVertex<VertexMarking> B = new MarkedVertex<>(150, 150, "B", null, null);
|
||||
MarkedVertex<VertexMarking> C = new MarkedVertex<>(150, 350, "C", null, null);
|
||||
MarkedVertex<VertexMarking> D = new MarkedVertex<>(250, 100, "D", null, null);
|
||||
MarkedVertex<VertexMarking> E = new MarkedVertex<>(250, 250, "E", null, null);
|
||||
MarkedVertex<VertexMarking> F = new MarkedVertex<>(350, 200, "F", null, null);
|
||||
MarkedVertex<VertexMarking> G = new MarkedVertex<>(450, 300, "G", null, null);
|
||||
MarkedVertex<VertexMarking> H = new MarkedVertex<>(450, 100, "Ende", null, null);
|
||||
|
||||
|
||||
// Hinzufügen der Knoten zum Graphen
|
||||
example4.addVertex(A);
|
||||
example4.addVertex(B);
|
||||
example4.addVertex(C);
|
||||
example4.addVertex(D);
|
||||
example4.addVertex(E);
|
||||
example4.addVertex(F);
|
||||
example4.addVertex(G);
|
||||
example4.addVertex(H);
|
||||
example4.addVertex(B1);
|
||||
example4.addVertex(C1);
|
||||
example4.addVertex(D1);
|
||||
example4.addVertex(B2);
|
||||
example4.addVertex(C2);
|
||||
example4.addVertex(D2);
|
||||
example4.addVertex(B3);
|
||||
example4.addVertex(C3);
|
||||
example4.addVertex(D3);
|
||||
example4.addVertex(B4);
|
||||
example4.addVertex(C4);
|
||||
example4.addVertex(D4);
|
||||
example4.addVertex(E1);
|
||||
example4.addVertex(E2);
|
||||
example4.addVertex(E3);
|
||||
example4.addVertex(E4);
|
||||
|
||||
// Erstellung der Kanten mit Gewichtungen
|
||||
example4.addEdge(new MarkedEdge<>("AB", A, B, new EdgeWeightMarking(4)));
|
||||
example4.addEdge(new MarkedEdge<>("AC", A, C, new EdgeWeightMarking(2)));
|
||||
example4.addEdge(new MarkedEdge<>("BC", B, C, new EdgeWeightMarking(5)));
|
||||
example4.addEdge(new MarkedEdge<>("BD", B, D, new EdgeWeightMarking(10)));
|
||||
example4.addEdge(new MarkedEdge<>("CD", C, D, new EdgeWeightMarking(3)));
|
||||
example4.addEdge(new MarkedEdge<>("CE", C, E, new EdgeWeightMarking(7)));
|
||||
example4.addEdge(new MarkedEdge<>("DE", D, E, new EdgeWeightMarking(2)));
|
||||
example4.addEdge(new MarkedEdge<>("DF", D, F, new EdgeWeightMarking(2)));
|
||||
example4.addEdge(new MarkedEdge<>("EF", E, F, new EdgeWeightMarking(5)));
|
||||
example4.addEdge(new MarkedEdge<>("EG", E, G, new EdgeWeightMarking(10)));
|
||||
example4.addEdge(new MarkedEdge<>("FG", F, G, new EdgeWeightMarking(3)));
|
||||
example4.addEdge(new MarkedEdge<>("FH", F, H, new EdgeWeightMarking(6)));
|
||||
example4.addEdge(new MarkedEdge<>("GH", G, H, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("AB1", A, B1, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("AB2", A, B2, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("AB3", A, B3, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("AB4", A, B4, new EdgeWeightMarking(1)));
|
||||
|
||||
example4.addEdge(new MarkedEdge<>("B1C1", B1, C1, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("B2C2", B2, C2, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("B3C3", B3, C3, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("B4C4", B4, C4, new EdgeWeightMarking(1)));
|
||||
|
||||
example4.addEdge(new MarkedEdge<>("C1D1", C1, D1, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("C2D2", C2, D2, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("C3D3", C3, D3, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("C4D4", C4, D4, new EdgeWeightMarking(1)));
|
||||
|
||||
example4.addEdge(new MarkedEdge<>("D1E1", D1, E1, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("D2E2", D2, E2, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("D3E3", D3, E3, new EdgeWeightMarking(1)));
|
||||
example4.addEdge(new MarkedEdge<>("D4E4", D4, E4, new EdgeWeightMarking(1)));
|
||||
|
||||
return example4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to add a bidirectional edge between two vertices in a graph.
|
||||
*
|
||||
* @param graph The graph instance where the edge should be added.
|
||||
* @param from The starting vertex of the edge.
|
||||
* @param to The ending vertex of the edge.
|
||||
* @param weight The weight marking of the edge.
|
||||
*/
|
||||
private void addBidirectionalEdge(DirectedGraph<VertexMarking, EdgeMarking> graph, MarkedVertex<VertexMarking> from, MarkedVertex<VertexMarking> to, EdgeWeightMarking weight) {
|
||||
MarkedEdge<EdgeMarking> forwardEdge = new MarkedEdge<>("edge" + from.getName() + "_" + to.getName(), from, to, weight);
|
||||
MarkedEdge<EdgeMarking> backwardEdge = new MarkedEdge<>("edge" + to.getName() + "_" + from.getName(), to, from, weight);
|
||||
graph.addEdge(forwardEdge);
|
||||
graph.addEdge(backwardEdge);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -412,6 +412,6 @@ public abstract class Graph<T extends VertexMarking, U extends EdgeMarking> {
|
||||
* @param n2 Destination vertex.
|
||||
* @return Length of the shortest path between the vertices.
|
||||
*/
|
||||
public abstract int getShortestPathAStar(MarkedVertex<T> n1, MarkedVertex<T> n2);
|
||||
public abstract double getShortestPathAStar(MarkedVertex<T> n1, MarkedVertex<T> n2);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ class WrapperElement<T extends VertexMarking> {
|
||||
// ATTRIBUTE
|
||||
|
||||
private MarkedVertex<T> element;
|
||||
private int priority;
|
||||
private double priority;
|
||||
|
||||
|
||||
// KONSTRUKTOR
|
||||
@ -69,7 +69,7 @@ class WrapperElement<T extends VertexMarking> {
|
||||
* @param element The marked vertex to wrap.
|
||||
* @param priority The priority associated with the element.
|
||||
*/
|
||||
public WrapperElement(MarkedVertex<T> element, int priority) {
|
||||
public WrapperElement(MarkedVertex<T> element, double priority) {
|
||||
this.element = element;
|
||||
this.priority = priority;
|
||||
}
|
||||
@ -92,7 +92,7 @@ class WrapperElement<T extends VertexMarking> {
|
||||
*
|
||||
* @return The priority.
|
||||
*/
|
||||
public int getPriority() {
|
||||
public double getPriority() {
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
@ -130,6 +130,6 @@ class WrapperComparator<T extends VertexMarking> implements Comparator<WrapperEl
|
||||
* priority is less than, equal to, or greater than the second element's priority.
|
||||
*/
|
||||
public int compare(WrapperElement<T> element1, WrapperElement<T> element2) {
|
||||
return Integer.compare(element1.getPriority(), element2.getPriority());
|
||||
return Double.compare(element1.getPriority(), element2.getPriority());
|
||||
}
|
||||
}
|
||||
|
@ -253,17 +253,18 @@ public class UndirectedGraph<T extends VertexMarking, U extends EdgeMarking> ext
|
||||
// Den nächsten Knoten, der am wenigsten kostet, besuchen
|
||||
WrapperElement<T> nextVertex = queue.poll();
|
||||
|
||||
// Knoten als besucht makieren
|
||||
visited.put(nextVertex.getElement(), true);
|
||||
|
||||
|
||||
// Logging
|
||||
textDescription = "Visit " + nextVertex.getElement().getName();
|
||||
System.out.println(textDescription);
|
||||
if (nextVertex.getElement().getScreenVertex().getColor() != Color.RED) {
|
||||
nextVertex.getElement().getScreenVertex().setColor(Color.BLUE);
|
||||
// Falls Knoten schon besucht
|
||||
if(!visited.get(nextVertex.getElement())){
|
||||
// Knoten als besucht makieren
|
||||
visited.put(nextVertex.getElement(), true);
|
||||
textDescription = "Visit " + nextVertex.getElement().getName();
|
||||
// Logging
|
||||
System.out.println(textDescription);
|
||||
if (nextVertex.getElement().getScreenVertex().getColor() != Color.RED) {
|
||||
nextVertex.getElement().getScreenVertex().setColor(Color.BLUE);
|
||||
}
|
||||
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
||||
}
|
||||
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
||||
|
||||
|
||||
// Wenn Weg gefunden, brich ab
|
||||
@ -349,7 +350,7 @@ public class UndirectedGraph<T extends VertexMarking, U extends EdgeMarking> ext
|
||||
* @param n2 The ending vertex of the shortest path.
|
||||
* @return The length of the shortest path between n1 and n2.
|
||||
*/
|
||||
public int getShortestPathAStar(MarkedVertex<T> n1, MarkedVertex<T> n2) {
|
||||
public double getShortestPathAStar(MarkedVertex<T> n1, MarkedVertex<T> n2) {
|
||||
|
||||
// Erstellt Hashmap um Distanz von Startnoten zu jedem Knoten auf dem Graph zu tracken
|
||||
// Erstellt Hashmap um zu tracken welche Knoten schon besucht wurden
|
||||
@ -357,11 +358,11 @@ public class UndirectedGraph<T extends VertexMarking, U extends EdgeMarking> ext
|
||||
// Initialisierung aller Distanzen auf UNENDLICH (= -1)
|
||||
// Initialisierung, dass kein Knoten besucht wurde
|
||||
// Initialisierung aller Vorgänger auf null
|
||||
HashMap<MarkedVertex<T>, Integer> distance = new HashMap<>();
|
||||
HashMap<MarkedVertex<T>, Double> distance = new HashMap<>();
|
||||
HashMap<MarkedVertex<T>, Boolean> visited = new HashMap<>();
|
||||
HashMap<MarkedVertex<T>, MarkedVertex<T>> predecessors = new HashMap<>();
|
||||
for (MarkedVertex<T> i: this.getAllVertexes()) {
|
||||
distance.put(i, -1);
|
||||
distance.put(i, -1.0);
|
||||
visited.put(i, false);
|
||||
predecessors.put(i, null);
|
||||
}
|
||||
@ -371,15 +372,15 @@ public class UndirectedGraph<T extends VertexMarking, U extends EdgeMarking> ext
|
||||
|
||||
// Distanz zu Startknoten auf 0
|
||||
// Weg zu Startknoten in die Schlange aufnehmen
|
||||
distance.put(n1, 0);
|
||||
distance.put(n1, 0.0);
|
||||
queue.add(new WrapperElement<>(n1, 0));
|
||||
|
||||
// Variable, die Distanz zwischen aktuellem Knoten und Nachfolger speichert
|
||||
int dist = 0;
|
||||
double dist = 0;
|
||||
// Variable, die Distanz zwischen dem potenziell nächsten Knoten und dem Zielknoten speichert
|
||||
int airDist = 0;
|
||||
double airDist = 0;
|
||||
// Variable, die Distanz zwischen dem aktuellen Knoten bis zum Endknoten speichert
|
||||
int distToFinish = 0;
|
||||
double distToFinish = 0;
|
||||
// Zähler für LogList
|
||||
int step = 0;
|
||||
// String für den Description Inhalt
|
||||
@ -396,18 +397,18 @@ public class UndirectedGraph<T extends VertexMarking, U extends EdgeMarking> ext
|
||||
// Den nächsten Knoten, der am wenigsten kostet, besuchen
|
||||
WrapperElement<T> nextVertex = queue.poll();
|
||||
|
||||
// Knoten als besucht makieren
|
||||
visited.put(nextVertex.getElement(), true);
|
||||
|
||||
|
||||
// Logging
|
||||
textDescription = "Visit " + nextVertex.getElement().getName();
|
||||
System.out.println(textDescription);
|
||||
if (nextVertex.getElement().getScreenVertex().getColor() != Color.RED) {
|
||||
nextVertex.getElement().getScreenVertex().setColor(Color.BLUE);
|
||||
// Falls Knoten schon besucht
|
||||
if(!visited.get(nextVertex.getElement())){
|
||||
// Knoten als besucht makieren
|
||||
visited.put(nextVertex.getElement(), true);
|
||||
textDescription = "Visit " + nextVertex.getElement().getName();
|
||||
// Logging
|
||||
System.out.println(textDescription);
|
||||
if (nextVertex.getElement().getScreenVertex().getColor() != Color.RED) {
|
||||
nextVertex.getElement().getScreenVertex().setColor(Color.BLUE);
|
||||
}
|
||||
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
||||
}
|
||||
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
||||
|
||||
|
||||
// Wenn Weg gefunden, brich ab
|
||||
if (nextVertex.getElement() == n2) {
|
||||
@ -436,8 +437,8 @@ public class UndirectedGraph<T extends VertexMarking, U extends EdgeMarking> ext
|
||||
if (j.getSource() == nextVertex.getElement() && j.getDestination() == i) {
|
||||
|
||||
//Berechnung der Heuristik über die Luftdistanz des nächsten Knoten zum Zielknoten
|
||||
airDist = (int) Math.sqrt(Math.pow((i.getCords()[0] - n2.getCords()[0]), 2)
|
||||
+ Math.pow((i.getCords()[1] - n2.getCords()[1]), 2));
|
||||
airDist = Math.sqrt(Math.pow((i.getCords()[0] - n2.getCords()[0]), 2)
|
||||
+ Math.pow((i.getCords()[1] - n2.getCords()[1]), 2)) / 100;
|
||||
|
||||
// Berechne Distanz zu nächstem Knoten
|
||||
EdgeWeightMarking marking = (EdgeWeightMarking) j.getMarking();
|
||||
@ -456,7 +457,7 @@ public class UndirectedGraph<T extends VertexMarking, U extends EdgeMarking> ext
|
||||
distance.put(i, dist);
|
||||
|
||||
// Logging
|
||||
textDescription = "Add " + i.getName() + " with " + dist + " weight to queue.";
|
||||
textDescription = "Add " + i.getName() + " with " + distToFinish + " weight to queue.";
|
||||
System.out.println(textDescription);
|
||||
if (i.getScreenVertex().getColor() != Color.RED) {
|
||||
i.getScreenVertex().setColor(Color.YELLOW);
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user