コード例 #1
0
        private List <NodeConfig> DetermineMavens()
        {
            var mavens = new List <NodeConfig>();

            var graph = new UndirectedGraph <string, Edge <string> >();

            foreach (var config in _configs)
            {
                graph.AddVertex(config.CurrentNode.Name);
                foreach (var connection in config.Connections)
                {
                    graph.AddVertex(connection.Name);
                    graph.AddEdge(new Edge <string>(config.CurrentNode.Name, connection.Name));
                }
            }

            var components = new Dictionary <string, int>();

            graph.ConnectedComponents(components);

            foreach (var i in components.Values.Distinct())
            {
                var names = components.Where(p => p.Value == i).Select(p => p.Key);

                var node = _configs.Where(config => names.Contains(config.CurrentNode.Name))
                           .OrderByDescending(x => x.Connections.Count).First();

                mavens.Add(node);
            }

            return(mavens);
        }
コード例 #2
0
ファイル: Grid3d.cs プロジェクト: M-JULIANI/scaffcity
        public int GetConnectedComponents()
        {
            var graph = new UndirectedGraph <Voxel, Edge <Voxel> >();

            graph.AddVertexRange(GetVoxels().Where(v => v.IsActive));
            graph.AddEdgeRange(GetFaces().Where(f => f.IsActive).Select(f => new Edge <Voxel>(f.Voxels[0], f.Voxels[1])));

            var components = new Dictionary <Voxel, int>();
            var count      = graph.ConnectedComponents(components);

            return(count);
        }
コード例 #3
0
ファイル: MapModel.cs プロジェクト: vrum/roguelike
        private void Process()
        {
            //Break tree on all edges and label as unlocked (contains start vertex) and locked tree

            foreach (var edgeToSplitOn in edgesToSplitOn)
            {
                map.RemoveEdge(edgeToSplitOn);
            }

            //We need to get the 2 subtrees created by this divide
            //This could be done by DFS from the source and target of the edge
            //Unfortunately, we don't have a top-level method to do that, so we get the connected components instead (may be slower)

            int componentCount = map.ConnectedComponents <int, TaggedEdge <int, string> >(components);

            //Which tree is the unlocked one?
            OriginComponentIndex = components[originVertex];
        }
