private static VCGenOutcome ChooseOutcome(VCGenOutcome o1, VCGenOutcome o2) { var vcOutcome1 = o1.outcome; var vcOutcome2 = o2.outcome; if (vcOutcome1 == vcOutcome2) { return(o1); } // Errors trump everything else if (vcOutcome1 == VC.ConditionGeneration.Outcome.Errors) { return(o1); } if (vcOutcome2 == VC.ConditionGeneration.Outcome.Errors) { return(o2); } // If one outcome is Correct, return the other in case it is "worse" if (vcOutcome1 == VC.ConditionGeneration.Outcome.Correct) { return(o2); } if (vcOutcome2 == VC.ConditionGeneration.Outcome.Correct) { return(o1); } // Neither outcome is correct, so if one outcome is ReachedBound, return the other in case it is "worse" if (vcOutcome1 == VC.ConditionGeneration.Outcome.ReachedBound) { return(o2); } if (vcOutcome2 == VC.ConditionGeneration.Outcome.ReachedBound) { return(o1); } // Both outcomes must be timeout or memout; arbitrarily choose the first return(o1); }
private ICEOutcome LearnInvFromTemplate(Dictionary<string, int> impl2Priority, Template t, int range, out VCGenOutcome overallOutcome) { overallOutcome = null; // create a new z3 context if (z3Context != null) { z3Context.context.Dispose(); z3Context.config.Dispose(); } z3Context = new Z3Context(); foreach (var func in existentialFunctions.Values) { // initialize function to an "Octagons" instance with the given template "t". function2Value[func.Name] = ICEDomainFactory.GetInstance("Octagons", t, ref z3Context, func.Name, range); } // add counterexamples into the z3Context. These are obtained from the earlier iterations of the template. foreach (var cex in counterExamples) { AddCounterExampleToZ3Context(cex); } var worklist = new SortedSet<Tuple<int, string>>(); name2Impl.Keys.Iter(k => worklist.Add(Tuple.Create(impl2Priority[k], k))); while (worklist.Any()) { var impl = worklist.First().Item2; worklist.Remove(worklist.First()); #region vcgen var gen = prover.VCExprGen; var terms = new List<Expr>(); foreach (var tup in impl2FuncCalls[impl]) { var controlVar = tup.Item2; var exprVars = tup.Item3; var varList = new List<Expr>(); exprVars.Args.OfType<Expr>().Iter(v => varList.Add(v)); var args = new List<Expr>(); controlVar.InParams.Iter(v => args.Add(Expr.Ident(v))); Expr term = Expr.Eq(new NAryExpr(Token.NoToken, new FunctionCall(controlVar), args), function2Value[tup.Item1].Gamma(varList)); if (controlVar.InParams.Count != 0) { term = new ForallExpr(Token.NoToken, new List<Variable>(controlVar.InParams.ToArray()), new Trigger(Token.NoToken, true, new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(controlVar), args) }), term); } terms.Add(term); } var env = BinaryTreeAnd(terms, 0, terms.Count - 1); env.Typecheck(new TypecheckingContext((IErrorSink)null)); var envVC = prover.Context.BoogieExprTranslator.Translate(env); var vc = gen.Implies(envVC, impl2VC[impl]); if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Verifying {0}: ", impl); //Console.WriteLine("env: {0}", envVC); var envFuncs = new HashSet<string>(); impl2FuncCalls[impl].Iter(tup => envFuncs.Add(tup.Item1)); envFuncs.Iter(f => PrintFunction(existentialFunctions[f])); } #endregion vcgen VCExpr finalVC; #region bound_value_of_cexs #if false finalVC = vc; #else int bound = 1000000; terms.Clear(); foreach (var tup in impl2FuncCalls[impl]) { var exprVars = tup.Item3; var varList = new List<Expr>(); exprVars.Args.OfType<Expr>().Where(v => v.Type.IsInt).Iter(v => varList.Add(v)); foreach (var variable in varList) { terms.Add(Expr.Le(variable, Expr.Literal(bound))); terms.Add(Expr.Ge(variable, Expr.Literal(-1 * bound))); //terms.Add(Expr.Ge(variable, Expr.Literal(0))); } } var boundcex = BinaryTreeAnd(terms, 0, terms.Count - 1); boundcex.Typecheck(new TypecheckingContext((IErrorSink)null)); var boundcexVC = prover.Context.BoogieExprTranslator.Translate(boundcex); finalVC = gen.Implies(boundcexVC, vc); #endif #endregion bound_value_of_cexs var handler = impl2ErrorHandler[impl].Item1; var collector = impl2ErrorHandler[impl].Item2; collector.Reset(impl); VCisValid = true; // set to false if control reaches HandleCounterExample realErrorEncountered = false; newSamplesAdded = false; var start = DateTime.Now; prover.Push(); prover.Assert(gen.Not(finalVC), true); prover.FlushAxiomsToTheoremProver(); prover.Check(); ProverInterface.Outcome proverOutcome = prover.CheckOutcomeCore(handler); //prover.BeginCheck(impl, vc, handler); //ProverInterface.Outcome proverOutcome = prover.CheckOutcomeCore(handler); var inc = (DateTime.Now - start); proverTime += inc; numProverQueries++; if (CommandLineOptions.Clo.Trace) Console.WriteLine("Prover Time taken = " + inc.TotalSeconds.ToString()); if (proverOutcome == ProverInterface.Outcome.TimeOut || proverOutcome == ProverInterface.Outcome.OutOfMemory) { Console.WriteLine("Z3 Prover for implementation {0} times out or runs out of memory !", impl); z3Context.context.Dispose(); z3Context.config.Dispose(); overallOutcome = new VCGenOutcome(proverOutcome, new List<Counterexample>()); return ICEOutcome.Timeout; } if (CommandLineOptions.Clo.Trace) Console.WriteLine(!VCisValid ? "SAT" : "UNSAT"); if (!VCisValid) { if (realErrorEncountered) { overallOutcome = new VCGenOutcome(ProverInterface.Outcome.Invalid, collector.real_errors); return ICEOutcome.ErrorFound; } Debug.Assert(newSamplesAdded); HashSet<string> funcsChanged; if (!learn(out funcsChanged)) { // learner timed out or there is no valid conjecture in the current given template overallOutcome = new VCGenOutcome(ProverInterface.Outcome.Invalid, collector.conjecture_errors); prover.Pop(); return ICEOutcome.InvariantNotFound; } // propagate dependent guys back into the worklist, including self var deps = new HashSet<string>(); deps.Add(impl); funcsChanged.Iter(f => deps.UnionWith(function2implAssumed[f])); funcsChanged.Iter(f => deps.UnionWith(function2implAsserted[f])); deps.Iter(s => worklist.Add(Tuple.Create(impl2Priority[s], s))); } prover.Pop(); } // The program was verified with the current template! overallOutcome = new VCGenOutcome(ProverInterface.Outcome.Valid, new List<Counterexample>()); return ICEOutcome.InvariantFound; }