예제 #1
0
 public BalancedNode(T payload)
 {
     this.payload = payload;
     leftBuddy    = null;
     rightBuddy   = null;
     id           = 0;
 }
예제 #2
0
 public BalancedNode(T payload, int id)
 {
     this.payload = payload;
     leftBuddy    = null;
     rightBuddy   = null;
     this.id      = id;
 }
예제 #3
0
 public BalancedNode(T payload, BalancedNode <T> leftBuddy, BalancedNode <T> rightBuddy, int id)
 {
     this.payload    = payload;
     this.leftBuddy  = leftBuddy;
     this.rightBuddy = rightBuddy;
     this.id         = id;
 }
예제 #4
0
        private void addRightNode(BalancedNode <T> n)
        {
            BalancedNode <T> newNode      = n;
            BalancedNode <T> currentRight = getRightestNode();

            currentRight.setRightBuddy(newNode);
            newNode.setLeftBuddy(currentRight);
        }
예제 #5
0
        private static BalancedNode <T> traverseRight(BalancedNode <T> n)
        {
            if (n.getRightBuddy() != null)
            {
                return(traverseRight(n.getRightBuddy()));
            }

            return(n);
        }
예제 #6
0
        public void popRight()
        {
            BalancedNode <T> leftestNode = getLeftestNode();

            leftestNode.getRightBuddy().setLeftBuddy(null);

            detachNode(leftestNode);
            addRightNode(leftestNode);

            setRootNode(rootNode.getRightBuddy());
        }
예제 #7
0
        public void popLeft()
        {
            BalancedNode <T> rightestNode = getRightestNode();

            rightestNode.getLeftBuddy().setRightBuddy(null);

            detachNode(rightestNode);
            addLeftNode(rightestNode);

            setRootNode(rootNode.getLeftBuddy());
        }
