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));
            }
        }
示例#2
0
        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));
        }
示例#4
0
        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));
        }
示例#7
0
        /// <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);
        }
示例#8
0
        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);
        }