예제 #1
0
        public void EdmondsKarpMaxFlow_NegativeCapacity_Throws()
        {
            const int source = 1;
            const int sink   = 4;

            var graph = new AdjacencyGraph <int, TaggedEdge <int, double> >();

            // TaggedEdge.Tag is the capacity of the edge
            graph.AddVerticesAndEdgeRange(new[]
            {
                new TaggedEdge <int, double>(1, 2, 3),
                new TaggedEdge <int, double>(1, 4, 4),
                new TaggedEdge <int, double>(2, 3, -1),
                new TaggedEdge <int, double>(3, 4, 1)
            });

            EdgeFactory <int, TaggedEdge <int, double> > edgeFactory = (sourceNode, targetNode) => new TaggedEdge <int, double>(sourceNode, targetNode, 0.0);
            var reverseEdgesAlgorithm = new ReversedEdgeAugmentorAlgorithm <int, TaggedEdge <int, double> >(graph, edgeFactory);

            reverseEdgesAlgorithm.AddReversedEdges();

            var algorithm = new EdmondsKarpMaximumFlowAlgorithm <int, TaggedEdge <int, double> >(graph, edge => edge.Tag, edgeFactory, reverseEdgesAlgorithm);

            Assert.Throws <NegativeCapacityException>(() => algorithm.Compute(source, sink));
        }
예제 #2
0
        /// <summary>
        /// Computes the Edmonds-Karp maximums flow
        /// for a graph with positive capacities and
        /// flows.
        /// </summary>
        /// <typeparam name="TVertex">The type of the vertex.</typeparam>
        /// <typeparam name="TEdge">The type of the edge.</typeparam>
        /// <param name="visitedGraph">The visited graph.</param>
        /// <param name="edgeCapacities">The edge capacities.</param>
        /// <param name="source">The source.</param>
        /// <param name="sink">The sink.</param>
        /// <param name="flowPredecessors">The flow predecessors.</param>
        /// <param name="edgeFactory">the edge factory</param>
        /// <returns></returns>
        public static double MaximumFlowEdmondsKarp <TVertex, TEdge>(
#if !NET20
            this
#endif
            IMutableVertexAndEdgeListGraph <TVertex, TEdge> visitedGraph,
            Func <TEdge, double> edgeCapacities,
            TVertex source,
            TVertex sink,
            out TryFunc <TVertex, TEdge> flowPredecessors,
            EdgeFactory <TVertex, TEdge> edgeFactory
            )
            where TEdge : IEdge <TVertex>
        {
            Contract.Requires(visitedGraph != null);
            Contract.Requires(edgeCapacities != null);
            Contract.Requires(source != null);
            Contract.Requires(sink != null);
            Contract.Requires(!source.Equals(sink));



            // compute maxflow
            var flow = new EdmondsKarpMaximumFlowAlgorithm <TVertex, TEdge>(
                visitedGraph,
                edgeCapacities,
                edgeFactory
                );

            flow.Compute(source, sink);
            flowPredecessors = flow.Predecessors.TryGetValue;
            return(flow.MaxFlow);
        }
예제 #3
0
		public EdmondsKarpMaximumFlowAlgorithm EdmundsKarp()
		{
			EdmondsKarpMaximumFlowAlgorithm maxFlow = new EdmondsKarpMaximumFlowAlgorithm(
				Graph, 
				Capacities, 
				ReversedEdges
				);
			return maxFlow;
		}
예제 #4
0
        private void InitializeGraph()
        {
            GenerateActivityGraph();

            _flowAgorithm =
                new EdmondsKarpMaximumFlowAlgorithm <int, Edge <int> >(
                    _graph,
                    CalculateActivitySuccessorCapacity,
                    CreateAdditionalEdgeFactory);
        }
