Exemplo n.º 1
0
        /*public static IEnumerable<IMutableVertexAndEdgeListGraph<TVertex, TEdge>> StronglyConnectedComponents<TVertex, TEdge>(this IVertexListGraph<TVertex, TEdge> g, Func<IMutableVertexAndEdgeListGraph<TVertex, TEdge>> componentMaker)
         *  where TEdge : QuickGraph.IEdge<TVertex>
         * {
         *  g.StronglyConnectedComponents(out var scc);
         *
         *  return scc.GroupBy(kv => kv.Value).Select(group =>
         *  {
         *      var c = componentMaker();
         *
         *      group.ForEach(kv => c.AddVertex(kv.Key));
         *
         *      foreach (var v1 in c.Vertices)
         *          foreach (var v2 in c.Vertices)
         *          {
         *              if (g.TryGetEdges(v1, v2, out var edges))
         *                  edges.ForEach(e => c.AddEdge(e));
         *          }
         *  });
         * }*/



        /// <summary>
        /// Returns the list of weakly connected components in a graph. A weakly connected component is one in which
        /// <list type="number">
        ///     <item>for every pair of vertices V,W, W is reachable from V, ignoring edge-direction, and </item>
        ///     <item>one cannot add another node U such that the first property still holds.</item>
        /// </list>
        /// </summary>
        /// <typeparam name="TGraph">The type of the produced components.</typeparam>
        /// <typeparam name="TVertex">The type of the vertices.</typeparam>
        /// <typeparam name="TEdge">The type of the edges.</typeparam>
        /// <param name="g">The graph.</param>
        /// <param name="componentMaker">A producer-function for empty empty components.</param>
        public static IList <TGraph> WeaklyConnectedComponents <TGraph, TVertex, TEdge>(this GraphBase <TVertex, TEdge> g, Func <TGraph> componentMaker)
            where TEdge : class, IEdge <TVertex>
            where TGraph : GraphBase <TVertex, TEdge>
        {
            var undirected = new NonDirectedGraph <TVertex, NonDirectedEdge <TVertex> >();

            g.Vertices.ForEach(undirected.Add);
            g.Edges.ForEach(e => undirected.Add(new NonDirectedEdge <TVertex>(e.StartVertex, e.EndVertex)));

            var subgraphs = new List <TGraph>();

            //Find the subgraphs (connected components that are candidates for being turned into trees).
            var dcGraphFinder = new DisconnectedGraphsFinder <TVertex, NonDirectedEdge <TVertex> >(
                () => new SubGraphView <TVertex, NonDirectedEdge <TVertex> >(undirected), undirected);

            dcGraphFinder.FindDisconnectedGraphs();

            foreach (var component in dcGraphFinder.FoundDisconnectedGraphs)
            {
                var subG = componentMaker();
                component.Vertices.ForEach(subG.Add);

                foreach (var v1 in component.Vertices)
                {
                    foreach (var v2 in component.Vertices)
                    {
                        g.GetEdges(v1, v2).ForEach(subG.Add);
                    }
                }

                subgraphs.Add(subG);
            }

            return(subgraphs);
        }
Exemplo n.º 2
0
        public void BasicDepthFirstSearchCrawlerTest()
        {
            // create example graph, non-directed.
            NonDirectedGraph <string, NonDirectedEdge <string> > graph = new NonDirectedGraph <string, NonDirectedEdge <string> >();

            // create edges. simply use string literals, which will point to the same vertices anyway.
            graph.Add(new NonDirectedEdge <string>("A", "B"));
            graph.Add(new NonDirectedEdge <string>("A", "C"));
            graph.Add(new NonDirectedEdge <string>("A", "G"));
            graph.Add(new NonDirectedEdge <string>("A", "F"));
            graph.Add(new NonDirectedEdge <string>("F", "D"));
            graph.Add(new NonDirectedEdge <string>("F", "E"));
            graph.Add(new NonDirectedEdge <string>("D", "E"));
            graph.Add(new NonDirectedEdge <string>("E", "G"));
            graph.Add(new NonDirectedEdge <string>("H", "I"));
            graph.Add(new NonDirectedEdge <string>("J", "K"));
            graph.Add(new NonDirectedEdge <string>("J", "L"));
            graph.Add(new NonDirectedEdge <string>("J", "M"));
            graph.Add(new NonDirectedEdge <string>("L", "M"));

            DepthFirstSearchTester <string, NonDirectedEdge <string> > dfs = new DepthFirstSearchTester <string, NonDirectedEdge <string> >(graph);

            dfs.Start();
            Assert.AreEqual(13, dfs.VerticesLoggedInOnVisiting.Count);
            Assert.AreEqual(13, dfs.VerticesLoggedInOnVisited.Count);

            // visual confirmation logging code
            Console.Write("Vertices logged in order by OnVisiting:\n\t");
            foreach (string v in dfs.VerticesLoggedInOnVisiting)
            {
                Console.Write(v + " ");
            }
            Console.Write("\n\nVertices logged in order by OnVisited:\n\t");
            foreach (string v in dfs.VerticesLoggedInOnVisited)
            {
                Console.Write(v + " ");
            }

            // start in another tree in the graph
            dfs.VerticesLoggedInOnVisited.Clear();
            dfs.VerticesLoggedInOnVisiting.Clear();
            dfs.Start("L");
            Assert.AreEqual(13, dfs.VerticesLoggedInOnVisiting.Count);
            Assert.AreEqual(13, dfs.VerticesLoggedInOnVisited.Count);

            Console.Write("\n\nVertices logged in order by OnVisiting:\n\t");
            foreach (string v in dfs.VerticesLoggedInOnVisiting)
            {
                Console.Write(v + " ");
            }
            Console.Write("\n\nVertices logged in order by OnVisited:\n\t");
            foreach (string v in dfs.VerticesLoggedInOnVisited)
            {
                Console.Write(v + " ");
            }
        }