Example #1
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);
        }
Example #2
0
 public DigraphPath(IDigraph g, int s)
 {
     _marked = new bool[g.V];
     _edgeTo = new int[g.V];
     _s      = s;
     dfs(g, s);
 }
Example #3
0
 public DigraphPath(IDigraph g, int startVertex)
 {
     _marked      = new bool[g.V];
     _edgeTo      = new int[g.V];
     _startVertex = startVertex;
     Dfs(g, startVertex);
 }
 private void dfs(IDigraph graph, int v)
 {
     _onStack[v] = true;
     _marked[v]  = true;
     foreach (int w in graph.Adj(v))
     {
         if (HasCycle)
         {
             return;
         }
         if (!_marked[w])
         {
             dfs(graph, w);
         }
         else if (_onStack[w])
         {
             _cycle = new Stack <int>();
             for (int x = v; x != w; x = _edgeTo[x])
             {
                 _cycle.Push(x);
             }
             _cycle.Push(w);
             _cycle.Push(v);
         }
     }
     _onStack[v] = false;
 }
Example #5
0
        /// <summary>
        /// (DIRECTED GRAPH) -Get all cycles of a directed graph.
        /// Based on Johnson's Algorithm:
        /// https://en.wikipedia.org/wiki/Johnson%27s_algorithm
        /// https://github.com/mission-peace/interview/blob/master/src/com/interview/graph/AllCyclesInDirectedGraphJohnson.java
        /// </summary>
        /// <param name="graph"></param>
        /// <returns></returns>
        public List <List <int> > GetAllCycles_DirectedGraph(IDigraph graph)
        {
            HashSet <int> blockedset = new HashSet <int>();
            Dictionary <int, HashSet <int> > blockedmap = new Dictionary <int, HashSet <int> >();
            Stack <int>        stack     = new Stack <int>();
            List <List <int> > allcycles = new List <List <int> >();

            int startindex = 0;

            while (startindex <= graph.VertexCount)
            {
                IDigraph subgraph          = CreateSubGraph(startindex, graph.VertexCount - 1, graph);
                List <HashSet <int> > sccs = GetSCC_DirectedGraph(subgraph);
                Nullable <int>        potentialleastvertex = LeastIndexSCC(sccs, subgraph);

                if (potentialleastvertex != null)
                {
                    int leastvertex = (int)potentialleastvertex;

                    blockedset.Clear();
                    blockedmap.Clear();
                    GetComponentCycles(leastvertex, leastvertex, subgraph, blockedset, blockedmap, stack, allcycles);

                    startindex = leastvertex + 1;
                }
                else
                {
                    break;
                }
            }


            return(allcycles);
        }
Example #6
0
 public FindShortestPathInDirectedGraph(IDigraph g, int startVertex)
 {
     _marked      = new bool[g.V];
     _edgeTo      = new int[g.V];
     _startVertex = startVertex;
     Bfs(g, startVertex);
 }
Example #7
0
        /// <summary>
        /// Thanks to Morton Mertner for a fix here
        /// </summary>
        /// <param name="g"></param>
        /// <param name="s"></param>
        /// <returns></returns>
        public static IDigraph DijkstrasAlgorithm(IDigraph g, int s)
        {
            int n = g.NumberOfVertices;

            Entry[] table = new Entry[n];
            for (int v = 0; v < n; ++v)
            {
                table[v] = new Entry(false,
                                     int.MaxValue, int.MaxValue);
            }
            table[s].distance = 0;
            IPriorityQueue queue = new BinaryHeap(g.NumberOfEdges);

            queue.Enqueue(new Association(0, g.GetVertex(s)));
            int vertexCount = 0;             // MM fix

            while (!queue.IsEmpty)
            {
                Association assoc = (Association)queue.DequeueMin();
                IVertex     v0    = (IVertex)assoc.Value;
                if (!table[v0.Number].known)
                {
                    table[v0.Number].known = true;
                    vertexCount++;                     // MM fix
                    foreach (IEdge e in v0.EmanatingEdges)
                    {
                        IVertex v1 = e.MateOf(v0);
                        int     d  = table[v0.Number].distance + (e.Weight != null ? (int)e.Weight : 0);
                        if (table[v1.Number].distance > d)
                        {
                            table[v1.Number].distance    = d;
                            table[v1.Number].predecessor = v0.Number;
                            queue.Enqueue(new Association(d, v1));
                        }
                    }
                }
            }
            // MM fixed loop to filter out unused edges and vertices
            IDigraph result = new DigraphAsLists(vertexCount);
            int      cv     = 0;

            int[] v2cv = new int[n];
            for (int v = 0; v < n; ++v)
            {
                if (table[v].known)
                {
                    result.AddVertex(cv, table[v].distance);
                    v2cv[v] = cv++;
                }
            }
            for (int v = 0; v < n; ++v)
            {
                if (v != s && table[v].known && table[v].distance < int.MaxValue)
                {
                    result.AddConnection(v2cv[v], v2cv[table[v].predecessor]);
                }
            }
            return(result);
        }