コード例 #4
0
ファイル: MapModel.cs プロジェクト: vrum/roguelike
        public MapCycleReducer(IEnumerable <TaggedEdge <int, string> > edges)
        {
            this.baseGraph = new UndirectedGraph <int, TaggedEdge <int, string> >();
            baseGraph.AddVerticesAndEdgeRange(edges);

            //Find minimum spanning tree
            mapMST = new MapMST(baseGraph.Edges);

            //Find all cycles within tree

            if (CycleDebug)
            {
                Console.WriteLine("--cycle finding--");
            }

            //Find all edges not in MST
            var allEdges   = baseGraph.Edges;
            var edgesInMST = mapMST.vertexPredecessors.Values;

            var backEdges = allEdges.Except(edgesInMST);

            if (CycleDebug)
            {
                Console.WriteLine("No of back edges: {0}", backEdges.Count());

                foreach (var edge in backEdges)
                {
                    Console.WriteLine(edge);
                }
            }

            //Calculate [all? - expensive?] shortest paths. Each edge has a distance of 1

            var cycleList = new List <IEnumerable <TaggedEdge <int, string> > >();

            //Find the shortest cycle for each back edge

            foreach (var backEdge in backEdges)
            {
                int startVertex = backEdge.Source;
                int endVertex   = backEdge.Target;

                var tryGetPath = mapMST.mst.ShortestPathsDijkstra(x => 1, startVertex);

                IEnumerable <TaggedEdge <int, string> > path;
                if (tryGetPath(endVertex, out path))
                {
                    cycleList.Add(path);
                    AddToAllCycles(path, backEdge);
                }
                else
                {
                    Console.WriteLine(String.Format("no path found for cycle, start: {0}, end: {1}", startVertex, endVertex));
                }
            }

            //Output to console all cycles
            if (CycleDebug)
            {
                foreach (var cycle in cycleList)
                {
                    Console.WriteLine("Cycle: ");

                    foreach (var edge in cycle)
                    {
                        Console.Write(String.Format("{0}\t", edge));
                    }

                    Console.Write("\r\n");
                }
            }

            //Combine any cycles that share a vertex
            //There will be at least 2 ways of getting to each vertex
            //Therefore these vertexes must be collasped

            //make a (probably unconnected) graph of all the vertexes in the cycles
            //(no need to add back-edges - if they are connected by this then they will be connected by 2 vertices)

            var cycleGraph    = new UndirectedGraph <int, TaggedEdge <int, string> >();
            var allCycleEdges = cycleList.SelectMany(lst => lst);

            cycleGraph.AddVerticesAndEdgeRange(allCycleEdges);

            //find the connected components
            //this gives us n sets of connected nodes which will be reduced to n single nodes in the final acyclic graph
            var components     = new Dictionary <int, int>();
            int componentCount = cycleGraph.ConnectedComponents <int, TaggedEdge <int, string> >(components);

            if (componentCount != 0)
            {
                if (CycleDebug)
                {
                    Console.WriteLine("Graph contains {0} strongly connected components", componentCount);
                }
                foreach (var kv in components)
                {
                    if (CycleDebug)
                    {
                        Console.WriteLine("Vertex {0} is connected to subgraph {1}", kv.Key, kv.Value);
                    }
                }
            }

            //Replace each connected component with a single vertex, and remember which nodes were rolled-up

            mapNoCycles.AddVerticesAndEdgeRange(baseGraph.Edges);

            //Maintain a map of vertex number mappings after cycle removal
            //Initialise with no-change case

            var roomMappingToNoCyclesWork = new Dictionary <int, int>();

            foreach (var vertex in baseGraph.Vertices)
            {
                roomMappingToNoCyclesWork[vertex] = vertex;
            }

            //Maintain a map of all edges after cycle removal to initial map
            var edgeMappingNoCycleToFullMapWork = new Dictionary <Connection, Connection>();

            //For each cycle
            for (int i = 0; i < componentCount; i++)
            {
                //Get all vertices in this cycle
                //Get all vertices (keys) with value (cycle no)
                var verticesInCycle = components.Where(kv => kv.Value == i).Select(kv => kv.Key);

                //First vertex (to be kept)
                //Other vertices (to be removed)
                var sortedVertices = verticesInCycle.ToList();
                sortedVertices.Sort();

                //First vertex defined as minimum to ease repeatibility
                var firstVertex             = sortedVertices.First();
                var verticesInCycleNotFirst = sortedVertices.Skip(1);

                //Get all non-internal edges from vertices in the cycle

                //Get all adjacent edges to vertices to remove in the cycle
                var edgesFromCycle = verticesInCycleNotFirst.SelectMany(v => baseGraph.AdjacentEdges(v));

                //Discard all edges between vertices
                //(we need to maintain edges that are either sourced from the cycle or target it)
                var exteriorEdges = edgesFromCycle.Where(edge => !verticesInCycle.Contains(edge.Source) || !verticesInCycle.Contains(edge.Target));

                //Remove all cycle vertices but first from graph
                foreach (int vertex in verticesInCycleNotFirst)
                {
                    //Update vertex map
                    roomMappingToNoCyclesWork[vertex] = firstVertex;

                    //Remove vertex from graph
                    mapNoCycles.RemoveVertex(vertex);
                }

                //Add all exterior edges onto the remaining cycle vertex
                foreach (var edge in exteriorEdges)
                {
                    //Maintain reverse mapping. Edges which are collasped map back to the original rooms (where the door actually is)
                    //Store in lowest node first ordering
                    edgeMappingNoCycleToFullMapWork.Add(new Connection(roomMappingToNoCyclesWork[edge.Source], roomMappingToNoCyclesWork[edge.Target]).Ordered, new Connection(edge.Source, edge.Target).Ordered);

                    //Rewrite edge
                    //Use mapped vertex indices, since those in this cycle (and other source cycles) will have been reduced
                    mapNoCycles.AddEdge(new TaggedEdge <int, string>(roomMappingToNoCyclesWork[edge.Source], roomMappingToNoCyclesWork[edge.Target], edge.Tag));
                }
            }

            //Fill in any unchanged edges in the edge mapping
            foreach (var edge in mapNoCycles.Edges)
            {
                if (!edgeMappingNoCycleToFullMapWork.ContainsKey(new Connection(edge.Source, edge.Target).Ordered))
                {
                    edgeMappingNoCycleToFullMapWork[new Connection(edge.Source, edge.Target).Ordered] = new Connection(edge.Source, edge.Target).Ordered;
                }
            }

            edgeMappingNoCycleToFullMap = edgeMappingNoCycleToFullMapWork.AsReadOnly();

            roomMappingFullToNoCycleMap = roomMappingToNoCyclesWork.AsReadOnly();
            //Reverse the above mapping
            var roomMappingFullToNoCycleGrouped = roomMappingToNoCyclesWork.GroupBy(kv => kv.Value);

            roomMappingNoCycleToFullMap = roomMappingFullToNoCycleGrouped.ToDictionary(g => g.Key, g => g.Select(kv => kv.Key).ToList()).AsReadOnly();

            if (CycleDebug)
            {
                Console.WriteLine(String.Format("Cycle reduction - Cycles removed: {2}, Vertices before: {0}, vertices after: {1}", baseGraph.Vertices.Count(), mapNoCycles.Vertices.Count(), componentCount));
            }
        }