public static IGraph ImportAdjacentListBalancedNodesCostCapacityEdges(string _FilePath) { Console.WriteLine("Starte Importieren: " + _FilePath); var hStopwatch = new Stopwatch(); hStopwatch.Start(); String[] hAdjacentListFileContent = { }; if (File.Exists(_FilePath)) { hAdjacentListFileContent = File.ReadAllLines(_FilePath); } // Initiales Anlegen der Knoten. var hGraph = new Graph(); var hNodeCount = Convert.ToInt32(hAdjacentListFileContent[0]); int hCurrentRow; int hCurrentNodeId = 0; for (hCurrentRow = 1; hCurrentRow < hNodeCount + 1; hCurrentRow++) { var hNodeBalance = Convert.ToDouble(hAdjacentListFileContent[hCurrentRow], CultureInfo.InvariantCulture); hGraph.TryToAddNode(new BalancedNode(hCurrentNodeId, hNodeBalance)); hCurrentNodeId++; } var hGraphNodes = hGraph.GetNodeDictionary(); while (hCurrentRow < hAdjacentListFileContent.Length) { var hRow = hAdjacentListFileContent[hCurrentRow]; var hEdgeInfo = hRow.Split('\t'); var hNodeAId = Convert.ToInt32(hEdgeInfo[0]); var hNodeBId = Convert.ToInt32(hEdgeInfo[1]); var hCostWeightValue = Convert.ToDouble(hEdgeInfo[2], CultureInfo.InvariantCulture); var hCapacityWeightValue = Convert.ToDouble(hEdgeInfo[3], CultureInfo.InvariantCulture); var hNodeA = hGraphNodes[hNodeAId]; var hNodeB = hGraphNodes[hNodeBId]; var hCostWeight = new CostWeighted(); hCostWeight.SetValue(hCostWeightValue); var hCapcacityWeight = new CapacityWeighted(); hCapcacityWeight.SetValue(hCapacityWeightValue); hGraph.CreateDirectedEdge(hNodeA, hNodeB, new IWeight[] { hCostWeight, hCapcacityWeight }); hCurrentRow++; } hStopwatch.Stop(); Console.WriteLine("Anzahl eingelesener Knoten:\t" + hGraph.GetNodeDictionary().Count.ToString()); Console.WriteLine("Anzahl eingelesener Kanten:\t" + hGraph.GetEdgeIndices().Count.ToString()); Console.WriteLine("Dauer Einlesevorgang:\t\t" + hStopwatch.ElapsedMilliseconds.ToString() + " ms"); Console.WriteLine(); return(hGraph); }
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; } }