/// <summary> /// Return lookup lemmas for each element in the old relation as well as the definition of the old relation, which /// is defined via an association list /// </summary> private static StateRelationData OldRelation( ISet <Variable> oldGlobalVars, IVariableTranslation <Variable> variableTranslation, out IList <OuterDecl> oldRelDecls) { //assume that passive version representing old variable of "g" is "g" itself var oldRelTuples = new List <Term>(); var varList = new List <Variable>(); var varToLookupLemma = new Dictionary <Variable, LemmaDecl>(); var uniqueNamer = new IsaUniqueNamer(); foreach (var v in oldGlobalVars) { if (variableTranslation.TryTranslateVariableId(v, out var varTermId, out _)) { oldRelTuples.Add(new TermTuple(varTermId, IsaCommonTerms.Inl(varTermId))); var lemma = new LemmaDecl( "lookup_old_rel" + uniqueNamer.GetName(v, v.Name), TermBinary.Eq(new TermApp(oldRel, varTermId), IsaCommonTerms.SomeOption(IsaCommonTerms.Inl(varTermId))), new Proof(new List <string> { "unfolding " + oldRelListName + "_def " + oldRelName + "_def", "by simp" }) ); varToLookupLemma.Add(v, lemma); varList.Add(v); }
public override int VisitLemmaDecl(LemmaDecl d) { _sb.Append("lemma ").Append(d.Name).Append(":"); if (!d.ContextElem.IsEmpty()) { _sb.AppendLine(); PrintContextElem(d.ContextElem); } _sb.AppendLine(); _sb.Append("shows "); bool first = true; foreach (var stmt in d.Statements) { if (first) { first = false; } else { _sb.Append(" and "); } AppendInner(_termPrinter.Visit(stmt)); } _sb.AppendLine(); PrintProof(d.Proof); return(0); }
public IEnumerable <OuterDecl> EndToEndProof( string entryCfgLemma, string passificationEndToEndLemma, Term vcAssm, IProgramAccessor programAccessor, CFGRepr cfg) { this.programAccessor = programAccessor; boogieContext = new BoogieContextIsa( IsaCommonTerms.TermIdentFromName("A"), IsaCommonTerms.TermIdentFromName("M"), IsaCommonTerms.TermIdentFromName(varContextName), IsaCommonTerms.TermIdentFromName("\\<Gamma>"), IsaCommonTerms.EmptyList ); var abbrev = new AbbreviationDecl( varContextName, new Tuple <IList <Term>, Term>(new List <Term>(), new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl())) ); var result = new List <OuterDecl> { abbrev }; var kStepRed = IsaBoogieTerm.RedCFGKStep( BoogieContextIsa.CreateWithNewVarContext( boogieContext, new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl()) ), programAccessor.CfgDecl(), IsaBoogieTerm.CFGConfigNode(new NatConst(cfg.GetUniqueIntLabel(cfg.entry)), IsaBoogieTerm.Normal(normalInitState)), IsaCommonTerms.TermIdentFromName("j"), IsaBoogieTerm.CFGConfig(finalNodeOrReturn, finalState) ); var proofSb = new StringBuilder(); proofSb.AppendLine("proof -"); proofSb.AppendLine("from " + redAssmName + " obtain j where Aux:" + "\"" + kStepRed + "\""); proofSb.AppendLine("by (meson rtranclp_imp_relpowp)"); proofSb.AppendLine("show ?thesis"); proofSb.AppendLine(ProofUtil.Apply("rule " + entryCfgLemma)); //TODO: don't hardcode this proofSb.AppendLine("unfolding cfg_to_dag_lemmas_def"); proofSb.AppendLine(ProofUtil.Apply("rule " + finterpAssmName)); proofSb.AppendLine("apply (rule Aux)"); proofSb.AppendLine("apply (rule dag_lemma_assms_same)"); proofSb.AppendLine("unfolding state_well_typed_def"); proofSb.AppendLine("apply (intro conjI)"); proofSb.AppendLine("using " + paramsLocalsAssmName + " apply simp"); proofSb.AppendLine("using " + constsGlobalsAssmName + " apply simp"); proofSb.AppendLine("using " + constsGlobalsAssmName + " " + oldGlobalAssmName + " apply simp"); proofSb.AppendLine("using " + binderEmptyAssmName + " apply simp"); proofSb.AppendLine(ProofUtil.Apply("rule " + passificationEndToEndLemma)); //TODO: don't hardcode this proofSb.AppendLine("unfolding glue_proof_def"); proofSb.AppendLine("apply (intro conjI)"); proofSb.AppendLine("apply assumption"); proofSb.AppendLine("using " + vcAssmName + " apply simp"); proofSb.AppendLine("using " + closedAssmName + " apply simp"); proofSb.AppendLine("using " + nonEmptyTypesAssmName + " apply simp"); proofSb.AppendLine(ProofUtil.Apply("rule " + finterpAssmName)); proofSb.AppendLine("using " + axiomAssmName + " apply simp"); proofSb.AppendLine("using " + paramsLocalsAssmName + " apply simp"); proofSb.AppendLine("using " + constsGlobalsAssmName + " apply simp"); proofSb.AppendLine("using " + binderEmptyAssmName + " apply simp"); proofSb.AppendLine("using " + oldGlobalAssmName + " apply simp"); proofSb.AppendLine("using " + preconditionsAssmName + " apply simp"); proofSb.AppendLine("done"); proofSb.AppendLine("qed"); var helperLemmaName = "end_to_end_theorem_aux"; var helperLemma = new LemmaDecl( helperLemmaName, LemmaContext(cfg, vcAssm), CfgToDagLemmaManager.CfgLemmaConclusion(boogieContext, programAccessor.PostconditionsDecl(), finalNodeOrReturn, finalState), new Proof(new List <string> { proofSb.ToString() }) ); result.Add(helperLemma); //transform end to end theorem to a compact representation var endToEndLemma = new LemmaDecl( "end_to_end_theorem", ContextElem.CreateWithAssumptions(new List <Term> { vcAssm }, new List <string> { "VC" }), ProcedureIsCorrect( programAccessor.FunctionsDecl(), IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()), programAccessor.AxiomsDecl(), programAccessor.ProcDecl()), new Proof( new List <string> { ProofUtil.Apply(ProofUtil.Rule(ProofUtil.OF("end_to_end_util", helperLemmaName))), "apply assumption " + "using VC apply simp " + " apply assumption+", ProofUtil.By("simp_all add: exprs_to_only_checked_spec_1 exprs_to_only_checked_spec_2 " + programAccessor.ProcDeclName() + "_def " + programAccessor.CfgDeclName() + "_def") } )); result.Add(endToEndLemma); return(result); }
public static Theory PassificationProof( string theoryName, string boogieToVcTheoryName, bool generateEndToEndLemma, LemmaDecl boogieToVcLemma, Term vcAssm, CFGRepr beforePassificationCfg, IDictionary <Block, Block> nonPassiveToPassiveBlock, PassiveRelationGen relationGen, IProgramAccessor beforePassiveProgAccess, IProgramAccessor passiveProgAccess, BoogieMethodData beforePassiveData, IVariableTranslationFactory beforePassiveFactory, IVariableTranslationFactory passiveFactory) { var varContextName = "\\<Lambda>1"; var passiveVarContextName = "\\<Lambda>2"; var varContextNonPassivePassive = Tuple.Create(varContextName, passiveVarContextName); var oldGlobalVars = GetOldGlobalVariables(beforePassificationCfg); var oldRelationData = OldRelation( oldGlobalVars, beforePassiveFactory.CreateTranslation().VarTranslation, out var oldRelListDecl); var passificationProofDecls = new List <OuterDecl>(); passificationProofDecls.AddRange(oldRelListDecl); passificationProofDecls.AddRange(oldRelationData.VarToLookupLemma.Values); if (oldRelationData.VarToLookupLemma.Any()) { passificationProofDecls.Add(new LemmasDecl(allOldLookupLemmasName, oldRelationData.VarToLookupLemma.Values.Select(lemma => lemma.Name).ToList())); } var beforePassiveLemmaManager = new PassificationLemmaManager( beforePassificationCfg, nonPassiveToPassiveBlock, beforePassiveProgAccess, passiveProgAccess, varContextNonPassivePassive, oldRelationData, relationGen, beforePassiveFactory, passiveFactory ); var lemmaNamer = new IsaUniqueNamer(); var varContextAbbrev = new AbbreviationDecl( varContextName, new Tuple <IList <Term>, Term>(new List <Term>(), beforePassiveProgAccess.VarContext()) ); var passiveVarContextAbbrev = new AbbreviationDecl( passiveVarContextName, new Tuple <IList <Term>, Term>(new List <Term>(), passiveProgAccess.VarContext()) ); passificationProofDecls.Add(varContextAbbrev); passificationProofDecls.Add(passiveVarContextAbbrev); passificationProofDecls.AddRange(beforePassiveLemmaManager.Prelude()); var cfgLemmas = new List <OuterDecl>(); foreach (var block in beforePassificationCfg.GetBlocksBackwards()) { var localAndCfgLemma = beforePassiveLemmaManager.GenerateBlockLemma( block, GetLemmaName(block, lemmaNamer), b => GetCfgLemmaName(b, lemmaNamer)); passificationProofDecls.Add(localAndCfgLemma.Item1); cfgLemmas.Add(localAndCfgLemma.Item2); } //add cfg lemmas at the end passificationProofDecls.AddRange(cfgLemmas); if (generateEndToEndLemma) { var endToEnd = new PassificationEndToEnd(); passificationProofDecls.AddRange(endToEnd.EndToEndProof( GetCfgLemmaName(beforePassificationCfg.entry, lemmaNamer), boogieToVcTheoryName + "." + boogieToVcLemma.Name, vcAssm, beforePassiveProgAccess, passiveProgAccess, varContextNonPassivePassive, oldRelationData, beforePassificationCfg, relationGen.LiveVarsBeforeBlock(beforePassificationCfg.entry), passiveFactory.CreateTranslation().VarTranslation )); } var imports = new List <string> { "Boogie_Lang.Semantics", "Boogie_Lang.Util", beforePassiveProgAccess.TheoryName(), passiveProgAccess.TheoryName(), "Boogie_Lang.PassificationML", boogieToVcTheoryName }; if (generateEndToEndLemma) { imports.Add("Boogie_Lang.PassificationEndToEnd"); } return(new Theory(theoryName, imports, passificationProofDecls)); }
public LemmaDecl GenerateCfgLemma( Block block, Block finalCfgBlock, bool isContainedInFinalCfg, IEnumerable <Block> successors, IEnumerable <Block> finalCfgSuccessors, Term cfg, Func <Block, string> cfgLemmaName, LemmaDecl BlockLemma) { var red = IsaBoogieTerm.RedCFGMulti( boogieContext, cfg, IsaBoogieTerm.CFGConfigNode(new NatConst(isaBlockInfo.BlockIds[block]), IsaBoogieTerm.Normal(normalInitState)), IsaBoogieTerm.CFGConfig(finalNode, finalState)); var assumption = new List <Term> { red }; var hasVcAssm = false; if (isContainedInFinalCfg) { assumption.Add(vcinst.GetVCObjInstantiation(finalCfgBlock, declToVCMapping)); hasVcAssm = true; } else { //vc assumption is conjunction of reachable successors in final cfg if (finalCfgSuccessors.Any()) { assumption.Add( LemmaHelper.ConjunctionOfSuccessorBlocks(finalCfgSuccessors, declToVCMapping, vcinst)); hasVcAssm = true; } } Term conclusion = new TermBinary(finalState, IsaBoogieTerm.Failure(), TermBinary.BinaryOpCode.Neq); var nodeLemma = isaBlockInfo.BlockCmdsMembershipLemma(block); var outEdgesLemma = isaBlockInfo.OutEdgesMembershipLemma(block); var proofMethods = new List <string>(); var eruleLocalBlock = "erule " + (hasVcAssm ? ProofUtil.OF(BlockLemma.Name, "_", "assms(2)") : BlockLemma.Name); if (isContainedInFinalCfg && LemmaHelper.FinalStateIsMagic(block)) { proofMethods.Add("apply (rule converse_rtranclpE2[OF assms(1)], fastforce)"); proofMethods.Add(ProofUtil.Apply("rule " + ProofUtil.OF("red_cfg_multi_backwards_step_magic", "assms(1)", nodeLemma))); proofMethods.Add(ProofUtil.By(eruleLocalBlock)); return(new LemmaDecl(cfgLemmaName(block), ContextElem.CreateWithAssumptions(assumption), conclusion, new Proof(proofMethods))); } if (successors.Any()) { proofMethods.Add("apply (rule converse_rtranclpE2[OF assms(1)], fastforce)"); var cfg_lemma = finalCfgSuccessors.Any() ? "red_cfg_multi_backwards_step" : "red_cfg_multi_backwards_step_2"; proofMethods.Add(ProofUtil.Apply("rule " + ProofUtil.OF(cfg_lemma, "assms(1)", nodeLemma))); proofMethods.Add(ProofUtil.Apply(eruleLocalBlock)); proofMethods.Add("apply (" + ProofUtil.Simp(outEdgesLemma) + ")"); foreach (var bSuc in successors) { proofMethods.Add("apply (erule member_elim, simp)"); proofMethods.Add("apply (erule " + cfgLemmaName(bSuc) + ", simp?" + ")"); } proofMethods.Add("by (simp add: member_rec(2))"); } else { proofMethods.Add("apply (rule converse_rtranclpE2[OF assms(1)], fastforce)"); proofMethods.Add("apply (rule " + ProofUtil.OF("red_cfg_multi_backwards_step_no_succ", "assms(1)", nodeLemma, outEdgesLemma) + ")"); if (isContainedInFinalCfg) { proofMethods.Add("using " + ProofUtil.OF(BlockLemma.Name, "_", "assms(2)") + " by blast"); } else { proofMethods.Add("using " + BlockLemma.Name + " by blast"); } } return(new LemmaDecl(cfgLemmaName(block), ContextElem.CreateWithAssumptions(assumption), conclusion, new Proof(proofMethods))); }
public static Theory ProgramToVcProof( string theoryName, bool generateEndToEndProof, CFGRepr finalCfg, CFGRepr afterPassificationCfg, IDictionary <Block, Block> afterPassiveToFinalBlock, IDictionary <Block, Block> afterPassiveToOrigBlock, IProgramAccessor passiveProgAccess, IProgramAccessor beforePassiveProgAccess, BoogieMethodData methodData, ProgramVcProofData vcProofData, IVariableTranslationFactory varFactory, TypePremiseEraserFactory eraserFactory, VCExpressionGenerator gen, out Term vcAssm, out LemmaDecl endToEndLemma) { var lemmaNamer = new IsaUniqueNamer(); var passiveLemmaManager = new VcPhaseLemmaManager( vcProofData.VcBoogieInfo.VcInst, methodData, vcProofData.VcFunctions, passiveProgAccess.BlockInfo(), varFactory); var afterPassiveReachableBlocks = ReachableBlocks(afterPassificationCfg); var finalProgramLemmas = GenerateVCLemmas(afterPassificationCfg, finalCfg, afterPassiveToFinalBlock, afterPassiveToOrigBlock, afterPassiveReachableBlocks, passiveLemmaManager, vcProofData.VcHintManager, lemmaNamer); var cfgProgramLemmas = GenerateCfgLemmas(afterPassificationCfg, finalCfg, afterPassiveToFinalBlock, afterPassiveReachableBlocks, finalProgramLemmas, passiveLemmaManager, passiveProgAccess.CfgDecl(), lemmaNamer); var afterPassificationDecls = new List <OuterDecl>(); foreach (var v in finalProgramLemmas.Values) { afterPassificationDecls.AddRange(v); } afterPassificationDecls.AddRange(cfgProgramLemmas.Values); var afterPassificationLocale = GenerateLocale("passification", passiveLemmaManager, afterPassificationDecls); var passiveOuterDecls = new List <OuterDecl> { vcProofData.VcLocale }; passiveOuterDecls.Add(afterPassificationLocale); //generate axiom var axiomUniqueNamer = new IsaUniqueNamer(); var axId = 0; var axiomToLemma = new Dictionary <Axiom, OuterDecl>(); var vcRewriteLemmaGen = new VcRewriteLemmaGen(eraserFactory, VCExprToIsaTranslator.CreateNameBasedTranslator(new IsaUniqueNamer())); var vcAxiomLemmaManager = new VcAxiomLemmaManager( vcProofData.VcBoogieInfo.VcInstAxiom, methodData, vcProofData.VcFunctions, vcRewriteLemmaGen, varFactory); var axiomLocaleRequiredDecls = new List <OuterDecl>(); foreach (var axiom in vcProofData.VcBoogieInfo.VcAxiomsInfo) { if (axiom is VcBoogieAxiomInfo vcBoogieAxiom) { var axiomVcLemma = vcAxiomLemmaManager.AxiomVcLemma( axiomUniqueNamer.GetName(axiom, "axiom_vc_" + axId), vcBoogieAxiom.Axiom, vcBoogieAxiom.Expr, out var requiredDecls); axiomToLemma.Add(vcBoogieAxiom.Axiom, axiomVcLemma); axiomLocaleRequiredDecls.AddRange(requiredDecls); } } /* we add the required declarations for the axiom locale to the outer theory, since the axiom locale fixes variables that could clash * with the declarations */ passiveOuterDecls.AddRange(axiomLocaleRequiredDecls); var axiomLocale = GenerateLocale("axioms", vcAxiomLemmaManager, axiomToLemma.Values.ToList()); passiveOuterDecls.Add(axiomLocale); if (generateEndToEndProof) { var endToEnd = new EndToEndVCProof( methodData, passiveProgAccess, vcProofData.VcFunctions, vcProofData.VcBoogieInfo, afterPassificationCfg, finalCfg, afterPassificationLocale.Name + "." + cfgProgramLemmas[afterPassificationCfg.entry].Name, axiomLocale.Name, ax => axiomLocale.Name + "." + axiomToLemma[ax].Name, varFactory, vcProofData.VcTranslator, eraserFactory, gen); passiveOuterDecls.AddRange(endToEnd.GenerateProof(out vcAssm, out endToEndLemma)); } else { vcAssm = null; endToEndLemma = null; } return (new Theory(theoryName, new List <string> { "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.VCHints", "Boogie_Lang.VCPhaseML", passiveProgAccess.TheoryName(), beforePassiveProgAccess.TheoryName() }, passiveOuterDecls)); }