Example #1
0
        private VCGenOutcome LearnInv(Dictionary<string, int> impl2Priority)
        {
            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);

                    /*
                    foreach (var variable in varList)
                    {
                        terms.Add(Expr.Le(variable, Expr.Literal(10)));
                        terms.Add(Expr.Ge(variable, Expr.Literal(-10)));
                    }
                    */
                }
                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;
                for (int i = 0; i <= bounds4cex.Count(); i++)
                {
#region boundcexvalues
                    /* Last iteration is when there are enforced no bounds on the cex values. */
                    if (i < bounds4cex.Count())
                    {
                        int bound = bounds4cex.ElementAt(i);
                        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);
                    }
                    else
                    {
                        //finalVC = vc;
                        
                        
                        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);
                         
                    }
#endregion boundcexvalues

                    var handler = impl2ErrorHandler[impl].Item1;
                    var collector = impl2ErrorHandler[impl].Item2;
                    collector.Reset(impl);
                    implicationCounterExamples.Clear();
                    VCisValid = true;   // set to false if control reaches HandleCounterExample
                    //realErrorEncountered = false;
                    //newSamplesAdded = false;
                    //this.posNegCexAdded = false;

                    var start = DateTime.Now;

                    prover.Push();
                    prover.Assert(gen.Not(finalVC), true);
                    prover.FlushAxiomsToTheoremProver();
                    prover.Check();
                    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);
                        return new VCGenOutcome(proverOutcome, new List<Counterexample>());
                    }

                    if (!VCisValid)
                    {
                        /* There was a counterexample found and acted upon while proving the method. */
                        if (collector.real_errors.Count > 0)
                        {
                            return new VCGenOutcome(ProverInterface.Outcome.Invalid, collector.real_errors);
                        }

                        if (collector.conjecture_errors.Count == 0)
                        {
                            // No positive or negative counter-example added. Need to add implication counter-examples
                            Debug.Assert(collector.implication_errors.Count > 0);
                            foreach (var cex in implicationCounterExamples)
                            {
                                AddCounterExample(cex);
                            }
                        }

                        //Debug.Assert(newSamplesAdded);
                        HashSet<string> funcsChanged;

                        if (!learn(out funcsChanged))
                        {
                            // learner timed out, ran into some errors, or if there is no consistent conjecture
                            prover.Pop();
                            if(collector.conjecture_errors.Count > 0)
                                return new VCGenOutcome(ProverInterface.Outcome.Invalid, collector.conjecture_errors);
                            else
                                return new VCGenOutcome(ProverInterface.Outcome.Invalid, collector.implication_errors);
                        }
                        // 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)));

                        // break out of the loop that iterates over various bounds.
                        prover.Pop();
                        break;
                    }
                    else
                    {
                        prover.Pop();
                    }
                }
            }
            // The program was verified
            return new VCGenOutcome(ProverInterface.Outcome.Valid, new List<Counterexample>());            
        }
Example #2
0
        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;
        }
