示例#1
0
        /// <summary>
        /// Computes the maximum flow between <paramref name="src"/> and
        /// <paramref name="sink"/>
        /// </summary>
        /// <param name="src"></param>
        /// <param name="sink"></param>
        /// <returns></returns>
        public override double Compute(IVertex src, IVertex sink)
        {
            if (src == null)
            {
                throw new ArgumentNullException("src");
            }
            if (sink == null)
            {
                throw new ArgumentNullException("sink");
            }

            foreach (IVertex u in VisitedGraph.Vertices)
            {
                foreach (IEdge e in VisitedGraph.OutEdges(u))
                {
                    ResidualCapacities[e] = Capacities[e];
                }
            }

            Colors[sink] = GraphColor.Gray;
            while (Colors[sink] != GraphColor.White)
            {
                PredecessorRecorderVisitor vis = new PredecessorRecorderVisitor(
                    Predecessors
                    );
                VertexBuffer Q = new VertexBuffer();
                BreadthFirstSearchAlgorithm bfs = new BreadthFirstSearchAlgorithm(
                    ResidualGraph,
                    Q,
                    Colors
                    );
                bfs.RegisterPredecessorRecorderHandlers(vis);
                bfs.Compute(src);

                if (Colors[sink] != GraphColor.White)
                {
                    Augment(src, sink);
                }
            }             // while

            double flow = 0;

            foreach (IEdge e in VisitedGraph.OutEdges(src))
            {
                flow += (Capacities[e] - ResidualCapacities[e]);
            }

            return(flow);
        }
        /// <summary>
        /// Computes a set of eulerian trail, starting at <paramref name="s"/>
        /// that spans the entire graph.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method computes a set of eulerian trail starting at <paramref name="s"/>
        /// that spans the entire graph.The algorithm outline is as follows:
        /// </para>
        /// <para>
        /// The algorithms iterates throught the Eulerian circuit of the augmented
        /// graph (the augmented graph is the graph with additional edges to make
        /// the number of odd vertices even).
        /// </para>
        /// <para>
        /// If the current edge is not temporary, it is added to the current trail.
        /// </para>
        /// <para>
        /// If the current edge is temporary, the current trail is finished and
        /// added to the trail collection. The shortest path between the
        /// start vertex <paramref name="s"/> and the target vertex of the
        /// temporary edge is then used to start the new trail. This shortest
        /// path is computed using the <see cref="BreadthFirstSearchAlgorithm"/>.
        /// </para>
        /// </remarks>
        /// <param name="s">start vertex</param>
        /// <returns>eulerian trail set, all starting at s</returns>
        /// <exception cref="ArgumentNullException">s is a null reference.</exception>
        /// <exception cref="Exception">Eulerian trail not computed yet.</exception>
        public EdgeCollectionCollection Trails(IVertex s)
        {
            if (s == null)
            {
                throw new ArgumentNullException("s");
            }
            if (this.Circuit.Count == 0)
            {
                throw new Exception("Circuit is empty");
            }

            // find the first edge in the circuit.
            int i = 0;

            for (i = 0; i < this.Circuit.Count; ++i)
            {
                IEdge e = this.Circuit[i];
                if (TemporaryEdges.Contains(e))
                {
                    continue;
                }
                if (e.Source == s)
                {
                    break;
                }
            }
            if (i == this.Circuit.Count)
            {
                throw new Exception("Did not find vertex in eulerian trail?");
            }

            // create collections
            EdgeCollectionCollection    trails = new EdgeCollectionCollection();
            EdgeCollection              trail  = new EdgeCollection();
            BreadthFirstSearchAlgorithm bfs    =
                new BreadthFirstSearchAlgorithm(VisitedGraph);
            PredecessorRecorderVisitor vis = new PredecessorRecorderVisitor();

            bfs.RegisterPredecessorRecorderHandlers(vis);
            bfs.Compute(s);

            // go throught the edges and build the predecessor table.
            int start = i;

            for (; i < this.Circuit.Count; ++i)
            {
                IEdge e = this.Circuit[i];
                if (TemporaryEdges.Contains(e))
                {
                    // store previous trail and start new one.
                    if (trail.Count != 0)
                    {
                        trails.Add(trail);
                    }
                    // start new trail
                    // take the shortest path from the start vertex to
                    // the target vertex
                    trail = vis.Path(e.Target);
                }
                else
                {
                    trail.Add(e);
                }
            }

            // starting again on the circuit
            for (i = 0; i < start; ++i)
            {
                IEdge e = this.Circuit[i];
                if (TemporaryEdges.Contains(e))
                {
                    // store previous trail and start new one.
                    if (trail.Count != 0)
                    {
                        trails.Add(trail);
                    }
                    // start new trail
                    // take the shortest path from the start vertex to
                    // the target vertex
                    trail = vis.Path(e.Target);
                }
                else
                {
                    trail.Add(e);
                }
            }

            // adding the last element
            if (trail.Count != 0)
            {
                trails.Add(trail);
            }

            return(trails);
        }