Пример #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="startvertex"></param>
        /// <param name="currentvertex"></param>
        /// <param name="graph"></param>
        /// <param name="blockedset"></param>
        /// <param name="blockedmap"></param>
        /// <param name="stack"></param>
        /// <param name="allcycles"></param>
        /// <returns></returns>
        private bool GetComponentCycles(int startvertex, int currentvertex, IDigraph graph, HashSet <int> blockedset, Dictionary <int, HashSet <int> > blockedmap, Stack <int> stack, List <List <int> > allcycles)
        {
            bool hascycle = false;

            stack.Push(currentvertex);
            blockedset.Add(currentvertex);

            if (graph.GetDegreeOut(currentvertex) > 0)
            {
                foreach (int neighbor in graph.GetVertexNeighborsOut(currentvertex))
                {
                    if (neighbor == startvertex)
                    {
                        List <int> cycle = new List <int>();
                        stack.Push(startvertex);
                        cycle.AddRange(stack);
                        cycle.Reverse();
                        stack.Pop();
                        allcycles.Add(cycle);
                        hascycle = true;
                    }

                    else if (!blockedset.Contains(neighbor))
                    {
                        bool gotcycle = GetComponentCycles(startvertex, neighbor, graph, blockedset, blockedmap, stack, allcycles);
                        if (gotcycle == true)
                        {
                            hascycle = true;
                        }
                    }
                }

                if (hascycle == true)
                {
                    UnBlock(currentvertex, blockedset, blockedmap);
                }

                else
                {
                    foreach (int neighbor in graph.GetVertexNeighborsOut(currentvertex))
                    {
                        HashSet <int> bset = GetBlockedSet(neighbor, blockedmap);
                        bset.Add(currentvertex);
                    }
                }

                stack.Pop();
                return(hascycle);
            }
            return(hascycle);
        }
Пример #2
0
        /// <summary>
        /// Creates graph consisting of strongly connected components only and then returns the
        /// minimum vertex among all the strongly connected components graph, ignores single vertex graph since it can't have a cycle
        /// potentially can return null.
        /// </summary>
        /// <param name="sccs"></param>
        /// <param name="graph"></param>
        /// <returns></returns>
        private Nullable <int> LeastIndexSCC(List <HashSet <int> > sccs, IDigraph graph)
        {
            int            min       = int.MaxValue;
            Nullable <int> minvertex = null;
            HashSet <int>  minscc    = null;

            foreach (HashSet <int> component in sccs)
            {
                if (component.Count == 1)
                {
                    continue;
                }

                foreach (int vertex in component)
                {
                    if (vertex < min)
                    {
                        min       = vertex;
                        minvertex = vertex;
                        minscc    = component;
                    }
                }
            }

            if (minvertex == null)
            {
                return(null);
            }

            IDigraph graphscc = new Digraph(graph.VertexCount);

            for (int i = 0; i < graph.VertexCount; i++)
            {
                graphscc.AddVertex();
            }
            for (int i = 0; i < graph.VertexCount; i++)
            {
                if (minscc.Contains(i))
                {
                    if (graph.GetDegreeOut(i) > 0)
                    {
                        foreach (int neighbor in graph.GetVertexNeighborsOut(i))
                        {
                            if (minscc.Contains(neighbor))
                            {
                                graphscc.AddEdge(i, neighbor);
                            }
                        }
                    }
                }
            }

            Nullable <int> potentialminvertex = null;

            if (graphscc.GetDegreeOut(min) > 0 || graphscc.GetDegreeIn(min) > 0)
            {
                potentialminvertex = minvertex;
            }
            return(potentialminvertex);
        }
