2024-06-15 14:48:28 +00:00
|
|
|
package graph;
|
|
|
|
|
2024-07-03 17:41:46 +00:00
|
|
|
import OurApplication.OurLogElement;
|
|
|
|
import logging.LogElementList;
|
2024-07-02 22:46:21 +00:00
|
|
|
import visualizationElements.Edge;
|
|
|
|
import visualizationElements.EdgeStyle;
|
|
|
|
import visualizationElements.Vertex;
|
|
|
|
|
2024-07-06 18:37:42 +00:00
|
|
|
import java.awt.Color;
|
2024-06-25 15:18:34 +00:00
|
|
|
import java.util.HashMap;
|
2024-06-15 14:48:28 +00:00
|
|
|
import java.util.Objects;
|
2024-06-25 15:18:34 +00:00
|
|
|
import java.util.PriorityQueue;
|
2024-06-15 14:48:28 +00:00
|
|
|
import java.util.Vector;
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents a directed graph with vertex and edge markings. This class extends the Graph class and
|
|
|
|
* provides additional functionality for directed graphs, including visualization and logging capabilities.
|
|
|
|
*
|
|
|
|
* @param <T> the type of vertex marking
|
|
|
|
* @param <U> the type of edge marking
|
|
|
|
*/
|
2024-06-15 19:55:30 +00:00
|
|
|
public class DirectedGraph<T extends VertexMarking, U extends EdgeMarking> extends Graph<T, U> {
|
|
|
|
|
2024-07-02 22:46:21 +00:00
|
|
|
// ATTRIBUTE
|
|
|
|
|
|
|
|
private visualizationElements.Graph screenGraph;
|
2024-07-03 17:41:46 +00:00
|
|
|
private LogElementList<OurLogElement> logList;
|
|
|
|
|
2024-07-02 22:46:21 +00:00
|
|
|
|
2024-06-15 19:55:30 +00:00
|
|
|
// KONSTRUKTOREN
|
2024-06-15 14:48:28 +00:00
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Constructs an empty directed graph.
|
|
|
|
*/
|
2024-06-15 14:48:28 +00:00
|
|
|
public DirectedGraph() {
|
|
|
|
super();
|
2024-07-02 22:46:21 +00:00
|
|
|
this.screenGraph = new visualizationElements.Graph(new Vector<Vertex>(), new Vector<Edge>(), true, EdgeStyle.Direct);
|
2024-07-03 17:41:46 +00:00
|
|
|
this.logList = new LogElementList<OurLogElement>();
|
2024-06-26 00:20:36 +00:00
|
|
|
}
|
2024-06-15 14:48:28 +00:00
|
|
|
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Constructs a directed graph from a string representation.
|
|
|
|
*
|
|
|
|
* @param s the string representation of the graph
|
|
|
|
*/
|
2024-06-15 14:48:28 +00:00
|
|
|
public DirectedGraph(String s) {
|
|
|
|
super(s);
|
2024-07-02 22:46:21 +00:00
|
|
|
this.screenGraph = new visualizationElements.Graph(new Vector<Vertex>(), new Vector<Edge>(), true, EdgeStyle.Direct);
|
2024-07-03 17:41:46 +00:00
|
|
|
this.logList = new LogElementList<OurLogElement>();
|
2024-07-02 22:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GET-ER
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Returns the screen graph associated with this directed graph.
|
|
|
|
*
|
|
|
|
* @return the screen graph
|
|
|
|
*/
|
2024-07-02 22:46:21 +00:00
|
|
|
public visualizationElements.Graph getScreenGraph() {
|
|
|
|
return this.screenGraph;
|
|
|
|
}
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a copy of the screen graph associated with this directed graph.
|
|
|
|
*
|
|
|
|
* @return a copy of the screen graph
|
|
|
|
*/
|
2024-07-04 19:18:57 +00:00
|
|
|
public visualizationElements.Graph getScreenGraphCopy() {
|
|
|
|
visualizationElements.Graph graphCopy = new visualizationElements.Graph(new Vector<Vertex>(), new Vector<Edge>(), true, EdgeStyle.Direct);
|
|
|
|
Vector<visualizationElements.Vertex> copiedVertexes = new Vector<>();
|
|
|
|
Vector<visualizationElements.Edge> copiedEdges = new Vector<>();
|
|
|
|
for (visualizationElements.Vertex vertexCopy : this.screenGraph.getVertexes()) {
|
|
|
|
visualizationElements.Vertex newCopiedVertex = new visualizationElements.Vertex(vertexCopy.getXpos(), vertexCopy.getYpos(), vertexCopy.getMarking(), vertexCopy.getColor());
|
|
|
|
copiedVertexes.add(newCopiedVertex);
|
|
|
|
graphCopy.setVertexes(copiedVertexes);
|
|
|
|
}
|
|
|
|
for (visualizationElements.Edge edgeCopy : this.screenGraph.getEdges()) {
|
|
|
|
visualizationElements.Edge newCopiedEdge = new visualizationElements.Edge(edgeCopy.getSource(), edgeCopy.getDestination(), edgeCopy.getMarking(), edgeCopy.getColor());
|
|
|
|
copiedEdges.add(newCopiedEdge);
|
|
|
|
graphCopy.setEdges(copiedEdges);
|
|
|
|
}
|
|
|
|
return graphCopy;
|
|
|
|
}
|
|
|
|
|
2024-07-02 22:46:21 +00:00
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Returns the log list associated with this directed graph.
|
|
|
|
*
|
|
|
|
* @return the log list
|
|
|
|
*/
|
2024-07-03 17:41:46 +00:00
|
|
|
public LogElementList<OurLogElement> getLogList() {
|
|
|
|
return this.logList;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-02 22:46:21 +00:00
|
|
|
// HINZUFÜGEN
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Adds an edge to the graph.
|
|
|
|
*
|
|
|
|
* @param e the edge to be added
|
|
|
|
*/
|
2024-07-02 22:46:21 +00:00
|
|
|
public void addEdge(MarkedEdge<U> e) {
|
|
|
|
super.addEdge(e);
|
|
|
|
this.screenGraph.getEdges().add(e.getScreenEdge());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Adds a vertex to the graph.
|
|
|
|
*
|
|
|
|
* @param n the vertex to be added
|
|
|
|
*/
|
2024-07-02 22:46:21 +00:00
|
|
|
public void addVertex(MarkedVertex<T> n) {
|
|
|
|
super.addVertex(n);
|
|
|
|
this.screenGraph.getVertexes().add(n.getScreenVertex());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// LÖSCHEN
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Removes an edge from the graph.
|
|
|
|
*
|
|
|
|
* @param e the edge to be removed
|
|
|
|
*/
|
2024-07-02 22:46:21 +00:00
|
|
|
public void removeEdge(MarkedEdge<U> e) {
|
|
|
|
super.removeEdge(e);
|
|
|
|
this.screenGraph.getEdges().remove(e.getScreenEdge());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Removes a vertex from the graph.
|
|
|
|
*
|
|
|
|
* @param n the vertex to be removed
|
|
|
|
*/
|
2024-07-02 22:46:21 +00:00
|
|
|
public void removeVertex(MarkedVertex<T> n) {
|
|
|
|
super.removeVertex(n);
|
|
|
|
this.screenGraph.getVertexes().remove(n.getScreenVertex());
|
2024-06-15 14:48:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-06-15 19:55:30 +00:00
|
|
|
// KNOTEN EIGENSCHAFTEN
|
2024-06-15 14:48:28 +00:00
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Checks if two vertices are strongly adjacent (i.e., there is a bidirectional edge between them).
|
|
|
|
*
|
|
|
|
* @param n1 the first vertex
|
|
|
|
* @param n2 the second vertex
|
|
|
|
* @return true if the vertices are strongly adjacent, false otherwise
|
|
|
|
*/
|
2024-06-15 14:48:28 +00:00
|
|
|
public boolean areStrongAdjacent(MarkedVertex<T> n1, MarkedVertex<T> n2) {
|
|
|
|
boolean n1ton2 = false;
|
|
|
|
boolean n2ton1 = false;
|
2024-06-25 15:18:34 +00:00
|
|
|
for (MarkedEdge<U> i: this.getAllEdges()) {
|
2024-06-15 14:48:28 +00:00
|
|
|
if (i.getSource() == n1 && i.getDestination() == n2) {
|
|
|
|
n1ton2 = true;
|
|
|
|
} else if (i.getSource() == n2 && i.getDestination() == n1) {
|
|
|
|
n2ton1 = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (n1ton2 && n2ton1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Checks if two vertices are strongly adjacent (i.e., there is a bidirectional edge between them) by their names.
|
|
|
|
*
|
|
|
|
* @param s1 the name of the first vertex
|
|
|
|
* @param s2 the name of the second vertex
|
|
|
|
* @return true if the vertices are strongly adjacent, false otherwise
|
|
|
|
* @throws NameDoesNotExistException if one of the vertices does not exist
|
|
|
|
*/
|
2024-06-15 14:48:28 +00:00
|
|
|
public boolean areStrongAdjacent(String s1, String s2) throws NameDoesNotExistException {
|
|
|
|
MarkedVertex<T> n1 = null;
|
|
|
|
MarkedVertex<T> n2 = null;
|
|
|
|
for (MarkedVertex<T> i: this.getAllVertexes()) {
|
|
|
|
if (Objects.equals(i.getName(), s1)) {
|
|
|
|
n1 = i;
|
|
|
|
} else if (Objects.equals(i.getName(), s2)) {
|
|
|
|
n2 = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (n1 == null || n2 == null) {
|
|
|
|
throw new NameDoesNotExistException("One of the Vertexes might not exist");
|
|
|
|
} else {
|
|
|
|
return areStrongAdjacent(n1, n2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Returns the in-degree of a vertex (i.e., the number of edges directed towards the vertex).
|
|
|
|
*
|
|
|
|
* @param n the vertex
|
|
|
|
* @return the in-degree of the vertex
|
|
|
|
*/
|
2024-06-15 14:48:28 +00:00
|
|
|
public int inDegree(MarkedVertex<T> n) {
|
|
|
|
int degree = 0;
|
2024-06-25 15:18:34 +00:00
|
|
|
for (MarkedEdge<U> i: this.getAllEdges()) {
|
2024-06-15 14:48:28 +00:00
|
|
|
if (i.getDestination() == n) {
|
|
|
|
degree += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return degree;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Returns the in-degree of a vertex by its name.
|
|
|
|
*
|
|
|
|
* @param s the name of the vertex
|
|
|
|
* @return the in-degree of the vertex
|
|
|
|
* @throws NameDoesNotExistException if the vertex does not exist
|
|
|
|
*/
|
2024-06-15 14:48:28 +00:00
|
|
|
public int inDegree(String s) throws NameDoesNotExistException{
|
|
|
|
for (MarkedVertex<T> i: this.getAllVertexes()) {
|
|
|
|
if (Objects.equals(i.getName(), s)) {
|
|
|
|
return inDegree(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new NameDoesNotExistException("One of the Vertexes might not exist");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Returns the out-degree of a vertex (i.e., the number of edges directed away from the vertex).
|
|
|
|
*
|
|
|
|
* @param n the vertex
|
|
|
|
* @return the out-degree of the vertex
|
|
|
|
*/
|
2024-06-15 14:48:28 +00:00
|
|
|
public int outDegree(MarkedVertex<T> n) {
|
|
|
|
int degree = 0;
|
2024-06-25 15:18:34 +00:00
|
|
|
for (MarkedEdge<U> i: this.getAllEdges()) {
|
2024-06-15 14:48:28 +00:00
|
|
|
if (i.getSource() == n) {
|
|
|
|
degree += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return degree;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Returns the out-degree of a vertex by its name.
|
|
|
|
*
|
|
|
|
* @param s the name of the vertex
|
|
|
|
* @return the out-degree of the vertex
|
|
|
|
* @throws NameDoesNotExistException if the vertex does not exist
|
|
|
|
*/
|
2024-06-15 14:48:28 +00:00
|
|
|
public int outDegree(String s) throws NameDoesNotExistException{
|
|
|
|
for (MarkedVertex<T> i: this.getAllVertexes()) {
|
|
|
|
if (Objects.equals(i.getName(), s)) {
|
|
|
|
return outDegree(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new NameDoesNotExistException("One of the Vertexes might not exist");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Returns a vector of predecessor vertices (i.e., vertices with edges directed towards the specified vertex).
|
|
|
|
*
|
|
|
|
* @param n the vertex
|
|
|
|
* @return a vector of predecessor vertices
|
|
|
|
*/
|
2024-06-15 14:48:28 +00:00
|
|
|
public Vector<MarkedVertex<T>> getPredecessors(MarkedVertex<T> n) {
|
2024-06-15 19:55:30 +00:00
|
|
|
Vector<MarkedVertex<T>> predecessors = new Vector<>();
|
2024-06-25 15:18:34 +00:00
|
|
|
for (MarkedEdge<U> i: this.getAllEdges()) {
|
2024-06-15 19:55:30 +00:00
|
|
|
if (i.getDestination() == n) {
|
2024-06-25 15:18:34 +00:00
|
|
|
predecessors.add((MarkedVertex<T>) i.getSource());
|
2024-06-15 19:55:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return predecessors;
|
2024-06-15 14:48:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Returns a vector of successor vertices (i.e., vertices with edges directed away from the specified vertex).
|
|
|
|
*
|
|
|
|
* @param n the vertex
|
|
|
|
* @return a vector of successor vertices
|
|
|
|
*/
|
2024-06-15 14:48:28 +00:00
|
|
|
public Vector<MarkedVertex<T>> getSuccessors(MarkedVertex<T> n) {
|
2024-06-15 19:55:30 +00:00
|
|
|
Vector<MarkedVertex<T>> successors = new Vector<>();
|
2024-06-25 15:18:34 +00:00
|
|
|
for (MarkedEdge<U> i: this.getAllEdges()) {
|
2024-06-15 19:55:30 +00:00
|
|
|
if (i.getSource() == n) {
|
2024-06-25 15:18:34 +00:00
|
|
|
successors.add((MarkedVertex<T>) i.getDestination());
|
2024-06-15 19:55:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return successors;
|
2024-06-15 14:48:28 +00:00
|
|
|
}
|
|
|
|
|
2024-06-25 15:18:34 +00:00
|
|
|
|
|
|
|
// AUFGABE 2
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Finds the shortest path between two vertices using Dijkstra's algorithm.
|
|
|
|
*
|
|
|
|
* @param n1 the starting vertex
|
|
|
|
* @param n2 the ending vertex
|
|
|
|
* @return the shortest distance from n1 to n2, or -1 if no path is found
|
|
|
|
*/
|
2024-06-25 15:18:34 +00:00
|
|
|
public int getShortestPathDijkstra(MarkedVertex<T> n1, MarkedVertex<T> n2) {
|
2024-06-26 00:20:36 +00:00
|
|
|
|
2024-06-25 15:18:34 +00:00
|
|
|
// Erstellt Hashmap um Distanz von Startnoten zu jedem Knoten auf dem Graph zu tracken
|
|
|
|
// Erstellt Hashmap um zu tracken welche Knoten schon besucht wurden
|
2024-07-07 18:34:38 +00:00
|
|
|
// Erstelle Hashmap um Vorgängerknoten zu tracken
|
2024-06-25 15:18:34 +00:00
|
|
|
// Initialisierung aller Distanzen auf UNENDLICH (= -1)
|
|
|
|
// Initialisierung, dass kein Knoten besucht wurde
|
2024-07-07 18:34:38 +00:00
|
|
|
// Initialisierung aller Vorgänger auf null
|
2024-06-25 15:18:34 +00:00
|
|
|
HashMap<MarkedVertex<T>, Integer> distance = new HashMap<>();
|
|
|
|
HashMap<MarkedVertex<T>, Boolean> visited = new HashMap<>();
|
2024-07-07 18:34:38 +00:00
|
|
|
HashMap<MarkedVertex<T>, MarkedVertex<T>> predecessors = new HashMap<>();
|
2024-06-25 15:18:34 +00:00
|
|
|
for (MarkedVertex<T> i: this.getAllVertexes()) {
|
|
|
|
distance.put(i, -1);
|
|
|
|
visited.put(i, false);
|
2024-07-07 18:34:38 +00:00
|
|
|
predecessors.put(i, null);
|
2024-06-25 15:18:34 +00:00
|
|
|
}
|
2024-06-26 00:20:36 +00:00
|
|
|
|
2024-06-25 15:18:34 +00:00
|
|
|
// Erstelle Schlange wo die nächsten Verbindungen drin sind
|
|
|
|
PriorityQueue<WrapperElement<T>> queue = new PriorityQueue<>(new WrapperComparator<T>());
|
|
|
|
|
|
|
|
// Distanz zu Startknoten auf 0
|
|
|
|
// Weg zu Startknoten in die Schlange aufnehmen
|
|
|
|
distance.put(n1, 0);
|
|
|
|
queue.add(new WrapperElement<>(n1, 0));
|
|
|
|
|
2024-06-26 00:20:36 +00:00
|
|
|
// Variable, die Distanz zwischen aktuellem Knoten und Nachfolger speichert
|
|
|
|
int dist = 0;
|
2024-07-03 17:41:46 +00:00
|
|
|
// Zähler für LogList
|
|
|
|
int step = 0;
|
2024-07-07 12:02:19 +00:00
|
|
|
// String für den Description Inhalt
|
|
|
|
String textDescription;
|
2024-06-26 00:20:36 +00:00
|
|
|
|
2024-07-05 12:00:35 +00:00
|
|
|
// Färben der Start und Ziel Knoten für Visualisierung + hinzufügen zur LogList
|
|
|
|
n1.getScreenVertex().setColor(Color.RED);
|
|
|
|
n2.getScreenVertex().setColor(Color.RED);
|
2024-07-07 12:02:19 +00:00
|
|
|
textDescription = "Startknoten: " + n1.getScreenVertex().getMarking()
|
|
|
|
+ ", Endknoten: " + n2.getScreenVertex().getMarking();
|
|
|
|
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
2024-07-05 12:00:35 +00:00
|
|
|
|
2024-07-07 18:34:38 +00:00
|
|
|
|
2024-06-25 15:18:34 +00:00
|
|
|
while (!queue.isEmpty()) {
|
|
|
|
// Den nächsten Knoten, der am wenigsten kostet, besuchen
|
|
|
|
WrapperElement<T> nextVertex = queue.poll();
|
2024-06-26 00:20:36 +00:00
|
|
|
|
2024-07-08 15:12:08 +00:00
|
|
|
// 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);
|
2024-07-08 15:35:55 +00:00
|
|
|
if (nextVertex.getElement().getScreenVertex().getColor() != Color.RED) {
|
|
|
|
nextVertex.getElement().getScreenVertex().setColor(Color.BLUE);
|
|
|
|
}
|
2024-07-08 15:12:08 +00:00
|
|
|
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
|
|
|
}
|
2024-07-02 22:46:21 +00:00
|
|
|
|
2024-07-07 18:34:38 +00:00
|
|
|
// Wenn Weg gefunden, brich ab
|
|
|
|
if (nextVertex.getElement() == n2) {
|
|
|
|
MarkedVertex<T> colorroute = n2;
|
|
|
|
while (colorroute != null) {
|
|
|
|
textDescription = colorroute.getName();
|
|
|
|
System.out.println(textDescription);
|
|
|
|
colorroute.getScreenVertex().setColor(Color.green);
|
|
|
|
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
|
|
|
|
|
|
|
colorroute = predecessors.get(colorroute);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//zurücksetzten der Färbungen
|
|
|
|
this.clearScreenGraphColor();
|
|
|
|
return distance.get(n2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-06-26 00:20:36 +00:00
|
|
|
// Gehe von diesem Knoten aus alle erreichbaren Knoten durch
|
2024-06-25 15:18:34 +00:00
|
|
|
for (MarkedVertex<T> i: this.getSuccessors(nextVertex.getElement())) {
|
2024-06-26 00:20:36 +00:00
|
|
|
|
|
|
|
// Kante finde, die den jetzigen und nächsten Knoten verbindet
|
|
|
|
for (MarkedEdge<U> j: this.getAllEdges()) {
|
|
|
|
if (j.getSource() == nextVertex.getElement() && j.getDestination() == i) {
|
|
|
|
|
|
|
|
// Berechne Distanz zu nächstem Knoten
|
2024-07-07 14:29:45 +00:00
|
|
|
EdgeWeightMarking marking = (EdgeWeightMarking) j.getMarking();
|
|
|
|
dist = distance.get(nextVertex.getElement()) + marking.getWeight();
|
2024-06-26 00:20:36 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wenn es schon einen kürzeren Weg zum Knoten gibt, überspringen
|
|
|
|
if ((distance.get(i) <= dist && distance.get(i) != -1) || visited.get(i)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-07-07 18:34:38 +00:00
|
|
|
// Vorgänger aktualisieren
|
|
|
|
predecessors.put(i, nextVertex.getElement());
|
|
|
|
|
2024-06-26 00:20:36 +00:00
|
|
|
// Aktualisiere Distanz von Start zu nächstem Knoten
|
|
|
|
distance.put(i, dist);
|
|
|
|
|
2024-07-02 22:46:21 +00:00
|
|
|
// Logging
|
2024-07-07 12:02:19 +00:00
|
|
|
textDescription = "Add " + i.getName() + " with " + dist + " weight to queue.";
|
|
|
|
System.out.println(textDescription);
|
2024-07-07 21:39:17 +00:00
|
|
|
if (i.getScreenVertex().getColor() != Color.RED) {
|
|
|
|
i.getScreenVertex().setColor(Color.YELLOW);
|
|
|
|
}
|
2024-07-07 12:02:19 +00:00
|
|
|
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
2024-07-02 22:46:21 +00:00
|
|
|
|
2024-06-26 00:20:36 +00:00
|
|
|
// Nehme nächsten Knoten in die Queue auf
|
|
|
|
queue.add(new WrapperElement<>(i, dist));
|
2024-06-25 15:18:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-05 22:51:44 +00:00
|
|
|
//zurücksetzten der Färbungen
|
|
|
|
this.clearScreenGraphColor();
|
|
|
|
|
2024-07-07 18:34:38 +00:00
|
|
|
MarkedVertex<T> colorroute = n2;
|
|
|
|
while (colorroute != null) {
|
|
|
|
textDescription = colorroute.getName();
|
|
|
|
System.out.println(textDescription);
|
|
|
|
colorroute.getScreenVertex().setColor(Color.green);
|
|
|
|
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
|
|
|
|
|
|
|
colorroute = predecessors.get(colorroute);
|
|
|
|
}
|
|
|
|
|
2024-07-03 19:49:51 +00:00
|
|
|
System.out.println("Done");
|
|
|
|
// Gibt Distanz zu gefragtem Knoten zurück
|
|
|
|
return distance.get(n2);
|
|
|
|
}
|
2024-07-05 13:12:42 +00:00
|
|
|
|
|
|
|
|
2024-07-07 22:11:04 +00:00
|
|
|
/**
|
|
|
|
* Finds the shortest path between two vertices using the A* algorithm.
|
|
|
|
*
|
|
|
|
* @param n1 the starting vertex
|
|
|
|
* @param n2 the ending vertex
|
|
|
|
* @return the shortest distance from n1 to n2, or -1 if no path is found
|
|
|
|
*/
|
2024-07-08 15:12:08 +00:00
|
|
|
public double getShortestPathAStar(MarkedVertex<T> n1, MarkedVertex<T> n2) {
|
2024-07-03 19:49:51 +00:00
|
|
|
|
|
|
|
// Erstellt Hashmap um Distanz von Startnoten zu jedem Knoten auf dem Graph zu tracken
|
|
|
|
// Erstellt Hashmap um zu tracken welche Knoten schon besucht wurden
|
2024-07-07 18:34:38 +00:00
|
|
|
// Erstelle Hashmap um Vorgängerknoten zu tracken
|
2024-07-03 19:49:51 +00:00
|
|
|
// Initialisierung aller Distanzen auf UNENDLICH (= -1)
|
|
|
|
// Initialisierung, dass kein Knoten besucht wurde
|
2024-07-07 18:34:38 +00:00
|
|
|
// Initialisierung aller Vorgänger auf null
|
2024-07-08 15:12:08 +00:00
|
|
|
HashMap<MarkedVertex<T>, Double> distance = new HashMap<>();
|
2024-07-03 19:49:51 +00:00
|
|
|
HashMap<MarkedVertex<T>, Boolean> visited = new HashMap<>();
|
2024-07-07 18:34:38 +00:00
|
|
|
HashMap<MarkedVertex<T>, MarkedVertex<T>> predecessors = new HashMap<>();
|
2024-07-03 19:49:51 +00:00
|
|
|
for (MarkedVertex<T> i: this.getAllVertexes()) {
|
2024-07-08 15:12:08 +00:00
|
|
|
distance.put(i, -1.0);
|
2024-07-03 19:49:51 +00:00
|
|
|
visited.put(i, false);
|
2024-07-07 18:34:38 +00:00
|
|
|
predecessors.put(i, null);
|
2024-07-03 19:49:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Erstelle Schlange wo die nächsten Verbindungen drin sind
|
|
|
|
PriorityQueue<WrapperElement<T>> queue = new PriorityQueue<>(new WrapperComparator<T>());
|
|
|
|
|
|
|
|
// Distanz zu Startknoten auf 0
|
|
|
|
// Weg zu Startknoten in die Schlange aufnehmen
|
2024-07-08 15:12:08 +00:00
|
|
|
distance.put(n1, 0.0);
|
2024-07-03 19:49:51 +00:00
|
|
|
queue.add(new WrapperElement<>(n1, 0));
|
|
|
|
|
|
|
|
// Variable, die Distanz zwischen aktuellem Knoten und Nachfolger speichert
|
2024-07-08 15:12:08 +00:00
|
|
|
double dist = 0;
|
2024-07-03 19:49:51 +00:00
|
|
|
// Variable, die Distanz zwischen dem potenziell nächsten Knoten und dem Zielknoten speichert
|
2024-07-08 15:12:08 +00:00
|
|
|
double airDist = 0;
|
2024-07-06 18:37:42 +00:00
|
|
|
// Variable, die Distanz zwischen dem aktuellen Knoten bis zum Endknoten speichert
|
2024-07-08 15:12:08 +00:00
|
|
|
double distToFinish = 0;
|
2024-07-03 19:49:51 +00:00
|
|
|
// Zähler für LogList
|
|
|
|
int step = 0;
|
2024-07-07 12:02:19 +00:00
|
|
|
// String für den Description Inhalt
|
|
|
|
String textDescription;
|
2024-07-03 19:49:51 +00:00
|
|
|
|
2024-07-05 12:00:35 +00:00
|
|
|
// Färben der Start und Ziel Knoten für Visualisierung + hinzufügen zur LogList
|
|
|
|
n1.getScreenVertex().setColor(Color.RED);
|
|
|
|
n2.getScreenVertex().setColor(Color.RED);
|
2024-07-07 12:02:19 +00:00
|
|
|
textDescription = "Startknoten: " + n1.getScreenVertex().getMarking()
|
|
|
|
+ ", Endknoten: " + n2.getScreenVertex().getMarking();
|
|
|
|
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
2024-07-05 12:00:35 +00:00
|
|
|
|
2024-07-03 19:49:51 +00:00
|
|
|
while (!queue.isEmpty()) {
|
|
|
|
// Den nächsten Knoten, der am wenigsten kostet, besuchen
|
|
|
|
WrapperElement<T> nextVertex = queue.poll();
|
|
|
|
|
|
|
|
|
2024-07-08 15:12:08 +00:00
|
|
|
// 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);
|
2024-07-08 15:35:55 +00:00
|
|
|
if (nextVertex.getElement().getScreenVertex().getColor() != Color.RED) {
|
|
|
|
nextVertex.getElement().getScreenVertex().setColor(Color.BLUE);
|
|
|
|
}
|
2024-07-08 15:12:08 +00:00
|
|
|
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
|
|
|
}
|
2024-07-03 19:49:51 +00:00
|
|
|
|
2024-07-07 18:34:38 +00:00
|
|
|
// Wenn Weg gefunden, brich ab
|
|
|
|
if (nextVertex.getElement() == n2) {
|
|
|
|
MarkedVertex<T> colorroute = n2;
|
|
|
|
while (colorroute != null) {
|
|
|
|
textDescription = colorroute.getName();
|
|
|
|
System.out.println(textDescription);
|
|
|
|
colorroute.getScreenVertex().setColor(Color.green);
|
|
|
|
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
|
|
|
|
|
|
|
colorroute = predecessors.get(colorroute);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//zurücksetzten der Färbungen
|
|
|
|
this.clearScreenGraphColor();
|
|
|
|
return distance.get(n2);
|
|
|
|
}
|
|
|
|
|
2024-07-03 19:49:51 +00:00
|
|
|
|
|
|
|
// Gehe von diesem Knoten aus alle erreichbaren Knoten durch
|
|
|
|
for (MarkedVertex<T> i: this.getSuccessors(nextVertex.getElement())) {
|
|
|
|
|
|
|
|
// Kante finde, die den jetzigen und nächsten Knoten verbindet
|
|
|
|
for (MarkedEdge<U> j: this.getAllEdges()) {
|
|
|
|
if (j.getSource() == nextVertex.getElement() && j.getDestination() == i) {
|
|
|
|
|
|
|
|
//Berechnung der Heuristik über die Luftdistanz des nächsten Knoten zum Zielknoten
|
2024-07-08 15:12:08 +00:00
|
|
|
airDist = Math.sqrt(Math.pow((i.getCords()[0] - n2.getCords()[0]), 2)
|
|
|
|
+ Math.pow((i.getCords()[1] - n2.getCords()[1]), 2)) / 100;
|
2024-07-03 19:49:51 +00:00
|
|
|
|
|
|
|
// Berechne Distanz zu nächstem Knoten
|
2024-07-07 14:29:45 +00:00
|
|
|
EdgeWeightMarking marking = (EdgeWeightMarking) j.getMarking();
|
|
|
|
dist = distance.get(nextVertex.getElement()) + marking.getWeight();
|
|
|
|
distToFinish = distance.get(nextVertex.getElement()) + marking.getWeight() + airDist;
|
2024-07-03 19:49:51 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wenn es schon einen kürzeren Weg zum Knoten gibt, überspringen
|
|
|
|
if ((distance.get(i) <= dist && distance.get(i) != -1) || visited.get(i)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-07-07 19:13:34 +00:00
|
|
|
// Vorgänger aktualisieren
|
|
|
|
predecessors.put(i, nextVertex.getElement());
|
|
|
|
|
2024-07-03 19:49:51 +00:00
|
|
|
// Aktualisiere Distanz von Start zu nächstem Knoten
|
|
|
|
distance.put(i, dist);
|
|
|
|
|
|
|
|
// Logging
|
2024-07-08 15:12:08 +00:00
|
|
|
textDescription = "Add " + i.getName() + " with " + distToFinish + " weight to queue.";
|
2024-07-07 12:02:19 +00:00
|
|
|
System.out.println(textDescription);
|
2024-07-07 21:39:17 +00:00
|
|
|
if (i.getScreenVertex().getColor() != Color.RED) {
|
|
|
|
i.getScreenVertex().setColor(Color.YELLOW);
|
|
|
|
}
|
2024-07-07 12:02:19 +00:00
|
|
|
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
2024-07-03 19:49:51 +00:00
|
|
|
|
|
|
|
// Nehme nächsten Knoten in die Queue auf
|
2024-07-06 18:37:42 +00:00
|
|
|
queue.add(new WrapperElement<>(i, distToFinish));
|
2024-07-03 19:49:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-05 22:51:44 +00:00
|
|
|
//zurücksetzten der Färbungen
|
|
|
|
this.clearScreenGraphColor();
|
|
|
|
|
2024-07-07 18:34:38 +00:00
|
|
|
MarkedVertex<T> colorroute = n2;
|
|
|
|
while (colorroute != null) {
|
|
|
|
textDescription = colorroute.getName();
|
|
|
|
System.out.println(textDescription);
|
|
|
|
colorroute.getScreenVertex().setColor(Color.green);
|
|
|
|
this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy()));
|
|
|
|
|
|
|
|
colorroute = predecessors.get(colorroute);
|
|
|
|
}
|
|
|
|
|
2024-07-03 17:41:46 +00:00
|
|
|
System.out.println("Done");
|
2024-06-26 00:20:36 +00:00
|
|
|
// Gibt Distanz zu gefragtem Knoten zurück
|
|
|
|
return distance.get(n2);
|
2024-06-25 15:18:34 +00:00
|
|
|
}
|
2024-07-08 19:15:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
public void createLoglistElement() {
|
|
|
|
this.logList.add(new OurLogElement(0, "", 0, this.getScreenGraphCopy()));
|
|
|
|
}
|
2024-06-15 14:48:28 +00:00
|
|
|
}
|