ProjektGraph/graph/DirectedGraph.java

375 lines
14 KiB
Java
Raw Normal View History

2024-06-15 14:48:28 +00:00
package graph;
2024-07-03 17:41:46 +00:00
import OurApplication.OurAlgorithm;
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-03 17:41:46 +00:00
import java.awt.*;
import java.io.*;
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;
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
// KONSTRUKTOREN
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
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
public visualizationElements.Graph getScreenGraph() {
return this.screenGraph;
}
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-03 17:41:46 +00:00
public LogElementList<OurLogElement> getLogList() {
return this.logList;
}
2024-07-02 22:46:21 +00:00
// HINZUFÜGEN
// Kante hinzufügen
public void addEdge(MarkedEdge<U> e) {
super.addEdge(e);
this.screenGraph.getEdges().add(e.getScreenEdge());
}
// Knoten hinzufügen
public void addVertex(MarkedVertex<T> n) {
super.addVertex(n);
this.screenGraph.getVertexes().add(n.getScreenVertex());
}
// LÖSCHEN
// Kante löschen
public void removeEdge(MarkedEdge<U> e) {
super.removeEdge(e);
this.screenGraph.getEdges().remove(e.getScreenEdge());
}
// Knoten löschen
public void removeVertex(MarkedVertex<T> n) {
super.removeVertex(n);
this.screenGraph.getVertexes().remove(n.getScreenVertex());
2024-06-15 14:48:28 +00:00
}
// KNOTEN EIGENSCHAFTEN
2024-06-15 14:48:28 +00:00
// Prüfung, ob zwei Knoten stark adjazent sind
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);
}
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);
}
}
// Prüfung des Eingangsgrades eines Knotens
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;
}
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");
}
// Prüfung des Ausgangsgrades eines Knotens
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;
}
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");
}
// Prüfung, welche Knoten Vorgänger sind
2024-06-15 14:48:28 +00:00
public Vector<MarkedVertex<T>> getPredecessors(MarkedVertex<T> n) {
Vector<MarkedVertex<T>> predecessors = new Vector<>();
2024-06-25 15:18:34 +00:00
for (MarkedEdge<U> i: this.getAllEdges()) {
if (i.getDestination() == n) {
2024-06-25 15:18:34 +00:00
predecessors.add((MarkedVertex<T>) i.getSource());
}
}
return predecessors;
2024-06-15 14:48:28 +00:00
}
// Prüfung, welche Knoten Nachfolger sind
2024-06-15 14:48:28 +00:00
public Vector<MarkedVertex<T>> getSuccessors(MarkedVertex<T> n) {
Vector<MarkedVertex<T>> successors = new Vector<>();
2024-06-25 15:18:34 +00:00
for (MarkedEdge<U> i: this.getAllEdges()) {
if (i.getSource() == n) {
2024-06-25 15:18:34 +00:00
successors.add((MarkedVertex<T>) i.getDestination());
}
}
return successors;
2024-06-15 14:48:28 +00:00
}
2024-06-25 15:18:34 +00:00
// AUFGABE 2
// Dijkstra-Algorithmus
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
// Initialisierung aller Distanzen auf UNENDLICH (= -1)
// Initialisierung, dass kein Knoten besucht wurde
HashMap<MarkedVertex<T>, Integer> distance = new HashMap<>();
HashMap<MarkedVertex<T>, Boolean> visited = new HashMap<>();
for (MarkedVertex<T> i: this.getAllVertexes()) {
distance.put(i, -1);
visited.put(i, false);
}
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-06-26 00:20:36 +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);
this.logList.add(new OurLogElement(step, "Step: " + step, 0, this.getScreenGraphCopy()));
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
// Knoten als besucht makieren
2024-06-25 15:18:34 +00:00
visited.put(nextVertex.getElement(), true);
2024-07-02 22:46:21 +00:00
// Logging
2024-06-26 00:20:36 +00:00
System.out.println("Visit " + nextVertex.getElement().getName());
nextVertex.getElement().getScreenVertex().setColor(Color.BLUE);
this.logList.add(new OurLogElement(step, "Step: " + step, 0, this.getScreenGraphCopy()));
2024-07-02 22:46:21 +00:00
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
dist = distance.get(nextVertex.getElement()) + j.getWeighting();
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;
}
// Aktualisiere Distanz von Start zu nächstem Knoten
distance.put(i, dist);
2024-07-02 22:46:21 +00:00
// Logging
2024-06-26 00:20:36 +00:00
System.out.println("Add " + i.getName() + " with " + dist + " weight to queue.");
nextVertex.getElement().getScreenVertex().setColor(Color.YELLOW);
this.logList.add(new OurLogElement(step, "Step: " + step, 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-03 19:49:51 +00:00
System.out.println("Done");
// Gibt Distanz zu gefragtem Knoten zurück
return distance.get(n2);
}
public int 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
// Initialisierung aller Distanzen auf UNENDLICH (= -1)
// Initialisierung, dass kein Knoten besucht wurde
HashMap<MarkedVertex<T>, Integer> distance = new HashMap<>();
HashMap<MarkedVertex<T>, Boolean> visited = new HashMap<>();
for (MarkedVertex<T> i: this.getAllVertexes()) {
distance.put(i, -1);
visited.put(i, false);
}
// 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));
// Variable, die Distanz zwischen aktuellem Knoten und Nachfolger speichert
int dist = 0;
// Variable, die Distanz zwischen dem potenziell nächsten Knoten und dem Zielknoten speichert
int airDist = 0;
// Zähler für LogList
int step = 0;
// Färben der Start und Ziel Knoten für Visualisierung + hinzufügen zur LogList
n1.getScreenVertex().setColor(Color.RED);
n2.getScreenVertex().setColor(Color.RED);
this.logList.add(new OurLogElement(step, "Step: " + step, 0, this.getScreenGraphCopy()));
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();
// Knoten als besucht makieren
visited.put(nextVertex.getElement(), true);
// Logging
System.out.println("Visit " + nextVertex.getElement().getName());
nextVertex.getElement().getScreenVertex().setColor(Color.BLUE);
this.logList.add(new OurLogElement(step, "Step: " + step, 0, this.getScreenGraphCopy()));
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
airDist = (int) Math.sqrt(Math.pow((i.getCords()[0] - n2.getCords()[0]), 2)
+ Math.pow((i.getCords()[1] - n2.getCords()[1]), 2));
// Berechne Distanz zu nächstem Knoten
dist = distance.get(nextVertex.getElement()) + j.getWeighting() + airDist;
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;
}
// Aktualisiere Distanz von Start zu nächstem Knoten
distance.put(i, dist);
// Logging
System.out.println("Add " + i.getName() + " with " + dist + " weight to queue.");
nextVertex.getElement().getScreenVertex().setColor(Color.YELLOW);
this.logList.add(new OurLogElement(step, "Step: " + step, 0, this.getScreenGraphCopy()));
2024-07-03 19:49:51 +00:00
// Nehme nächsten Knoten in die Queue auf
queue.add(new WrapperElement<>(i, dist));
}
}
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-06-15 14:48:28 +00:00
}