public void If() { // Artificially construct an if construct. var graph = TestGraphs.CreateIfElse(); var n1 = graph.GetNodeById(1); var n2 = graph.GetNodeById(2); var n3 = graph.GetNodeById(3); var n4 = graph.GetNodeById(4); // Record a depth first traversal. var traversal = new DepthFirstTraversal(); var recorder = new TraversalOrderRecorder(traversal); traversal.Run(n1); // Check if n1 is before any node in the traversal. Assert.All(graph.GetNodes(), n => Assert.True(n1 == n || recorder.GetIndex(n1) < recorder.GetIndex(n))); // DFS should either pick n2 or n3. If n2, then n4 is before n3, otherwise before n2. if (recorder.GetIndex(n2) < recorder.GetIndex(n3)) { Assert.True(recorder.GetIndex(n4) < recorder.GetIndex(n3)); } else { Assert.True(recorder.GetIndex(n4) < recorder.GetIndex(n2)); } }
public void BreadthFirstOrderTest() { var traversal = new BreadthFirstTraversal(); var orderRecorder = new TraversalOrderRecorder(traversal); traversal.Run(Tree.Nodes["1"]); Assert.True(orderRecorder.GetIndex(Tree.Nodes["2"]) < orderRecorder.GetIndex(Tree.Nodes["4A"])); Assert.True(orderRecorder.GetIndex(Tree.Nodes["3A"]) < orderRecorder.GetIndex(Tree.Nodes["4A"])); }
public void SingleNode() { var graph = TestGraphs.CreateSingularGraph(); var startNode = graph.GetNodeById(1); // Record a depth first traversal. var traversal = new DepthFirstTraversal(); var recorder = new TraversalOrderRecorder(traversal); traversal.Run(startNode); Assert.Single(recorder.GetTraversal()); Assert.Equal(0, recorder.GetIndex(startNode)); }
public void DepthFirstOrderTest() { var traversal = new DepthFirstTraversal(); var recorder = new TraversalOrderRecorder(traversal); traversal.Run(Tree.Nodes["1"]); if (recorder.GetIndex(Tree.Nodes["2"]) < recorder.GetIndex(Tree.Nodes["3A"])) { Assert.True(recorder.GetIndex(Tree.Nodes["4A"]) < recorder.GetIndex(Tree.Nodes["3A"])); } else { Assert.True(recorder.GetIndex(Tree.Nodes["5"]) < recorder.GetIndex(Tree.Nodes["4A"])); } }
public void PathReversed() { // Artificially construct a path of four nodes in sequential order. var graph = TestGraphs.CreatePath(); // Record a depth first traversal. var traversal = new DepthFirstTraversal(true); var recorder = new TraversalOrderRecorder(traversal); traversal.Run(graph.GetNodeById(4)); // Traversal should exactly be the path. Assert.Equal(new INode[] { graph.GetNodeById(4), graph.GetNodeById(3), graph.GetNodeById(2), graph.GetNodeById(1), }, recorder.GetTraversal()); }
public void LoopReversed() { // Artificially construct a looping construct. var graph = TestGraphs.CreateLoop(); var n1 = graph.GetNodeById(1); var n2 = graph.GetNodeById(2); var n3 = graph.GetNodeById(3); var n4 = graph.GetNodeById(4); // Record a depth first traversal. var traversal = new DepthFirstTraversal(true); var recorder = new TraversalOrderRecorder(traversal); traversal.Run(n4); // Check if n1 is before any node in the traversal. Assert.All(graph.GetNodes(), n => Assert.True(n4 == n || recorder.GetIndex(n4) < recorder.GetIndex(n))); Assert.True(recorder.GetIndex(n1) > recorder.GetIndex(n3)); }
/// <summary> /// Computes the dominator tree of a control flow graph, defined by its entrypoint. /// </summary> /// <param name="entrypoint">The entrypoint of the control flow graph.</param> /// <returns>A dictionary mapping all the nodes to their immediate dominator.</returns> /// <remarks> /// The algorithm used is based on the one engineered by Lengauer and Tarjan. /// https://www.cs.princeton.edu/courses/archive/fall03/cs528/handouts/a%20fast%20algorithm%20for%20finding.pdf /// https://www.cl.cam.ac.uk/~mr10/lengtarj.pdf /// </remarks> private static IDictionary <IIdentifiedNode, IIdentifiedNode> GetImmediateDominators(IIdentifiedNode entrypoint) { var idom = new Dictionary <IIdentifiedNode, IIdentifiedNode>(); var semi = new Dictionary <IIdentifiedNode, IIdentifiedNode>(); var ancestor = new Dictionary <IIdentifiedNode, IIdentifiedNode>(); var bucket = new Dictionary <IIdentifiedNode, ISet <IIdentifiedNode> >(); var traversal = new DepthFirstTraversal(); var order = new TraversalOrderRecorder(traversal); var parents = new ParentRecorder(traversal); traversal.Run(entrypoint); var orderedNodes = order.GetTraversal(); foreach (var node in orderedNodes.Cast <IIdentifiedNode>()) { idom[node] = null; semi[node] = node; ancestor[node] = null; bucket[node] = new HashSet <IIdentifiedNode>(); } for (int i = orderedNodes.Count - 1; i >= 1; i--) { var current = (IIdentifiedNode)orderedNodes[i]; var parent = (IIdentifiedNode)parents.GetParent(current); // step 2 foreach (var predecessor in current.GetPredecessors().Cast <IIdentifiedNode>()) { var u = Eval(predecessor, ancestor, semi, order); if (order.GetIndex(semi[current]) > order.GetIndex(semi[u])) { semi[current] = semi[u]; } } bucket[semi[current]].Add(current); Link(parent, current, ancestor); // step 3 foreach (var bucketNode in bucket[parent]) { var u = Eval(bucketNode, ancestor, semi, order); if (order.GetIndex(semi[u]) < order.GetIndex(semi[bucketNode])) { idom[bucketNode] = u; } else { idom[bucketNode] = parent; } } bucket[parent].Clear(); } // step 4 for (int i = 1; i < orderedNodes.Count; i++) { var w = (IIdentifiedNode)orderedNodes[i]; if (idom[w] != semi[w]) { idom[w] = idom[idom[w]]; } } idom[entrypoint] = entrypoint; return(idom); }
private static IIdentifiedNode Eval(IIdentifiedNode node, IDictionary <IIdentifiedNode, IIdentifiedNode> ancestors, IDictionary <IIdentifiedNode, IIdentifiedNode> semi, TraversalOrderRecorder order) { var a = ancestors[node]; while (a != null && ancestors[a] != null) { if (order.GetIndex(semi[node]) > order.GetIndex(semi[a])) { node = a; } a = ancestors[a]; } return(node); }