예제 #1
0
        /// <summary>
        /// Used internally
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        public void FinishVertex(Object sender, VertexEventArgs args)
        {
            IVertex v = args.Vertex;

            foreach (IEdge e in VisitedGraph.OutEdges(v))
            {
                IVertex w = e.Target;

                if (Components[w] == int.MaxValue)
                {
                    Roots[v] = MinDiscoverTime(Roots[v], Roots[w]);
                }
            }

            if (Roots[v] == v)
            {
                IVertex w = null;
                do
                {
                    w = (IVertex)m_Stack.Peek();
                    m_Stack.Pop();
                    Components[w] = m_Count;
                }while (w != v);
                ++m_Count;
            }
        }
        /// <inheritdoc />
        protected override void InternalCompute()
        {
            while (_heap.Count != 0)
            {
                ThrowIfCancellationRequested();

                TVertex vertex = _heap.Dequeue();
                if (InDegrees[vertex] != 0)
                {
                    throw new NonAcyclicGraphException();
                }

                _sortedVertices.Add(vertex);
                OnVertexAdded(vertex);

                // Update the count of its adjacent vertices
                foreach (TEdge edge in VisitedGraph.OutEdges(vertex))
                {
                    --InDegrees[edge.Target];

                    Debug.Assert(InDegrees[edge.Target] >= 0);

                    _heap.Update(edge.Target);
                }
            }

            SortedVertices = _sortedVertices.ToArray();
        }
        /// <summary>
        /// Execute the EDFS starting with the vertex s
        /// </summary>
        /// <param name="v">Starting vertex</param>
        public void Compute(IVertex v)
        {
            if (v == null)
            {
                throw new ArgumentNullException("entry point");
            }

            Initialize();

            // start whith him:
            OnStartVertex(v);

            // process each out edge of v
            foreach (IEdge e in VisitedGraph.OutEdges(v))
            {
                if (EdgeColors[e] == GraphColor.White)
                {
                    OnStartEdge(e);
                    Visit(e, 0);
                }
            }

            // process the rest of the graph edges
            foreach (IEdge e in VisitedGraph.Edges)
            {
                if (EdgeColors[e] == GraphColor.White)
                {
                    OnStartEdge(e);
                    Visit(e, 0);
                }
            }
        }
        private void ComputeNoInit([NotNull] TVertex root)
        {
            IEnumerable <TVertex> orderedVertices = VisitedGraph.TopologicalSort();

            OnDiscoverVertex(root);
            foreach (TVertex vertex in orderedVertices)
            {
                OnStartVertex(vertex);
                OnExamineVertex(vertex);
                foreach (TEdge edge in VisitedGraph.OutEdges(vertex))
                {
                    OnExamineEdge(edge);
                    OnDiscoverVertex(edge.Target);

                    bool decreased = Relax(edge);
                    if (decreased)
                    {
                        OnTreeEdge(edge);
                    }
                    else
                    {
                        OnEdgeNotRelaxed(edge);
                    }
                }
                OnFinishVertex(vertex);
            }
        }
예제 #5
0
        private void InitAlgorithm()
        {
            vertices = new LinLogVertex[VisitedGraph.VertexCount];

            var vertexMap = new Dictionary <TVertex, LinLogVertex>();

            //vertexek indexelése
            int i = 0;

            foreach (TVertex v in VisitedGraph.Vertices)
            {
                vertices[i] = new LinLogVertex
                {
                    Index           = i,
                    OriginalVertex  = v,
                    Attractions     = new LinLogEdge[VisitedGraph.Degree(v)],
                    RepulsionWeight = 0,
                    Position        = VertexPositions[v]
                };
                vertexMap[v] = vertices[i];
                i++;
            }

            //minden vertex-hez felépíti az attractionWeights, attractionIndexes,
            //és a repulsionWeights struktúrát, valamint átmásolja a pozícióját a VertexPositions-ból
            foreach (var v in vertices)
            {
                int attrIndex = 0;
                foreach (var e in VisitedGraph.InEdges(v.OriginalVertex))
                {
                    double weight = e is WeightedEdge <TVertex>?((e as WeightedEdge <TVertex>).Weight) : 1;
                    v.Attractions[attrIndex] = new LinLogEdge
                    {
                        Target           = vertexMap[e.Source],
                        AttractionWeight = weight
                    };
                    //TODO look at this line below
                    //v.RepulsionWeight += weight;
                    v.RepulsionWeight += 1;
                    attrIndex++;
                }

                foreach (var e in VisitedGraph.OutEdges(v.OriginalVertex))
                {
                    double weight = e is WeightedEdge <TVertex>?((e as WeightedEdge <TVertex>).Weight) : 1;
                    v.Attractions[attrIndex] = new LinLogEdge
                    {
                        Target           = vertexMap[e.Target],
                        AttractionWeight = weight
                    };
                    //v.RepulsionWeight += weight;
                    v.RepulsionWeight += 1;
                    attrIndex++;
                }

                v.RepulsionWeight = Math.Max(v.RepulsionWeight, Parameters.gravitationMultiplier);
            }

            repulsionMultiplier = ComputeRepulsionMultiplier();
        }