예제 #5
0
        public static string Test()
        {
            ////////////////////////////////////////
            // test maximum flow algorith
            //////////////////////////////////////////
            var    g      = new BidirectionalGraph <string, Edge <string> >(true);
            string source = "A";
            string sink   = "G";

            //Vertices
            //////////////
            g.AddVertex("A"); g.AddVertex("B"); g.AddVertex("C"); g.AddVertex("D");
            g.AddVertex("E"); g.AddVertex("F"); g.AddVertex("G");

            //Edge
            ////////////
            var edgesList = new List <Edge <string> >();
            var ad        = new Edge <string>("A", "D"); g.AddEdge(ad); edgeCapacitiesDictionaryTest.Add(ad, 2);
            var ab        = new Edge <string>("A", "B"); g.AddEdge(ab); edgeCapacitiesDictionaryTest.Add(ab, 3);
            var bc        = new Edge <string>("B", "C"); g.AddEdge(bc); edgeCapacitiesDictionaryTest.Add(bc, 3);
            var ca        = new Edge <string>("C", "A"); g.AddEdge(ca); edgeCapacitiesDictionaryTest.Add(ca, 4);
            var cd        = new Edge <string>("C", "D"); g.AddEdge(cd); edgeCapacitiesDictionaryTest.Add(cd, 1);
            var de        = new Edge <string>("D", "E"); g.AddEdge(de); edgeCapacitiesDictionaryTest.Add(de, 7);
            var df        = new Edge <string>("D", "F"); g.AddEdge(df); edgeCapacitiesDictionaryTest.Add(df, 4);
            var eb        = new Edge <string>("E", "B"); g.AddEdge(eb); edgeCapacitiesDictionaryTest.Add(eb, 1);
            var ce        = new Edge <string>("C", "E"); g.AddEdge(ce); edgeCapacitiesDictionaryTest.Add(ce, 2);
            var eg        = new Edge <string>("E", "G"); g.AddEdge(eg); edgeCapacitiesDictionaryTest.Add(eg, 3);
            var fg        = new Edge <string>("F", "G"); g.AddEdge(fg); edgeCapacitiesDictionaryTest.Add(fg, 4);

            /////////////////////////////////////
            // creating the augmentor
            ////////////////////////////////////
            var reversedEdgeAugmentor = new ReversedEdgeAugmentorAlgorithm <string, Edge <string> >(g, MyEdgeFactoryTest);

            reversedEdgeAugmentor.AddReversedEdges();

            // (other option)                                                                           new PushRelabelMaximumFlowAlgorithm
            MaximumFlowAlgorithm <string, Edge <string> > algo = new EdmondsKarpMaximumFlowAlgorithm <string, Edge <string> >(g, /*e => 2*/ ComputeCapacityTest, reversedEdgeAugmentor.ReversedEdges);



            algo.Compute(source, sink);
            //algo.Compute();
            StringBuilder sb = new StringBuilder();

            sb.AppendLine(string.Format("MaxFlow: {0}", algo.MaxFlow));

            sb.AppendLine("Press <ENTER> to complete");
            return(sb.ToString());
        }
예제 #6
0
        public static double Get(AdjacencyGraph <string, EquatableTaggedEdge <string, double> > graph, string source, string sink)
        {
            // edgeFactory will be used to create the reversed edges to store residual capacities using the ReversedEdgeAugmentorAlgorithm-class.
            // The edgeFactory assigns a capacity of 0.0 for the new edges because the initial (residual) capacity must be 0.0.
            EdgeFactory <string, EquatableTaggedEdge <string, double> > edgeFactory = (sourceNode, targetNode) => new EquatableTaggedEdge <string, double>(sourceNode, targetNode, 0.0);
            var reverseEdgesAlgorithm = new ReversedEdgeAugmentorAlgorithm <string, EquatableTaggedEdge <string, double> >(graph, edgeFactory);

            reverseEdgesAlgorithm.AddReversedEdges();

            var algorithm = new EdmondsKarpMaximumFlowAlgorithm <string, EquatableTaggedEdge <string, double> >(graph, edge => edge.Tag, edgeFactory, reverseEdgesAlgorithm);

            algorithm.Compute(source, sink);
            return(algorithm.MaxFlow);
        }
