private TriggerAnnotation AnnotatePotentialCandidate(Expression expr) { bool expr_is_killer = false; HashSet<OldExpr> oldExprSet; if (cache.exprsInOldContext.TryGetValue(expr, out oldExprSet)) { // oldExpr has been set to the value found } else { oldExprSet = null; } var new_exprs = TriggerUtils.MaybeWrapInOld(TriggerUtils.PrepareExprForInclusionInTrigger(expr, out expr_is_killer), oldExprSet); // We expect there to be at least one "new_exprs". // We also expect that the computation of new_term.Variables, collected_terms, and children_contain_killers will be the // same for each of the "new_exprs". // Therefore, we use the values of these variables from the last iteration in the expression that is ultimately returned. TriggerTerm new_term = null; List<TriggerTerm> collected_terms = null; var children_contain_killers = false; foreach (var new_expr in new_exprs) { new_term = new TriggerTerm { Expr = new_expr, OriginalExpr = expr, Variables = CollectVariables(expr) }; collected_terms = CollectExportedCandidates(expr); children_contain_killers = CollectIsKiller(expr); if (!children_contain_killers) { // Add only if the children are not killers; the head has been cleaned up into non-killer form collected_terms.Add(new_term); } } Contract.Assert(new_term != null); // this checks our assumption that "new_exprs" contains at least one value. // This new node is a killer if its children were killers, or if it's non-cleaned-up head is a killer return new TriggerAnnotation(children_contain_killers || expr_is_killer, new_term.Variables, collected_terms); }
internal TermComparison CompareTo(TriggerTerm other) { if (this == other) { return TermComparison.SameStrength; } else if (Expr.AllSubExpressions(true, true).Any(other.Expr.ExpressionEq)) { return TermComparison.Stronger; } else { return TermComparison.NotStronger; } }
/// <summary> /// Simple formulas like [P0(i) && P1(i) && P2(i) && P3(i) && P4(i)] yield very /// large numbers of multi-triggers, most of which are useless. As it copies its /// argument, this method updates various datastructures that allow it to /// efficiently track ownership relations between formulae and bound variables, /// and sets the IsRedundant flag of the returned set, allowing the caller to /// discard that set of terms, and the ones that would have been built on top of /// it, thus ensuring that the only sets of terms produced in the end are sets /// of terms in which each element contributes (owns) at least one variable. /// /// Note that this is trickier than just checking every term for new variables; /// indeed, a new term that does bring new variables in can make an existing /// term redundant (see redundancy-detection-does-its-job-properly.dfy). /// </summary> internal SetOfTerms CopyWithAdd(TriggerTerm term, ISet <BoundVar> relevantVariables) { var copy = new SetOfTerms(); copy.Terms = new List <TriggerTerm>(Terms); copy.variables = new HashSet <BoundVar>(variables); copy.termOwningAUniqueVar = new Dictionary <BoundVar, TriggerTerm>(termOwningAUniqueVar); copy.uniqueVarsOwnedByATerm = new Dictionary <TriggerTerm, ISet <BoundVar> >(uniqueVarsOwnedByATerm); copy.Terms.Add(term); var varsInNewTerm = new HashSet <BoundVar>(term.BoundVars); varsInNewTerm.IntersectWith(relevantVariables); var ownedByNewTerm = new HashSet <BoundVar>(); // Check #0: does this term bring anything new? copy.IsRedundant = IsRedundant || varsInNewTerm.All(bv => copy.variables.Contains(bv)); copy.variables.UnionWith(varsInNewTerm); // Check #1: does this term claiming ownership of all its variables cause another term to become useless? foreach (var v in varsInNewTerm) { TriggerTerm originalOwner; if (copy.termOwningAUniqueVar.TryGetValue(v, out originalOwner)) { var alsoOwnedByOriginalOwner = copy.uniqueVarsOwnedByATerm[originalOwner]; alsoOwnedByOriginalOwner.Remove(v); if (!alsoOwnedByOriginalOwner.Any()) { copy.IsRedundant = true; } } else { ownedByNewTerm.Add(v); copy.termOwningAUniqueVar[v] = term; } } // Actually claim ownership copy.uniqueVarsOwnedByATerm[term] = ownedByNewTerm; return(copy); }
private TriggerAnnotation AnnotatePotentialCandidate(Expression expr) { bool expr_is_killer = false; var new_expr = TriggerUtils.MaybeWrapInOld(TriggerUtils.PrepareExprForInclusionInTrigger(expr, out expr_is_killer), cache.exprsInOldContext.Contains(expr)); var new_term = new TriggerTerm { Expr = new_expr, OriginalExpr = expr, Variables = CollectVariables(expr) }; List <TriggerTerm> collected_terms = CollectExportedCandidates(expr); var children_contain_killers = CollectIsKiller(expr); if (!children_contain_killers) { // Add only if the children are not killers; the head has been cleaned up into non-killer form collected_terms.Add(new_term); } // This new node is a killer if its children were killers, or if it's non-cleaned-up head is a killer return(new TriggerAnnotation(children_contain_killers || expr_is_killer, new_term.Variables, collected_terms)); }
internal static bool Eq(TriggerTerm t1, TriggerTerm t2) { return(ExprExtensions.ExpressionEq(t1.Expr, t2.Expr)); }
private bool SubsetGenerationPredicate(TriggerUtils.SetOfTerms terms, TriggerTerm additionalTerm) { return(true); // FIXME Remove this //return additionalTerm.Variables.Where(v => v is BoundVar && !terms.Any(t => t.Variables.Contains(v))).Any(); }