/// <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); }
/// <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)); }
/// <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); }
/// <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)); }