Example #8
0
        public TopologicalSort(IDigraph g)
        {
            var cycleDirected = new DirectedCycle(g);

            if (!cycleDirected.HasCycle)
            {
                var dfs = new DepthFirstOrder(g);
                _order = dfs.ReversePost;
            }
        }
Example #9
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);
        }
Example #10
0
 public DirectedDFS(IDigraph g, IEnumerable <int> sources)
 {
     _marked = new bool[g.V];
     foreach (int w in sources)
     {
         if (!_marked[w])
         {
             Dfs(g, w);
         }
     }
 }
Example #11
0
 private void Dfs(IDigraph g, int v)
 {
     _marked[v] = true;
     _count++;
     foreach (int i in g.Adj(v))
     {
         if (!_marked[i])
         {
             Dfs(g, i);
         }
     }
 }
        // edge in reverse postorder (Proposition F. Reverse postorder in a DAG is a topological sort.)

        public DepthFirstOrder(IDigraph g)
        {
            _marked = new bool[g.V];

            for (int v = 0; v < g.V; v++)
            {
                if (!_marked[v])
                {
                    Dfs(g, v);
                }
            }
        }
Example #13
0
        /// <summary>
        ///
        /// </summary>
        public static TileModel CreateFromGraph(TileMap map, IDigraph graph, int seed = 0)
        {
            for (int i = 0; i < graph.VertexCount; i++)
            {
                if (graph.GetDegreeOut(i) != map.TileDegree)
                {
                    throw new ArgumentException($"Vertex {i} is not compatible with the given tile map.");
                }
            }

            return(new TileModel(map, graph.GetVertexNeighborOut, graph.VertexCount, seed));
        }
 private void dfs(IDigraph graph, int v)
 {
     _marked[v] = true;   // отмечаем вершину
     _id[v]     = _count; // поставляем номер компонента
     foreach (int i in graph.Adj(v))
     {
         if (_marked[i])
         {
             continue;
         }
         dfs(graph, i);
     }
 }
Example #15
0
 private void Dfs(IDigraph graph, int v)
 {
     _marked[v] = true;
     foreach (int w in graph.Adj(v))
     {
         if (_marked[w])
         {
             continue;
         }
         _edgeTo[w] = v;
         Dfs(graph, w);
     }
 }
Example #16
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);
        }
Example #17
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);
        }
Example #18
0
        /// <summary>
        ///
        /// </summary>
        public static TileModel CreateFromGraph <T>(TileMap <T> tiles, IDigraph graph, int seed = 0)
        {
            int degree = tiles.TileDegree;

            for (int i = 0; i < graph.VertexCount; i++)
            {
                if (graph.GetDegreeOut(i) != degree)
                {
                    throw new ArgumentException($"Vertex {i} is not compatible with the given tile map.");
                }
            }

            return(new TileModel(tiles.CreateConstraints(), graph.GetVertexNeighborOut, graph.VertexCount, tiles.TileCount, seed));
        }
 private void Dfs(IDigraph g, int v)
 {
     _pre.Enqueue(v);
     _marked[v] = true;
     for (int w = 0; w < g.V; w++)
     {
         if (!_marked[v])
         {
             Dfs(g, w);
         }
     }
     _post.Enqueue(v);
     _reversePost.Push(v);
 }
        public KosarajuDigraphStronglyConnectedComponents(IDigraph g)
        {
            _marked = new bool[g.V];
            _id     = new int[g.V];
            var dfo = new DepthFirstOrder(g.Reverse());

            foreach (int w in dfo.ReversePost)
            {
                if (!_marked[w])
                {
                    dfs(g, w); //помечаем все вершины, которые достижимы из данной
                    _count++;  // увеличиваем номер компонента
                }
            }
        }
        public DirectedCycle(IDigraph g)
        {
            _onStack = new bool[g.V];
            _marked  = new bool[g.V];
            _edgeTo  = new int[g.V];

            for (int v = 0; v < g.V; v++)
            {
                if (_marked[v])
                {
                    continue;
                }
                dfs(g, v);
            }
        }
