public void FindSCC_WithSingleNode() { var graph = new List <int>[] { new List <int>() { }, }; var expected = new List <List <int> > { new List <int> { 0 } }; var result = StronglyConnectedComponents.FindStronglyConnectedComponents(graph); result.ForEach(scc => scc.Sort()); result = result.OrderBy(scc => scc.Count).ThenBy(scc => scc.First()).ToList(); Assert.AreEqual(expected.Count, result.Count, "Incorrect amount of strongly connected components."); for (int i = 0; i < expected.Count; i++) { CollectionAssert.AreEqual( expected[i], result[i], $"Expected component to be [{string.Join(", ", expected[i])}], but was [{string.Join(", ", result[i])}]."); } }
public static List<Block/*!*/>/*!*/ UnrollLoops(Block start, int unrollMaxDepth, bool soundLoopUnrolling) { Contract.Requires(start != null); Contract.Requires(0 <= unrollMaxDepth); Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>())); Dictionary<Block, GraphNode/*!*/> gd = new Dictionary<Block, GraphNode/*!*/>(); HashSet<Block> beingVisited = new HashSet<Block>(); GraphNode gStart = GraphNode.ComputeGraphInfo(null, start, gd, beingVisited); // Compute SCCs StronglyConnectedComponents<GraphNode/*!*/> sccs = new StronglyConnectedComponents<GraphNode/*!*/>(gd.Values, Preds, Succs); Contract.Assert(sccs != null); sccs.Compute(); Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>> containingSCC = new Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>>(); foreach (SCC<GraphNode/*!*/> scc in sccs) { foreach (GraphNode/*!*/ n in scc) { Contract.Assert(n != null); containingSCC[n] = scc; } } LoopUnroll lu = new LoopUnroll(unrollMaxDepth, soundLoopUnrolling, containingSCC, new List<Block/*!*/>()); lu.Visit(gStart); lu.newBlockSeqGlobal.Reverse(); return lu.newBlockSeqGlobal; }
// Compute SCCs and determine a priority order for impls static Dictionary <string, int> DeterminePriorityOrder(Program program, Graph <string> callgraph) { var impls = new HashSet <string>(); program.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => impls.Add(impl.Name)); var sccs = new StronglyConnectedComponents <string>(callgraph.Nodes, new Adjacency <string>(n => DualHoudini ? callgraph.Successors(n) : callgraph.Predecessors(n)), new Adjacency <string>(n => DualHoudini ? callgraph.Predecessors(n) : callgraph.Successors(n))); sccs.Compute(); // impl -> priority var impl2Priority = new Dictionary <string, int>(); int p = 0; foreach (var scc in sccs) { foreach (var impl in scc) { impl2Priority.Add(impl, p); p++; } } return(impl2Priority); }
public void Discover_ShouldFind4SCC() { var sccProcessor = new StronglyConnectedComponents <char, int>(); var result = sccProcessor.Discover(_graph); result.Count.Should().Be(4); }
public static List <Block /*!*/> /*!*/ UnrollLoops(Block start, int unrollMaxDepth, bool soundLoopUnrolling) { Contract.Requires(start != null); Contract.Requires(0 <= unrollMaxDepth); Contract.Ensures(cce.NonNullElements(Contract.Result <List <Block> >())); Dictionary <Block, GraphNode /*!*/> gd = new Dictionary <Block, GraphNode /*!*/>(); HashSet <Block> beingVisited = new HashSet <Block>(); GraphNode gStart = GraphNode.ComputeGraphInfo(null, start, gd, beingVisited); // Compute SCCs StronglyConnectedComponents <GraphNode /*!*/> sccs = new StronglyConnectedComponents <GraphNode /*!*/>(gd.Values, Preds, Succs); Contract.Assert(sccs != null); sccs.Compute(); Dictionary <GraphNode /*!*/, SCC <GraphNode /*!*/> > containingSCC = new Dictionary <GraphNode /*!*/, SCC <GraphNode /*!*/> >(); foreach (SCC <GraphNode /*!*/> scc in sccs) { foreach (GraphNode /*!*/ n in scc) { Contract.Assert(n != null); containingSCC[n] = scc; } } LoopUnroll lu = new LoopUnroll(unrollMaxDepth, soundLoopUnrolling, containingSCC, new List <Block /*!*/>()); lu.Visit(gStart); lu.newBlockSeqGlobal.Reverse(); return(lu.newBlockSeqGlobal); }
private static IReadOnlyList <HashSet <ValueTag> > ComputePhiSCCs( HashSet <ValueTag> phiFunctions, Dictionary <ValueTag, HashSet <ValueTag> > phiArgs, Dictionary <ValueTag, ValueTag> copyMap) { // Computes all phi SCCs in the subgraph induced by phis. return(StronglyConnectedComponents.Compute( phiFunctions, arg => phiArgs[arg].Where(phiFunctions.Contains))); }
public void Discover_ShouldFind5LargestSCC() { var sccProcessor = new StronglyConnectedComponents <int, int>(); var result = sccProcessor.Discover(_graph); var biggestSizes = result.Select(g => g.Count()) .OrderByDescending(c => c) .Take(5).ToList(); biggestSizes.ForEach(Console.WriteLine); }
public void Test() { var g = GraphGenerator.dag4StronglyConnectedComponents(); var scc = new StronglyConnectedComponents(g); for (var v = 0; v < g.V(); ++v) { console.WriteLine(v + "\t:" + scc.componentId(v)); } }
public void Search_must_work() { string path = Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName, "TestFiles", "TestGraph.txt"); Graph <string> graph = GraphGenerator.LoadFromFile(path, isDirected: true); List <List <Vertex <string> > > stronglyConnectedComponents = StronglyConnectedComponents <string> .Search(graph); Assert.AreEqual(2, stronglyConnectedComponents.Count); Assert.AreEqual(4, stronglyConnectedComponents[0].Count); Assert.AreEqual(1, stronglyConnectedComponents[1].Count); }
public IEnumerable <Method> OrderedMethods() { // components are reverse ordered List <List <Method> > components = StronglyConnectedComponents.Compute(this.callGraph); for (int i = components.Count - 1; i >= 0; i--) { foreach (Method method in components[i]) { yield return(method); } } }
public void Test() { var graph1 = new DirectedWeightedGraph(false); for (int i = 'a'; i <= 'e'; i++) { graph1.AddVertex(Convert.ToString(Convert.ToChar(i))); } graph1.AddEdge("a", "b", 1); graph1.AddEdge("b", "a", 2); graph1.AddEdge("c", "a", 3); graph1.AddEdge("c", "b", 600); graph1.AddEdge("c", "d", 0); graph1.AddEdge("d", "c", 7); graph1.AddEdge("d", "b", 7); var list = new List <List <Vertex> >(); var subList1 = new List <Vertex>(); var subList2 = new List <Vertex>(); var subList3 = new List <Vertex>(); subList1.Add(graph1.GetVertex("b")); subList1.Add(graph1.GetVertex("a")); subList2.Add(graph1.GetVertex("d")); subList2.Add(graph1.GetVertex("c")); subList3.Add(graph1.GetVertex("e")); list.Add(subList1); list.Add(subList2); list.Add(subList3); var testList = StronglyConnectedComponents <DirectedWeightedGraph> .GetComponents(graph1); Assert.AreEqual(list.Count, testList.Count); for (int subList = 0; subList <= 1; subList++) { for (int vertex = 0; vertex <= 1; vertex++) { Assert.AreEqual(list[subList][vertex], testList[subList][vertex]); } } Assert.AreEqual(list[2][0], testList[2][0]); }
private void CalculateConnectedComponents(IGraph graph, bool stronglyConnected) { ResultItemCollection <Component> components; if (stronglyConnected) { var result = new StronglyConnectedComponents().Run(graph); components = result.Components; } else { var result = new ConnectedComponents().Run(graph); components = result.Components; } if (components.Count > 0) { // generate a color array var colors = GenerateColors(false, components.Count); var visitedEdges = new HashSet <IEdge>(); for (var i = 0; i < components.Count; i++) { var component = components[i]; var color = colors[i]; foreach (var edge in component.InducedEdges) { // each edge of the same cycle get the same tag visitedEdges.Add(edge); var tag = InitializeTag(edge); tag.CurrentColor = color; } component.Nodes.ForEach(node => { InitializeTag(node).CurrentColor = color; }); } foreach (var edge in graph.Edges) { if (visitedEdges.Add(edge)) { InitializeTag(edge); } } } }
public HashSet <VariableDescriptor> DependsOn(VariableDescriptor v) { if (DependsOnSCCsDAG == null) { if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Variable dependence: computing SCCs"); } Adjacency <VariableDescriptor> next = new Adjacency <VariableDescriptor>(dependsOnNonTransitive.Successors); Adjacency <VariableDescriptor> prev = new Adjacency <VariableDescriptor>(dependsOnNonTransitive.Predecessors); StronglyConnectedComponents <VariableDescriptor> DependsOnSCCs = new StronglyConnectedComponents <VariableDescriptor>( dependsOnNonTransitive.Nodes, next, prev); DependsOnSCCs.Compute(); VariableDescriptorToSCC = new Dictionary <VariableDescriptor, SCC <VariableDescriptor> >(); foreach (var scc in DependsOnSCCs) { foreach (var s in scc) { VariableDescriptorToSCC[s] = scc; } } DependsOnSCCsDAG = new Graph <SCC <VariableDescriptor> >(); foreach (var edge in dependsOnNonTransitive.Edges) { if (VariableDescriptorToSCC[edge.Item1] != VariableDescriptorToSCC[edge.Item2]) { DependsOnSCCsDAG.AddEdge(VariableDescriptorToSCC[edge.Item1], VariableDescriptorToSCC[edge.Item2]); } } SCC <VariableDescriptor> dummy = new SCC <VariableDescriptor>(); foreach (var n in dependsOnNonTransitive.Nodes) { DependsOnSCCsDAG.AddEdge(VariableDescriptorToSCC[n], dummy); } if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Variable dependence: SCCs computed!"); } } return(DependsOn(VariableDescriptorToSCC[v])); }
public bool MayReach(Block src, Block dst) { if (ReachabilityGraphSCCsDAG == null) { if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Interprocedural reachability: computing SCCs"); } Adjacency <Block> next = new Adjacency <Block>(reachabilityGraph.Successors); Adjacency <Block> prev = new Adjacency <Block>(reachabilityGraph.Predecessors); StronglyConnectedComponents <Block> ReachabilitySCCs = new StronglyConnectedComponents <Block>( reachabilityGraph.Nodes, next, prev); ReachabilitySCCs.Compute(); BlockToSCC = new Dictionary <Block, SCC <Block> >(); foreach (var scc in ReachabilitySCCs) { foreach (var s in scc) { BlockToSCC[s] = scc; } } ReachabilityGraphSCCsDAG = new Graph <SCC <Block> >(); foreach (var edge in reachabilityGraph.Edges) { if (BlockToSCC[edge.Item1] != BlockToSCC[edge.Item2]) { ReachabilityGraphSCCsDAG.AddEdge(BlockToSCC[edge.Item1], BlockToSCC[edge.Item2]); } } SCC <Block> dummy = new SCC <Block>(); foreach (var n in reachabilityGraph.Nodes) { ReachabilityGraphSCCsDAG.AddEdge(BlockToSCC[n], dummy); } if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Interprocedural reachability: SCCs computed!"); } } return(ReachableFrom(BlockToSCC[src]).Contains(dst)); }
private bool IsFinitelyInstantiable() { var sccs = new StronglyConnectedComponents <TypeVariable>(typeVariableDependencyGraph.Nodes, typeVariableDependencyGraph.Predecessors, typeVariableDependencyGraph.Successors); sccs.Compute(); foreach (var scc in sccs) { foreach (var edge in strongDependencyEdges) { if (scc.Contains(edge.Item1) && scc.Contains(edge.Item2)) { return(false); } } } return(true); }
private void ConstructStagesDAG() { if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Annotation dependence analysis: Computing SCCs"); } Adjacency <string> next = new Adjacency <string>(AnnotationDependences.Successors); Adjacency <string> prev = new Adjacency <string>(AnnotationDependences.Predecessors); SCCs = new StronglyConnectedComponents <string>( AnnotationDependences.Nodes, next, prev); SCCs.Compute(); if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Annotation dependence analysis: Building stages DAG"); } Dictionary <string, SCC <string> > rep = new Dictionary <string, SCC <string> >(); foreach (var scc in SCCs) { foreach (var s in scc) { rep[s] = scc; } } StagesDAG = new Graph <SCC <string> >(); foreach (var edge in AnnotationDependences.Edges) { if (rep[edge.Item1] != rep[edge.Item2]) { StagesDAG.AddEdge(rep[edge.Item1], rep[edge.Item2]); } } SCC <string> dummy = new SCC <string>(); foreach (var scc in SCCs) { StagesDAG.AddEdge(scc, dummy); } }
/// <summary> /// Lädt einen Graphen aus der angegebenen Datei und berechnet für diesen die strongly connected components /// </summary> /// <param name="fileName"></param> public static void CallStrongConnect(string fileName) { Graph <string> graph = ApplicationHelper.LoadGraph(fileName, true); List <List <Vertex <string> > > components = StronglyConnectedComponents <string> .Search(graph); // Das Ergebnis in eine Datei schreiben. string baseFileName = fileName.Split('.')[0]; ApplicationHelper.WriteResult( baseFileName, "strongConnectResult_", "", components.Select( (list) => "Component " + components.IndexOf(list) + ":" + Environment.NewLine + list.Select((edge) => edge.ToString()).Aggregate((a, b) => a + Environment.NewLine + b))) ; }
private void ConstructStagesDAG() { if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Annotation dependence analysis: Computing SCCs"); } Adjacency<string> next = new Adjacency<string>(AnnotationDependences.Successors); Adjacency<string> prev = new Adjacency<string>(AnnotationDependences.Predecessors); SCCs = new StronglyConnectedComponents<string>( AnnotationDependences.Nodes, next, prev); SCCs.Compute(); if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Annotation dependence analysis: Building stages DAG"); } Dictionary<string, SCC<string>> rep = new Dictionary<string, SCC<string>>(); foreach (var scc in SCCs) { foreach (var s in scc) { rep[s] = scc; } } StagesDAG = new Graph<SCC<string>>(); foreach (var edge in AnnotationDependences.Edges) { if (rep[edge.Item1] != rep[edge.Item2]) { StagesDAG.AddEdge(rep[edge.Item1], rep[edge.Item2]); } } SCC<string> dummy = new SCC<string>(); foreach (var scc in SCCs) { StagesDAG.AddEdge(scc, dummy); } }
public void TestScc() { // https://en.wikipedia.org/wiki/Strongly_connected_component // // Adjacency list of directed graph with 8 nodes: // // [1] -> 2 // [2] -> 3 -> 5 -> 6 // [3] -> 4 -> 7 // [4] -> 3 -> 8 // [5] -> 1 -> 6 // [6] -> 7 // [7] -> 6 // [8] -> 4 -> 7 // // Adjacency matrix: var A = SparseMatrix.OfRowMajor(8, 8, new double[8 * 8] { 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1 }); int n = A.ColumnCount; var scc = StronglyConnectedComponents.Generate(A); var r = new int[] { 0, 3, 6, 8 }; var p = new int[] { 0, 1, 4, 2, 3, 7, 5, 6 }; Assert.AreEqual(scc.Blocks, 3); CollectionAssert.AreEqual(scc.BlockPointers, r); CollectionAssert.AreEqual(scc.Indices, p); }
public static List <SCC <Procedure> > ComputeOrderedSCCs(Graph <Procedure> graph) { Adjacency <Procedure> next = new Adjacency <Procedure>(graph.Successors); Adjacency <Procedure> prev = new Adjacency <Procedure>(graph.Predecessors); var sccs = new StronglyConnectedComponents <Procedure>(graph.Nodes, next, prev); sccs.Compute(); //sccs.Iter(s => { s.Iter(p => Console.Write(p + ", ")); Console.WriteLine(); }); var order = sccs.ToList(); for (int i = 0; i < order.Count; i++) { for (int j = i + 1; j < order.Count; j++) { Debug.Assert(order[i].All(p => order[j].All(p2 => !graph.Edge(p2, p)))); } } return(order); }
/** * Returns List::List::Object with the Lists of nodes of all elementary * cycles in the graph. * * @return List::List::Object with the Lists of the elementary cycles. */ public List <List <int> > getElementaryCycles() { this.cycles = new List <List <int> >(); this.blocked = graphNodes.ToDictionary(n => n, n => false); this.B = graphNodes.ToDictionary(n => n, n => new List <int>()); this.stack = new List <int>(); StronglyConnectedComponents sccs = new StronglyConnectedComponents(adjList); int s = 0; while (true) { SCCResult sccResult = sccs.getAdjacencyList(s, graphNodes); if (sccResult != null && sccResult.getAdjList() != null) { var scc = sccResult.getAdjList(); s = sccResult.getLowestNodeId(); foreach (var j in scc.Keys) { if ((scc[j] != null) && (scc[j].Count > 0)) { blocked[j] = false; B[j] = new List <int>(); } } findCycles(s, s, scc); s = StronglyConnectedComponents.getNextNode(s, graphNodes); } else { break; } } return(cycles); }
public Implementation(IToken/*!*/ tok, string/*!*/ name, List<TypeVariable>/*!*/ typeParams, List<Variable>/*!*/ inParams, List<Variable>/*!*/ outParams, List<Variable>/*!*/ localVariables, [Captured] List<Block/*!*/>/*!*/ blocks, QKeyValue kv) : base(tok, name, typeParams, inParams, outParams) { Contract.Requires(name != null); Contract.Requires(inParams != null); Contract.Requires(outParams != null); Contract.Requires(localVariables != null); Contract.Requires(cce.NonNullElements(blocks)); LocVars = localVariables; Blocks = blocks; BlockPredecessorsComputed = false; scc = null; Attributes = kv; }
/// <summary> /// Compute the strongly connected compontents of the blocks in the implementation. /// As a side effect, it also computes the "predecessor" relation for the block in the implementation /// </summary> override public void ComputeStronglyConnectedComponents() { if (!this.BlockPredecessorsComputed) ComputePredecessorsForBlocks(); Adjacency<Block/*!*/> next = new Adjacency<Block/*!*/>(Successors); Adjacency<Block/*!*/> prev = new Adjacency<Block/*!*/>(Predecessors); this.scc = new StronglyConnectedComponents<Block/*!*/>(this.Blocks, next, prev); scc.Compute(); foreach (Block/*!*/ block in this.Blocks) { Contract.Assert(block != null); block.Predecessors = new List<Block>(); } }
public void FindSCC_WithMultipleComponents() { var graph = new List <int>[] { new List <int>() { 1, 11, 13 }, // children of node 0 new List <int>() { 6 }, // children of node 1 new List <int>() { 0 }, // children of node 2 new List <int>() { 4 }, // children of node 3 new List <int>() { 3, 6 }, // children of node 4 new List <int>() { 13 }, // children of node 5 new List <int>() { 0, 11 }, // children of node 6 new List <int>() { 12 }, // children of node 7 new List <int>() { 6, 11 }, // children of node 8 new List <int>() { 0 }, // children of node 9 new List <int>() { 4, 6, 10 }, // children of node 10 new List <int>() { }, // children of node 11 new List <int>() { 7 }, // children of node 12 new List <int>() { 2, 9 }, // children of node 13 }; var expected = new List <List <int> > { new List <int> { 5 }, new List <int> { 8 }, new List <int> { 10 }, new List <int> { 11 }, new List <int> { 3, 4 }, new List <int> { 7, 12 }, new List <int> { 0, 1, 2, 6, 9, 13 }, }; var result = StronglyConnectedComponents.FindStronglyConnectedComponents(graph); result.ForEach(scc => scc.Sort()); result = result.OrderBy(scc => scc.Count).ThenBy(scc => scc.First()).ToList(); Assert.AreEqual(expected.Count, result.Count, "Incorrect amount of strongly connected components."); for (int i = 0; i < expected.Count; i++) { CollectionAssert.AreEqual( expected[i], result[i], $"Expected component to be [{string.Join(", ", expected[i])}], but was [{string.Join(", ", result[i])}]."); } }
public VCGenOutcome ComputeSummaries() { // Compute SCCs and determine a priority order for impls var Succ = new Dictionary<string, HashSet<string>>(); var Pred = new Dictionary<string, HashSet<string>>(); name2Impl.Keys.Iter(s => Succ[s] = new HashSet<string>()); name2Impl.Keys.Iter(s => Pred[s] = new HashSet<string>()); foreach(var impl in name2Impl.Keys) { Succ[impl] = new HashSet<string>(); impl2functionsAsserted[impl].Iter(f => function2implAssumed[f].Iter(succ => { Succ[impl].Add(succ); Pred[succ].Add(impl); })); } var sccs = new StronglyConnectedComponents<string>(name2Impl.Keys, new Adjacency<string>(n => Pred[n]), new Adjacency<string>(n => Succ[n])); sccs.Compute(); // impl -> priority var impl2Priority = new Dictionary<string, int>(); int p = 0; foreach (var scc in sccs) { foreach (var impl in scc) { impl2Priority.Add(impl, p); p++; } } VCGenOutcome overallOutcome = null; string[] templates = {"(1)", "(1;1)", "(2)", "((1;1);1)", "((1;1),1)", "(1;2)", "(3)", "(1;3)", "(4)", "(5;2)"}; if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Max integral value in the program: " + constantRange); } for (int i = 0; i < templates.Count(); i++) { var template = templates[i]; TemplateParser.initialize(template); Template t = TemplateParser.Parse(); List<int> cvalues = new List<int>(); cvalues.Add(2); int maxRange = constantRange > i ? constantRange : i; if (maxRange > 2) cvalues.Add(maxRange); foreach (var cvalue in cvalues) { if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Inferring Invariants in the template Octagons" + template + " with constantRange = " + cvalue); } ICEOutcome result = LearnInvFromTemplate(impl2Priority, t, cvalue, out overallOutcome); // The program was verified with the current template! if (result == ICEOutcome.InvariantFound) { if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Inferred Invariants in the template Octagons" + template + " with constantRange = " + cvalue); } if (cvalue <= 2) goto exit; int min = 2; int max = cvalue; int mid = (min + max) / 2; while (min <= max) { VCGenOutcome overallOutcomePrime = null; if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Inferring Invariants in the template Octagons" + template + " with constantRange = " + mid); } ICEOutcome resultPrime = LearnInvFromTemplate(impl2Priority, t, mid, out overallOutcomePrime); if (resultPrime == ICEOutcome.InvariantFound) { max = mid - 1; mid = (max + min) / 2; if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Inferred Invariants in the template Octagons" + template + " with constantRange = " + mid); } } else if (resultPrime == ICEOutcome.InvariantNotFound) { min = mid + 1; mid = (min + max) / 2; } else if (resultPrime == ICEOutcome.ErrorFound) { throw new AbsHoudiniInternalError("Contrary results: Invariant found for constants < " + cvalue + "; error found for constants <" + mid); } else if (resultPrime == ICEOutcome.Timeout) { break; } } // last iteration did not work. So try min again. if (min != mid) { ICEOutcome resultPrime = LearnInvFromTemplate(impl2Priority, t, min, out overallOutcome); Debug.Assert(resultPrime == ICEOutcome.InvariantFound); } goto exit; } else if (result == ICEOutcome.ErrorFound) goto exit; else if (result == ICEOutcome.Timeout) return overallOutcome; Debug.Assert(result == ICEOutcome.InvariantNotFound); } // end of loop over template constants } // end of loop over boolean (structure of the) templates exit: z3Context.context.Dispose(); z3Context.config.Dispose(); if (true) { Console.WriteLine("Prover time = {0}", proverTime.TotalSeconds.ToString("F2")); Console.WriteLine("Number of prover queries = " + numProverQueries); Console.WriteLine("Z3 Learner time = {0}", z3LearnerTime.TotalSeconds.ToString("F2")); Console.WriteLine("Number of Z3 Learner queries = " + numZ3LearnerQueries); Console.WriteLine("Total time: {0}", proverTime.Add(z3LearnerTime).TotalSeconds.ToString("F2")); Console.WriteLine("Number of examples:" + this.numPosExamples); Console.WriteLine("Number of counter-examples:" + this.numNegCounterExamples); Console.WriteLine("Number of implications:" + this.numImplications); Console.WriteLine("Total size of sample: " + (int)(this.numPosExamples + this.numNegCounterExamples + 2 * this.numImplications)); #if C5 Console.WriteLine("Total points repeated in the sample: " + this.C5repeatedPoints); #endif //Console.WriteLine("Range of constants in the template = " + constantRange); } if (CommandLineOptions.Clo.PrintAssignment) { // Print the answer existentialFunctions.Values.Iter(PrintFunction); } #if C5 generateC5Files(); #endif return overallOutcome; }
public static bool Check(Program program) { var checkingContext = new CheckingContext(null); var functionDependencyChecker = new FunctionDependencyChecker(); program.TopLevelDeclarations.OfType <Function>().Iter(function => { var expr = QKeyValue.FindExprAttribute(function.Attributes, "inline"); if (expr != null && expr.Type != Type.Bool) { checkingContext.Error(function.tok, "Parameter to :inline attribute on a function must be Boolean"); } if (QKeyValue.FindBoolAttribute(function.Attributes, "inline") && QKeyValue.FindBoolAttribute(function.Attributes, "define")) { checkingContext.Error(function.tok, "A function may not have both :inline and :define attributes"); } if (QKeyValue.FindBoolAttribute(function.Attributes, "inline") && function.Body == null) { checkingContext.Error(function.tok, "Function with :inline attribute must have a body"); } if (QKeyValue.FindBoolAttribute(function.Attributes, "define") && function.DefinitionBody == null) { checkingContext.Error(function.tok, "Function with :define attribute must have a body"); } }); if (checkingContext.ErrorCount > 0) { return(false); } program.TopLevelDeclarations.OfType <Function>() .Iter(function => functionDependencyChecker.VisitFunction(function)); var functionDependencyGraph = functionDependencyChecker.functionDependencyGraph; var selfLoops = functionDependencyGraph.Edges.SelectMany(edge => edge.Item1 == edge.Item2 ? new[] { edge.Item1 } : Enumerable.Empty <Function>()).ToHashSet(); var sccs = new StronglyConnectedComponents <Function>( functionDependencyGraph.Nodes, functionDependencyGraph.Predecessors, functionDependencyGraph.Successors); sccs.Compute(); sccs.Iter(scc => { if (scc.Count > 1 || scc.Count == 1 && selfLoops.Contains(scc.First())) { var errorMsg = "Call cycle detected among functions"; var first = true; var token = Token.NoToken; scc.Iter(function => { if (first) { first = false; errorMsg += ": "; token = function.tok; } else { errorMsg += ", "; } errorMsg += function.Name; }); checkingContext.Error(token, errorMsg); } }); return(checkingContext.ErrorCount == 0); }
// Callgraph-ordered public override IEnumerable <Method> OrderedMethods() { var components = StronglyConnectedComponents.Compute(this.callGraph); // components are in caller to callee order, so reverse it components.Reverse(); var classGraph = new SingleEdgeGraph <Type, Unit>(null); var mAlreadyThere = new Set <Type>(); Predicate <Node> nodeStartVisitor = n => { if (n.Kind != Node.Tag.method) { return(true); } var m = n.Method; var dt = this.md.DeclaringType(m); if (mAlreadyThere.Add(dt)) { classGraph.AddNode(dt); } // add edge dt -> type(each successor) foreach (var suc in this.callGraph.Successors(n)) { if (suc.Two.Kind != Node.Tag.method) { continue; } var succmethod = suc.Two.Method; var tsuc = this.md.DeclaringType(succmethod); if (mAlreadyThere.Add(tsuc)) { classGraph.AddNode(tsuc); } classGraph.AddEdge(dt, Unit.Value, tsuc); } return(true); }; var dfs_construct_class_graph = new DepthFirst.Visitor <Node, Unit>(this.callGraph, nodeStartVisitor); dfs_construct_class_graph.VisitAll(); // Now get the ordering of the class graph var class_components = StronglyConnectedComponents.Compute(classGraph); class_components.Reverse(); // Stores the class order var class_order = new Dictionary <Type, int>(); int index = 0; foreach (var compo in class_components) { foreach (var cl in compo) { class_order.Add(cl, index++); } } var indexes = new Dictionary <Method, int>(); Comparison <Method> compareMethods = (m1, m2) => { var t1 = class_order[this.md.DeclaringType(m1)]; var t2 = class_order[this.md.DeclaringType(m2)]; if (t1 != t2) { return(t2 - t1); } // regarding to class order, m1 == m2, i.e. keep global methods order return(indexes[m2] - indexes[m1]); }; // Stores the global method order to decide inside class graph strong components // And populate the method list var ordered_methods = new PriorityQueue <Method>(compareMethods); index = 0; foreach (var component in components) { foreach (var node in component) { if (node.Kind == Node.Tag.method) { indexes[node.Method] = index++; ordered_methods.Add(node.Method); } } } while (ordered_methods.Count > 0) { yield return(ordered_methods.Pull()); } }
public override CBAProgram runCBAPass(CBAProgram program) { var nameImplMap = BoogieUtil.nameImplMapping(program); // Construct call graph, compute SCCs var graph = new Graph <string>(); foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { impl.Blocks.Iter(block => block.Cmds.OfType <CallCmd>().Iter(cmd => graph.AddEdge(impl.Name, cmd.callee))); } graph.AddSource(program.mainProcName); var preds = new Adjacency <string>(st => graph.Predecessors(st)); var succs = new Adjacency <string>(st => graph.Successors(st)); var sccs = new StronglyConnectedComponents <string>(graph.Nodes, preds, succs); sccs.Compute(); //var dotFileCnt = 1; // For each SCC, compute backedges foreach (var scc in sccs) { if (scc.Count == 1) { var onlyProc = scc.First(); if (nameImplMap.ContainsKey(onlyProc) && QKeyValue.FindBoolAttribute(nameImplMap[onlyProc].Attributes, "LoopProcedure")) { continue; } if (graph.Successors(onlyProc).All(callee => callee != onlyProc)) { continue; } } Console.Write("Considering SCC: "); scc.Iter(s => Console.Write("{0} ", s)); Console.WriteLine(); foundRecursion = true; // pick source var sccProcs = new HashSet <string>(scc); var src = scc.FirstOrDefault(proc => graph.Predecessors(proc).Any(pred => !sccProcs.Contains(pred))); if (src == null) { src = scc.First(); } var grey = new HashSet <string>(); var black = new HashSet <string>(); grey.Add(src); backedges = new HashSet <Tuple <string, string> >(); dfsTreeParent = new Dictionary <string, string>(); someCycles = new List <HashSet <string> >(); dfs(graph, src, sccProcs, grey, black); InferWhatToCut(graph, scc); // create copies var procCopies = new Dictionary <Tuple <string, int>, Procedure>(); var implCopies = new Dictionary <Tuple <string, int>, Implementation>(); foreach (var name in scc) { var impl = nameImplMap[name]; program.RemoveTopLevelDeclaration(impl); program.RemoveTopLevelDeclaration(impl.Proc); for (int i = 0; i < CommandLineOptions.Clo.RecursionBound; i++) { var dup = new FixedDuplicator(true); var nimpl = dup.VisitImplementation(impl); var nproc = dup.VisitProcedure(impl.Proc); nimpl.Name += string.Format("#{0}", i); nproc.Name += string.Format("#{0}", i); nimpl.Proc = nproc; program.AddTopLevelDeclaration(nimpl); program.AddTopLevelDeclaration(nproc); procCopies.Add(Tuple.Create(impl.Name, i), nproc); implCopies.Add(Tuple.Create(impl.Name, i), nimpl); } } // redirect calls foreach (var name in scc) { foreach (var pred in graph.Predecessors(name)) { if (sccProcs.Contains(pred)) { continue; } var pimpl = nameImplMap[pred]; foreach (var blk in pimpl.Blocks) { var newcmds = new List <Cmd>(); foreach (var cmd in blk.Cmds) { var ccmd = cmd as CallCmd; if (ccmd == null || !sccProcs.Contains(ccmd.callee)) { newcmds.Add(cmd); continue; } newcmds.Add( new CallCmd(ccmd.tok, ccmd.callee + string.Format("#{0}", CommandLineOptions.Clo.RecursionBound - 1), ccmd.Ins, ccmd.Outs, ccmd.Attributes, ccmd.IsAsync)); } blk.Cmds = newcmds; } } for (int i = 0; i < CommandLineOptions.Clo.RecursionBound; i++) { var impl = implCopies[Tuple.Create(name, i)]; foreach (var blk in impl.Blocks) { var newcmds = new List <Cmd>(); foreach (var cmd in blk.Cmds) { var ccmd = cmd as CallCmd; if (ccmd == null || !sccProcs.Contains(ccmd.callee)) { newcmds.Add(cmd); continue; } var cnt = i; if (CutEdge(name, ccmd.callee)) { cnt--; } if (cnt < 0) { newcmds.Add(new AssumeCmd(Token.NoToken, Expr.False)); } else { newcmds.Add(new CallCmd(ccmd.tok, ccmd.callee + string.Format("#{0}", cnt), ccmd.Ins, ccmd.Outs, ccmd.Attributes, ccmd.IsAsync)); } } blk.Cmds = newcmds; } } } } return(program); }
public RHS(CBAProgram program, IWeight iw) { this.iw = iw; this.program = program; intraGraphs = new List <IntraGraph>(); id2Graph = new Dictionary <string, IntraGraph>(); Succ = new Dictionary <string, HashSet <IntraGraph> >(); Pred = new Dictionary <string, HashSet <IntraGraph> >(); computeTime = TimeSpan.Zero; // Make all the graphs program.TopLevelDeclarations .OfType <Implementation>() .Iter(impl => intraGraphs.Add( new IntraGraph(impl, iw, p => { if (!id2Graph.ContainsKey(p)) { return(null); } else { return(id2Graph[p].summary); } } ))); intraGraphs.Iter(g => id2Graph.Add(g.Id, g)); intraGraphs.Iter(g => { Succ.Add(g.Id, new HashSet <IntraGraph>()); Pred.Add(g.Id, new HashSet <IntraGraph>()); }); intraGraphs.Iter(g => g.Callees .Where(s => id2Graph.ContainsKey(s)) .Iter(s => { Succ[g.Id].Add(id2Graph[s]); Pred[s].Add(g); } )); // assign priorities var sccs = new StronglyConnectedComponents <IntraGraph>( intraGraphs, new Adjacency <IntraGraph>(g => Succ[g.Id]), new Adjacency <IntraGraph>(g => Pred[g.Id])); sccs.Compute(); var priority = intraGraphs.Count; foreach (var scc in sccs) { /* * if (scc.Count > 1) * { * Console.WriteLine("SCC size: {0}", scc.Count); * scc.Iter(g => Console.WriteLine("{0}", g.Id)); * } */ scc.Iter(g => g.priority = priority); priority--; } }
public IntraGraph(Implementation impl, IWeight iw, Func <string, IWeight> ProcSummary) { this.impl = impl; this.Id = impl.Name; this.ProcSummary = ProcSummary; priority = 0; idToNode = new Dictionary <string, Node>(); Nodes = new List <Node>(); Edges = new List <Edge>(); calleeToEdgeSrc = new Dictionary <string, HashSet <Node> >(); this.iw = iw; this.summary = iw.Zero(impl); this.precondition = iw.Zero(impl); returnNodes = new List <Node>(); summaryChanged = false; preconditionChanged = false; computedBefore = false; // Create nodes foreach (var block in impl.Blocks) { var n1 = new Node(block.Label + "::in", iw.Zero(impl)); var n2 = new Node(block.Label + "::out", iw.Zero(impl)); Nodes.Add(n1); Nodes.Add(n2); var edge = new Edge(n1, n2, block.Cmds.OfType <Cmd>()); n1.AddEdge(edge); n2.AddEdge(edge); Edges.Add(edge); // return nodes if (block.TransferCmd is ReturnCmd) { returnNodes.Add(n2); } // calls foreach (var callee in edge.Callees) { if (!calleeToEdgeSrc.ContainsKey(callee)) { calleeToEdgeSrc.Add(callee, new HashSet <Node>()); } calleeToEdgeSrc[callee].Add(n1); } } Nodes.Iter(n => idToNode.Add(n.Id, n)); entryNode = idToNode[impl.Blocks[0].Label + "::in"]; // connecting edges foreach (var block in impl.Blocks) { var gc = block.TransferCmd as GotoCmd; if (gc == null) { continue; } var src = idToNode[block.Label + "::out"]; var edges = gc.labelNames .OfType <string>() .Select(s => idToNode[s + "::in"]) .Select(tgt => new Edge(src, tgt, new Cmd[] { })); edges.Iter(e => { Edges.Add(e); e.src.AddEdge(e); e.tgt.AddEdge(e); }); } // Compute priorities var sccs = new StronglyConnectedComponents <Node>(Nodes, new Adjacency <Node>(n => n.Successors.Select(e => e.tgt)), new Adjacency <Node>(n => n.Predecessors.Select(e => e.src))); sccs.Compute(); int p = 0; foreach (var scc in sccs) { scc.Iter(n => n.priority = p); p++; } }
public void computeSummaries(ISummaryElement summaryClass) { this.summaryClass = summaryClass; var main = program.TopLevelDeclarations .OfType <Implementation>() .Where(impl => QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint")) .FirstOrDefault(); Debug.Assert(main != null); program.TopLevelDeclarations .OfType <Implementation>() .Iter(impl => impl2Summary.Add(impl.Name, summaryClass.GetFlaseSummary(program, impl))); // Build call graph var Succ = new Dictionary <Implementation, HashSet <Implementation> >(); var Pred = new Dictionary <Implementation, HashSet <Implementation> >(); name2Impl.Values.Iter(impl => Succ.Add(impl, new HashSet <Implementation>())); name2Impl.Values.Iter(impl => Pred.Add(impl, new HashSet <Implementation>())); foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { foreach (var blk in impl.Blocks) { foreach (var cmd in blk.Cmds.OfType <CallCmd>()) { if (!name2Impl.ContainsKey(cmd.callee)) { continue; } Succ[impl].Add(name2Impl[cmd.callee]); Pred[name2Impl[cmd.callee]].Add(impl); } } } // Build SCC var sccs = new StronglyConnectedComponents <Implementation>(name2Impl.Values, new Adjacency <Implementation>(n => Succ[n]), new Adjacency <Implementation>(n => Pred[n])); sccs.Compute(); // impl -> priority var impl2Priority = new Dictionary <string, int>(); int p = 0; foreach (var scc in sccs) { scc.Iter(n => impl2Priority.Add(n.Name, p)); p++; } var worklist = new SortedSet <Tuple <int, Implementation> >(); name2Impl.Values .Iter(impl => worklist.Add(Tuple.Create(impl2Priority[impl.Name], impl))); while (worklist.Any()) { var impl = worklist.First().Item2; worklist.Remove(worklist.First()); var changed = ProcessImpl(impl); if (changed) { Pred[impl].Iter(pred => worklist.Add(Tuple.Create(impl2Priority[pred.Name], pred))); } } foreach (var tup in impl2Summary) { Console.WriteLine("Summary of {0}:", tup.Key); Console.WriteLine("{0}", tup.Value); } prover.Close(); CommandLineOptions.Clo.TheProverFactory.Close(); }
public TwoSat(int N) { scc = new StronglyConnectedComponents(N << 1); Answer = new bool[N]; }
public HashSet<VariableDescriptor> DependsOn(VariableDescriptor v) { if (DependsOnSCCsDAG == null) { if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Variable dependence: computing SCCs"); } Adjacency<VariableDescriptor> next = new Adjacency<VariableDescriptor>(dependsOnNonTransitive.Successors); Adjacency<VariableDescriptor> prev = new Adjacency<VariableDescriptor>(dependsOnNonTransitive.Predecessors); StronglyConnectedComponents<VariableDescriptor> DependsOnSCCs = new StronglyConnectedComponents<VariableDescriptor>( dependsOnNonTransitive.Nodes, next, prev); DependsOnSCCs.Compute(); VariableDescriptorToSCC = new Dictionary<VariableDescriptor, SCC<VariableDescriptor>>(); foreach (var scc in DependsOnSCCs) { foreach (var s in scc) { VariableDescriptorToSCC[s] = scc; } } DependsOnSCCsDAG = new Graph<SCC<VariableDescriptor>>(); foreach (var edge in dependsOnNonTransitive.Edges) { if (VariableDescriptorToSCC[edge.Item1] != VariableDescriptorToSCC[edge.Item2]) { DependsOnSCCsDAG.AddEdge(VariableDescriptorToSCC[edge.Item1], VariableDescriptorToSCC[edge.Item2]); } } SCC<VariableDescriptor> dummy = new SCC<VariableDescriptor>(); foreach (var n in dependsOnNonTransitive.Nodes) { DependsOnSCCsDAG.AddEdge(VariableDescriptorToSCC[n], dummy); } if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Variable dependence: SCCs computed!"); } } return DependsOn(VariableDescriptorToSCC[v]); }
public Implementation(IToken/*!*/ tok, string/*!*/ name, List<TypeVariable>/*!*/ typeParams, List<Variable>/*!*/ inParams, List<Variable>/*!*/ outParams, List<Variable>/*!*/ localVariables, [Captured] StmtList/*!*/ structuredStmts, QKeyValue kv, Errors/*!*/ errorHandler) : base(tok, name, typeParams, inParams, outParams) { Contract.Requires(tok != null); Contract.Requires(name != null); Contract.Requires(typeParams != null); Contract.Requires(inParams != null); Contract.Requires(outParams != null); Contract.Requires(localVariables != null); Contract.Requires(structuredStmts != null); Contract.Requires(errorHandler != null); LocVars = localVariables; StructuredStmts = structuredStmts; BigBlocksResolutionContext ctx = new BigBlocksResolutionContext(structuredStmts, errorHandler); Blocks = ctx.Blocks; BlockPredecessorsComputed = false; scc = null; Attributes = kv; }
public VCGenOutcome ComputeSummaries() { // Compute SCCs and determine a priority order for impls var Succ = new Dictionary<string, HashSet<string>>(); var Pred = new Dictionary<string, HashSet<string>>(); name2Impl.Keys.Iter(s => Succ[s] = new HashSet<string>()); name2Impl.Keys.Iter(s => Pred[s] = new HashSet<string>()); foreach(var impl in name2Impl.Keys) { Succ[impl] = new HashSet<string>(); impl2functionsAsserted[impl].Iter(f => function2implAssumed[f].Iter(succ => { Succ[impl].Add(succ); Pred[succ].Add(impl); })); } var sccs = new StronglyConnectedComponents<string>(name2Impl.Keys, new Adjacency<string>(n => Pred[n]), new Adjacency<string>(n => Succ[n])); sccs.Compute(); // impl -> priority var impl2Priority = new Dictionary<string, int>(); int p = 0; foreach (var scc in sccs) { foreach (var impl in scc) { impl2Priority.Add(impl, p); p++; } } VCGenOutcome overallOutcome = null; var start = DateTime.Now; overallOutcome = LearnInv(impl2Priority); var elapsed = DateTime.Now; this.totaltime = elapsed - start; if (true) { Console.WriteLine("Prover time = {0}", proverTime.TotalSeconds.ToString("F2")); Console.WriteLine("Number of prover queries = " + numProverQueries); Console.WriteLine("C5 Learner time = {0}", c5LearnerTime.TotalSeconds.ToString("F2")); //Console.WriteLine("time to parse JSON and construct Boogie Model = {0}", jsontime.TotalSeconds.ToString("F2")); Console.WriteLine("Number of C5 Learner queries = " + c5LearnerQueries); //Console.WriteLine("Total time: {0}", proverTime.Add(c5LearnerTime).TotalSeconds.ToString("F2")); Console.WriteLine("Total time: {0}", totaltime.Subtract(jsontime).TotalSeconds.ToString("F2")); Console.WriteLine("Number of examples:" + this.numPosExamples); Console.WriteLine("Number of counter-examples:" + this.numNegCounterExamples); Console.WriteLine("Number of implications:" + this.numImplications); /*Console.WriteLine("Average tree size: " + ((double)this.totalTreeSize / (double)this.c5LearnerQueries)); Console.WriteLine("Last tree size: " + this.lastTreeSize); Console.WriteLine("Average truetrue implications: " + ((double)this.total_truetrue_implications / (double)this.c5LearnerQueries)); Console.WriteLine("last truetrue implications: " + this.last_truetrue_implications); Console.WriteLine("Average falsetrue implications: " + ((double)this.total_falsetrue_implications/ (double)this.c5LearnerQueries)); Console.WriteLine("last falsetrue implications: " + this.last_falsetrue_implications); Console.WriteLine("Average falsefalse implications: " + ((double)this.total_falsefalse_implications / (double)this.c5LearnerQueries)); Console.WriteLine("last falsefalse implications: " + this.last_falsefalse_implications); */ } if (CommandLineOptions.Clo.PrintAssignment) { // Print the existential functions existentialFunctions.Values.Iter(PrintFunction); } return overallOutcome; }
public bool MayReach(Block src, Block dst) { if (ReachabilityGraphSCCsDAG == null) { if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Interprocedural reachability: computing SCCs"); } Adjacency<Block> next = new Adjacency<Block>(reachabilityGraph.Successors); Adjacency<Block> prev = new Adjacency<Block>(reachabilityGraph.Predecessors); StronglyConnectedComponents<Block> ReachabilitySCCs = new StronglyConnectedComponents<Block>( reachabilityGraph.Nodes, next, prev); ReachabilitySCCs.Compute(); BlockToSCC = new Dictionary<Block, SCC<Block>>(); foreach (var scc in ReachabilitySCCs) { foreach (var s in scc) { BlockToSCC[s] = scc; } } ReachabilityGraphSCCsDAG = new Graph<SCC<Block>>(); foreach (var edge in reachabilityGraph.Edges) { if (BlockToSCC[edge.Item1] != BlockToSCC[edge.Item2]) { ReachabilityGraphSCCsDAG.AddEdge(BlockToSCC[edge.Item1], BlockToSCC[edge.Item2]); } } SCC<Block> dummy = new SCC<Block>(); foreach (var n in reachabilityGraph.Nodes) { ReachabilityGraphSCCsDAG.AddEdge(BlockToSCC[n], dummy); } if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Interprocedural reachability: SCCs computed!"); } } return ReachableFrom(BlockToSCC[src]).Contains(dst); }
static void Main() { var graph = new List <int>[] { new List <int>() { 1, 11, 13 }, // children of node 0 new List <int>() { 6 }, // children of node 1 new List <int>() { 0 }, // children of node 2 new List <int>() { 4 }, // children of node 3 new List <int>() { 3, 6 }, // children of node 4 new List <int>() { 13 }, // children of node 5 new List <int>() { 0, 11 }, // children of node 6 new List <int>() { 12 }, // children of node 7 new List <int>() { 6, 11 }, // children of node 8 new List <int>() { 0 }, // children of node 9 new List <int>() { 4, 6, 10 }, // children of node 10 new List <int>() { }, // children of node 11 new List <int>() { 7 }, // children of node 12 new List <int>() { 2, 9 }, // children of node 13 }; var result = StronglyConnectedComponents.FindStronglyConnectedComponents(graph); Console.WriteLine("Strongly Connected Components:"); foreach (var component in result) { Console.WriteLine("{{{0}}}", string.Join(", ", component)); } }