예제 #1
0
        public void MaxFlowTwiceTest()
        {
            var fg = new FlowGraph(3);

            Assert.That(fg.AddEdge(0, 1, 1), Is.Zero);
            Assert.That(fg.AddEdge(0, 2, 1), Is.EqualTo(1));
            Assert.That(fg.AddEdge(1, 2, 1), Is.EqualTo(2));
            Assert.That(fg.MaxFlow(0, 2), Is.EqualTo(2));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 1, 1)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(0, 2, 1, 1)));
            Assert.That(fg.GetEdge(2), Is.EqualTo(new FlowGraph.Edge(1, 2, 1, 1)));

            fg.ChangeEdge(0, 100, 10);
            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 100, 10)));

            Assert.That(fg.MaxFlow(0, 2), Is.Zero);
            Assert.That(fg.MaxFlow(0, 1), Is.EqualTo(90));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 100, 100)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(0, 2, 1, 1)));
            Assert.That(fg.GetEdge(2), Is.EqualTo(new FlowGraph.Edge(1, 2, 1, 1)));

            Assert.That(fg.MaxFlow(2, 0), Is.EqualTo(2));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 100, 99)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(0, 2, 1, 0)));
            Assert.That(fg.GetEdge(2), Is.EqualTo(new FlowGraph.Edge(1, 2, 1, 0)));
        }
예제 #2
0
        static int[] FindMatching(bool[][] bipartiteGraph)
        {
            int numLeft  = bipartiteGraph.Length;
            int numRight = bipartiteGraph[0].Length;

            int[]     matching = new int[numLeft];
            FlowGraph graph    = ReadGraph(bipartiteGraph);

            MaxFlow(graph, 0, graph.Size() - 1);
            for (int i = 0; i < numLeft; i++)
            {
                foreach (int id in graph.GetIds(i + 1))
                {
                    Edge edge = graph.GetEdge(id);
                    if (edge.flow == 1)
                    {
                        matching[i] = edge.to - numLeft;
                        break;
                    }
                    matching[i] = -1;
                }
            }

            return(matching);
        }
예제 #3
0
        public void MinCostFlowSelfLoopTest()
        {
            var fg = new FlowGraph(3);

            Assert.That(fg.AddEdge(0, 0, 100, 123), Is.Zero);
            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 0, 100, 0, 123)));
        }
예제 #4
0
        public void MaxFlowMinCutTest()
        {
            var fg = new FlowGraph(3);

            Assert.That(fg.AddEdge(0, 1, 2), Is.Zero);
            Assert.That(fg.AddEdge(1, 2, 1), Is.EqualTo(1));
            Assert.That(fg.MaxFlow(0, 2), Is.EqualTo(1));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 2, 1)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(1, 2, 1, 1)));

            var minCut = fg.MinCut(0);

            Assert.That(minCut[0], Is.True);
            Assert.That(minCut[1], Is.True);
            Assert.That(minCut[2], Is.False);
        }
예제 #5
0
        public void ArgumentOutOfRangeExceptionInAddEdgeAndGetEdge([Values(-1, 3)] int v)
        {
            var fg = new FlowGraph(3);

            Assert.Throws <ArgumentOutOfRangeException>(() => fg.AddEdge(v, 1, 10));
            Assert.Throws <ArgumentOutOfRangeException>(() => fg.AddEdge(0, v, 10));
            Assert.Throws <ArgumentOutOfRangeException>(() => fg.GetEdge(v));
        }
예제 #6
0
        public void MaxFlowSimpleTest()
        {
            var fg = new FlowGraph(4);

            Assert.That(fg.AddEdge(0, 1, 1), Is.Zero);
            Assert.That(fg.AddEdge(0, 2, 1), Is.EqualTo(1));
            Assert.That(fg.AddEdge(1, 3, 1), Is.EqualTo(2));
            Assert.That(fg.AddEdge(2, 3, 1), Is.EqualTo(3));
            Assert.That(fg.AddEdge(1, 2, 1), Is.EqualTo(4));
            Assert.That(fg.MaxFlow(0, 3), Is.EqualTo(2));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 1, 1)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(0, 2, 1, 1)));
            Assert.That(fg.GetEdge(2), Is.EqualTo(new FlowGraph.Edge(1, 3, 1, 1)));
            Assert.That(fg.GetEdge(3), Is.EqualTo(new FlowGraph.Edge(2, 3, 1, 1)));
            Assert.That(fg.GetEdge(4), Is.EqualTo(new FlowGraph.Edge(1, 2, 1, 0)));
        }