예제 #7
0
        public void EdmondsKarpMaxFlow_WrongVertices_Throws()
        {
            var graph = new AdjacencyGraph <TestVertex, TaggedEdge <TestVertex, double> >();
            EdgeFactory <TestVertex, TaggedEdge <TestVertex, double> > edgeFactory = (source, target) => new TaggedEdge <TestVertex, double>(source, target, 0.0);
            var reverseEdgesAlgorithm = new ReversedEdgeAugmentorAlgorithm <TestVertex, TaggedEdge <TestVertex, double> >(graph, edgeFactory);

            reverseEdgesAlgorithm.AddReversedEdges();

            var algorithm = new EdmondsKarpMaximumFlowAlgorithm <TestVertex, TaggedEdge <TestVertex, double> >(graph, edge => edge.Tag, edgeFactory, reverseEdgesAlgorithm);

            var vertex1 = new TestVertex("1");
            var vertex2 = new TestVertex("2");

            Assert.Throws <InvalidOperationException>(() => algorithm.Compute());

            algorithm = new EdmondsKarpMaximumFlowAlgorithm <TestVertex, TaggedEdge <TestVertex, double> >(
                graph,
                edge => edge.Tag,
                edgeFactory,
                reverseEdgesAlgorithm)
            {
                Source = vertex1
            };
            Assert.Throws <InvalidOperationException>(() => algorithm.Compute());

            algorithm = new EdmondsKarpMaximumFlowAlgorithm <TestVertex, TaggedEdge <TestVertex, double> >(
                graph,
                edge => edge.Tag,
                edgeFactory,
                reverseEdgesAlgorithm)
            {
                Source = vertex1,
                Sink   = vertex2
            };
            Assert.Throws <VertexNotFoundException>(() => algorithm.Compute());

            algorithm = new EdmondsKarpMaximumFlowAlgorithm <TestVertex, TaggedEdge <TestVertex, double> >(
                graph,
                edge => edge.Tag,
                edgeFactory,
                reverseEdgesAlgorithm)
            {
                Source = vertex1,
                Sink   = vertex2
            };
            graph.AddVertex(vertex1);
            Assert.Throws <VertexNotFoundException>(() => algorithm.Compute());
        }
예제 #8
0
        public void NotReachableSink()
        {
            const string source = "A";
            const string sink   = "G";

            var graph = new AdjacencyGraph <string, TaggedEdge <string, double> >(true);

            graph.AddVertexRange(new[] { "A", "B", "C", "D", "E", "F", "G" });

            // TaggedEdge.Tag is the capacity of the edge
            graph.AddEdgeRange(new[]
            {
                new TaggedEdge <string, double>("A", "D", 3),
                new TaggedEdge <string, double>("A", "B", 3),
                new TaggedEdge <string, double>("B", "C", 4),
                new TaggedEdge <string, double>("C", "A", 3),
                new TaggedEdge <string, double>("C", "D", 1),
                new TaggedEdge <string, double>("D", "E", 2),
                new TaggedEdge <string, double>("D", "F", 6),
                new TaggedEdge <string, double>("E", "B", 1),
                new TaggedEdge <string, double>("C", "E", 2)
            });

            // edgeFactory will be used to create the reversed edges to store residual capacities using the ReversedEdgeAugmentorAlgorithm-class.
            // The edgeFactory assigns a capacity of 0.0 for the new edges because the initial (residual) capacity must be 0.0.
            EdgeFactory <string, TaggedEdge <string, double> > edgeFactory = (sourceNode, targetNode) => new TaggedEdge <string, double>(sourceNode, targetNode, 0.0);
            var reverseEdgesAlgorithm = new ReversedEdgeAugmentorAlgorithm <string, TaggedEdge <string, double> >(graph, edgeFactory);

            reverseEdgesAlgorithm.AddReversedEdges();

            var algorithm = new EdmondsKarpMaximumFlowAlgorithm <string, TaggedEdge <string, double> >(graph, edge => edge.Tag, edgeFactory, reverseEdgesAlgorithm);

            algorithm.Compute(source, sink);

            Assert.AreEqual(source, algorithm.Source);
            Assert.AreEqual(sink, algorithm.Sink);
            Assert.AreEqual(graph.VertexCount, algorithm.VerticesColors.Count);
            foreach (KeyValuePair <string, GraphColor> pair in algorithm.VerticesColors)
            {
                Assert.AreEqual(
                    pair.Key == sink ? GraphColor.White : GraphColor.Black,
                    pair.Value);
            }
            Assert.AreEqual(0, algorithm.MaxFlow);
        }