Example #22
0
        /// <summary>
        /// Writes a dot-notation of the given <paramref name="graph"/> to the given <paramref name="writer"/>.
        /// </summary>
        /// <param name="graph">The given graph to write out.</param>
        /// <param name="writer">The writer to write the graph structure to.</param>
        /// <param name="nodeLabelFunction">A function that generates the labels for the nodes.</param>
        /// <param name="edgeLabelFunction">A function that generates the labels for the edges.</param>
        public static void WriteDotStream(this IDigraph graph, TextWriter writer, Func <int, string> nodeLabelFunction, Func <int, int, string> edgeLabelFunction)
        {
            writer.Write(KeywordDigraph);
            writer.WriteLine(KeywordEnvUp);
            int l = graph.Length;

            for (int node = 0x00; node < l; node++)
            {
                writer.Write(KeywordIdent);
                writer.Write(NodePrefix);
                writer.Write(node);
                string nlabel = nodeLabelFunction(node);
                if (nlabel != null && nlabel != string.Empty)
                {
                    writer.Write(KeywordOptUp);
                    writer.Write(KeywordLabel);
                    writer.Write(KeywordKeyVal);
                    writer.Write(KeywordString);
                    writer.Write(nlabel);
                    writer.Write(KeywordString);
                    writer.Write(KeywordOptDn);
                }
                writer.WriteLine(KeywordSeparator);
            }
            foreach (Tuple <int, int> edge in graph.GetEdges())
            {
                writer.Write(KeywordIdent);
                writer.Write(NodePrefix);
                writer.Write(edge.Item1);
                writer.Write(KeywordDiedge);
                writer.Write(NodePrefix);
                writer.Write(edge.Item2);
                string elabel = edgeLabelFunction(edge.Item1, edge.Item2);
                if (elabel != null && elabel != string.Empty)
                {
                    writer.Write(KeywordOptUp);
                    writer.Write(KeywordLabel);
                    writer.Write(KeywordKeyVal);
                    writer.Write(KeywordString);
                    writer.Write(elabel);
                    writer.Write(KeywordString);
                    writer.Write(KeywordOptDn);
                }
                writer.WriteLine(KeywordSeparator);
            }
            writer.WriteLine(KeywordEnvDn);
        }
Example #23
0
        private void Bfs(IDigraph g, int s)
        {
            var q = new Queue <int>();

            _marked[s] = true;
            q.Enqueue(s);
            while (q.Count > 0)
            {
                int v = q.Dequeue();
                foreach (int w in g.Adj(v))
                {
                    if (!_marked[w])
                    {
                        _edgeTo[w] = v;
                        _marked[w] = true;
                        q.Enqueue(w);
                    }
                }
            }
        }
Example #24
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);
        }
Example #25
0
        /// <summary>
        /// Critical path analysis algorithm
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        public static IDigraph CriticalPathAnalysis(IDigraph g)
        {
            //TODO: more info here
            int i = g.NumberOfVertices;

            int[] nums1 = new int[(uint)i];
            nums1[0] = 0;
            g.TopologicalOrderTraversal(new EarliestTimeVisitor(nums1));
            int[] nums2 = new int[(uint)i];
            nums2[i - 1] = nums1[i - 1];
            g.DepthFirstTraversal(new PostOrder(new LatestTimeVisitor(nums2)), 0);
            IDigraph digraph1 = new DigraphAsLists(i);

            for (int j = 0; j < i; j++)
            {
                digraph1.AddVertex(j);
            }
            IEnumerator iEnumerator = g.Edges.GetEnumerator();

            try
            {
                while (iEnumerator.MoveNext())
                {
                    IEdge edge = (IEdge)iEnumerator.Current;
                    int   k    = nums2[edge.V1.Number] - nums1[edge.V0.Number] - (int)edge.Weight;
                    digraph1.AddConnection(edge.V0.Number, edge.V1.Number, (int)edge.Weight);
                }
            }
            finally
            {
                IDisposable iDisposable = iEnumerator as IDisposable;
                if (iDisposable != null)
                {
                    iDisposable.Dispose();
                }
            }
            return(DijkstrasAlgorithm(digraph1, 0));
        }