Пример #3
0
        /// <summary>
        /// (DIRECTED GRAPH) -Get all strongly connected components of a directed graph.
        /// Based on Kosaraju's Algorithm:
        /// https://en.wikipedia.org/wiki/Strongly_connected_component
        /// https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm
        /// </summary>
        /// <param name="graph"></param>
        /// <returns></returns>
        public List <HashSet <int> > GetSCC_DirectedGraph(IDigraph graph)
        {
            //stack contains vertices by finish time(reverse order)
            Stack <int> stack = new Stack <int>();
            //hashset contains visited vertices
            HashSet <int> visited = new HashSet <int>();
            //List contains all vertices
            List <int> vertices = new List <int>();
            //List of hashsets of vertices representing cycles
            List <HashSet <int> > connectedcomponents = new List <HashSet <int> >();

            //get all connected vertices
            //add all vertices with edges to unvisited list
            for (int i = 0; i < graph.VertexCount; i++)
            {
                List <int> neighborsout = (List <int>)graph.GetVertexNeighborsOut(i);
                List <int> neighborsin  = (List <int>)graph.GetVertexNeighborsIn(i);
                if (neighborsout.Count > 0 || neighborsin.Count > 0)
                {
                    vertices.Add(i);
                }
            }

            foreach (int vertex in vertices)
            {
                if (visited.Contains(vertex))
                {
                    continue;
                }

                DFSUtil(vertex, visited, stack, graph);
            }

            //reverse the graph
            IDigraph reversegraph = ReverseGraph(graph);

            //empty visited hashset
            visited.Clear();

            while (stack.Count > 0)
            {
                //get + remove vertex int at top of the stack
                int vertex = stack.Pop();
                if (visited.Contains(vertex))
                {
                    continue;
                }

                HashSet <int> componentset = new HashSet <int>();
                DFSUtilReverseGraph(vertex, visited, componentset, reversegraph);
                connectedcomponents.Add(componentset);
            }

            return(connectedcomponents);
        }
Пример #4
0
        /// <summary>
        /// Depth first search by vertex finish time in decreasing order on the reversed graph
        /// </summary>
        /// <param name="vertex"></param>
        /// <param name="visited"></param>
        /// <param name="set"></param>
        /// <param name="reversegraph"></param>
        private void DFSUtilReverseGraph(int vertex, HashSet <int> visited, HashSet <int> componentset, IDigraph reversegraph)
        {
            visited.Add(vertex);
            componentset.Add(vertex);

            foreach (int neighbor in reversegraph.GetVertexNeighborsOut(vertex))
            {
                if (visited.Contains(neighbor))
                {
                    continue;
                }
                DFSUtilReverseGraph(neighbor, visited, componentset, reversegraph);
            }
        }
Пример #5
0
        /// <summary>
        /// Depth first search populates the stack with vertices ordered by finish time (vertex finishing last at top)
        /// </summary>
        /// <param name="vertex"></param>
        /// <param name="visited"></param>
        /// <param name="stack"></param>
        /// <param name="graph"></param>
        private void DFSUtil(int vertex, HashSet <int> visited, Stack <int> stack, IDigraph graph)
        {
            visited.Add(vertex);
            foreach (int neighbor in graph.GetVertexNeighborsOut(vertex))
            {
                if (visited.Contains(neighbor))
                {
                    continue;
                }
                DFSUtil(neighbor, visited, stack, graph);
            }

            stack.Push(vertex);
        }
Пример #6
0
        /// <summary>
        /// (DIRECTED GRAPH) -Create a subgraph of an input graph between a start and end vertex (includes start and end vertex)
        /// </summary>
        /// <param name="startindex"></param>
        /// <param name="endvertex"></param>
        /// <param name="graph"></param>
        /// <returns></returns>
        public IDigraph CreateSubGraph(int startindex, int endvertex, IDigraph graph)
        {
            IDigraph subgraph = new Digraph(graph.VertexCount);

            for (int i = 0; i < graph.VertexCount; i++)
            {
                subgraph.AddVertex();
            }

            for (int i = startindex; i <= endvertex; i++)
            {
                List <int> neighbors = (List <int>)graph.GetVertexNeighborsOut(i);
                foreach (int neighbor in neighbors)
                {
                    if (neighbor >= startindex && neighbor <= endvertex)
                    {
                        subgraph.AddEdge(i, neighbor);
                    }
                }
            }
            return(subgraph);
        }
Пример #7
0
        /// <summary>
        /// (DIRECTED GRAPH) -Create a copy of the directed graph that is reversed
        /// </summary>
        /// <param name="graph"></param>
        /// <returns></returns>
        public IDigraph ReverseGraph(IDigraph graph)
        {
            IDigraph reversegraph = new Digraph(graph.VertexCount);

            for (int i = 0; i < graph.VertexCount; i++)
            {
                reversegraph.AddVertex();
            }

            for (int i = 0; i < graph.VertexCount; i++)
            {
                List <int> vertexneighbors = (List <int>)graph.GetVertexNeighborsOut(i);
                //for each vertex that is connected, create a reverse edge with its neighbors
                if (vertexneighbors.Count > 0)
                {
                    foreach (int neighbor in vertexneighbors)
                    {
                        reversegraph.AddEdge(neighbor, i);
                    }
                }
            }

            return(reversegraph);
        }