예제 #9
0
        public void EdmondsKarpMaxFlow_Throws()
        {
            var graph = new AdjacencyGraph <TestVertex, TaggedEdge <TestVertex, double> >();
            EdgeFactory <TestVertex, TaggedEdge <TestVertex, double> > edgeFactory = (source, target) => new TaggedEdge <TestVertex, double>(source, target, 0.0);
            var reverseEdgesAlgorithm = new ReversedEdgeAugmentorAlgorithm <TestVertex, TaggedEdge <TestVertex, double> >(graph, edgeFactory);

            reverseEdgesAlgorithm.AddReversedEdges();

            var algorithm = new EdmondsKarpMaximumFlowAlgorithm <TestVertex, TaggedEdge <TestVertex, double> >(graph, edge => edge.Tag, edgeFactory, reverseEdgesAlgorithm);

            var vertex = new TestVertex("1");

            // ReSharper disable AssignNullToNotNullAttribute
            Assert.Throws <ArgumentNullException>(() => algorithm.Compute(null, vertex));
            Assert.Throws <ArgumentNullException>(() => algorithm.Compute(vertex, null));
            Assert.Throws <ArgumentNullException>(() => algorithm.Compute(null, null));
            // ReSharper restore AssignNullToNotNullAttribute
        }
        public void GetVertexColor_Throws()
        {
            var graph = new AdjacencyGraph <int, Edge <int> >();

            graph.AddVertexRange(new[] { 0, 1 });

            Func <Edge <int>, double>      capacities  = edge => 1.0;
            EdgeFactory <int, Edge <int> > edgeFactory = (source, target) => new Edge <int>(source, target);
            var reverseEdgesAlgorithm = new ReversedEdgeAugmentorAlgorithm <int, Edge <int> >(graph, edgeFactory);

            reverseEdgesAlgorithm.AddReversedEdges();

            var algorithm = new EdmondsKarpMaximumFlowAlgorithm <int, Edge <int> >(graph, capacities, edgeFactory, reverseEdgesAlgorithm);

            algorithm.Compute(0, 1);

            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
            Assert.Throws <VertexNotFoundException>(() => algorithm.GetVertexColor(2));
        }
예제 #11
0
        public void GetVertexColor()
        {
            var graph = new AdjacencyGraph <int, Edge <int> >();

            graph.AddVerticesAndEdge(new Edge <int>(1, 2));
            graph.AddVertex(3);

            Func <Edge <int>, double>      capacities  = edge => 1.0;
            EdgeFactory <int, Edge <int> > edgeFactory = (source, target) => new Edge <int>(source, target);
            var reverseEdgesAlgorithm = new ReversedEdgeAugmentorAlgorithm <int, Edge <int> >(graph, edgeFactory);

            reverseEdgesAlgorithm.AddReversedEdges();

            var algorithm = new EdmondsKarpMaximumFlowAlgorithm <int, Edge <int> >(graph, capacities, edgeFactory, reverseEdgesAlgorithm);

            algorithm.Compute(1, 2);

            Assert.AreEqual(GraphColor.Black, algorithm.GetVertexColor(1));
            Assert.AreEqual(GraphColor.White, algorithm.GetVertexColor(2));
            Assert.AreEqual(GraphColor.White, algorithm.GetVertexColor(3));
        }
예제 #12
0
        public static string Main(BidirectionalGraph <Word, Edge <Word> > g)
        {
            gr = g;
            foreach (var item in g.Edges)
            {
                //edgeCapacitiesDictionary.Add(item, 0);
            }
            var reversedEdgeAugmentor = new ReversedEdgeAugmentorAlgorithm <Word, Edge <Word> >(g, MyEdgeFactory);

            reversedEdgeAugmentor.AddReversedEdges();

            //p.;

            // (other option) new PushRelabelMaximumFlowAlgorithm
            MaximumFlowAlgorithm <Word, Edge <Word> > algo = new EdmondsKarpMaximumFlowAlgorithm <Word, Edge <Word> >(g, ComputeCapacity, reversedEdgeAugmentor.ReversedEdges);

            Dictionary <Edge <Word>, double> d = new Dictionary <Edge <Word>, double>();

            foreach (var item in g.Edges)
            {
                algo = new EdmondsKarpMaximumFlowAlgorithm <Word, Edge <Word> >(g, ComputeCapacity, reversedEdgeAugmentor.ReversedEdges);
                double value = algo.Compute(item.Source, item.Target);

                d.Add(item, value);
            }

            //algo.Compute();
            //algo.Compute(source, sink);


            //return algo.MaxFlow;

            StringBuilder sb = new StringBuilder();

            foreach (var item in d)
            {
                sb.AppendLine(item.ToString());
            }
            return(sb.ToString());
        }