예제 #6
0
        internal void ComputeNoInit(IVertex s)
        {
            VertexCollection         orderedVertices = new VertexCollection();
            TopologicalSortAlgorithm topoSorter      = new TopologicalSortAlgorithm(VisitedGraph, orderedVertices);

            topoSorter.Compute();

            OnDiscoverVertex(s);

            foreach (IVertex v in orderedVertices)
            {
                OnExamineVertex(v);

                foreach (IEdge e in VisitedGraph.OutEdges(v))
                {
                    OnDiscoverVertex(e.Target);
                    bool decreased = Relax(e);
                    if (decreased)
                    {
                        OnEdgeRelaxed(e);
                    }
                    else
                    {
                        OnEdgeNotRelaxed(e);
                    }
                }
                OnFinishVertex(v);
            }
        }
        private void FirstWalk(TVertex v)
        {
            var data = datas[v];

            visitedVertices.Add(v);
            data.d = 0;

            float s = 0;

            foreach (var edge in VisitedGraph.OutEdges(v))
            {
                var otherVertex = edge.Target;
                var otherData   = datas[otherVertex];

                if (!visitedVertices.Contains(otherVertex))
                {
                    FirstWalk(otherVertex);
                    data.d      = Math.Max(data.d, otherData.r);
                    otherData.a = (float)Math.Atan(((float)otherData.r) / (data.d + otherData.r));
                    s          += otherData.a;
                }
            }


            AdjustChildren(v, data, s);
            SetRadius(v, data);
        }
        //=======================================================================
        // The main purpose of this routine is to set distance[v]
        // to the smallest value allowed by the valid labeling constraints,
        // which are:
        // distance[t] = 0
        // distance[u] <= distance[v] + 1   for every residual edge (u,v)
        //
        private int RelabelDistance(IVertex u)
        {
            int minEdges = 0;

            workSinceLastUpdate += beta;

            int minDistance = VisitedGraph.VerticesCount;

            distances[u] = minDistance;

            // Examine the residual out-edges of vertex i, choosing the
            // edge whose target vertex has the minimal distance.
            for (int ai = 0; ai < VisitedGraph.OutDegree(u); ai++)
            {
                ++workSinceLastUpdate;
                IEdge   a = VisitedGraph.OutEdges(u)[ai];
                IVertex v = a.Target;
                if (IsResidualEdge(a) && distances[v] < minDistance)
                {
                    minDistance = distances[v];
                    minEdges    = ai;
                }
            }
            ++minDistance;

            if (minDistance < n)
            {
                distances[u] = minDistance;                             // this is the main action
                current[u]   = minEdges;
                maxDistance  = Math.Max(minDistance, maxDistance);
            }
            return(minDistance);
        }