예제 #7
0
        public void MinCostFlowSimpleTest()
        {
            var fg = new FlowGraph(4);

            fg.AddEdge(0, 1, 1, 1);
            fg.AddEdge(0, 2, 1, 1);
            fg.AddEdge(1, 3, 1, 1);
            fg.AddEdge(2, 3, 1, 1);
            fg.AddEdge(1, 2, 1, 1);
            var actual = fg.MinCostSlope(0, 3, 10).ToArray();

            Assert.That(actual[0], Is.EqualTo((0, 0)));
            Assert.That(actual[1], Is.EqualTo((2, 4)));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 1, 1, 1)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(0, 2, 1, 1, 1)));
            Assert.That(fg.GetEdge(2), Is.EqualTo(new FlowGraph.Edge(1, 3, 1, 1, 1)));
            Assert.That(fg.GetEdge(3), Is.EqualTo(new FlowGraph.Edge(2, 3, 1, 1, 1)));
            Assert.That(fg.GetEdge(4), Is.EqualTo(new FlowGraph.Edge(1, 2, 1, 0, 1)));
        }
예제 #8
0
        public void MaxFlowComplexTest()
        {
            var fg = new FlowGraph(2);

            Assert.That(fg.AddEdge(0, 1, 1), Is.Zero);
            Assert.That(fg.AddEdge(0, 1, 2), Is.EqualTo(1));
            Assert.That(fg.AddEdge(0, 1, 3), Is.EqualTo(2));
            Assert.That(fg.AddEdge(0, 1, 4), Is.EqualTo(3));
            Assert.That(fg.AddEdge(0, 1, 5), Is.EqualTo(4));
            Assert.That(fg.AddEdge(0, 0, 6), Is.EqualTo(5));
            Assert.That(fg.AddEdge(1, 1, 7), Is.EqualTo(6));
            Assert.That(fg.MaxFlow(0, 1), Is.EqualTo(15));

            Assert.That(fg.GetEdge(0), Is.EqualTo(new FlowGraph.Edge(0, 1, 1, 1)));
            Assert.That(fg.GetEdge(1), Is.EqualTo(new FlowGraph.Edge(0, 1, 2, 2)));
            Assert.That(fg.GetEdge(2), Is.EqualTo(new FlowGraph.Edge(0, 1, 3, 3)));
            Assert.That(fg.GetEdge(3), Is.EqualTo(new FlowGraph.Edge(0, 1, 4, 4)));
            Assert.That(fg.GetEdge(4), Is.EqualTo(new FlowGraph.Edge(0, 1, 5, 5)));

            var minCut = fg.MinCut(0);

            Assert.That(minCut[0], Is.True);
            Assert.That(minCut[1], Is.False);
        }
        public static FlowGraph <T> FordFulkerson <T>(this FlowGraph <T> graph)
        {
            if (graph.Edges.Where(e => !e.Capacity.HasValue).Any())
            {
                throw new ArgumentException("In dem Graphen muss für jede Kante eine Kapazität definiert sein.");
            }

            // Sicherstellen, dass der Fluss bei allen Kanten initialisiert ist.
            foreach (Edge <T> e in graph.Edges.Where(e => !e.Flow.HasValue))
            {
                e.Flow = 0;
            }

            // Eine Kopie des Graphens erstellen.
            FlowGraph <T> maxFlowGraph = graph.Copy();

            // Den Residualgraph erstellen
            FlowGraph <T> residualGraph = maxFlowGraph.GetResidualGraph();

            while (residualGraph.DepthFirstSearch(residualGraph.Source, residualGraph.Target, out List <Edge <T> > path))
            {
                int minAugmentingFlow = path.Select(e => Math.Abs(e.Flow.Value)).Min();

                foreach (Edge <T> edge in path)
                {
                    //Edge<T> edgeToModify = maxFlowGraph.Edges.Where(e => e.From.Equals(edge.From) && e.To.Equals(edge.To)).Single();
                    Edge <T> edgeToModify = maxFlowGraph.GetEdge(edge.From, edge.To);
                    if (edge.Flow.Value > 0)
                    {
                        edgeToModify.Flow += minAugmentingFlow;
                    }
                    else
                    {
                        edgeToModify.Flow -= minAugmentingFlow;
                    }
                    // edgeToModify.Flow += edge.Flow;
                }

                residualGraph = maxFlowGraph.GetResidualGraph();
            }

            return(maxFlowGraph);
        }