예제 #13
0
        public static EdmondsKarpMaximumFlowAlgorithm <T, Edge <T> > CreateAlgorithmAndMaybeDoComputation <T>(
            [NotNull] ContractScenario <T> scenario)
        {
            var graph = new AdjacencyGraph <T, Edge <T> >();

            graph.AddVerticesAndEdgeRange(scenario.EdgesInGraph.Select(e => new Edge <T>(e.Source, e.Target)));
            graph.AddVertexRange(scenario.SingleVerticesInGraph);

            double Capacities(Edge <T> edge) => 1.0;
            Edge <T> EdgeFactory(T source, T target) => new Edge <T>(source, target);

            var reverseEdgesAlgorithm = new ReversedEdgeAugmentorAlgorithm <T, Edge <T> >(graph, EdgeFactory);

            reverseEdgesAlgorithm.AddReversedEdges();

            var algorithm = new EdmondsKarpMaximumFlowAlgorithm <T, Edge <T> >(graph, Capacities, EdgeFactory, reverseEdgesAlgorithm);

            if (scenario.DoComputation)
            {
                algorithm.Compute(scenario.Root, scenario.AccessibleVerticesFromRoot.First());
            }
            return(algorithm);
        }
        /// <inheritdoc />
        protected override void InternalCompute()
        {
            ICancelManager cancelManager = Services.CancelManager;

            BipartiteToMaximumFlowGraphAugmentorAlgorithm <TVertex, TEdge> augmentor = null;
            ReversedEdgeAugmentorAlgorithm <TVertex, TEdge> reverser = null;

            try
            {
                if (cancelManager.IsCancelling)
                {
                    return;
                }

                // Augmenting the graph
                augmentor = new BipartiteToMaximumFlowGraphAugmentorAlgorithm <TVertex, TEdge>(
                    this,
                    VisitedGraph,
                    SourceToVertices,
                    VerticesToSink,
                    VertexFactory,
                    EdgeFactory);
                augmentor.Compute();

                if (cancelManager.IsCancelling)
                {
                    return;
                }

                // Adding reverse edges
                reverser = new ReversedEdgeAugmentorAlgorithm <TVertex, TEdge>(
                    VisitedGraph,
                    EdgeFactory);
                reverser.AddReversedEdges();

                if (cancelManager.IsCancelling)
                {
                    return;
                }

                // Compute maximum flow
                var flow = new EdmondsKarpMaximumFlowAlgorithm <TVertex, TEdge>(
                    this,
                    VisitedGraph,
                    edge => 1.0,
                    EdgeFactory,
                    reverser);

                flow.Compute(augmentor.SuperSource, augmentor.SuperSink);

                if (cancelManager.IsCancelling)
                {
                    return;
                }

                foreach (TEdge edge in VisitedGraph.Edges)
                {
                    if (Math.Abs(flow.ResidualCapacities[edge]) < float.Epsilon)
                    {
                        if (edge.Source.Equals(augmentor.SuperSource) ||
                            edge.Source.Equals(augmentor.SuperSink) ||
                            edge.Target.Equals(augmentor.SuperSource) ||
                            edge.Target.Equals(augmentor.SuperSink))
                        {
                            // Skip all edges that connect to SuperSource or SuperSink
                            continue;
                        }

                        _matchedEdges.Add(edge);
                    }
                }
            }
            finally
            {
                if (reverser != null && reverser.Augmented)
                {
                    reverser.RemoveReversedEdges();
                }
                if (augmentor != null && augmentor.Augmented)
                {
                    augmentor.Rollback();
                }
            }
        }
