Ejemplo n.º 1
0
        private static void AnalyzeDependencyWithUnsatCore(VCExpr programVC, Constant outConstant, Dependencies result, string procName, List <Constant> inputGuardConsts, List <Constant> outputGuardConsts)
        {
            #region Description of UNSAT core logic implemented below

            /*
             *  Given VC, I, O, o
             *  - preInp = (\wedge_{i \in I} i)
             *  - preOut = (\wedge_{o' \in O} !o') \wedge o
             *  - VC' = (preOut => VC)
             *  - checkValid preInp => VC'
             *  - if invalid return
             *  - A += !VC'
             *  - A += I
             *  - if (CheckAssumption(A, out core) != valid) ABORT
             */
            #endregion

            //Should call VerifyVC before invoking CheckAssumptions
            List <Counterexample> cexs;
            var preInp = inputGuardConsts
                         .Aggregate(VCExpressionGenerator.True, (x, y) => VC.exprGen.And(x, VC.translator.LookupVariable(y)));
            var preOut = outputGuardConsts
                         .Where(x => x != outConstant)
                         .Aggregate(VCExpressionGenerator.True, (x, y) => VC.exprGen.And(x, VC.exprGen.Not(VC.translator.LookupVariable(y))));
            preOut = VC.exprGen.And(preOut, VC.translator.LookupVariable(outConstant));
            var newVC = VC.exprGen.Implies(preOut, programVC);

            //TODO: Really really ugly way to get to the Variable in the guardOutput
            var vexpr  = (Expr)Utils.AttributeUtils.GetAttributeVals(outConstant.Attributes, RefineConsts.modSetGuradAttribute)[1];
            var vident = vexpr as IdentifierExpr;
            if (vident == null)
            {
                throw new Exception(string.Format("Illegal variable expression {0} in {1} attribute", vexpr, RefineConsts.modSetGuardName));
            }
            var v = vident.Decl;

            //check for validity (presence of all input eq implies output is equal)
            var outcome = VC.VerifyVC("RefineDependency", VC.exprGen.Implies(preInp, newVC), out cexs);
            Console.Write("-");
            if (outcome == ProverInterface.Outcome.Invalid)
            {
                Console.WriteLine("\t VC not valid, returning");
                result[v].Add(Utils.VariableUtils.NonDetVar);
                Console.WriteLine("\t Dependency of {0} =  <{1}>", v, string.Join(",", result[v]));
                return;
            }
            if (outcome == ProverInterface.Outcome.OutOfMemory ||
                outcome == ProverInterface.Outcome.TimeOut ||
                outcome == ProverInterface.Outcome.Undetermined)
            {
                Console.WriteLine("\t VC inconclusive, returning");
                result[v].Add(Utils.VariableUtils.NonDetVar);
                Console.WriteLine("\t Dependency of {0} =  <{1}>", v, string.Join(",", result[v]));
                return;
            }

            List <int> unsatClauseIdentifiers = new List <int>();
            var        assumptions            = new List <VCExpr>();
            assumptions.Add(VC.exprGen.Not(newVC));

            //Add the list of all input constants
            inputGuardConsts.ForEach(x => assumptions.Add(VC.translator.LookupVariable(x)));

            //VERY IMPORTANT: TO USE UNSAT CORE, SET ContractInfer to true in CommandLineOptions.Clo.
            outcome = ProverInterface.Outcome.Undetermined;
            outcome = VC.proverInterface.CheckAssumptions(assumptions, out unsatClauseIdentifiers, VC.handler);
            Console.Write("+");
            if (outcome == ProverInterface.Outcome.Invalid && unsatClauseIdentifiers.Count() == 0)
            {
                Console.WriteLine("Something went wrong! Unsat core with 0 elements for {0}", outConstant);
                return;
            }
            if (!unsatClauseIdentifiers.Remove(0)) //newVC should be always at 0, since it has to participate in inconsistency
            {
                Console.WriteLine("Something went wrong! The VC itself is not part of UNSAT core");
                return;
            }

            //Core may not be minimal (e.g. testdependencyDummy.bpl), need to iterate
            var core0 = unsatClauseIdentifiers.Select(i => assumptions[i]);
            var core  = new List <VCExpr>(core0);
            if (!Analysis.noMinUnsatCore)
            {
                core0
                .Iter(b =>
                {
                    core.Remove(b);
                    preInp  = core.Aggregate(VCExpressionGenerator.True, (x, y) => VC.exprGen.And(x, y));
                    outcome = VC.VerifyVC("RefineDependency", VC.exprGen.Implies(preInp, newVC), out cexs);
                    Console.Write(".");
                    if (outcome != ProverInterface.Outcome.Valid)
                    {
                        core.Add(b);
                        return;
                    }
                });
            }
            //We are about to refine the dependency of v, so we start with the empty set
            result[v] = new VarSet();
            //TODO: THIS HAS TO GO AWAY with proper variables!!!
            foreach (var ig in inputGuardConsts)
            {
                if (core.Contains(VC.translator.LookupVariable(ig)))
                {
                    IdentifierExpr iexpr = (IdentifierExpr)Utils.AttributeUtils.GetAttributeVals(ig.Attributes, RefineConsts.readSetGuradAttribute)[1];
                    result[v].Add(iexpr.Decl);
                }
            }
            Console.WriteLine("\t Dependency of {0} = <{1}>",
                              v,
                              string.Join(",", result[v]));
        }