예제 #10
0
 static void MaxFlow(FlowGraph graph, int from, int to)
 {
     while (true)
     {
         bool foundPath = false;
         var  queue     = new Queue <int>();
         var  parentIds = new int[graph.Size()];
         for (int i = 0; i < parentIds.Length; i++)
         {
             parentIds[i] = -1; //unvisited nodes are -1
         }
         queue.Enqueue(0);
         //Breadth-first search, finding shortest path
         while (queue.Count != 0 && !foundPath)
         {
             int node = queue.Dequeue();
             var ids  = graph.GetIds(node); // all the edges from current node
             foreach (int id in ids)
             {
                 var edge = graph.GetEdge(id);
                 if (edge.flow < edge.capacity && parentIds[edge.to] == -1) // if there's capacity left and "edge pointing" vertice isn't visited
                 {
                     if (edge.to == edge.from)
                     {
                         continue;
                     }
                     parentIds[edge.to] = id;
                     if (edge.to == graph.Size() - 1) // we found path
                     {
                         foundPath = true;
                         break;
                     }
                     queue.Enqueue(edge.to);
                 }
             }
         }
         if (!foundPath)
         {
             break;
         }
         //find the value of the flow
         to = graph.Size() - 1;
         var minCap = -1;
         //calculate min capacity
         while (to != 0)
         {
             var id   = parentIds[to];
             var edge = graph.GetEdge(id);
             if (minCap == -1 || (edge.capacity - edge.flow) < minCap)
             {
                 minCap = edge.capacity - edge.flow;
             }
             to = edge.from;
         }
         to = graph.Size() - 1;
         //adding flow to edges
         while (to != 0)
         {
             var id   = parentIds[to];
             var edge = graph.GetEdge(id);
             graph.AddFlow(id, minCap);
             to = edge.from;
         }
     }
 }