예제 #8
0
        public int size()
        {
            var size = 0;
            BalancedNode <T> node = getLeftestNode();

            while (node != null)
            {
                size += 1;
                node  = node.getRightBuddy();
            }

            return(size);
        }
        public void Execute()
        {
            var hNodeDictionary = FUsedGraph.GetNodeDictionary();
            var hNodeCount      = hNodeDictionary.Count;

            // Erstellen der SuperQuelle
            var hSuperSource = new BalancedNode(hNodeCount, 0.0);

            FUsedGraph.TryToAddNode(hSuperSource);

            // Erstellen der SuperSenke
            var hSuperTarget = new BalancedNode(hNodeCount + 1, 0.0);

            FUsedGraph.TryToAddNode(hSuperTarget);

            // Balance der Knoten prüfen und an SuperQuelle und SuperSenke anhängen
            foreach (var hNode in hNodeDictionary.Values)
            {
                var hNodeBalance = ((BalancedNode)hNode).Balance;
                if (hNodeBalance > 0.0)
                {
                    // Es ist eine Quelle. Die SuperQuelle soll nun eine Kante auf diesen Knoten haben. Die Kapazität der Kante entspricht der Balance des Knotens
                    var hNewEdge = new DirectedEdge(hSuperSource, hNode);
                    hNewEdge.AddWeight(new CapacityWeighted(hNodeBalance));
                    FUsedGraph.AddEdge(hNewEdge); // Todo: Prüfen ob es richtig funktioniert
                }
                else if (hNodeBalance < 0.0)
                {
                    // Es ist eine Senke. Dieser Knoten soll nun eine Kante zur SuperSenke haben. Die Kapazität der Kante entspricht der Balance des Knotens
                    var hNewEdge = new DirectedEdge(hNode, hSuperTarget);
                    hNewEdge.AddWeight(new CapacityWeighted(-1.0 * hNodeBalance));
                    FUsedGraph.AddEdge(hNewEdge); // Todo: Prüfen ob es richtig funktioniert
                }
            }

            FUsedGraph.UpdateNeighbourInfoInNodes();


            // Nun soll der Edmonds-Karp Algorithmus ausgeführt werden. Dabei werden die SuperQuelle und SuperSenke verwendet
            var hEdmondsKarpAlgorithm = new EdmondsKarpAlgorithm(FUsedGraph);
            var hFlow = hEdmondsKarpAlgorithm.Execute(hSuperSource.Id, hSuperTarget.Id);


            // Nutzt die SuperQuelle die Kantenkapazitäten voll aus?
            foreach (var hNeighborEdge in hSuperSource.NeighbourEdges)
            {
                var hNeighborEdgeHash = hNeighborEdge.Edge.EdgeHashInfo()[0];
                var hFlowValue        = hFlow[hNeighborEdgeHash];
                var hEdgeCapacity     = hNeighborEdge.Edge.GetWeightValue <CapacityWeighted>();
                if (!hFlowValue.Equals(hEdgeCapacity))
                {
                    // Kein gültiger b-Fluss (Graph kann nicht alles übertragen)
                    FUsedGraph.RemoveNode(hSuperSource);
                    FUsedGraph.RemoveNode(hSuperTarget);
                    Console.WriteLine("Kein Fluss möglich");
                    return;
                }
            }

            // Löschen der SuperQuelle, SuperSenke und den verbindenden Kanten
            FUsedGraph.RemoveNode(hSuperSource);
            FUsedGraph.RemoveNode(hSuperTarget);

            // Den Fluss übernehmen. Dabei aber die Infos zur SuperQuelle und SuperSenke Ignorieren
            var hTotalFlow            = 0.0;
            var hGraphEdgeDictionary  = FUsedGraph.GenerateEdgeHashDictionary();
            var hFlussGraphDictionary = new Dictionary <string, double>();

            foreach (var hEdgeHash in hGraphEdgeDictionary.Keys)
            {
                hFlussGraphDictionary.Add(hEdgeHash, 0.0);
            }
            foreach (var hFlowInfo in hFlow)
            {
                if (hFlussGraphDictionary.ContainsKey(hFlowInfo.Key))
                {
                    hFlussGraphDictionary[hFlowInfo.Key] = hFlowInfo.Value;
                }
            }



            // Solange es noch negative Zyklen gibt
            var hFoundNegativeCycle = true;

            while (hFoundNegativeCycle)
            {
                hFoundNegativeCycle = false;

                // Residualgraphen erstellen
                var hResidualGraph      = ResidualGraphGenerator.GenerateCostCapacity(FUsedGraph, hFlussGraphDictionary);
                var hEdgeHashDictionary = hResidualGraph.GenerateEdgeHashDictionary();

                // Ausgehend von jedem Knoten wird versucht ein negativer Zykel zu finden
                foreach (var hNode in hResidualGraph.GetNodeDictionary())
                {
                    // Negativen Zyklus bezüglich den Kosten suchen
                    var hBellmanFordAlgorithm = new BellmanFordAlgorithm(hResidualGraph);
                    hBellmanFordAlgorithm.Execute(hNode.Value.Id);
                    if (hBellmanFordAlgorithm.HasNegativeCycles)
                    {
                        // Negativen Zyklus gefunden
                        hFoundNegativeCycle = true;

                        // ToDo Auf diesem Zyklus die maximale Kapazität ermitteln
                        var hEdgeHashesOfCycle  = hBellmanFordAlgorithm.CycleEdges;
                        var hMinCapacityInCycle = Double.PositiveInfinity;
                        foreach (var hEdgeInCycleHash in hEdgeHashesOfCycle)
                        {
                            var hEdgeCapcaityValue = hEdgeHashDictionary[hEdgeInCycleHash].GetWeightValue <CapacityWeighted>();
                            if (hEdgeCapcaityValue < hMinCapacityInCycle)
                            {
                                hMinCapacityInCycle = hEdgeCapcaityValue;
                            }
                        }

                        hTotalFlow += hMinCapacityInCycle;

                        // ToDo Fluss auf dem Originalen Graphen entsprechend anpassen (Orginial Kante, Nicht-Original Kante)
                        foreach (var hEdgeInCycleHash in hEdgeHashesOfCycle)
                        {
                            if (ResidualGraphGenerator.HinkantenEdgeHashes.Contains(hEdgeInCycleHash))
                            {
                                // Hinkante
                                // Diese Kante kann ich im Flussgraphen Dictionary direkt ansprechen da die Konten im Hash in der richtigen Reihenfolge stehen
                                hFlussGraphDictionary[hEdgeInCycleHash] += hMinCapacityInCycle;
                            }
                            else if (ResidualGraphGenerator.RueckKantenEdgeHashes.Contains(hEdgeInCycleHash))
                            {
                                // Bei der Breitensuche im Augmentieren Graphen wurde eine Rückkante verwendet.
                                // Diese Rückkante existiert so im originalen Graphen nicht weshalb auch der Hash-Value nicht passt.
                                // Dieser ist lediglich verdreht. Also wird der HashWert vorher noch gespiegelt um die ursprüngliche Kante zu identifizieren
                                var hHashValueOfOriginalEdge = HelpFunctions.InvertEdgeHash(hEdgeInCycleHash);
                                hFlussGraphDictionary[hHashValueOfOriginalEdge] -= hMinCapacityInCycle;
                            }
                        }


                        break;
                    }
                }
            }

            // Kosten des Flusses ermitteln
            var hFlowCost = 0.0;

            foreach (var hEdgeInFlow in hFlussGraphDictionary)
            {
                var hEdge = hGraphEdgeDictionary[hEdgeInFlow.Key];
                hFlowCost += hEdge.GetWeightValue <CostWeighted>() * hEdgeInFlow.Value;
            }

            Console.WriteLine("Kostenminimaler Fluss:\t" + hFlowCost);
        }
예제 #10
0
 public BalancedList(BalancedNode <T> rootNode)
 {
     this.rootNode = rootNode;
 }
예제 #11
0
 public void add(BalancedNode <T> leftNode, BalancedNode <T> rightNode)
 {
     addLeftNode(leftNode);
     addRightNode(rightNode);
 }
예제 #12
0
 public static BalancedList <T> createNewList(BalancedNode <T> node)
 {
     return(new BalancedList <T>(node));
 }
예제 #13
0
 private void setRootNode(BalancedNode <T> n)
 {
     this.rootNode = n;
 }
예제 #14
0
 private static void detachNode(BalancedNode <T> n)
 {
     n.leftBuddy  = null;
     n.rightBuddy = null;
 }
예제 #15
0
 public void setRightBuddy(BalancedNode <T> rightBuddy)
 {
     this.rightBuddy = rightBuddy;
 }
예제 #16
0
 public void setLeftBuddy(BalancedNode <T> leftBuddy)
 {
     this.leftBuddy = leftBuddy;
 }