Пример #1
0
        public static bool ApplyTemplates(HashSet <int> templates)
        {
            var commonGlobals = Minimize.FindCommonGlobals();
            var ret           = false;

            // Prune away ones that don't have constants associated with them
            templates = new HashSet <int>(
                templates.Where(t => !templateMap[t].All(tup => tup.Value.SetEquals(fileToKeepConstants[tup.Key]))));

            // Prune away ones that don't talk about common globals
            templates = new HashSet <int>(
                templates.Where(t =>
            {
                var expr = SimplifyExpr.ToExpr(templateToStr[t]);
                var vu   = new GlobalVarsUsed();
                vu.VisitExpr(expr);
                return(vu.globalsUsed.IsSubsetOf(commonGlobals));
            }));

            var newFileToProg = new Dictionary <string, PersistentProgram>();

            var templateToConstants = new Dictionary <int, int>();

            templates.Iter(t => templateToConstants.Add(t, 0));

            foreach (var tup in fileToProg)
            {
                var program = tup.Value.getProgram();
                BoogieUtil.DoModSetAnalysis(program);
                var globals = new HashSet <string>(program.TopLevelDeclarations.OfType <GlobalVariable>().Select(g => g.Name));

                var newconstants = new HashSet <Constant>();

                foreach (var t in templates)
                {
                    var expr   = SimplifyExpr.ToExpr(templateToStr[t]);
                    var nonold = new GatherNonOldVariables();
                    nonold.VisitExpr(expr);

                    var mustmod = new HashSet <string>(nonold.variables);
                    mustmod.IntersectWith(globals);

                    foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
                    {
                        var mod = new HashSet <string>(impl.Proc.Modifies.Select(ie => ie.Name));
                        if (!mustmod.IsSubsetOf(mod))
                        {
                            continue;
                        }

                        // create new constant
                        var nc = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "PMnewConst" + (NewConstCounter++),
                                                                            btype.Bool), false);
                        nc.AddAttribute("existential");
                        newconstants.Add(nc);
                        if (!templateMap[t].ContainsKey(tup.Key))
                        {
                            templateMap[t].Add(tup.Key, new HashSet <string>());
                        }
                        templateMap[t][tup.Key].Add(nc.Name);

                        ret = true;
                        templateToConstants[t]++;

                        impl.Proc.Ensures.Add(new Ensures(false, Expr.Imp(Expr.Ident(nc), expr)));
                    }
                }

                program.AddTopLevelDeclarations(newconstants);
                newFileToProg.Add(tup.Key, new PersistentProgram(program));
            }
            fileToProg = newFileToProg;

            foreach (var tup in templateToConstants)
            {
                Console.WriteLine("Applying template {0}: {1} ({2} constants created)", tup.Key, templateToStr[tup.Key], tup.Value);
            }

            return(ret);
        }