예제 #9
0
        private void OnVertexFinished([NotNull] TVertex vertex)
        {
            foreach (TEdge edge in VisitedGraph.OutEdges(vertex))
            {
                TVertex target = edge.Target;
                if (Components[target] == int.MaxValue)
                {
                    Roots[vertex] = MinDiscoverTime(Roots[vertex], Roots[target]);
                }
            }

            if (Roots[vertex].Equals(vertex))
            {
                TVertex w;
                do
                {
                    w             = _stack.Pop();
                    Components[w] = ComponentCount;

                    ComponentsPerStep.Add(ComponentCount);
                    VerticesPerStep.Add(w);
                    ++Steps;
                }while (!w.Equals(vertex));

                ++ComponentCount;
            }
        }
        private bool FindAdjacentOddVertex(
            TVertex u,
            ICollection <TVertex> oddVertices,
            EdgeFactory <TVertex, TEdge> edgeFactory,
            out bool foundAdjacent)
        {
            bool found = false;

            foundAdjacent = false;
            foreach (TEdge edge in VisitedGraph.OutEdges(u))
            {
                TVertex v = edge.Target;
                if (!EqualityComparer <TVertex> .Default.Equals(v, u) && oddVertices.Contains(v))
                {
                    foundAdjacent = true;
                    // Check that v does not have an out-edge towards u
                    if (HasEdgeToward(u, v))
                    {
                        continue;
                    }

                    // Add temporary edge
                    AddTemporaryEdge(u, v, oddVertices, edgeFactory);

                    // Set u to null
                    found = true;
                    break;
                }
            }

            return(found);
        }
예제 #11
0
        private bool FindAdjacentOddVertex(
            [NotNull] TVertex u,
            [NotNull, ItemNotNull] List <TVertex> oddVertices,
            [NotNull, InstantHandle] EdgeFactory <TVertex, TEdge> edgeFactory,
            out bool foundAdjacent)
        {
            bool found = false;

            foundAdjacent = false;
            foreach (TEdge edge in VisitedGraph.OutEdges(u))
            {
                TVertex v = edge.Target;
                if (!v.Equals(u) && oddVertices.Contains(v))
                {
                    foundAdjacent = true;
                    // Check that v does not have an out-edge towards u
                    if (HasEdgeToward(u, v))
                    {
                        continue;
                    }

                    // Add temporary edge
                    AddTemporaryEdge(u, v, oddVertices, edgeFactory);

                    // Set u to null
                    found = true;
                    break;
                }
            }

            return(found);
        }
        private void SecondWalk([NotNull] TVertex vertex, double x, double y, float l, float t)
        {
            Debug.Assert(vertex != null);

            var position = new Point(x, y);

            VerticesPositions[vertex] = position;
            _visitedVertices.Add(vertex);
            BalloonData data = _data[vertex];

            float dd     = l * data.D;
            float p      = (float)(t + Math.PI);
            int   degree = VisitedGraph.OutDegree(vertex);
            float fs     = degree == 0 ? 0 : data.F / degree;
            float pr     = 0;

            foreach (TEdge edge in VisitedGraph.OutEdges(vertex))
            {
                TVertex otherVertex = edge.Target;
                if (_visitedVertices.Contains(otherVertex))
                {
                    continue;
                }

                BalloonData otherData = _data[otherVertex];
                float       aa        = data.C * otherData.A;
                float       rr        = (float)(data.D * Math.Tan(aa) / (1 - Math.Tan(aa)));
                p += pr + aa + fs;

                float xx = (float)((l * rr + dd) * Math.Cos(p));
                float yy = (l * rr + dd) * Math.Sign(p);
                pr = aa;
                SecondWalk(otherVertex, x + xx, y + yy, l * data.C, p);
            }
        }
        private void OnVertexFinished([NotNull] TVertex vertex)
        {
            foreach (TVertex target in VisitedGraph.OutEdges(vertex).Select(edge => edge.Target))
            {
                if (Components[target] == int.MaxValue)
                {
                    Roots[vertex] = MinDiscoverTime(Roots[vertex], Roots[target]);
                }
            }

            if (EqualityComparer <TVertex> .Default.Equals(Roots[vertex], vertex))
            {
                TVertex w;
                do
                {
                    w             = _stack.Pop();
                    Components[w] = ComponentCount;

                    ComponentsPerStep.Add(ComponentCount);
                    VerticesPerStep.Add(w);
                    ++Steps;
                }while (!EqualityComparer <TVertex> .Default.Equals(w, vertex));

                ++ComponentCount;
            }
        }
        private void SecondWalk(TVertex v, TVertex r, double x, double y, float l, float t)
        {
            Point pos = new Point(x, y);

            VertexPositions[v] = pos;
            visitedVertices.Add(v);
            BalloonData data = datas[v];

            float dd     = l * data.d;
            float p      = (float)(t + Math.PI);
            int   degree = VisitedGraph.OutDegree(v);
            float fs     = (degree == 0 ? 0 : data.f / degree);
            float pr     = 0;

            foreach (var edge in VisitedGraph.OutEdges(v))
            {
                var otherVertex = edge.Target;
                if (visitedVertices.Contains(otherVertex))
                {
                    continue;
                }

                var   otherData = datas[otherVertex];
                float aa        = data.c * otherData.a;
                float rr        = (float)(data.d * Math.Tan(aa) / (1 - Math.Tan(aa)));
                p += pr + aa + fs;

                float xx = (float)((l * rr + dd) * Math.Cos(p));
                float yy = (float)((l * rr + dd) * Math.Sign(p));
                pr = aa;;
                SecondWalk(otherVertex, v, x + xx, y + yy, l * data.c, p);
            }
        }
        private void FirstWalk([NotNull] TVertex vertex)
        {
            Debug.Assert(vertex != null);

            BalloonData data = _data[vertex];

            _visitedVertices.Add(vertex);
            data.D = 0;

            float s = 0;

            foreach (TEdge edge in VisitedGraph.OutEdges(vertex))
            {
                TVertex     otherVertex = edge.Target;
                BalloonData otherData   = _data[otherVertex];

                if (!_visitedVertices.Contains(otherVertex))
                {
                    FirstWalk(otherVertex);
                    data.D      = Math.Max(data.D, otherData.R);
                    otherData.A = (float)Math.Atan((float)otherData.R / (data.D + otherData.R));
                    s          += otherData.A;
                }
            }

            AdjustChildren(data, s);
            SetRadius(data);
        }
