Example #1
0
        bool SuppressMatchingLoops()
        {
            // NOTE: This only looks for self-loops; that is, loops involving a single
            // quantifier.

            // For a given quantifier q, we introduce a triggering relation between trigger
            // candidates by writing t1 → t2 if instantiating q from t1 introduces a ground
            // term that matches t2. Then, we notice that this relation is transitive, since
            // all triggers yield the same set of terms. This means that any matching loop
            // t1 → ... → t1 can be reduced to a self-loop t1 → t1. Detecting such
            // self-loops is then only a matter of finding terms in the body of the
            // quantifier that match a given trigger.

            // Of course, each trigger that actually appears in the body of the quantifier
            // yields a trivial self-loop (e.g. P(i) in [∀ i {P(i)} ⋅ P(i)]), so we
            // ignore this type of loops. In fact, we ignore any term in the body of the
            // quantifier that matches one of the terms of the trigger (this ensures that
            // [∀ x {f(x), f(f(x))} ⋅ f(x) = f(f(x))] is not a loop). And we even
            // ignore terms that almost match a trigger term, modulo a single variable
            // (this ensures that [∀ x y {a(x, y)} ⋅ a(x, y) == a(y, x)] is not a loop).
            // In addition, we ignore cases where the only differences between a trigger
            // and a trigger match are places where a variable is replaced with an
            // expression whose free variables do not intersect that of the quantifier
            // in which that expression is found. For examples of this behavious, see
            // triggers/literals-do-not-cause-loops.
            // This ignoring logic is implemented by the CouldCauseLoops method.
            bool foundloop = false;

            foreach (var q in quantifiers)
            {
                var looping        = new List <TriggerCandidate>();
                var loopingMatches = new List <TriggerMatch>();

                var safe = TriggerUtils.Filter(
                    q.Candidates,
                    candidate => candidate.LoopingSubterms(q.quantifier).ToList(),
                    (candidate, loopingSubterms) => !loopingSubterms.Any(),
                    (candidate, loopingSubterms) => {
                    looping.Add(candidate);
                    loopingMatches       = loopingSubterms.ToList();
                    candidate.Annotation = "may loop with " + loopingSubterms.MapConcat(t => "\"" + Printer.ExprToString(t.OriginalExpr) + "\"", ", ");
                }).ToList();

                q.CouldSuppressLoops = safe.Count > 0;
                q.LoopingMatches     = loopingMatches;
                if (!q.AllowsLoops && q.CouldSuppressLoops)
                {
                    q.Candidates = safe;
                    q.RejectedCandidates.AddRange(looping);
                }

                if (looping.Count > 0)
                {
                    foundloop = true;
                }
            }
            return(foundloop);
        }
Example #2
0
 void SelectTriggers()
 {
     foreach (var q in quantifiers) //FIXME Check whether this makes verification faster
     {
         q.Candidates = TriggerUtils.Filter(q.Candidates,
                                            candidate => q.Candidates.Where(candidate.IsStrongerThan).ToList(),
                                            (candidate, weakerCandidates) => !weakerCandidates.Any(),
                                            (candidate, weakerCandidates) => {
             q.RejectedCandidates.Add(candidate);
             candidate.Annotation = "more specific than " + String.Join(", ", weakerCandidates);
         }).ToList();
     }
 }
Example #3
0
        /// <summary>
        /// Collect triggers from the body of each quantifier, and share them
        /// between all quantifiers. This method assumes that all quantifiers
        /// actually come from the same context, and were the result of a split that
        /// gave them all the same variables.
        /// </summary>
        /// <param name="triggersCollector"></param>
        void CollectAndShareTriggers(TriggersCollector triggersCollector)
        {
            List <TriggerTerm> pool = new List <TriggerTerm>();

            foreach (var q in quantifiers)
            {
                var candidates = triggersCollector.CollectTriggers(q.quantifier).Deduplicate(TriggerTerm.Eq);
                // filter out the candidates that was "second-class"
                var filtered = TriggerUtils.Filter(candidates, tr => tr, (tr, _) => !tr.IsTranslatedToFunctionCall(), (tr, _) => { }).ToList();
                // if there are only "second-class" candidates, add them back.
                if (filtered.Count == 0)
                {
                    filtered = candidates;
                }
                pool.AddRange(filtered);
            }
            var distinctPool = pool.Deduplicate(TriggerTerm.Eq);

            foreach (var q in quantifiers)
            {
                q.CandidateTerms = distinctPool; // The list of candidate terms is immutable
                q.Candidates     = TriggerUtils.AllNonEmptySubsets(distinctPool, SubsetGenerationPredicate, q.quantifier.BoundVars).Select(set => set.ToTriggerCandidate()).ToList();
            }
        }
Example #4
0
 internal void TrimInvalidTriggers()
 {
     Contract.Requires(CandidateTerms != null);
     Contract.Requires(Candidates != null);
     Candidates = TriggerUtils.Filter(Candidates, tr => tr, (tr, _) => tr.MentionsAll(quantifier.BoundVars), (tr, _) => { }).ToList();
 }