using Graphing; using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; namespace Microsoft.Boogie { public static class GraphAlgorithms { public static List> LoopyTopSort(this Graph g) { Contract.Assert(g.Reducible); int n = g.Nodes.Count; var nodeToNumber = new Dictionary(n); var numberToNode = new Node[n]; var allNodes = new List(); int counter = 0; foreach (Node node in g.Nodes) { numberToNode[counter] = node; nodeToNumber[node] = counter; allNodes.Add(counter); counter++; } var loops = new List[n]; foreach (var h in g.Headers) { var loopNodes = new HashSet(); foreach (var b in g.BackEdgeNodes(h)) loopNodes.UnionWith(g.NaturalLoops(h, b)); loops[nodeToNumber[h]] = new List(loopNodes.Select(node => nodeToNumber[node])); } var successors = new List[n]; int[] incomingEdges = new int[n]; foreach (var e in g.Edges) { Contract.Assert(e.Item1 != null); Contract.Assert(e.Item2 != null); int source = nodeToNumber[e.Item1], target = nodeToNumber[e.Item2]; if (loops[target] == null || !loops[target].Contains(source)) { if (successors[source] == null) successors[source] = new List(); successors[source].Add(target); incomingEdges[target]++; } } var sortedNodes = new List>(); var regionStack = new Stack>>(); regionStack.Push(new Tuple>(default(Node), allNodes)); while (regionStack.Count != 0) { int rootIndex = -1; foreach (var i in regionStack.Peek().Item2) { if (incomingEdges[i] == 0) { rootIndex = i; break; } } if (rootIndex == -1) { var region = regionStack.Pop(); if (regionStack.Count != 0) sortedNodes.Add(new Tuple(region.Item1, true)); continue; } incomingEdges[rootIndex] = -1; sortedNodes.Add(new Tuple(numberToNode[rootIndex], false)); if (successors[rootIndex] != null) foreach (int s in successors[rootIndex]) incomingEdges[s]--; if (loops[rootIndex] != null) regionStack.Push(new Tuple>(numberToNode[rootIndex], loops[rootIndex])); } return sortedNodes; } } }