예제 #15
0
        protected override void InternalCompute()
        {
            var cancelManager = this.Services.CancelManager;

            this.MatchedEdges.Clear();

            BipartiteToMaximumFlowGraphAugmentorAlgorithm <TVertex, TEdge> augmentor = null;
            ReversedEdgeAugmentorAlgorithm <TVertex, TEdge> reverser = null;

            try
            {
                if (cancelManager.IsCancelling)
                {
                    return;
                }


                //augmenting graph
                augmentor = new BipartiteToMaximumFlowGraphAugmentorAlgorithm <TVertex, TEdge>(
                    this,
                    this.VisitedGraph,
                    this.VertexSetA,
                    this.VertexSetB,
                    this.VertexFactory,
                    this.EdgeFactory);
                augmentor.Compute();

                if (cancelManager.IsCancelling)
                {
                    return;
                }

                //adding reverse edges
                reverser = new ReversedEdgeAugmentorAlgorithm <TVertex, TEdge>(
                    this,
                    this.VisitedGraph,
                    this.EdgeFactory
                    );
                reverser.AddReversedEdges();
                if (cancelManager.IsCancelling)
                {
                    return;
                }


                // compute maxflow
                var flow = new EdmondsKarpMaximumFlowAlgorithm <TVertex, TEdge>(
                    this,
                    this.VisitedGraph,
                    e => 1,
                    this.EdgeFactory
                    );

                flow.Compute(augmentor.SuperSource, augmentor.SuperSink);

                if (cancelManager.IsCancelling)
                {
                    return;
                }



                foreach (var edge in this.VisitedGraph.Edges)
                {
                    if (flow.ResidualCapacities[edge] == 0)
                    {
                        if (edge.Source.Equals(augmentor.SuperSource) ||
                            edge.Source.Equals(augmentor.SuperSource) ||
                            edge.Target.Equals(augmentor.SuperSink) ||
                            edge.Target.Equals(augmentor.SuperSink))
                        {
                            //Skip all edges that connect to SuperSource or SuperSink
                            continue;
                        }

                        this.MatchedEdges.Add(edge);
                    }
                }
            }
            finally
            {
                if (reverser != null && reverser.Augmented)
                {
                    reverser.RemoveReversedEdges();
                    reverser = null;
                }
                if (augmentor != null && augmentor.Augmented)
                {
                    augmentor.Rollback();
                    augmentor = null;
                }
            }
        }
예제 #16
0
        public void Constructor()
        {
            var graph = new AdjacencyGraph <int, Edge <int> >();
            Func <Edge <int>, double>      capacities  = edge => 1.0;
            EdgeFactory <int, Edge <int> > edgeFactory = (source, target) => new Edge <int>(source, target);
            var reverseEdgesAlgorithm = new ReversedEdgeAugmentorAlgorithm <int, Edge <int> >(graph, edgeFactory);

            var algorithm = new EdmondsKarpMaximumFlowAlgorithm <int, Edge <int> >(
                graph,
                capacities,
                edgeFactory,
                reverseEdgesAlgorithm);

            AssertAlgorithmProperties(
                algorithm,
                graph,
                capacities,
                edgeFactory);

            algorithm = new EdmondsKarpMaximumFlowAlgorithm <int, Edge <int> >(
                null,
                graph,
                capacities,
                edgeFactory,
                reverseEdgesAlgorithm);
            AssertAlgorithmProperties(
                algorithm,
                graph,
                capacities,
                edgeFactory);

            #region Local function

            void AssertAlgorithmProperties <TVertex, TEdge>(
                EdmondsKarpMaximumFlowAlgorithm <TVertex, TEdge> algo,
                IMutableVertexAndEdgeListGraph <TVertex, TEdge> g,
                Func <TEdge, double> c,
                EdgeFactory <int, Edge <int> > eFactory)
                where TEdge : IEdge <TVertex>
            {
                AssertAlgorithmState(algo, g);
                CollectionAssert.IsEmpty(algo.Predecessors);
                Assert.AreSame(c, algo.Capacities);
                CollectionAssert.IsEmpty(algo.ResidualCapacities);
                if (eFactory is null)
                {
                    Assert.IsNotNull(algo.EdgeFactory);
                }
                else
                {
                    Assert.AreSame(eFactory, algo.EdgeFactory);
                }
                CollectionAssert.IsEmpty(algo.ReversedEdges);
                Assert.AreEqual(default(TVertex), algo.Source);
                Assert.AreEqual(default(TVertex), algo.Sink);
                Assert.AreEqual(0.0, algo.MaxFlow);
                CollectionAssert.IsEmpty(algo.VerticesColors);
            }

            #endregion
        }
