Example #1
0
        /// <summary>
        /// Enumerates edges of the graph in a breadth-first order.
        /// </summary>
        /// <param name="graph">The graph.</param>
        /// <param name="source">The source.</param>
        /// <param name="vertexCount">The number of vertices.</param>
        /// <returns>An enumerator to enumerate the edges of a depth-first search tree.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graph"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="vertexCount"/> is less than zero.
        /// </exception>
        public IEnumerator <TEdge> EnumerateEdges(TGraph graph, int source, int vertexCount)
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }

            if (vertexCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(vertexCount));
            }

            if (unchecked ((uint)source >= vertexCount))
            {
                yield break;
            }

            byte[] exploredSet = ArrayPool <byte> .Shared.Rent(vertexCount);

            Array.Clear(exploredSet, 0, exploredSet.Length);
            var queue = new Internal.Queue <int>();

            try
            {
                SetHelpers.Add(exploredSet, source);
                queue.Add(source);

                while (queue.TryTake(out int u))
                {
#if DEBUG
                    Debug.Assert(SetHelpers.Contains(exploredSet, u));
#endif
                    TEdgeEnumerator outEdges = graph.EnumerateOutEdges(u);
                    while (outEdges.MoveNext())
                    {
                        TEdge e = outEdges.Current;
                        if (!graph.TryGetHead(e, out int v))
                        {
                            continue;
                        }

                        if (SetHelpers.Contains(exploredSet, v))
                        {
                            continue;
                        }

                        yield return(e);

                        SetHelpers.Add(exploredSet, v);
                        queue.Add(v);
                    }
                }
            }
            finally
            {
                // The Dispose call will happen on the original value of the local if it is the argument to a using statement.
                queue.Dispose();
                ArrayPool <byte> .Shared.Return(exploredSet);
            }
        }
Example #2
0
        /// <summary>
        /// Traverses the graph in a BFS manner starting from the single source.
        /// </summary>
        /// <param name="graph">The graph.</param>
        /// <param name="source">The source.</param>
        /// <param name="colorMap">The vertex color map.</param>
        /// <param name="handler">
        /// The <see cref="IBfsHandler{TGraph,TVertex,TEdge}"/> implementation to use
        /// for the actions taken during the graph traversal.
        /// </param>
        /// <typeparam name="TColorMap">The type of the vertex color map.</typeparam>
        /// <typeparam name="THandler">The type of the events handler.</typeparam>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graph"/> is <see langword="null"/>,
        /// or <paramref name="colorMap"/> is <see langword="null"/>,
        /// or <paramref name="handler"/> is <see langword="null"/>.
        /// </exception>
        public void Traverse <TColorMap, THandler>(
            TGraph graph, TVertex source, TColorMap colorMap, THandler handler)
            where TColorMap : IDictionary <TVertex, Color>
            where THandler : IBfsHandler <TGraph, TVertex, TEdge>
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }

            if (colorMap == null)
            {
                throw new ArgumentNullException(nameof(colorMap));
            }

            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

            var queue = new Internal.Queue <TVertex>();

            colorMap[source] = Color.Gray;
            handler.OnDiscoverVertex(graph, source);
            queue.Add(source);

            TraverseCore(graph, queue, colorMap, handler);
        }
