コード例 #1
0
        public void AllVerticesDiscovered(IGraph <int> graph)
        {
            var visitor = new BasicVisitor <int>();

            DFSTraversal.Traverse(graph, 0, visitor);

            Assert.That(visitor.DiscoveredVertices, Is.EquivalentTo(graph.Vertices));
        }
コード例 #2
0
        /// <summary>
        /// Checks if a given graph is planar and provides a planar embedding if so.
        /// </summary>
        /// <param name="graph">Graph</param>
        /// <param name="embedding">Planar embedding if a given graph is planar, null otherwise</param>
        /// <returns>True if planar, false otherwise</returns>
        public bool IsPlanar(IGraph <T> graph, out PlanarEmbedding <T> embedding)
        {
            // Transforms input graph
            TransformGraph(graph);

            // Init helper collections
            selfLoopsNew  = new List <IEdge <Vertex <T> > >();
            mergeStackNew = new Stack <MergeInfo>();

            // Use DFS traversal to add basic information to each of the vertices
            var visitor = new DFSTraversalVisitor <T>();

            DFSTraversal.Traverse(transformedGraph, visitor);

            // Sort vertices by dfs number ASC
            verticesByDFSNumberNew = BucketSort.Sort(transformedGraph.Vertices, x => x.DFSNumber, transformedGraph.VerticesCount);

            // Sort vertices by low point ASC
            verticesByLowPointNew = BucketSort.Sort(transformedGraph.Vertices, x => x.LowPoint, transformedGraph.VerticesCount);

            // Init vertex fields
            foreach (var vertex in transformedGraph.Vertices)
            {
                vertex.BackEdges    = new List <IEdge <Vertex <T> > >();
                vertex.Visited      = int.MaxValue;
                vertex.BackedgeFlag = transformedGraph.VerticesCount + 1;
                vertex.Flipped      = false;

                var dfsParent = vertex.Parent;

                if (vertex != dfsParent)
                {
                    var parentEdge = vertex.DFSEdge;
                    vertex.FaceHandle     = new FaceHandle <Vertex <T> >(vertex, parentEdge);
                    vertex.DFSChildHandle = new FaceHandle <Vertex <T> >(dfsParent, parentEdge);
                }
                else
                {
                    vertex.FaceHandle     = new FaceHandle <Vertex <T> >(vertex, (Vertex <T>)null);             // TODO: change
                    vertex.DFSChildHandle = new FaceHandle <Vertex <T> >(dfsParent, (Vertex <T>)null);
                }

                vertex.CanonicalDFSChild     = vertex;
                vertex.PertinentRoots        = new LinkedList <FaceHandle <Vertex <T> > >();
                vertex.SeparatedDFSChildList = new LinkedList <Vertex <T> >();
            }

            // Init separated dfs child lists
            //
            // Original Boost comment:
            // We need to create a list of not-yet-merged depth-first children for
            // each vertex that will be updated as bicomps get merged. We sort each
            // list by ascending lowpoint, which allows the externally_active
            // function to run in constant time, and we keep a pointer to each
            // vertex's representation in its parent's list, which allows merging
            //in constant time.
            foreach (var vertex in verticesByLowPointNew)
            {
                var dfsParent = vertex.Parent;

                if (vertex != dfsParent)
                {
                    var node = dfsParent.SeparatedDFSChildList.AddLast(vertex);
                    vertex.SeparatedNodeInParentList = node;
                }
            }

            // Call the main algorithm
            var isPlanar = IsPlanar();

            if (!isPlanar)
            {
                embedding = null;
                return(false);
            }

            embedding = GetPlanarEmbedding();
            return(true);
        }
コード例 #3
0
        public List <List <TNode> > GetCycles(Graphs.IGraph <TNode> graph)
        {
            var convertedGraph = new UndirectedAdjacencyListGraph <TNode>();

            foreach (var vertex in graph.Vertices)
            {
                convertedGraph.AddVertex(vertex);
            }

            foreach (var edge in graph.Edges)
            {
                convertedGraph.AddEdge(edge.From, edge.To);
            }

            var getCyclesVisitor = new GetGraphCyclesVisitor <TNode>();

            DFSTraversal.Traverse(convertedGraph, getCyclesVisitor);

            var cyclesBaseRaw = getCyclesVisitor.GetCycles();
            var edges         = graph.Edges.ToList();
            var cyclesBase    = cyclesBaseRaw.Select(x => new Cycle(x, edges)).ToList();
            var cycles        = new List <Cycle>(cyclesBase);

            foreach (var cycle1 in cyclesBase)
            {
                foreach (var cycle2 in cyclesBase)
                {
                    if (cycle1 == cycle2)
                    {
                        continue;
                    }

                    var newEdges      = new bool[edges.Count];
                    var hasSharedEdge = false;

                    for (int i = 0; i < edges.Count; i++)
                    {
                        var edge1 = cycle1.Edges[i];
                        var edge2 = cycle2.Edges[i];

                        if (edge1 && edge2)
                        {
                            hasSharedEdge = true;
                        }
                        else
                        {
                            newEdges[i] = edge1 || edge2;
                        }
                    }

                    if (hasSharedEdge)
                    {
                        if (cycles.All(x => !x.Edges.SequenceEqual(newEdges)))
                        {
                            cycles.Add(new Cycle(newEdges, edges));
                        }
                    }
                }
            }

            return(cycles.Select(x => x.Nodes).ToList());
        }