public void PathfindingSetup() { _rand = new Random(RandSeed); // Re-seed Random generator before each test. if (_navigator != null) { return; } _nodes = new Dictionary <EntityId, PathNode>(); var edges = new List <PathEdge>(); var dir = AppDomain.CurrentDomain.BaseDirectory; SnapshotParsingUtils.SetGraphNodes(Path.Combine(dir, Resources.SanfranMicroPointsCsv), _nodes); SnapshotParsingUtils.SetGraphEdges(Path.Combine(dir, Resources.SanfranMicroGraphCsv), _nodes, edges); _nodesArray = _nodes.Values.ToArray(); _outbounds = new Dictionary <PathNode, List <PathEdge> >(); foreach (var edge in edges) { if (_outbounds.ContainsKey(edge.Source) == false) { _outbounds.Add(edge.Source, new List <PathEdge>()); } _outbounds[edge.Source].Add(edge); } _navigator = new DefaultGraphNavigator(_nodes, edges); }
public NodeInfo(object node, IGraphNavigator navigator) { this.node = node; this.enext = navigator.NextNodes(node).GetEnumerator(); }
/// <summary> /// Convenient <c>DFS</c> function. Call the full <c>dfs</c> function /// with new_subgraph_visitor set to <c>null</c>. /// </summary> public static void dfs ( IEnumerable roots, IGraphNavigator navigator, DNodePredicate avoid, DNodeVisitor begin_visitor, DNodeVisitor end_visitor) { SearchDepthFirst(roots, navigator, avoid, null, begin_visitor, end_visitor); }
/// <summary> /// DFS traversal of the (sub)graph rooted in a set of nodes. /// </summary> /// <param name="roots">Roots of the traversed subgraph. The subgraph /// rooted in the first root will be traversed in DFS order; next, if /// the second root wasn't reached yet, the subgraph rooted in it will /// be traversed in DFS order and so on. The order of /// the roots is given by the corresponding <c>IEnumerator</c>.</param> /// <param name="navigator">Navigator that describes the graph structure.</param> /// <param name="avoid">Encountered nodes that satisfy this predicate will be /// ignored by the DFS traversal (together with their attached arcs). <c>null</c> /// corresponds to the predicate that is always false (i.e., no encountered node /// will be ignored).</param> /// <param name="new_subgraph_visitor">Visitor for the root node of each /// new subgraph: the roots (see the roots parameter) /// are explored in order; if a root node has not been already reached /// by the DFS traversal of the previous roots, <c>new_subgraph_visitor</c> /// will be called on it, and next the subgraph rooted in it will be DFS /// traversed.</param> /// <param name="begin_visitor">Node visitor to be called when a node is reached /// for the first time by the DFS traversal. <c>null</c> corresponds to no /// visitor.</param> /// <param name="end_visitor">Node visitor to be called when the exploration of /// a node has finished. <c>null</c> corresponds to no visitor.</param> public static void SearchDepthFirst ( IEnumerable roots, IGraphNavigator navigator, DNodePredicate avoid, DNodeVisitor new_subgraph_visitor, DNodeVisitor begin_visitor, DNodeVisitor end_visitor ) { // set of already seen nodes IMutableSet seen_nodes = new HashSet(); // DFS Stack: holds the currently explored path; simulates the call // stack of a recursive implementation of DFS. Stack/*<NodeInfo>*/ stack = new Stack(); foreach(object root in roots) { if( ((avoid != null) && avoid(root)) || seen_nodes.Contains(root)) continue; call_visitor(new_subgraph_visitor, root); seen_nodes.Add(root); call_visitor(begin_visitor, root); stack.Push(new NodeInfo(root, navigator)); while(stack.Count != 0) { NodeInfo info = (NodeInfo) stack.Peek(); if(info.enext.MoveNext()) { object next_node = info.enext.Current; // ignore nodes as dictated by "avoid" if((avoid != null) && avoid(next_node)) continue; if(!seen_nodes.Contains(next_node)) { // new and non-avoidable node! // mark it as seen, seen_nodes.Add(next_node); // call the begin visitor, call_visitor(begin_visitor, next_node); // and put the node on the DFS stack stack.Push(new NodeInfo(next_node, navigator)); } } else { // the visit of info.node has finished // apply end visitor call_visitor(end_visitor, info.node); // remove the top of the stack stack.Pop(); } } } }
/// <summary> /// Topologically sorts the graph rooted in <c>roots</c> and described by /// <c>nav</c>. Throws a <c>CyclicGraphException</c> if the graph contains /// a cycle. Otherwise, returns a topologically sorted list of the graph nodes. /// The returned list is in ascending order: it starts with the nodes that don't /// have any out-arc (i.e., arcs going out of them) and ends with the nodes /// that don't have any in-arcs (i.e., arcs going into them). If the navigator /// works in constant time, the topological sort works in time linear with the /// number of nodes plus the number of edges. /// /// </summary> public static IList TopologicallySortGraph (DSetFactory setfactory, IEnumerable roots, IGraphNavigator navigator) { TopSortData data = new TopSortData(setfactory); data.all_nodes.AddAll(ReachableNodes(setfactory, roots, navigator)); if(data.all_nodes.Count == 0) return data.list; // find the real roots: those nodes with no arcs pointing to them data.real_roots.AddAll(roots); foreach(object node in data.all_nodes) foreach(object next_node in navigator.NextNodes(node)) data.real_roots.Remove(next_node); // if there is no real root, we have a cycle if(data.real_roots.Count == 0) throw new CyclicGraphException(); dfs(data.real_roots, navigator, null, null, new DNodeVisitor(data.sort_end_visitor)); #if NEVER // check for cyles IMutableSet seen = new HashSet(); foreach(object node in data.list) { foreach(object next_node in navigator.NextNodes(node)) // all arcs must go behind in the list, to already seen nodes if(!seen.Contains(next_node)) throw new CyclicGraphException(); seen.Add(node); } #endif return data.list; }
public static ISet ReachableNodes (DSetFactory setfactory, IEnumerable roots, IGraphNavigator navigator) { return ReachableNodes(setfactory, roots, navigator, null); }
public SCCFactory (IGraphNavigator navigator) { this.navigator = navigator; }
public static IGraphNavigator BFSpanningTree(IEnumerable roots, IGraphNavigator navigator, DNodePredicate avoid) { BFSpanningBuilder bfb = new BFSpanningBuilder(); bfs(roots, navigator, avoid, null, new DEdgeVisitor(bfb.VisitEdge)); return bfb; }
/// <summary> /// Constructs a <c>BackwardGraphNavigator</c> that reverses an /// <c>IGraphNavigator</c>. /// </summary> /// <param name="navigator">The navigator that is reversed.</param> public BackwardGraphNavigator(IGraphNavigator navigator) { this.navigator = navigator; }
/// <summary> /// Constructs a navigator into a graph which is the union of two graphs /// (where the graphs are seen as edge sets). /// </summary> /// <param name="nav1">Navigator for the first graph.</param> /// <param name="nav2">Navigator for the second graph.</param> public UnionGraphNavigator(IGraphNavigator nav1, IGraphNavigator nav2) { this.nav1 = nav1; this.nav2 = nav2; }
public SCCFactory(IGraphNavigator navigator) { this.navigator = navigator; }
/// <summary> /// Use the <c>nav</c> navigator to explore the graph rooted in the /// objects from the <c>roots</c> set, decomposes it into strongly /// connected components. Returns the set of strongly connected components. /// </summary> public static IEnumerable /*<StronglyConnectedComponent>*/ ConstructSCCs(IEnumerable roots, IGraphNavigator navigator) { return((new SCCFactory(navigator)).ConstructSCCs(roots)); }
public FinallyBlockDuplicator ( ControlFlowGraph cfg, Method method, IList/*<Block>*/ new_blocks, Hashtable/*<Block,Block>*/ block2next, NormalFlowBlockNavigator nfbnav, IList/*<ExceptionHandler>*/ all_ehs ) { this.dupVisitor = new DupVisitor(method.DeclaringType.DeclaringModule, method.DeclaringType); this.cfg = cfg; this.method = method; this.new_blocks = new_blocks; this.block2next = block2next; this.bnav = new UnionGraphNavigator(nfbnav, new ControlFlowGraph.ExcpFlowBlockNavigator(cfg)); this.allExceptionHandlers = all_ehs; // init the block -> index map this.b2index = new Hashtable(); StatementList blocks = method.Body.Statements; for(int i = 0; i < blocks.Count; i++) { b2index[(Block) blocks[i]] = i; } // init the exception handler -> last block map this.lastHandledBlock = new Hashtable(); foreach (ExceptionHandler eh in this.allExceptionHandlers) { if (eh.HandlerType != NodeType.Finally && eh.HandlerType != NodeType.FaultHandler) { continue; } this.lastHandledBlock[eh] = LastBlockInsideHandler(eh); } // 2. deal with the "leave" instructions TreatLeaveInstructions (); // 3. The original finally / fault handlers should be turned into catch handlers ConvertFinallyHandlerIntoCatchHandler(); }
/// <summary> /// Does a breadth first traversal of the given graph /// </summary> /// <param name="roots">The roots of the traversal.</param> /// <param name="avoid">If not null, is a predicate to avoid certain nodes</param> /// <param name="visitRoot">If not null, called for each root that is not avoided.</param> /// <param name="visitEdge">Called for each edges in the bf traversal, i.e., only for edges going to unvisited nodes.</param> public static void bfs(IEnumerable roots, IGraphNavigator navigator, DNodePredicate avoid, DNodeVisitor visitRoot, DEdgeVisitor visitEdge) { Queue queue = new Queue(); IMutableSet seen = new HashSet(); // initialize queue with roots foreach(object o in roots) { if (avoid==null || !avoid(o)) { queue.Enqueue(o); seen.Add(o); if (visitRoot != null) visitRoot(o); } } while(queue.Count > 0) { object node = queue.Dequeue(); foreach(object succ in navigator.NextNodes(node)) { if ((avoid == null || !avoid(succ)) && !seen.Contains(succ)) { seen.Add(succ); queue.Enqueue(succ); visitEdge(node, succ); } } } }
/// <summary> /// Only nodes in given set are considered part of the graph. /// </summary> public FilteredGraphNavigator(ISet nodes, IGraphNavigator graph) { this.graph = graph; this.nodes = nodes; }
public static bool IsReachable(IGraphNavigator navigator, object from, object to) { TargetInfo targetInfo = new TargetInfo(to); dfs(new object[1]{from}, navigator, null, new DNodeVisitor(targetInfo.Visit), null); return targetInfo.Found; }
public static ISet ReachableNodes (DSetFactory setfactory, IEnumerable roots, IGraphNavigator navigator, DNodePredicate avoid) { ReachableNodesData data = new ReachableNodesData(setfactory); SearchDepthFirst(roots, navigator, avoid, null, new DNodeVisitor(data.reachable_visitor), null); return data.all_nodes; }
public static int GraphDepth (IGraphNavigator graph, object startNode, DDepthAssigner da) { GraphDepthComputer gdc = new GraphDepthComputer(da); dfs(new object[]{startNode}, graph, null, new DNodeVisitor(gdc.BeginVisitor), new DNodeVisitor(gdc.EndVisitor)); return gdc.MaxDepth; }
/// <summary> /// Use the <c>nav</c> navigator to explore the graph rooted in the /// objects from the <c>roots</c> set, decomposes it into strongly /// connected components. Returns the set of strongly connected components. /// </summary> public static IEnumerable/*<StronglyConnectedComponent>*/ ConstructSCCs(IEnumerable roots, IGraphNavigator navigator) { return (new SCCFactory(navigator)).ConstructSCCs(roots); }