Example #3
0
        // MAXSAT
        public void Explain(ProverInterface proverInterface, 
            Dictionary<Variable, bool> assignment, Variable refutedConstant)
        {
            Contract.Assert(CommandLineOptions.Clo.ExplainHoudini);

            collector.examples.Clear();

            // debugging
            houdiniAssertConstants.Iter(v => System.Diagnostics.Debug.Assert(assignment.ContainsKey(v)));
            houdiniAssumeConstants.Iter(v => System.Diagnostics.Debug.Assert(assignment.ContainsKey(v)));
            Contract.Assert(assignment.ContainsKey(refutedConstant));
            Contract.Assert(houdiniAssertConstants.Contains(refutedConstant));

            var hardAssumptions = new List<VCExpr>();
            var softAssumptions = new List<VCExpr>();

            Boogie2VCExprTranslator exprTranslator = proverInterface.Context.BoogieExprTranslator;
            VCExpressionGenerator exprGen = proverInterface.VCExprGen;
            var controlExpr = VCExpressionGenerator.True;

            foreach (var tup in assignment)
            {
            Variable constant = tup.Key;
            VCExprVar exprVar = exprTranslator.LookupVariable(constant);
            var val = tup.Value;

            if (houdiniAssumeConstants.Contains(constant))
            {
                if (tup.Value)
                    hardAssumptions.Add(exprVar);
                else
                    // Previously removed assumed candidates are the soft constraints
                    softAssumptions.Add(exprVar);
            }
            else if (houdiniAssertConstants.Contains(constant))
            {
                if (constant == refutedConstant)
                    hardAssumptions.Add(exprVar);
                else
                    hardAssumptions.Add(exprGen.Not(exprVar));
            }
            else
            {
                if (tup.Value)
                    hardAssumptions.Add(exprVar);
                else
                    hardAssumptions.Add(exprGen.Not(exprVar));
            }

            // For an asserted condition (c ==> \phi),
            // ExplainHoudini's extra control constants (c_pos, c_neg) are used as follows:
            //   (true, true): "assert \phi"
            //   (false, _): "assert false"
            //   (true, false): "assert true"
            if (constant != refutedConstant && constantToControl.ContainsKey(constant.Name))
            {
                var posControl = constantToControl[constant.Name].Item1;
                var negControl = constantToControl[constant.Name].Item2;

                // Handle self-recursion
                if (houdiniAssertConstants.Contains(constant) && houdiniAssumeConstants.Contains(constant))
                {
                    // disable this assert
                    controlExpr = exprGen.And(controlExpr, exprGen.And(exprTranslator.LookupVariable(posControl), exprGen.Not(exprTranslator.LookupVariable(negControl))));
                }
                else
                {
                    // default values for control variables
                    controlExpr = exprGen.And(controlExpr, exprGen.And(exprTranslator.LookupVariable(posControl), exprTranslator.LookupVariable(negControl)));
                }
            }
            }

            hardAssumptions.Add(exprGen.Not(conjecture));

            // default values for control variables
            Contract.Assert(constantToControl.ContainsKey(refutedConstant.Name));
            var pc = constantToControl[refutedConstant.Name].Item1;
            var nc = constantToControl[refutedConstant.Name].Item2;

            var controlExprNoop = exprGen.And(controlExpr,
            exprGen.And(exprTranslator.LookupVariable(pc), exprTranslator.LookupVariable(nc)));

            var controlExprFalse = exprGen.And(controlExpr,
            exprGen.And(exprGen.Not(exprTranslator.LookupVariable(pc)), exprGen.Not(exprTranslator.LookupVariable(nc))));

            if (CommandLineOptions.Clo.Trace)
            {
            Console.WriteLine("Verifying (MaxSat) " + descriptiveName);
            }
            DateTime now = DateTime.UtcNow;

            var el = CommandLineOptions.Clo.ProverCCLimit;
            CommandLineOptions.Clo.ProverCCLimit = 1;

            var outcome = ProverInterface.Outcome.Undetermined;

            do
            {
            List<int> unsatisfiedSoftAssumptions;

            hardAssumptions.Add(controlExprNoop);
            outcome = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions, out unsatisfiedSoftAssumptions, handler);
            hardAssumptions.RemoveAt(hardAssumptions.Count - 1);

            if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.Undetermined)
                break;

            var reason = new HashSet<string>();
            unsatisfiedSoftAssumptions.Iter(i => reason.Add(softAssumptions[i].ToString()));
            if (CommandLineOptions.Clo.Trace)
            {
                Console.Write("Reason for removal of {0}: ", refutedConstant.Name);
                reason.Iter(r => Console.Write("{0} ", r));
                Console.WriteLine();
            }

            // Get rid of those constants from the "reason" that can even make
            // "assert false" pass

            hardAssumptions.Add(controlExprFalse);
            var softAssumptions2 = new List<VCExpr>();
            for (int i = 0; i < softAssumptions.Count; i++)
            {
                if (unsatisfiedSoftAssumptions.Contains(i))
                {
                    softAssumptions2.Add(softAssumptions[i]);
                    continue;
                }
                hardAssumptions.Add(softAssumptions[i]);
            }

            var unsatisfiedSoftAssumptions2 = new List<int>();
            outcome = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions2, out unsatisfiedSoftAssumptions2, handler);

            if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.Undetermined)
                break;

            unsatisfiedSoftAssumptions2.Iter(i => reason.Remove(softAssumptions2[i].ToString()));
            if (CommandLineOptions.Clo.Trace)
            {
                Console.Write("Revised reason for removal of {0}: ", refutedConstant.Name);
                reason.Iter(r => Console.Write("{0} ", r));
                Console.WriteLine();
            }
            foreach (var r in reason)
            {
                Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=red ];", refutedConstant.Name, r, descriptiveName);
            }
            } while (false);

            if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.Undetermined)
            {
            Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=red ];", refutedConstant.Name, "TimeOut", descriptiveName);
            }

            CommandLineOptions.Clo.ProverCCLimit = el;

            double queryTime = (DateTime.UtcNow - now).TotalSeconds;
            stats.proverTime += queryTime;
            stats.numProverQueries++;
            if (CommandLineOptions.Clo.Trace)
            {
            Console.WriteLine("Time taken = " + queryTime);
            }
        }