Dateien nach "graph" hochladen

This commit is contained in:
Jonathan-Kalmbach 2024-07-10 05:24:10 +00:00
commit d70ce4a163
5 changed files with 641 additions and 0 deletions

71
graph/Anwendung.java Normal file
View File

@ -0,0 +1,71 @@
package graph;
import static java.awt.Color.black;
public class Anwendung {
public static void main(String[] args) {
// Erstellen eines gerichteten Graphen
DirectedGraph<VertexMarking, EdgeMarking> graph = new DirectedGraph<>();
// Erstellen und Hinzufügen von Knoten
MarkedVertex<VertexMarking> vertexA = new MarkedVertex<>("A", new VertexMarking() {
}, 10, 10, black);
MarkedVertex<VertexMarking> vertexB = new MarkedVertex<>("B", new VertexMarking() {
}, 10, 100, black);
MarkedVertex<VertexMarking> vertexC = new MarkedVertex<>("C", new VertexMarking() {
}, 100, 10, black);
MarkedVertex<VertexMarking> vertexD = new MarkedVertex<>("D", new VertexMarking() {
}, 600, 100, black);
MarkedVertex<VertexMarking> vertexE = new MarkedVertex<>("E", new VertexMarking() {
}, 100, 60, black);
MarkedVertex<VertexMarking> vertexF = new MarkedVertex<>("F", new VertexMarking() {
}, 160, 100, black);
MarkedVertex<VertexMarking> vertexG = new MarkedVertex<>("G", new VertexMarking() {
}, 100, 160, black);
graph.addVertex(vertexA);
graph.addVertex(vertexB);
graph.addVertex(vertexC);
graph.addVertex(vertexD);
graph.addVertex(vertexE);
graph.addVertex(vertexF);
graph.addVertex(vertexG);
// Erstellen und Hinzufügen von Kanten
graph.addEdge(new MarkedEdge<>("Edge1", vertexA, vertexB, new EdgeMarking() {
}));
graph.addEdge(new MarkedEdge<>("Edge2", vertexB, vertexC, new EdgeMarking() {
}));
graph.addEdge(new MarkedEdge<>("Edge3", vertexC, vertexD, new EdgeMarking() {
}));
graph.addEdge(new MarkedEdge<>("Edge7", vertexC, vertexE, new EdgeMarking() {
}));
graph.addEdge(new MarkedEdge<>("Edge4", vertexD, vertexE, new EdgeMarking() {
}));
graph.addEdge(new MarkedEdge<>("Edge8", vertexD, vertexG, new EdgeMarking() {
}));
graph.addEdge(new MarkedEdge<>("Edge5", vertexE, vertexF, new EdgeMarking() {
}));
graph.addEdge(new MarkedEdge<>("Edge6", vertexF, vertexG, new EdgeMarking() {
}));
//System.out.println(graph.areStrongAdjacent("A", "B"));
//System.out.println(graph.numberOfEdges());
System.out.println("Vorgänger von A");
System.out.println(graph.getPredecessors(vertexA));
System.out.println("Vorgänger von D");
System.out.println(graph.getPredecessors(vertexD));
System.out.println("Vorgänger von D");
System.out.println(graph.getSuccessors(vertexC));
System.out.println(graph.topSort(vertexA));
System.out.println("");
}
}

330
graph/DirectedGraph.java Normal file
View File