예제 #16
0
        /// <summary>
        /// Used internally
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void FinishVertex(Object sender, VertexEventArgs args)
        {
            IVertex v = args.Vertex;

            foreach (IEdge e in VisitedGraph.OutEdges(v))
            {
                IVertex w = e.Target;

                if (this.Components[w] == int.MaxValue)
                {
                    this.Roots[v] = MinDiscoverTime(this.Roots[v], this.Roots[w]);
                }
            }

            if (Roots[v] == v)
            {
                IVertex w = null;
                do
                {
                    w = (IVertex)this.stack.Peek();
                    this.stack.Pop();
                    this.Components[w] = count;
                }while (w != v);
                ++count;
            }
        }
        protected override void InternalCompute()
        {
            Initialize();

            // start whith him:
            if (this.RootVertex != null)
            {
                OnStartVertex(this.RootVertex);

                // process each out edge of v
                foreach (Edge e in VisitedGraph.OutEdges(this.RootVertex))
                {
                    if (EdgeColors[e] == GraphColor.White)
                    {
                        OnStartEdge(e);
                        Visit(e, 0);
                    }
                }
            }

            // process the rest of the graph edges
            foreach (Edge e in VisitedGraph.Edges)
            {
                if (EdgeColors[e] == GraphColor.White)
                {
                    OnStartEdge(e);
                    Visit(e, 0);
                }
            }
        }
예제 #18
0
 private IEdgeEnumerable SelectOutEdgesNotInCircuit(IVertex v)
 {
     return(new FilteredEdgeEnumerable(
                VisitedGraph.OutEdges(v),
                new NotInCircuitEdgePredicate(Circuit, TemporaryCircuit)
                ));
 }
