Beispiel #1
0
        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);
        }
Beispiel #2
0
        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;
            }
        }