@ -0,0 +1,330 @@
package graph;
import java.awt.*;
import java.util.*;
import java.util.List;
import java.util.Queue;
import logging.GraphLogElement;
import logging.LogElement;
import logging.LogElementList;
import logging.NewLogElement;
import testApplication.TestLogElement;
import visualizationElements.EdgeStyle;
import javax.swing.*;
public class DirectedGraph<T extends VertexMarking, U extends EdgeMarking> extends Graph<T, U> {
private boolean hasCycle = false;
LogElementList<LogElement> logList = new LogElementList<>(); // Erzeugen einer LogElementList für die Protokollierung
LogElementList<TestLogElement> graphLogList = new LogElementList<>(); // Erzeugen einer LogElementListe von TestLogElementen, in der der Zustand des Graphen protokolliert wird
private visualizationElements.Graph visualizedGraph;
int step = 0;
public DirectedGraph() {
super();
this.visualizedGraph = new visualizationElements.Graph(new Vector<visualizationElements.Vertex>(), new Vector <visualizationElements.Edge>(), true, EdgeStyle.Direct);
}
public DirectedGraph(String s) {
super(s);
this.visualizedGraph = new visualizationElements.Graph(new Vector<visualizationElements.Vertex>(), new Vector <visualizationElements.Edge>(), true, EdgeStyle.Direct);
}
public visualizationElements.Graph getVisualizedGraph() {
return this.visualizedGraph;
}
public visualizationElements.Graph copyVisualizedGraph() {
// Neue Instanz des Graphen erstellen
visualizationElements.Graph snapshotOfVisualizedGraph = new visualizationElements.Graph(new Vector<>(), new Vector<>(), true, EdgeStyle.Direct);
// Kopiere alle Vertexes
Vector<visualizationElements.Vertex> snapshotOfVertexes = new Vector<>();
// Iteration über alle Vertexe
for (visualizationElements.Vertex vertex : this.visualizedGraph.getVertexes()) {
// Dem Vector der Vertexe alle Vertexe des visualizedGraph hinzufügen, wobei die Methoden für x,y,Marking und Farbe abgerufen werden
snapshotOfVertexes.add(new visualizationElements.Vertex(vertex.getXpos(), vertex.getYpos(), vertex.getMarking(), vertex.getColor()));
}
snapshotOfVisualizedGraph.setVertexes(snapshotOfVertexes); // Setze die kopierten Vertexes im neuen Graphen
// Kopiere alle Edges
Vector<visualizationElements.Edge> snapshotOfEdges = new Vector<>();
for (visualizationElements.Edge edge : this.visualizedGraph.getEdges()) {
// Dem Vector der Edges alle Edges des visualizedGraph hinzufügen, auch hier wieder Methodenabruf für Source,Destination, Marking und Farbe
snapshotOfEdges.add(new visualizationElements.Edge(edge.getSource(), edge.getDestination(), edge.getMarking(), edge.getColor()));
}
snapshotOfVisualizedGraph.setEdges(snapshotOfEdges); // Setze die kopierten Edges im neuen Graphen
return snapshotOfVisualizedGraph;
}
public void addEdge(MarkedEdge<U> e){
super.addEdge(e);
this.visualizedGraph.getEdges().add(e.getScreenEdge());
}
public void addVertex(MarkedVertex<T> v){
super.addVertex(v);
this.visualizedGraph.getVertexes().add(v.getScreenVertex());
}
public boolean removeEdge(MarkedEdge<U> e){
super.removeEdge(e);
this.visualizedGraph.getEdges().remove(e.getScreenEdge());
return true;
}
public boolean removeVertex(MarkedVertex<T> v){
super.removeVertex(v);
this.visualizedGraph.getVertexes().remove(v.getScreenVertex());
return true;
}
public Vector<visualizationElements.Edge> getEdges() {
return this.visualizedGraph.getEdges();
}
public Vector<visualizationElements.Vertex> getVertexes() {
return this.visualizedGraph.getVertexes();
}
public LogElementList<LogElement> getLogList(){
return this.logList;
}
public LogElementList<TestLogElement> getNewLogList(){
return this.graphLogList;
}
public Vector<MarkedVertex<T>> getPredecessors(MarkedVertex<T> n) {
Vector<MarkedVertex<T>> predecessors = new Vector<>();
for (MarkedEdge<U> edge : getAllEdges()) {
if (edge.getDestination().equals(n)) {
predecessors.add((MarkedVertex<T>) edge.getSource());
}
}
return predecessors;
}
public Vector<MarkedVertex<T>> getSuccessors(MarkedVertex<T> n) {
Vector<MarkedVertex<T>> successors = new Vector<>();
for (MarkedEdge<U> edge : getAllEdges()) {
if (edge.getSource().equals(n)) {
successors.add((MarkedVertex<T>) edge.getDestination());
}
}
return successors;
}
public int inDegree(MarkedVertex<T> n) {
return getPredecessors(n).size();
}
public int inDegree(String s) {
for (MarkedVertex<T> vertex : getAllVertexes()) {
if (vertex.getName().equals(s)) {
return inDegree(vertex);
}
}
return 0;
}
public int outDegree(MarkedVertex<T> n) {
return getSuccessors(n).size();
}
public int outDegree(String s) {
for (MarkedVertex<T> vertex : getAllVertexes()) {
if (vertex.getName().equals(s)) {
return outDegree(vertex);
}
}
return 0;
}
public boolean areStrongAdjacent(MarkedVertex<T> n1, MarkedVertex<T> n2) {
// Implement the logic for strong adjacency in directed graphs
return (hasEdge(n1, n2) && hasEdge(n2, n1));
}
public boolean areStrongAdjacent(String s1, String s2) {
// Implement the logic for strong adjacency using names
return (hasEdge(s1, s2)&&hasEdge(s2, s1));
}
@Override
public boolean areAdjacent(MarkedVertex<T> n1, MarkedVertex<T> n2) {
return hasEdge(n1, n2);
}
@Override
public boolean areAdjacent(String s1, String s2) {
return hasEdge(s1, s2);
}
public Vector<MarkedVertex<T>> breadthFirstSearch(MarkedVertex<T> startVertex) {
// Anlegen der Maps, die Farbe udn Distanz speichern
Map<MarkedVertex<T>, String> color = new HashMap<>();
Map<MarkedVertex<T>, Integer> distance = new HashMap<>();
// Vector für die Rückgabe aller gefundenen Knoten
Vector<MarkedVertex<T>> vertices = new Vector<>();
// Schlange von MarkedVertex als LinkedList
Queue<MarkedVertex<T>> queue = new LinkedList<>();
// step für die Protokollierung
step = 0;
this.graphLogList.add(new TestLogElement(0, "0", 0, this.copyVisualizedGraph()));
for (MarkedVertex<T> v : getAllVertexes()) {
color.put(v, "weiß"); // Alle Knoten zunächst weiß
distance.put(v, Integer.MAX_VALUE); // Unendliche Distanz
v.getScreenVertex().setColor(Color.white); // Setzen der Farbe weiß, des ScreenVertex
// Protokollierung für Konsolenausgabe & Visualisierung
logList.add(new LogElement(step++, "Farbe weiß gesetzt für: " + v.getName() + ", Distanz auf unendlich gesetzt."));
this.graphLogList.add(new TestLogElement(1, "0", 0,this.copyVisualizedGraph()));
}
// Startknoten initialisieren und als Grau markieren
color.put(startVertex, "grau"); // in Map
startVertex.getScreenVertex().setColor(Color.gray); // als ScreenVertex
this.graphLogList.add(new TestLogElement(2, "0", 0,this.copyVisualizedGraph()));
// startVertex in Distanzmap, in Queue und in gefundene Vertexe
distance.put(startVertex, 0);
queue.add(startVertex);
vertices.add(startVertex);
logList.add(new LogElement(step++, "Startknoten " + startVertex.getName() + " auf grau gesetzt, Distanz = 0."));
while (!queue.isEmpty()) {
MarkedVertex<T> current = queue.poll(); // Oberstes Element der Schlange als momentanten Knoten setzen
logList.add(new LogElement(step++, "Dequeue Knoten: " + current.getName())); // Protokollierung
// Prozessieren aller Nachbarn des aktuellen Knotens
for (MarkedVertex<T> neighbor : getNeighbors(current)) {
if (color.get(neighbor).equals("weiß")) { // Wenn der Nachbar noch nicht besucht wurde
color.put(neighbor, "grau");
neighbor.getScreenVertex().setColor(Color.gray);
// alle Nachbarn des aktuellen Knoten werden in die Maps und in die Queue aufgenommen
distance.put(neighbor, distance.get(current) + 1);
queue.add(neighbor);
vertices.add(neighbor);
// Protokollierung
logList.add(new LogElement(step++, "Nachbar " + neighbor.getName() + " auf grau gesetzt, Distanz erhöht zu " + distance.get(neighbor)));
this.graphLogList.add(new TestLogElement(3, "0", 0,this.copyVisualizedGraph()));
}
}
current.getScreenVertex().setColor(Color.black);
color.put(current, "schwarz"); // Markieren des aktuellen Knotens als vollständig verarbeitet
queue.remove(current);
logList.add(new LogElement(step++, "Knoten " + current.getName() + " auf schwarz gesetzt."));
this.graphLogList.add(new TestLogElement(4, "0", 0,this.copyVisualizedGraph()));
}
logResults();
return vertices;
}
private List<MarkedVertex<T>> getNeighbors(MarkedVertex<T> vertex) {
List<MarkedVertex<T>> neighbors = new ArrayList<>();
for (MarkedEdge<U> edge : getAllEdges()) {
if (edge.getSource().equals(vertex)) {
neighbors.add((MarkedVertex<T>) edge.getDestination());
}
// Breitensuche in beide Richtungen, da auch Nachbarn, die auf den Knoten zeigen, als Nachbarn erkannt werden (kann verändert werden, indem man einfach das else if ausklammert)
else if (edge.getDestination().equals(vertex)){
neighbors.add((MarkedVertex<T>) edge.getSource());
}
}
return neighbors;
}
Map<MarkedVertex<T>, Integer> ToSoNr = new HashMap<>();
Map<MarkedVertex<T>, String> Besucht = new HashMap<>();
int nummer = getAllVertexes().size();
public boolean topSort(MarkedVertex<T> n1){
// Zurücksetzen der verwendeten Maps
Besucht.clear();
ToSoNr.clear();
step = 0; // Step als 0 deklarieren als Protokollierungsvariable
n1.getScreenVertex().setColor(Color.white); // Startknoten n1 als weiß setzen, für bessere Übersichtlichkeit bei Visualisierung
this.graphLogList.add(new TestLogElement(0, "0", 0,this.copyVisualizedGraph())); // Übergabe aktueller Graph an graphLogList
for (MarkedVertex<T> vertex : getAllVertexes()){ // Für jeden Vertex überprüfe, ob er schon in Besucht vorhanden ist
if (!Besucht.containsKey(vertex)){ // Bei Reihenfolge von Eingabe A,B,C erst den A nehmen, und dann Rekursion bis C
logList.add(new LogElement(step++, "Nicht besucht: " + vertex.getName()));
tsprozedur(vertex); // Übergabe von unbesuchtem Knoten an tsprozedur
}
}
// Wenn die Knoten alle abgearbeitet wurden ohne Zyklus:
if (!hasCycle) {
logList.add(new LogElement(step++, "Topologische Sortierung erfolgreich."));
}
// Ausgabe der ToSoNr Map auf der Konsole
for (Map.Entry<MarkedVertex<T>, Integer> entry : ToSoNr.entrySet()) {
MarkedVertex<T> vertex = entry.getKey();
Integer num = entry.getValue();
System.out.println("Vertex: " + vertex.getName() + ", Nummer: " + num);
}
logResults();
return hasCycle;
}
public void tsprozedur(MarkedVertex<T> n1){
// Knoten als in Bearbeitung markieren
Besucht.put(n1, "in Bearbeitung");
logList.add(new LogElement(step++, "Wurde besucht - " + n1.getName())); // Logging
for (MarkedVertex<T> vertex : getSuccessors(n1)) {
// Zyklus gefunden, wenn der Nachfolger bereits in Bearbeitung ist
// Wenn Nachfolger in Besucht existiert und "in Bearbeitung" markiert ist und es nicht der direkte Vorgänger ist (Doppelkante)
if (Besucht.get(vertex) != null && Besucht.get(vertex).equals("in Bearbeitung") && !getPredecessors(n1).contains(vertex)) {
logList.add(new LogElement(step++, "Zyklus gefunden bei Knoten " + vertex.getName() + " von " + n1.getName()));
vertex.getScreenVertex().setColor(Color.red);
n1.getScreenVertex().setColor(Color.red);
this.graphLogList.add(new TestLogElement(2, "0", 0,this.copyVisualizedGraph())); // In graphLogList wird eine aktuelle Instanz des Graphen gespeichert
hasCycle = true;
return;
}
// Falls Nachfolger noch nicht besucht wurde -> Eine Rekursion tiefer mit Nachfolger
else if (!Besucht.containsKey(vertex)) {
tsprozedur(vertex);
if (hasCycle) return; // Stoppe weitere Verarbeitung, wenn Zyklus gefunden
}
}
// Markiere Knoten als vollständig besucht
// Wenn es keinen Nachfolger mehr zum rekursiven Aufruf gibt
Besucht.put(n1, "besucht"); // Setze Knoten n1 in Besucht-Map auf "besucht"
ToSoNr.put(n1, (nummer--)+getAllVertexes().size()); //Setze Knoten n1 in TopSortNummer-Map auf Anzahl aller Knoten - nummer(bei letztem Knoten -1)
logList.add(new LogElement(step++, "Knoten " + n1.getName() + " als vollständig besucht markiert. Topologische Nummer:" + ToSoNr.get(n1))); // Protokollierung für Konsolenausgabe
n1.getScreenVertex().setMarking(String.valueOf(ToSoNr.get(n1))); // Setze die Bezeichnung der Knoten als Nummer für die Visualisierung
this.graphLogList.add(new TestLogElement(1, "0", 0,this.copyVisualizedGraph())); // In graphLogList wird eine aktuelle Instanz des Graphen gespeichert
}
public boolean hasCycle(MarkedVertex<T> n1){
return topSort(n1);
}
private void logResults() { // Iteration über logList mit Konsolenausgabe
for (LogElement element : logList) {
System.out.println("Step " + element.getStep() + ": " + element.getDescription());
}
}
}