예제 #19
0
        private void FirstWalk(TVertex v)
        {
            var data = _datas[v];

            _visitedVertices.Add(v);
            data.D = 0;

            float s = 0;

            foreach (var edge in VisitedGraph.OutEdges(v))
            {
                var otherVertex = edge.Target;
                var otherData   = _datas[otherVertex];

                if (_visitedVertices.Contains(otherVertex))
                {
                    continue;
                }
                FirstWalk(otherVertex);
                data.D      = Math.Max(data.D, otherData.R);
                otherData.A = (float)Math.Atan(((float)otherData.R) / (data.D + otherData.R));
                s          += otherData.A;
            }


            AdjustChildren(v, data, s);
            SetRadius(v, data);
        }
        private void ExpandNode(
            [NotNull] TVertex n,
            [NotNull] IDictionary <TEdge, GraphColor> operators,
            double cost,
            [NotNull] BinaryHeap <double, TVertex> open)
        {
            // Skip self-edges
            foreach (TEdge edge in VisitedGraph.OutEdges(n).Where(e => !e.IsSelfEdge()))
            {
                bool hasColor = operators.TryGetValue(edge, out GraphColor edgeColor);
                if (!hasColor || edgeColor == GraphColor.White)
                {
                    double weight = _edgeWeights(edge);
                    double nCost  = _distanceRelaxer.Combine(cost, weight);

                    // (7) For each neighboring node of n' mark the operator from n to n' as used
                    // (8) For each node n', if there is no copy of n' in Open add it
                    // else save in open on the copy of n' with lowest cost. Mark as used all operators
                    // as used in any of the copies
                    operators[edge] = GraphColor.Gray;
                    if (open.MinimumUpdate(nCost, edge.Target))
                    {
                        OnTreeEdge(edge);
                    }
                }
                else
                {
                    Debug.Assert(edgeColor == GraphColor.Gray);

                    // Edge already seen, remove it
                    operators.Remove(edge);
                }
            }
        }
        private bool TryGetSuccessor([NotNull] IDictionary <TEdge, int> visited, [NotNull] TVertex vertex, out TEdge successor)
        {
            IEnumerable <TEdge> outEdges = VisitedGraph.OutEdges(vertex);
            IEnumerable <TEdge> edges    = outEdges.Where(edge => !visited.ContainsKey(edge));

            return(EdgeChain.TryGetSuccessor(edges, vertex, out successor));
        }
예제 #22
0
        /// <inheritdoc />
        protected override void InternalCompute()
        {
            if (!TryGetRootVertex(out TVertex root))
            {
                throw new InvalidOperationException("Root vertex not set.");
            }

            // Start with root vertex
            OnStartVertex(root);

            ICancelManager cancelManager = Services.CancelManager;

            // Process each out edge of the root one
            foreach (TEdge edge in VisitedGraph.OutEdges(root))
            {
                if (cancelManager.IsCancelling)
                {
                    return;
                }

                if (!EdgesColors.ContainsKey(edge))
                {
                    OnStartEdge(edge);
                    Visit(edge, 0);
                }
            }
        }
예제 #23
0
        /// <summary>
        /// Does a depth first search on the vertex u
        /// </summary>
        /// <param name="u">vertex to explore</param>
        /// <param name="depth">current recursion depth</param>
        /// <exception cref="ArgumentNullException">u cannot be null</exception>
        public void Visit(IVertex u, int depth)
        {
            if (depth > this.maxDepth)
            {
                return;
            }
            if (u == null)
            {
                throw new ArgumentNullException("u");
            }

            Colors[u] = GraphColor.Gray;
            OnDiscoverVertex(u);

            IVertex v = null;

            foreach (IEdge e in VisitedGraph.OutEdges(u))
            {
                OnExamineOutEdge(e);
                v = e.Target;
                GraphColor c = Colors[v];
                if (c == GraphColor.White)
                {
                    OnTreeOutEdge(e);
                    Visit(v, depth + 1);
                }
                else if (c == GraphColor.Gray)
                {
                    OnBackOutEdge(e);
                }
                else
                {
                    OnForwardOrCrossOutEdge(e);
                }
            }

            foreach (IEdge e in VisitedGraph.InEdges(u))
            {
                OnExamineInEdge(e);
                v = e.Source;
                GraphColor c = Colors[v];
                if (c == GraphColor.White)
                {
                    OnTreeInEdge(e);
                    Visit(v, depth + 1);
                }
                else if (c == GraphColor.Gray)
                {
                    OnBackInEdge(e);
                }
                else
                {
                    OnForwardOrCrossInEdge(e);
                }
            }

            Colors[u] = GraphColor.Black;
            OnFinishVertex(u);
        }
