package graph; import OurApplication.OurAlgorithm; import OurApplication.OurLogElement; import logging.LogElementList; import visualizationElements.Edge; import visualizationElements.EdgeStyle; import visualizationElements.Vertex; import java.awt.*; import java.io.*; import java.util.HashMap; import java.util.Objects; import java.util.PriorityQueue; import java.util.Vector; public class DirectedGraph extends Graph { // ATTRIBUTE private visualizationElements.Graph screenGraph; private LogElementList logList; // KONSTRUKTOREN public DirectedGraph() { super(); this.screenGraph = new visualizationElements.Graph(new Vector(), new Vector(), true, EdgeStyle.Direct); this.logList = new LogElementList(); } public DirectedGraph(String s) { super(s); this.screenGraph = new visualizationElements.Graph(new Vector(), new Vector(), true, EdgeStyle.Direct); this.logList = new LogElementList(); } // GET-ER public visualizationElements.Graph getScreenGraph() { return this.screenGraph; } public visualizationElements.Graph getScreenGraphCopy() { visualizationElements.Graph graphCopy = new visualizationElements.Graph(new Vector(), new Vector(), true, EdgeStyle.Direct); Vector copiedVertexes = new Vector<>(); Vector 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; } public LogElementList getLogList() { return this.logList; } // HINZUFÜGEN // Kante hinzufügen public void addEdge(MarkedEdge e) { super.addEdge(e); this.screenGraph.getEdges().add(e.getScreenEdge()); } // Knoten hinzufügen public void addVertex(MarkedVertex n) { super.addVertex(n); this.screenGraph.getVertexes().add(n.getScreenVertex()); } // LÖSCHEN // Kante löschen public void removeEdge(MarkedEdge e) { super.removeEdge(e); this.screenGraph.getEdges().remove(e.getScreenEdge()); } // Knoten löschen public void removeVertex(MarkedVertex n) { super.removeVertex(n); this.screenGraph.getVertexes().remove(n.getScreenVertex()); } // KNOTEN EIGENSCHAFTEN // Prüfung, ob zwei Knoten stark adjazent sind public boolean areStrongAdjacent(MarkedVertex n1, MarkedVertex n2) { boolean n1ton2 = false; boolean n2ton1 = false; for (MarkedEdge i: this.getAllEdges()) { 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 n1 = null; MarkedVertex n2 = null; for (MarkedVertex 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 public int inDegree(MarkedVertex n) { int degree = 0; for (MarkedEdge i: this.getAllEdges()) { if (i.getDestination() == n) { degree += 1; } } return degree; } public int inDegree(String s) throws NameDoesNotExistException{ for (MarkedVertex 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 public int outDegree(MarkedVertex n) { int degree = 0; for (MarkedEdge i: this.getAllEdges()) { if (i.getSource() == n) { degree += 1; } } return degree; } public int outDegree(String s) throws NameDoesNotExistException{ for (MarkedVertex 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 public Vector> getPredecessors(MarkedVertex n) { Vector> predecessors = new Vector<>(); for (MarkedEdge i: this.getAllEdges()) { if (i.getDestination() == n) { predecessors.add((MarkedVertex) i.getSource()); } } return predecessors; } // Prüfung, welche Knoten Nachfolger sind public Vector> getSuccessors(MarkedVertex n) { Vector> successors = new Vector<>(); for (MarkedEdge i: this.getAllEdges()) { if (i.getSource() == n) { successors.add((MarkedVertex) i.getDestination()); } } return successors; } // AUFGABE 2 // Dijkstra-Algorithmus public int getShortestPathDijkstra(MarkedVertex n1, MarkedVertex 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, Integer> distance = new HashMap<>(); HashMap, Boolean> visited = new HashMap<>(); for (MarkedVertex i: this.getAllVertexes()) { distance.put(i, -1); visited.put(i, false); } // Erstelle Schlange wo die nächsten Verbindungen drin sind PriorityQueue> queue = new PriorityQueue<>(new WrapperComparator()); // 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; // 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())); while (!queue.isEmpty()) { // Den nächsten Knoten, der am wenigsten kostet, besuchen WrapperElement 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())); // Gehe von diesem Knoten aus alle erreichbaren Knoten durch for (MarkedVertex i: this.getSuccessors(nextVertex.getElement())) { // Kante finde, die den jetzigen und nächsten Knoten verbindet for (MarkedEdge 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); // 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())); // Nehme nächsten Knoten in die Queue auf queue.add(new WrapperElement<>(i, dist)); } } System.out.println("Done"); // Gibt Distanz zu gefragtem Knoten zurück return distance.get(n2); } public int getShortestPathAStar(MarkedVertex n1, MarkedVertex 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, Integer> distance = new HashMap<>(); HashMap, Boolean> visited = new HashMap<>(); for (MarkedVertex i: this.getAllVertexes()) { distance.put(i, -1); visited.put(i, false); } // Erstelle Schlange wo die nächsten Verbindungen drin sind PriorityQueue> queue = new PriorityQueue<>(new WrapperComparator()); // 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())); while (!queue.isEmpty()) { // Den nächsten Knoten, der am wenigsten kostet, besuchen WrapperElement 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())); // Gehe von diesem Knoten aus alle erreichbaren Knoten durch for (MarkedVertex i: this.getSuccessors(nextVertex.getElement())) { // Kante finde, die den jetzigen und nächsten Knoten verbindet for (MarkedEdge 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())); // Nehme nächsten Knoten in die Queue auf queue.add(new WrapperElement<>(i, dist)); } } System.out.println("Done"); // Gibt Distanz zu gefragtem Knoten zurück return distance.get(n2); } }