private VCExpr ToVcExpr(Expr expr, Dictionary <string, VCExpr> incarnations, VCExpressionGenerator gen) { if (expr is LiteralExpr) { var val = (expr as LiteralExpr).Val; if (val is bool) { if ((bool)val) { return(VCExpressionGenerator.True); } else { return(VCExpressionGenerator.False); } } else if (val is Microsoft.BaseTypes.BigNum) { return(gen.Integer((Microsoft.BaseTypes.BigNum)val)); } throw new NotImplementedException("Cannot handle literals of this type"); } if (expr is IdentifierExpr) { return(ToVcVar((expr as IdentifierExpr).Name, incarnations, false)); } if (expr is OldExpr) { var ide = (expr as OldExpr).Expr as IdentifierExpr; Debug.Assert(ide != null); return(ToVcVar(ide.Name, incarnations, true)); } if (expr is NAryExpr) { var nary = expr as NAryExpr; if (nary.Fun is UnaryOperator) { Debug.Assert((nary.Fun as UnaryOperator).Op == UnaryOperator.Opcode.Not); return(gen.Not(ToVcExpr(nary.Args[0], incarnations, gen))); } if (nary.Fun is BinaryOperator) { return(gen.Function(Translate(nary.Fun as BinaryOperator), ToVcExpr(nary.Args[0], incarnations, gen), ToVcExpr(nary.Args[1], incarnations, gen))); } Debug.Assert(false, "No other op is handled"); } throw new NotImplementedException(string.Format("Expr of type {0} is not handled", expr.GetType().ToString())); }
private VCExpr BuildAxiom(ProverInterface proverInterface, Dictionary <Variable, bool> currentAssignment) { ProverContext proverContext = proverInterface.Context; Boogie2VCExprTranslator exprTranslator = proverContext.BoogieExprTranslator; VCExpressionGenerator exprGen = proverInterface.VCExprGen; VCExpr expr = VCExpressionGenerator.True; foreach (KeyValuePair <Variable, bool> kv in currentAssignment) { Variable constant = kv.Key; VCExprVar exprVar = exprTranslator.LookupVariable(constant); if (kv.Value) { expr = exprGen.And(expr, exprVar); } else { expr = exprGen.And(expr, exprGen.Not(exprVar)); } } if (CommandLineOptions.Clo.ExplainHoudini) { // default values for ExplainHoudini control variables foreach (var constant in explainConstantsNegative.Concat(explainConstantsPositive)) { expr = exprGen.And(expr, exprTranslator.LookupVariable(constant)); } } /* * foreach (Variable constant in this.houdiniConstants) { * VCExprVar exprVar = exprTranslator.LookupVariable(constant); * if (currentAssignment[constant]) { * expr = exprGen.And(expr, exprVar); * } * else { * expr = exprGen.And(expr, exprGen.Not(exprVar)); * } * } */ if (CommandLineOptions.Clo.Trace) { Console.WriteLine("Houdini assignment axiom: " + expr); } return(expr); }
// 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.OutOfResource || 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.OutOfResource || outcome == ProverInterface.Outcome.Undetermined) { break; } unsatisfiedSoftAssumptions2.Iter(i => reason.Remove(softAssumptions2[i].ToString())); var reason1 = new HashSet <string>(); //these are the reasons for inconsistency unsatisfiedSoftAssumptions2.Iter(i => reason1.Add(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); } //also add the removed reasons using dotted edges (requires- x != 0, requires- x == 0 ==> assert x != 0) foreach (var r in reason1) { Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=blue style=dotted ];", refutedConstant.Name, r, descriptiveName); } } while (false); if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.OutOfResource || 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); } }
public void GenerateVC() { if (initialized) return; if (CommandLineOptions.Clo.SIBoolControlVC) { GenerateVCBoolControl(); initialized = true; return; } List<Variable> outputVariables = new List<Variable>(); List<Expr> assertConjuncts = new List<Expr>(); foreach (Variable v in impl.OutParams) { Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type)); outputVariables.Add(c); Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v)); assertConjuncts.Add(eqExpr); } foreach (IdentifierExpr e in impl.Proc.Modifies) { if (e.Decl == null) continue; Variable v = e.Decl; Constant c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, impl.Name + "_" + v.Name, v.TypedIdent.Type)); outputVariables.Add(c); Expr eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, c), new IdentifierExpr(Token.NoToken, v)); assertConjuncts.Add(eqExpr); } exitAssertCmd = new AssertCmd(Token.NoToken, Expr.Not(Expr.BinaryTreeAnd(assertConjuncts))); Program program = vcgen.program; ProverInterface proverInterface = vcgen.prover; vcgen.ConvertCFG2DAG(impl); vcgen.PassifyImpl(impl, out mvInfo); VCExpressionGenerator gen = proverInterface.VCExprGen; var exprGen = proverInterface.Context.ExprGen; var translator = proverInterface.Context.BoogieExprTranslator; controlFlowVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "@cfc", Microsoft.Boogie.Type.Int)); VCExpr controlFlowVariableExpr = translator.LookupVariable(controlFlowVariable); vcgen.InstrumentCallSites(impl); if (PassiveImplInstrumentation != null) PassiveImplInstrumentation(impl); label2absy = new Dictionary<int, Absy>(); VCGen.CodeExprConversionClosure cc = new VCGen.CodeExprConversionClosure(label2absy, proverInterface.Context); translator.SetCodeExprConverter(cc.CodeExprToVerificationCondition); vcexpr = gen.Not(vcgen.GenerateVCAux(impl, controlFlowVariableExpr, label2absy, proverInterface.Context)); if (controlFlowVariableExpr != null) { VCExpr controlFlowFunctionAppl = exprGen.ControlFlowFunctionApplication(controlFlowVariableExpr, exprGen.Integer(BigNum.ZERO)); VCExpr eqExpr = exprGen.Eq(controlFlowFunctionAppl, exprGen.Integer(BigNum.FromInt(impl.Blocks[0].UniqueId))); vcexpr = exprGen.And(eqExpr, vcexpr); } callSites = vcgen.CollectCallSites(impl); recordProcCallSites = vcgen.CollectRecordProcedureCallSites(impl); privateExprVars = new List<VCExprVar>(); foreach (Variable v in impl.LocVars) { privateExprVars.Add(translator.LookupVariable(v)); } foreach (Variable v in impl.OutParams) { privateExprVars.Add(translator.LookupVariable(v)); } interfaceExprVars = new List<VCExprVar>(); foreach (Variable v in program.GlobalVariables) { interfaceExprVars.Add(translator.LookupVariable(v)); } foreach (Variable v in impl.InParams) { interfaceExprVars.Add(translator.LookupVariable(v)); } foreach (Variable v in outputVariables) { interfaceExprVars.Add(translator.LookupVariable(v)); } initialized = true; }
public VCExpr get(Term arg) { if (memo.ContainsKey(arg)) { return(memo[arg]); } VCExpr res = null; switch (arg.GetKind()) { case TermKind.Numeral: var numstr = arg.GetNumeralString(); if (arg.GetSort().GetSortKind() == SortKind.Int) { res = gen.Integer(Basetypes.BigNum.FromString(numstr)); } else { res = gen.Real(Basetypes.BigDec.FromString(numstr)); } break; case TermKind.App: var args = arg.GetAppArgs(); var vcargs = new VCExpr[args.Length]; for (int i = 0; i < args.Length; i++) { vcargs[i] = get(args[i]); } switch (arg.GetAppDecl().GetKind()) { case DeclKind.Add: if (vcargs.Length == 0) { if (arg.GetSort().GetSortKind() == SortKind.Int) { res = gen.Integer(Basetypes.BigNum.ZERO); } else { res = gen.Real(Basetypes.BigDec.ZERO); } } else { res = vcargs[0]; for (int k = 1; k < vcargs.Length; k++) { res = gen.Add(res, vcargs[k]); } } break; case DeclKind.And: res = VCExpressionGenerator.True; for (int i = 0; i < vcargs.Length; i++) { res = gen.AndSimp(res, vcargs[i]); } break; case DeclKind.Div: Debug.Assert(vcargs.Length == 2); res = gen.Function(VCExpressionGenerator.RealDivOp, vcargs[0], vcargs[1]); break; case DeclKind.Eq: Debug.Assert(vcargs.Length == 2); res = gen.Eq(vcargs[0], vcargs[1]); break; case DeclKind.False: res = VCExpressionGenerator.False; break; case DeclKind.Ge: Debug.Assert(vcargs.Length == 2); res = gen.Function(VCExpressionGenerator.GeOp, vcargs[0], vcargs[1]); break; case DeclKind.Gt: Debug.Assert(vcargs.Length == 2); res = gen.Gt(vcargs[0], vcargs[1]); break; case DeclKind.IDiv: Debug.Assert(vcargs.Length == 2); res = gen.Function(VCExpressionGenerator.DivOp, vcargs[0], vcargs[1]); break; case DeclKind.Iff: Debug.Assert(vcargs.Length == 2); var l = create_let(args[0], vcargs[0]); var r = create_let(args[1], vcargs[1]); return(gen.And(gen.Implies(l, r), gen.Implies(r, l))); case DeclKind.Implies: Debug.Assert(vcargs.Length == 2); res = gen.Implies(vcargs[0], vcargs[1]); break; case DeclKind.Ite: Debug.Assert(vcargs.Length == 3); res = gen.Function(VCExpressionGenerator.IfThenElseOp, vcargs[0], vcargs[1], vcargs[2]); break; case DeclKind.Le: Debug.Assert(vcargs.Length == 2); res = gen.Function(VCExpressionGenerator.LeOp, vcargs[0], vcargs[1]); break; case DeclKind.Lt: Debug.Assert(vcargs.Length == 2); res = gen.Function(VCExpressionGenerator.LtOp, vcargs[0], vcargs[1]); break; case DeclKind.Mod: Debug.Assert(vcargs.Length == 2); res = gen.Function(VCExpressionGenerator.ModOp, vcargs[0], vcargs[1]); break; case DeclKind.Mul: Debug.Assert(vcargs.Length == 2); res = gen.Function(VCExpressionGenerator.MulOp, vcargs[0], vcargs[1]); break; case DeclKind.Not: Debug.Assert(vcargs.Length == 1); res = gen.Not(vcargs[0]); break; case DeclKind.Or: res = VCExpressionGenerator.False; for (int i = 0; i < vcargs.Length; i++) { res = gen.OrSimp(res, vcargs[i]); } break; case DeclKind.Select: Debug.Assert(vcargs.Length == 2); res = gen.Select(vcargs[0], vcargs[1]); break; case DeclKind.Store: Debug.Assert(vcargs.Length == 3); res = gen.Store(vcargs[0], vcargs[1], vcargs[2]); break; case DeclKind.Sub: Debug.Assert(vcargs.Length == 2); res = gen.Function(VCExpressionGenerator.SubOp, vcargs[0], vcargs[1]); break; case DeclKind.True: res = VCExpressionGenerator.True; break; case DeclKind.Uminus: Debug.Assert(vcargs.Length == 1); var argzero = null; if (vcargs[0].Type.IsInt) { argzero = gen.Integer(Basetypes.BigNum.ZERO); } else { argzero = gen.Real(Basetypes.BigDec.ZERO); } res = gen.Function(VCExpressionGenerator.SubOp, argzero, vcargs[0]); break; case DeclKind.ToInt: Debug.Assert(vcargs.Length == 1); res = gen.Function(VCExpressionGenerator.ToIntOp, vcargs[0]); break; case DeclKind.ToReal: Debug.Assert(vcargs.Length == 1); res = gen.Function(VCExpressionGenerator.ToRealOp, vcargs[0]); break; case DeclKind.Uninterpreted: var name = arg.GetAppDecl().GetDeclName(); if (args.Length == 0) { // a 0-ary constant is a VCExprVar if (!constants_inv.TryGetValue(arg, out res)) { throw new Exception("Z3 returned unknown constant: " + name); } } else { Function f; if (!functions_inv.TryGetValue(arg.GetAppDecl(), out f)) { throw new Exception("Z3 returned unknown function: " + name); } List <VCExpr> vcargsList = new List <VCExpr>(vcargs); res = gen.Function(f, vcargsList); } break; default: throw new Exception("Unknown Z3 operator"); } break; default: Debug.Assert(false); throw new Exception("Unknown Z3 AST kind"); } memo.Add(arg, res); return(res); }