Example #26
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);
        }
Example #27
0
 /// <summary>
 /// Writes a dot-notation of the given <paramref name="graph"/> to the given <paramref name="writer"/>.
 /// </summary>
 /// <param name="graph">The given graph to write out.</param>
 /// <param name="writer">The writer to write the graph structure to.</param>
 /// <remarks>
 /// <para>The <see cref="M:DefaultNodeLabelFunction"/> is used to label the nodes, the method returns the index
 /// the node prefixed with <c>"n"</c>.</para>
 /// <para>The <see cref="M:DefaultEdgeLabelFunction"/> is used to label the edges, the method returns the empty
 /// string for each edge.</para>
 /// </remarks>
 public static void WriteDotStream(this IDigraph graph, TextWriter writer)
 {
     WriteDotStream(graph, writer, DefaultNodeLabelFunction, DefaultEdgeLabelFunction);
 }
Example #28
0
        /// <summary>
        /// An algorithm for finding the shortest path between two graph vertices
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        public static IDigraph FloydsAlgorithm(IDigraph g)
        {
            int vertexCount = g.NumberOfVertices;

            int[,] distance = new int[vertexCount, vertexCount];
            for (int j1 = 0; j1 < vertexCount; j1++)
            {
                for (int k1 = 0; k1 < vertexCount; k1++)
                {
                    distance[j1, k1] = int.MaxValue;                    //means infinity actually
                }
            }
            IEnumerator iEnumerator = g.Edges.GetEnumerator();

            try
            {
                while (iEnumerator.MoveNext())
                {
                    IEdge edge = (IEdge)iEnumerator.Current;
                    distance[edge.V0.Number, edge.V1.Number] = (int)edge.Weight;
                }
            }
            finally
            {
                IDisposable iDisposable = iEnumerator as IDisposable;
                if (iDisposable != null)
                {
                    iDisposable.Dispose();
                }
            }


            for (int j2 = 0; j2 < vertexCount; j2++)
            {
                for (int k2 = 0; k2 < vertexCount; k2++)
                {
                    Console.WriteLine(j2 + "->" + k2);
                    for (int i2 = 0; i2 < vertexCount; i2++)
                    {
                        if (distance[j2, i2] != int.MaxValue && distance[i2, k2] != int.MaxValue)
                        {
                            int i3 = distance[j2, i2] + distance[i2, k2];
                            if (distance[j2, k2] > i3)
                            {
                                distance[j2, k2] = i3;
                                Console.WriteLine("  " + i2);
                            }
                        }
                    }
                }
            }
            IDigraph digraph1 = new DigraphAsMatrix(vertexCount);

            for (int j3 = 0; j3 < vertexCount; j3++)
            {
                digraph1.AddVertex(j3);
            }
            for (int k3 = 0; k3 < vertexCount; k3++)
            {
                for (int i4 = 0; i4 < vertexCount; i4++)
                {
                    if (distance[k3, i4] != int.MaxValue)
                    {
                        digraph1.AddConnection(k3, i4, distance[k3, i4]);
                    }
                }
            }
            return(digraph1);
        }
Example #29
0
 /// <summary>
 /// Writes a dot-notation of the given <paramref name="graph"/> to the given <paramref name="writer"/>.
 /// </summary>
 /// <param name="graph">The given graph to write out.</param>
 /// <param name="writer">The writer to write the graph structure to.</param>
 /// <param name="nodeLabelFunction">A function that generates the labels for the nodes.</param>
 /// <remarks>
 /// <para>The <see cref="M:DefaultEdgeLabelFunction"/> is used to label the edges, the method returns the empty
 /// string for each edge.</para>
 /// </remarks>
 public static void WriteDotStream(this IDigraph graph, TextWriter writer, Func <int, string> nodeLabelFunction)
 {
     WriteDotStream(graph, writer, nodeLabelFunction, DefaultEdgeLabelFunction);
 }
Example #30
0
 public DirectedDFS(IDigraph g, int startVertex)
 {
     _marked = new bool[g.V];
     Dfs(g, startVertex);
 }