public void AllVerticesDiscovered(IGraph <int> graph) { var visitor = new BasicVisitor <int>(); DFSTraversal.Traverse(graph, 0, visitor); Assert.That(visitor.DiscoveredVertices, Is.EquivalentTo(graph.Vertices)); }
/// <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); }
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()); }