예제 #24
0
        /// <summary>
        /// Compute the condensation graph and store it in the supplied graph 'cg'
        /// </summary>
        /// <param name="cg">
        /// Instance of mutable graph in which the condensation graph
        /// transformation is stored
        /// </param>
        public void Create(IMutableVertexAndEdgeListGraph cg)
        {
            if (cg == null)
            {
                throw new ArgumentNullException("cg");
            }

            if (components == null)
            {
                ComputeComponents();
            }

            //  components list contains collection of
            // input graph Vertex for each SCC Vertex_ID
            // (i.e Vector< Vector<Vertex> > )
            //	Key = SCC Vertex ID
            sccVertexMap = BuildSCCVertexMap(components);

            //	Lsit of SCC vertices
            VertexCollection      toCgVertices = new VertexCollection();
            IDictionaryEnumerator it           = sccVertexMap.GetEnumerator();

            while (it.MoveNext())
            //	as scc_vertex_map is a sorted list, order of SCC IDs will match CG vertices
            {
                IVertex curr = cg.AddVertex();
                OnInitCondensationGraphVertex(new CondensationGraphVertexEventArgs(curr, (IVertexCollection)it.Value));
                toCgVertices.Add(curr);
            }

            for (int srcSccId = 0; srcSccId < sccVertexMap.Keys.Count; srcSccId++)
            {
                VertexCollection adj = new VertexCollection();
                foreach (IVertex u in (IVertexCollection)sccVertexMap[srcSccId])
                {
                    foreach (IEdge e in VisitedGraph.OutEdges(u))
                    {
                        IVertex v           = e.Target;
                        int     targetSccId = components[v];
                        if (srcSccId != targetSccId)
                        {
                            // Avoid loops in the condensation graph
                            IVertex sccV = toCgVertices[targetSccId];
                            if (!adj.Contains(sccV))                                            // Avoid parallel edges
                            {
                                adj.Add(sccV);
                            }
                        }
                    }
                }
                IVertex s = toCgVertices[srcSccId];
                foreach (IVertex t in adj)
                {
                    cg.AddEdge(s, t);
                }
            }
        }
예제 #25
0
        private bool HasEdgeToward([NotNull] TVertex u, [NotNull] TVertex v)
        {
            Debug.Assert(u != null);
            Debug.Assert(v != null);

            return(VisitedGraph
                   .OutEdges(v)
                   .Any(outEdge => EqualityComparer <TVertex> .Default.Equals(outEdge.Target, u)));
        }
예제 #26
0
 private IEnumerable <TEdge> SelectOutEdgesNotInCircuit(TVertex v)
 {
     foreach (var edge in VisitedGraph.OutEdges(v))
     {
         if (this.NotInCircuit(edge))
         {
             yield return(edge);
         }
     }
 }