Пример #2
0
        static void Main(string[] args)
        {
            Console.CancelKeyPress += Console_CancelKeyPress;

            if (args.Length < 1)
            {
                Console.WriteLine("ProofMin file(s).bpl [options]");
                return;
            }

            var boogieArgs     = "";
            var once           = false;
            var printcontracts = false;
            var keepPatterns   = new HashSet <string>();
            var filePatterns   = new HashSet <string>();

            for (int i = 0; i < args.Length; i++)
            {
                if (!args[i].StartsWith("/") && args[i].EndsWith(".bpl"))
                {
                    filePatterns.Add(args[i]);
                    continue;
                }

                if (args[i].StartsWith("/files:"))
                {
                    filePatterns.UnionWith(
                        System.IO.File.ReadAllLines(args[i].Substring("/files:".Length)));
                    continue;
                }

                if (args[i] == "/break")
                {
                    System.Diagnostics.Debugger.Launch();
                    continue;
                }
                if (args[i] == "/once")
                {
                    once = true;
                    continue;
                }
                if (args[i] == "/noSI")
                {
                    Minimize.useSI   = false;
                    Minimize.usePerf = 2.0;
                    continue;
                }
                if (args[i] == "/dbg")
                {
                    dbg          = true;
                    Minimize.dbg = true;
                    continue;
                }
                if (args[i] == "/printAssignment")
                {
                    printcontracts = true;
                    continue;
                }

                if (args[i].StartsWith("/keep:"))
                {
                    keepPatterns.Add(args[i].Substring("/keep:".Length));
                    continue;
                }

                if (args[i].StartsWith("/initBound:"))
                {
                    InitBound = Int32.Parse(args[i].Substring("/initBound:".Length));
                    continue;
                }

                if (args[i] == "/perf")
                {
                    Minimize.usePerf = 2.0;
                    continue;
                }

                if (args[i] == "/cnf")
                {
                    SimplifyExpr.SimplifyToCNF = true;
                    continue;
                }

                if (args[i].StartsWith("/perf:"))
                {
                    Minimize.usePerf = double.Parse(args[i].Substring("/perf:".Length));
                    continue;
                }

                boogieArgs += args[i] + " ";
            }

            // Initialize Boogie
            boogieArgs += " /typeEncoding:m /weakArrayTheory /errorLimit:1 ";
            Initalize(boogieArgs);

            // Get the input files
            var files = new HashSet <string>();

            foreach (var fp in filePatterns)
            {
                var fname   = System.IO.Path.GetFileName(fp);
                var dirname = System.IO.Path.GetDirectoryName(fp);
                if (dirname == "")
                {
                    dirname = ".";
                }
                files.UnionWith(System.IO.Directory.GetFiles(dirname, fname));
            }

            if (files.Count == 0)
            {
                Console.WriteLine("No files given");
                return;
            }
            Console.WriteLine("Found {0} files", files.Count);

            if (once)
            {
                Debug.Assert(files.Count() == 1);
                RunOnce(new PersistentProgram(BoogieUtil.ReadAndResolve(files.First(), true)), printcontracts);
                return;
            }

            Minimize.sw.Start();
            Minimize.ReadFiles(files, keepPatterns);

            Dictionary <int, int> templateToPerfDelta = new Dictionary <int, int>();
            HashSet <int>         min = new HashSet <int>();

            var dropped            = new HashSet <int>();
            var ApplyTemplatesDone = false;

            do
            {
                do
                {
                    Dictionary <int, int> t2d;
                    var min2 = Minimize.FindMin(dropped, out t2d);

                    // dropped
                    var templates = new HashSet <int>(Minimize.templateToStr.Keys);
                    dropped = templates.Difference(min2);

                    // merge perf
                    foreach (var tup in t2d)
                    {
                        if (!templateToPerfDelta.ContainsKey(tup.Key))
                        {
                            templateToPerfDelta.Add(tup.Key, tup.Value);
                        }
                        else
                        {
                            templateToPerfDelta[tup.Key] += tup.Value;
                        }
                    }

                    Console.WriteLine("Obtained minimal templates, at size {0}", min2.Count);

                    if (min.SetEquals(min2))
                    {
                        Console.WriteLine("Reached fixpoint; we're done");
                        break;
                    }

                    min = min2;

                    Console.WriteLine("Contemplating re-running with broken down templates");

                    var rerun = false;
                    Minimize.candidateToCost = new Dictionary <int, int>();
                    var newTemplates = new HashSet <int>();
                    min2.Iter(t => { var b = Minimize.PruneDisjuncts(t, ref newTemplates); rerun |= b; });

                    if (!rerun)
                    {
                        Console.WriteLine("Nothing to break; we're done");
                        break;
                    }

                    dropped.ExceptWith(newTemplates);
                    Console.WriteLine("Rerunning Minimization");
                } while (true);

                if (ApplyTemplatesDone)
                {
                    break;
                }
                ApplyTemplatesDone = true;

                // compute common set of globals
                var rr = Minimize.ApplyTemplates(min.Difference(Minimize.priorFullyInstantiatedTemplates));
                if (!rr)
                {
                    break;
                }
            } while (true);

            foreach (var c in min)
            {
                Console.WriteLine("Template to origin info for {0} : {1}", c, Minimize.templateToStr[c]);
                if (!Minimize.templateToOriginExpr.ContainsKey(c) || Minimize.templateToOriginExpr[c].Count == 0)
                {
                    continue;
                }
                foreach (var tup in Minimize.templateToOriginExpr[c])
                {
                    Console.WriteLine("  {0}{1}", tup.Item1 ? "{:loop} " : "", tup.Item2.ToString());
                }
            }


            foreach (var c in min)
            {
                var    gen = Minimize.templateToStr[c];
                string ret = gen;
                if (Minimize.templateToOriginExpr.ContainsKey(c) && Minimize.templateToOriginExpr[c].Count != 0)
                {
                    var isloop = Minimize.templateToOriginExpr[c].All(tup => tup.Item1);
                    var exprs  = Minimize.templateToOriginExpr[c].Select(tup => SimplifyExpr.ExprToTemplateSpecific(tup.Item2, isloop));
                    ret = exprs.First();
                    ret = exprs.All(s => s == ret) ? ret : gen;
                    ret = isloop ? string.Format("{{:loop}} {0}", ret) : ret;
                }
                Console.WriteLine("Additional contract required: {0}", ret);
            }

            foreach (var tup in templateToPerfDelta)
            {
                if (tup.Value <= 2)
                {
                    continue;
                }
                Console.WriteLine("Contract to pref: {0} {1}", tup.Value, Minimize.templateToStr[tup.Key]);
            }

            Console.WriteLine("Cache hits on calls to PruneAndRun: {0} / {1}", Minimize.CacheHit, Minimize.IterCnt);
        }