39
graph/Edge.java Normal file
View File

@ -0,0 +1,39 @@
package graph;
public abstract class Edge {
private String name;
private Vertex source;
private Vertex destination;
public Edge() {}
public Edge(String s, Vertex n1, Vertex n2) {
this.name = s;
this.source = n1;
this.destination = n2;
}
public Vertex getDestination() {
return destination;
}
public String getName() {
return name;
}
public Vertex getSource() {
return source;
}
public void setDestination(Vertex n) {
this.destination = n;
}
public void setName(String s) {
this.name = s;
}
public void setSource(Vertex n) {
this.source = n;
}
}

4
graph/EdgeMarking.java Normal file
View File

@ -0,0 +1,4 @@
package graph;
public abstract class EdgeMarking extends Marking{
}

197
graph/Graph.java Normal file
View File

@ -0,0 +1,197 @@
package graph;
import logging.LogElement;
import logging.LogElementList;
import java.util.Vector;
public abstract class Graph<T extends VertexMarking, U extends EdgeMarking> {
private String name;
private Vector<MarkedVertex<T>> vertexes = new Vector<>();
private Vector<MarkedEdge<U>> edges = new Vector<>();
public Graph() {}
public Graph(String s) {
this.name = s;
}
public void addEdge(MarkedEdge<U> e) {
edges.add(e);
}
public void addVertex(MarkedVertex<T> n) {
vertexes.add(n);
}
public boolean areAdjacent(MarkedVertex<T> n1, MarkedVertex<T> n2){
for (MarkedEdge<U> edge: edges){
if (edge.getSource() == n1 && edge.getDestination() == n2 || edge.getDestination() == n1 && edge.getSource() == n2){
return true;
}
}
return false;
}
public boolean areAdjacent(String s1, String s2){
for (MarkedEdge<U> edge: edges){
if (edge.getSource().getName().equals(s1) && edge.getDestination().getName().equals(s2)){
return true;
}
else if (edge.getSource().getName().equals(s2) && edge.getDestination().getName().equals(s1)){
return true;
}
}
return false;
}
public int degree() {
return edges.size();
}
public Vector<MarkedEdge<U>> getAllEdges() {
return this.edges;
}
public Vector<MarkedVertex<T>> getAllVertexes() {
return this.vertexes;
}
public String getName() {
return this.name;
}
public abstract visualizationElements.Graph getVisualizedGraph();
public abstract LogElementList<LogElement> getLogList();
/*
public Vector <Vertex> getNeighbors(Vertex n1){
Vector<Vertex> neighbors = new Vector<>();
for (MarkedEdge<U> edge : edges) {
if (edge.getSource().equals(n1)) {
neighbors.add(edge.getDestination());
}
else if (edge.getDestination().equals(n1)){
neighbors.add(edge.getSource());
}
}
return neighbors;
}
*/
public boolean hasEdge(MarkedEdge<U> e) {
return edges.contains(e);
}
public boolean hasEdge(String s) {
for (MarkedEdge<U> edge : edges) {
if (edge.getName().equals(s)) {
return true;
}
}
return false;
}
public boolean hasEdge(MarkedVertex<T> v1, MarkedVertex<T> v2) {
for (MarkedEdge<U> edge : edges) {
if (edge.getSource().equals(v1) && edge.getDestination().equals(v2)) {
return true;
}
else if (edge.getSource().equals(v2) && edge.getDestination().equals(v1)) {
return true;
}
}
return false;
}
public boolean hasEdge(String s1, String s2) {
for (MarkedEdge<U> edge : edges) {
if (edge.getSource().getName().equals(s1) && edge.getDestination().getName().equals(s2)) {
return true;
}
else if (edge.getSource().getName().equals(s2) && edge.getDestination().getName().equals(s1)) {
return true;
}
}
return false;
}
public boolean hasLoop(MarkedVertex<T> n) {
for (MarkedEdge<U> edge : edges) {
if (edge.getSource().equals(n) && edge.getDestination().equals(n)) {
return true;
}
}
return false;
}
public boolean hasLoop(String s) {
for (MarkedEdge<U> edge : edges) {
if (edge.getSource().getName().equals(s) && edge.getDestination().getName().equals(s)) {
return true;
}
}
return false;
}
public Boolean hasVertex(MarkedVertex<T> n) {
return vertexes.contains(n);
}
public boolean hasVertex(String s) {
for (MarkedVertex<T> vertex : vertexes) {
if (vertex.getName().equals(s)) {
return true;
}
}
return false;
}
public int numberOfEdges() {
return edges.size();
}
public int numberOfVertexes() {
return vertexes.size();
}
public boolean removeEdge(MarkedEdge<U> e) {
return edges.remove(e);
}
public boolean removeEdge(String s) {
for (MarkedEdge<U> edge : edges) {
if (edge.getName().equals(s)) {
return edges.remove(edge);
}
}
return false;
}
public boolean removeVertex(MarkedVertex<T> n) {
return vertexes.remove(n);
}
public boolean removeVertex(String s) {
for (MarkedVertex<T> vertex : vertexes) {
if (vertex.getName().equals(s)) {
return vertexes.remove(vertex);
}
}
return false;
}
public void setName(String n) {
this.name = n;
}
@Override
public String toString() {
return "Graph{" + "name='" + name + '\'' + ", vertexes=" + vertexes + ", edges=" + edges + '}';
}
}