Example #3
0
        private static void TraverseCore <TColorMap, THandler>(
            TGraph graph, Internal.Queue <TVertex> queue, TColorMap colorMap, THandler handler)
            where TColorMap : IDictionary <TVertex, Color>
            where THandler : IBfsHandler <TGraph, TVertex, TEdge>
        {
            Debug.Assert(graph != null, "graph != null");
            Debug.Assert(colorMap != null, "colorMap != null");
            Debug.Assert(handler != null, "handler != null");

            try
            {
                while (queue.TryTake(out TVertex u))
                {
#if DEBUG
                    Debug.Assert(GetColorOrDefault(colorMap, u) != default);
#endif
                    handler.OnExamineVertex(graph, u);
                    TEdgeEnumerator outEdges = graph.EnumerateOutEdges(u);
                    while (outEdges.MoveNext())
                    {
                        TEdge e = outEdges.Current;
                        if (!graph.TryGetHead(e, out TVertex v))
                        {
                            continue;
                        }

                        handler.OnExamineEdge(graph, e);
                        Color vColor = GetColorOrDefault(colorMap, v);
                        switch (vColor)
                        {
                        case Color.None:
                        case Color.White:
                            handler.OnTreeEdge(graph, e);
                            colorMap[v] = Color.Gray;
                            handler.OnDiscoverVertex(graph, v);
                            queue.Add(v);
                            break;

                        case Color.Gray:
                            handler.OnNonTreeGrayHeadEdge(graph, e);
                            break;

                        case Color.Black:
                            handler.OnNonTreeBlackHeadEdge(graph, e);
                            break;
                        }
                    }

                    colorMap[u] = Color.Black;
                    handler.OnFinishVertex(graph, u);
                }
            }
            finally
            {
                // The Dispose call will happen on the original value of the local if it is the argument to a using statement.
                queue.Dispose();
            }
        }
        /// <summary>
        /// Enumerates vertices of the graph in a breadth-first order starting from the single source.
        /// </summary>
        /// <param name="graph">The graph.</param>
        /// <param name="source">The source.</param>
        /// <param name="exploredSet">The set of explored vertices.</param>
        /// <typeparam name="TExploredSet">The type of the set of explored vertices.</typeparam>
        /// <returns>An enumerator to enumerate the vertices of a breadth-first search tree.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graph"/> is <see langword="null"/>,
        /// or <paramref name="exploredSet"/> is <see langword="null"/>.
        /// </exception>
        public IEnumerator <TVertex> EnumerateVertices <TExploredSet>(
            TGraph graph, TVertex source, TExploredSet exploredSet)
            where TExploredSet : ISet <TVertex>
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }

            if (exploredSet == null)
            {
                throw new ArgumentNullException(nameof(exploredSet));
            }

            var queue = new Internal.Queue <TVertex>();

            try
            {
                exploredSet.Add(source);
                yield return(source);

                queue.Add(source);

                while (queue.TryTake(out TVertex u))
                {
#if DEBUG
                    Debug.Assert(exploredSet.Contains(u));
#endif
                    TEdgeEnumerator outEdges = graph.EnumerateOutEdges(u);
                    while (outEdges.MoveNext())
                    {
                        TEdge e = outEdges.Current;
                        if (!graph.TryGetHead(e, out TVertex v))
                        {
                            continue;
                        }

                        if (exploredSet.Contains(v))
                        {
                            continue;
                        }

                        exploredSet.Add(v);
                        yield return(v);

                        queue.Add(v);
                    }
                }
            }
            finally
            {
                // The Dispose call will happen on the original value of the local if it is the argument to a using statement.
                queue.Dispose();
            }
        }
Example #5
0
        /// <summary>
        /// Traverses the graph in a BFS manner starting from the multiple sources.
        /// </summary>
        /// <param name="graph">The graph.</param>
        /// <param name="sources">The sources enumerator.</param>
        /// <param name="colorMap">The vertex color map.</param>
        /// <param name="handler">
        /// The <see cref="IBfsHandler{TGraph,TVertex,TEdge}"/> implementation to use
        /// for the actions taken during the graph traversal.
        /// </param>
        /// <typeparam name="TVertexEnumerator">The type of the vertex enumerator.</typeparam>
        /// <typeparam name="TColorMap">The type of the vertex color map.</typeparam>
        /// <typeparam name="THandler">The type of the events handler.</typeparam>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graph"/> is <see langword="null"/>,
        /// or <paramref name="sources"/> is <see langword="null"/>,
        /// or <paramref name="colorMap"/> is <see langword="null"/>,
        /// or <paramref name="handler"/> is <see langword="null"/>.
        /// </exception>
        public void Traverse <TVertexEnumerator, TColorMap, THandler>(
            TGraph graph, TVertexEnumerator sources, TColorMap colorMap, THandler handler)
            where TVertexEnumerator : IEnumerator <TVertex>
            where TColorMap : IDictionary <TVertex, Color>
            where THandler : IBfsHandler <TGraph, TVertex, TEdge>
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }

            if (sources == null)
            {
                throw new ArgumentNullException(nameof(sources));
            }

            if (colorMap == null)
            {
                throw new ArgumentNullException(nameof(colorMap));
            }

            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

            var queue = new Internal.Queue <TVertex>();

            while (sources.MoveNext())
            {
                TVertex s = sources.Current;
                colorMap[s] = Color.Gray;
                handler.OnDiscoverVertex(graph, s);
                queue.Add(s);
            }

            TraverseCore(graph, queue, colorMap, handler);
        }