예제 #17
0
        protected override void InternalCompute()
        {
            this.matchedEdges.Clear();
            AllVerticesGraphAugmentorAlgorithm <TVertex, TEdge> augmentor = null;
            ReversedEdgeAugmentorAlgorithm <TVertex, TEdge>     reverser  = null;

            try
            {
                if (this.IsAborting)
                {
                    return;
                }

                //augmenting graph
                augmentor = new AllVerticesGraphAugmentorAlgorithm <TVertex, TEdge>(
                    this.VisitedGraph,
                    this.VertexFactory,
                    this.EdgeFactory);
                augmentor.Compute();
                if (this.IsAborting)
                {
                    return;
                }


                // adding reverse edges
                reverser = new ReversedEdgeAugmentorAlgorithm <TVertex, TEdge>(
                    this.VisitedGraph,
                    this.EdgeFactory
                    );
                reverser.AddReversedEdges();
                if (this.IsAborting)
                {
                    return;
                }


                // compute maxflow
                EdmondsKarpMaximumFlowAlgorithm <TVertex, TEdge> flow = new EdmondsKarpMaximumFlowAlgorithm <TVertex, TEdge>(
                    this.VisitedGraph,
                    AlgoUtility.ConstantCapacities(this.VisitedGraph, 1),
                    reverser.ReversedEdges
                    );
                flow.Compute(augmentor.SuperSource, augmentor.SuperSink);
                if (this.IsAborting)
                {
                    return;
                }


                foreach (TEdge edge in this.VisitedGraph.Edges)
                {
                    if (this.IsAborting)
                    {
                        return;
                    }

                    if (flow.ResidualCapacities[edge] == 0)
                    {
                        this.matchedEdges.Add(edge);
                    }
                }
            }
            finally
            {
                if (reverser != null && reverser.Augmented)
                {
                    reverser.RemoveReversedEdges();
                    reverser = null;
                }
                if (augmentor != null && augmentor.Augmented)
                {
                    augmentor.Rollback();
                    augmentor = null;
                }
            }
        }