예제 #27
0
        /// <summary>
        /// Does a depth first search on the vertex u
        /// </summary>
        /// <param name="u">vertex to explore</param>
        /// <exception cref="ArgumentNullException">u cannot be null</exception>
        public void Visit(IVertex u)
        {
            if (u == null)
            {
                throw new ArgumentNullException("u");
            }

            IVertex v = null;

            Colors[u] = GraphColor.Gray;
            VertexEventArgs uArgs = new VertexEventArgs(u);

            if (this.DiscoverVertex != null)
            {
                DiscoverVertex(this, uArgs);
            }

            foreach (IEdge e in VisitedGraph.OutEdges(u))
            {
                EdgeEventArgs eArgs = new EdgeEventArgs(e);
                if (this.ExamineEdge != null)
                {
                    ExamineEdge(this, eArgs);
                }
                v = e.Target;
                if (Colors[v] == GraphColor.White)
                {
                    if (this.TreeEdge != null)
                    {
                        TreeEdge(this, eArgs);
                    }
                    Visit(v);
                }
                else if (Colors[v] == GraphColor.Gray)
                {
                    if (this.BackEdge != null)
                    {
                        BackEdge(this, eArgs);
                    }
                }
                else
                {
                    if (this.ForwardOrCrossEdge != null)
                    {
                        ForwardOrCrossEdge(this, eArgs);
                    }
                }
            }

            Colors[u] = GraphColor.Black;
            if (this.FinishVertex != null)
            {
                FinishVertex(this, uArgs);
            }
        }
        private bool IsFlow()
        {
            // check edge flow values
            foreach (IVertex u in VisitedGraph.Vertices)
            {
                foreach (IEdge a in VisitedGraph.OutEdges(u))
                {
                    if (Capacities[a] > 0)
                    {
                        if ((ResidualCapacities[a] + ResidualCapacities[ReversedEdges[a]]
                             != Capacities[a] + Capacities[ReversedEdges[a]]) ||
                            (ResidualCapacities[a] < 0) ||
                            (ResidualCapacities[ReversedEdges[a]] < 0))
                        {
                            return(false);
                        }
                    }
                }
            }

            // check conservation
            double sum;

            foreach (IVertex u in VisitedGraph.Vertices)
            {
                if (u != src && u != sink)
                {
                    if (excessFlow[u] != 0)
                    {
                        return(false);
                    }
                    sum = 0;
                    foreach (IEdge a in VisitedGraph.OutEdges(u))
                    {
                        if (Capacities[a] > 0)
                        {
                            sum -= Capacities[a] - ResidualCapacities[a];
                        }
                        else
                        {
                            sum += ResidualCapacities[a];
                        }
                    }

                    if (excessFlow[u] != sum)
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
        public void Visit(TVertex s)
        {
            if (this.IsAborting)
            {
                return;
            }

            this.VertexColors[s] = GraphColor.Gray;
            OnDiscoverVertex(s);

            this.vertexQueue.Push(s);
            while (this.vertexQueue.Count != 0)
            {
                if (this.IsAborting)
                {
                    return;
                }
                TVertex u = this.vertexQueue.Pop();

                OnExamineVertex(u);
                foreach (TEdge e in VisitedGraph.OutEdges(u))
                {
                    TVertex v = e.Target;
                    OnExamineEdge(e);

                    GraphColor vColor = VertexColors[v];
                    if (vColor == GraphColor.White)
                    {
                        OnTreeEdge(e);
                        VertexColors[v] = GraphColor.Gray;
                        OnDiscoverVertex(v);
                        this.vertexQueue.Push(v);
                    }
                    else
                    {
                        OnNonTreeEdge(e);
                        if (vColor == GraphColor.Gray)
                        {
                            OnGrayTarget(e);
                        }
                        else
                        {
                            OnBlackTarget(e);
                        }
                    }
                }
                VertexColors[u] = GraphColor.Black;

                OnFinishVertex(u);
            }
        }
        //=======================================================================
        // This function is called "push" in Goldberg's h_prf implementation,
        // but it is called "discharge" in the paper and in hi_pr.c.
        private void Discharge(IVertex u)
        {
            while (true)
            {
                int ai;
                for (ai = current[u]; ai < VisitedGraph.OutDegree(u); ai++)
                {
                    IEdge a = VisitedGraph.OutEdges(u)[ai];
                    if (IsResidualEdge(a))
                    {
                        IVertex v = a.Target;
                        if (IsAdmissible(u, v))
                        {
                            if (v != sink && excessFlow[v] == 0)
                            {
                                RemoveFromInactiveList(v);
                                AddToActiveList(v, layers[distances[v]]);
                            }
                            PushFlow(a);
                            if (excessFlow[u] == 0)
                            {
                                break;
                            }
                        }
                    }
                }

                PreflowLayer layer = layers[distances[u]];
                int          du    = distances[u];

                if (ai == VisitedGraph.OutDegree(u))                            // i must be relabeled
                {
                    RelabelDistance(u);
                    if (layer.ActiveVertices.Count == 0 &&
                        layer.InactiveVertices.Count == 0)
                    {
                        Gap(du);
                    }
                    if (distances[u] == n)
                    {
                        break;
                    }
                }
                else
                {                                                                               // i is no longer active
                    current[u] = ai;
                    AddToInactiveList(u, layer);
                    break;
                }
            }
        }