public static void Main(string[] args) { var myGraph = new Graph(); myGraph.AddEdge("V0", "V3", 1); myGraph.AddEdge("V0", "V1", 2); myGraph.AddEdge("V1", "V4", 10); myGraph.AddEdge("V1", "V3", 3); myGraph.AddEdge("V2", "V5", 8); myGraph.AddEdge("V2", "V0", 4); myGraph.AddEdge("V3", "V4", 2); myGraph.AddEdge("V3", "V6", 4); myGraph.AddEdge("V3", "V5", 8); myGraph.AddEdge("V3", "V2", 2); myGraph.AddEdge("V4", "V6", 6); myGraph.AddEdge("V6", "V5", 1); Console.WriteLine("Unweighted: "); Unweighted.Calculate(myGraph, "V1"); Console.WriteLine(myGraph); Console.WriteLine(); Console.WriteLine("Dijkstra: "); Dijkstra.Calculate(myGraph, "V1"); Console.WriteLine(myGraph); }
public void Execute(int _SourceNodeId, int _TargetNodeId, bool _IgnoreTarget = false) { //Console.WriteLine("Start Bellman Ford"); FNodeDictionary = FUsedGraph.GetNodeDictionary(); var hNodeCount = FNodeDictionary.Count; var hStartNode = FNodeDictionary[_SourceNodeId]; // Initialisierung FHasNegativeCylces = false; foreach (var hNode in FNodeDictionary.Values) { FCostDictionary.Add(hNode, Double.PositiveInfinity); FParentNodeEdge.Add(hNode, null); } FCostDictionary[hStartNode] = 0.0; // Bellman Ford Iterationen: |V|-1 var hBellmanFordRanToEnd = true; for (int hBellmanFordIteration = 0; hBellmanFordIteration < hNodeCount - 1; hBellmanFordIteration++) { var hCostsImproved = BellmanFordIteration(); // Wenn in einer Iteration keine Verbesserung mehr stattfindet müssen die folgenden auch nicht mehr betrachtet werden if (!hCostsImproved) { hBellmanFordRanToEnd = false; break; } } // Detektion von Negativen Zyklen: // Wenn |V|-1 Durchläufe gemacht wurden wird jetzt noch ein Durchlauf gemacht um zu prüfen ob es einen negativen Zyklus gibt. var hGraphHasNegativeCycle = false; if (hBellmanFordRanToEnd) { var hCostsImproved = BellmanFordIteration(); hGraphHasNegativeCycle = hCostsImproved; } // Ausgabe negativer Zyklus oder Ermittlung des Pfads if (hGraphHasNegativeCycle) { FHasNegativeCylces = true; // Bei einem Zyklus laufe ich solange die Parents durch bis ich wieder beim ursprünglichen Knoten auskomme // Ermitteln der negativen Zyklen var hAvailableNodes = new List <INode>(FParentNodeEdge.Keys); var hCycleList = new List <int>(); var hCycleDetected = false; var hCycleCosts = 0.0; CycleEdges = new List <string>(); while (!hCycleDetected) { // Startknoten auswählen, dessen Parent nicht null ist (=> kann bei >= 2 Zusammenhangskomponenten auftreten INode hStartNodeInCycleDetection = hAvailableNodes[0]; foreach (var hNode in hAvailableNodes) { if (FParentNodeEdge[hNode] != null) { hStartNodeInCycleDetection = hNode; break; } } var hCurrentNode = hStartNodeInCycleDetection; hCycleList.Clear(); CycleEdges.Clear(); hCycleCosts = 0.0; // Pfad entlang laufen while (hCurrentNode != null) { // Prüfen ob der Knoten im aktuellen Pfad schon vorkam if (hCycleList.Contains(hCurrentNode.Id)) { if (hCycleList[0] == hCurrentNode.Id) { // Zyklus fertig. Beim Startknoten geschlossen // Wert zurückgeben hCycleDetected = true; } else { // Zyklus vorhanden, aber es sind noch Nicht-Zyklus-Knoten vorhanden hAvailableNodes.Remove(hStartNodeInCycleDetection); } break; } else { // Knoten in den aktuellen Pfad einfügen hCycleList.Add(hCurrentNode.Id); CycleEdges.AddRange(FParentNodeEdge[hCurrentNode].Edge.EdgeHashInfo()); hCycleCosts += (FParentNodeEdge[hCurrentNode].Edge.GetWeightValue()); // Nächsten Knoten betrachten hCurrentNode = FParentNodeEdge[hCurrentNode].Node; } } // Wenn der aktuelle Knoten == null ist gab es von dem ersten Knoten aus keinen Zyklus hAvailableNodes.Remove(hStartNodeInCycleDetection); } // Zyklus gefunden. Die Elemente noch in eine richtige Reihenfolge bringen hCycleList.Reverse(); FCycleNodes = hCycleList; CycleCosts = hCycleCosts; // Ausgabe: //Console.WriteLine("Graph enthält einen negativen Zyklus"); //Console.WriteLine(string.Join(",", FCycleNodes)); //Console.WriteLine("Zykluskosten: " + CycleCosts); } else { if (!_IgnoreTarget && (FParentNodeEdge[FNodeDictionary[_TargetNodeId]] != null)) { FShortestPathToTarget = new List <string>(); var hTargetNode = FNodeDictionary[_TargetNodeId]; // Vom Zielknoten rückwärts bis zum Startknoten laufen var hTmpNode = hTargetNode; var hShortestPathStack = new Stack <int>(); var hCosts = 0.0; while (hTmpNode != hStartNode) { FShortestPathToTarget.Add(FParentNodeEdge[hTmpNode].Node.Id.ToString() + "-" + hTmpNode.Id.ToString()); hCosts += FParentNodeEdge[hTmpNode].Edge.GetWeightValue(); hShortestPathStack.Push(hTmpNode.Id); hTmpNode = FParentNodeEdge[hTmpNode].Node; // Ermitteln des Parents } FTargetFound = true; hShortestPathStack.Push(hStartNode.Id); FShortestPathToTarget.Reverse(); // Ausgabe //Console.WriteLine("Kürzeste Route:\t" + string.Join(",", hShortestPathStack)); //Console.WriteLine("Kosten:\t" + hCosts); } // Kürzeste Wege Baum erstellen // Neues Grafen Objekt erstellen und die Knoten anlegen IGraph hNewGraph = new Graph(); foreach (var hParentNodeEdge in FParentNodeEdge) { hNewGraph.CreateNewNode(hParentNodeEdge.Key.Id); } foreach (var hParentNodeEdge in FParentNodeEdge) { // Startknoten hat keinen Value if (hParentNodeEdge.Value != null) { IWeight hNewWeight = null; if (hParentNodeEdge.Value.Edge.IsWeighted()) { if (hParentNodeEdge.Value.Edge.GetWeight() is CostWeighted) { hNewWeight = new CostWeighted(hParentNodeEdge.Value.Edge.GetWeightValue()); } } else { hNewWeight = new Unweighted(); } var hEdge = hParentNodeEdge.Value.Edge; if (hEdge is DirectedEdge) { hNewGraph.CreateDirectedEdge(hParentNodeEdge.Value.Node.Id, hParentNodeEdge.Key.Id, hNewWeight); } else if (hEdge is UndirectedEdge) { hNewGraph.CreateUndirectedEdge(hParentNodeEdge.Value.Node.Id, hParentNodeEdge.Key.Id, hNewWeight); } } } hNewGraph.UpdateNeighbourInfoInNodes(); FShortestPathGraph = hNewGraph; } }