예제 #18
0
        public void SimpleFlow()
        {
            const string source = "A";
            const string sink   = "G";

            var graph = new AdjacencyGraph <string, EquatableTaggedEdge <string, double> >(true);

            graph.AddVertexRange(new[] { "A", "B", "C", "D", "E", "F", "G" });

            // TaggedEdge.Tag is the capacity of the edge
            graph.AddEdgeRange(new[]
            {
                new EquatableTaggedEdge <string, double>("A", "D", 3),
                new EquatableTaggedEdge <string, double>("A", "B", 3),
                new EquatableTaggedEdge <string, double>("B", "C", 4),
                new EquatableTaggedEdge <string, double>("C", "A", 3),
                new EquatableTaggedEdge <string, double>("C", "D", 1),
                new EquatableTaggedEdge <string, double>("D", "E", 2),
                new EquatableTaggedEdge <string, double>("D", "F", 6),
                new EquatableTaggedEdge <string, double>("E", "B", 1),
                new EquatableTaggedEdge <string, double>("C", "E", 2),
                new EquatableTaggedEdge <string, double>("E", "G", 1),
                new EquatableTaggedEdge <string, double>("F", "G", 9)
            });

            // edgeFactory will be used to create the reversed edges to store residual capacities using the ReversedEdgeAugmentorAlgorithm-class.
            // The edgeFactory assigns a capacity of 0.0 for the new edges because the initial (residual) capacity must be 0.0.
            EdgeFactory <string, EquatableTaggedEdge <string, double> > edgeFactory = (sourceNode, targetNode) => new EquatableTaggedEdge <string, double>(sourceNode, targetNode, 0.0);
            var reverseEdgesAlgorithm = new ReversedEdgeAugmentorAlgorithm <string, EquatableTaggedEdge <string, double> >(graph, edgeFactory);

            reverseEdgesAlgorithm.AddReversedEdges();

            var algorithm = new EdmondsKarpMaximumFlowAlgorithm <string, EquatableTaggedEdge <string, double> >(graph, edge => edge.Tag, edgeFactory, reverseEdgesAlgorithm);

            algorithm.Compute(source, sink);

            Assert.AreEqual(source, algorithm.Source);
            Assert.AreEqual(sink, algorithm.Sink);
            Assert.AreEqual(5, algorithm.MaxFlow);
            CheckReversedEdges();
            CheckPredecessors();
            CheckResidualCapacities();

            #region Local function

            void CheckReversedEdges()
            {
                Assert.IsTrue(algorithm.ReversedEdges.Count % 2 == 0);
                foreach (var pair in algorithm.ReversedEdges)
                {
                    Assert.AreEqual(pair.Key.Source, pair.Value.Target);
                    Assert.AreEqual(pair.Key.Target, pair.Value.Source);
                }
            }

            void CheckPredecessors()
            {
                Assert.AreEqual(graph.VertexCount - 1, algorithm.Predecessors.Count);
                CollectionAssert.AreEquivalent(
                    new Dictionary <string, EquatableTaggedEdge <string, double> >
                {
                    ["B"] = new EquatableTaggedEdge <string, double>("A", "B", 3),
                    ["C"] = new EquatableTaggedEdge <string, double>("B", "C", 4),
                    ["D"] = new EquatableTaggedEdge <string, double>("E", "D", 0),
                    ["E"] = new EquatableTaggedEdge <string, double>("C", "E", 2),
                    ["F"] = new EquatableTaggedEdge <string, double>("D", "F", 6),
                    ["G"] = new EquatableTaggedEdge <string, double>("F", "G", 9),
                },
                    algorithm.Predecessors);
            }

            void CheckResidualCapacities()
            {
                Assert.AreEqual(graph.EdgeCount, algorithm.ResidualCapacities.Count);
                CollectionAssert.AreEquivalent(
                    new Dictionary <EquatableTaggedEdge <string, double>, double>
                {
                    [new EquatableTaggedEdge <string, double>("A", "B", 3)] = 1,
                    [new EquatableTaggedEdge <string, double>("A", "C", 0)] = 0,
                    [new EquatableTaggedEdge <string, double>("A", "D", 3)] = 0,
                    [new EquatableTaggedEdge <string, double>("B", "A", 0)] = 2,
                    [new EquatableTaggedEdge <string, double>("B", "C", 4)] = 2,
                    [new EquatableTaggedEdge <string, double>("B", "E", 0)] = 0,
                    [new EquatableTaggedEdge <string, double>("C", "A", 3)] = 3,
                    [new EquatableTaggedEdge <string, double>("C", "B", 0)] = 2,
                    [new EquatableTaggedEdge <string, double>("C", "D", 1)] = 0,
                    [new EquatableTaggedEdge <string, double>("C", "E", 2)] = 1,
                    [new EquatableTaggedEdge <string, double>("D", "A", 0)] = 3,
                    [new EquatableTaggedEdge <string, double>("D", "C", 0)] = 1,
                    [new EquatableTaggedEdge <string, double>("D", "E", 2)] = 2,
                    [new EquatableTaggedEdge <string, double>("D", "F", 6)] = 2,
                    [new EquatableTaggedEdge <string, double>("E", "B", 1)] = 1,
                    [new EquatableTaggedEdge <string, double>("E", "C", 0)] = 1,
                    [new EquatableTaggedEdge <string, double>("E", "D", 0)] = 0,
                    [new EquatableTaggedEdge <string, double>("E", "G", 1)] = 0,
                    [new EquatableTaggedEdge <string, double>("F", "D", 0)] = 4,
                    [new EquatableTaggedEdge <string, double>("F", "G", 9)] = 5,
                    [new EquatableTaggedEdge <string, double>("G", "E", 0)] = 1,
                    [new EquatableTaggedEdge <string, double>("G", "F", 0)] = 4,
                },
                    algorithm.ResidualCapacities);
            }

            #endregion
        }