예제 #11
0
        public void LoadFlowGraph_must_work()
        {
            string path = Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName, "TestFiles", "FlowGraph.txt");

            FlowGraph <string> graph = (FlowGraph <string>)GraphGenerator.LoadFromFile(path);

            // Die Vertices prüfen
            Assert.IsTrue(graph.HasEdge(new Vertex <string>("s"), new Vertex <string>("a")));
            Assert.IsTrue(graph.HasEdge(new Vertex <string>("s"), new Vertex <string>("b")));
            Assert.IsTrue(graph.HasEdge(new Vertex <string>("a"), new Vertex <string>("b")));
            Assert.IsTrue(graph.HasEdge(new Vertex <string>("a"), new Vertex <string>("c")));
            Assert.IsTrue(graph.HasEdge(new Vertex <string>("b"), new Vertex <string>("c")));
            Assert.IsTrue(graph.HasEdge(new Vertex <string>("b"), new Vertex <string>("d")));
            Assert.IsTrue(graph.HasEdge(new Vertex <string>("c"), new Vertex <string>("d")));
            Assert.IsTrue(graph.HasEdge(new Vertex <string>("c"), new Vertex <string>("t")));
            Assert.IsTrue(graph.HasEdge(new Vertex <string>("d"), new Vertex <string>("t")));

            // Die Kapzitäten und Flüsse prüfen.
            Assert.AreEqual(5, graph.GetEdge(new Vertex <string>("s"), new Vertex <string>("a")).Capacity);
            Assert.AreEqual(5, graph.GetEdge(new Vertex <string>("s"), new Vertex <string>("a")).Flow);

            Assert.AreEqual(7, graph.GetEdge(new Vertex <string>("s"), new Vertex <string>("b")).Capacity);
            Assert.AreEqual(3, graph.GetEdge(new Vertex <string>("s"), new Vertex <string>("b")).Flow);

            Assert.AreEqual(7, graph.GetEdge(new Vertex <string>("a"), new Vertex <string>("b")).Capacity);
            Assert.AreEqual(3, graph.GetEdge(new Vertex <string>("a"), new Vertex <string>("b")).Flow);

            Assert.AreEqual(4, graph.GetEdge(new Vertex <string>("a"), new Vertex <string>("c")).Capacity);
            Assert.AreEqual(2, graph.GetEdge(new Vertex <string>("a"), new Vertex <string>("c")).Flow);

            Assert.AreEqual(3, graph.GetEdge(new Vertex <string>("b"), new Vertex <string>("c")).Capacity);
            Assert.AreEqual(3, graph.GetEdge(new Vertex <string>("b"), new Vertex <string>("c")).Flow);

            Assert.AreEqual(3, graph.GetEdge(new Vertex <string>("b"), new Vertex <string>("d")).Capacity);
            Assert.AreEqual(3, graph.GetEdge(new Vertex <string>("b"), new Vertex <string>("d")).Flow);

            Assert.AreEqual(4, graph.GetEdge(new Vertex <string>("c"), new Vertex <string>("d")).Capacity);
            Assert.AreEqual(0, graph.GetEdge(new Vertex <string>("c"), new Vertex <string>("d")).Flow);

            Assert.AreEqual(5, graph.GetEdge(new Vertex <string>("c"), new Vertex <string>("t")).Capacity);
            Assert.AreEqual(5, graph.GetEdge(new Vertex <string>("c"), new Vertex <string>("t")).Flow);

            Assert.AreEqual(6, graph.GetEdge(new Vertex <string>("d"), new Vertex <string>("t")).Capacity);
            Assert.AreEqual(3, graph.GetEdge(new Vertex <string>("d"), new Vertex <string>("t")).Flow);
        }
예제 #12
0
        static int MaxFlow(FlowGraph graph, int from, int to)
        {
            int flow = 0;

            while (true)
            {
                bool foundPath = false;
                var  queue     = new Queue <int>();
                var  parentIds = new int[graph.Size()];
                for (int i = 0; i < parentIds.Length; i++)
                {
                    parentIds[i] = -1; //unvisited nodes are -1
                }
                queue.Enqueue(0);
                //bfs
                while (queue.Count != 0 && !foundPath)
                {
                    int node = queue.Dequeue();
                    var ids  = graph.GetIds(node); // all the edges from current node
                    foreach (int id in ids)
                    {
                        var edge = graph.GetEdge(id);
                        if (edge.flow < edge.capacity && parentIds[edge.to] == -1)
                        {
                            if (edge.to == edge.from)
                            {
                                continue;
                            }
                            parentIds[edge.to] = id;
                            if (edge.to == graph.Size() - 1) // we found path
                            {
                                foundPath = true;
                                break;
                            }
                            queue.Enqueue(edge.to);
                        }
                    }
                }
                if (!foundPath)
                {
                    break;
                }
                //find the value of the flow
                to = graph.Size() - 1;
                var minCap = -1;
                //calculate min capacity
                while (to != 0)
                {
                    var id   = parentIds[to];
                    var edge = graph.GetEdge(id);
                    if (minCap == -1 || (edge.capacity - edge.flow) < minCap)
                    {
                        minCap = edge.capacity - edge.flow;
                    }
                    to = edge.from;
                }
                to = graph.Size() - 1;
                //adding flow to edges
                while (to != 0)
                {
                    var id   = parentIds[to];
                    var edge = graph.GetEdge(id);
                    graph.AddFlow(id, minCap);
                    to = edge.from;
                }
            }
            //calculate the flow
            // to do that we only sum the flows of the start node
            foreach (int id in graph.GetIds(0))
            {
                var edge = graph.GetEdge(id);
                flow += edge.flow;
            }
            return(flow);
        }