/* * Let the "tail formula" of the exit path be the path formula for all edges of the * exit path except the first. We find the set of all terms in the tail formula in which * all program variables appear with SSA index 1 (meaning this regards their state upon exit * of the loop, and prior to any subsequent modification), and we form a fresh-parameter * linear combination of these terms for the LHS of our template. The RHS is another * fresh parameter, and the relation is the one passed as argument. * * The idea is to try this method after the exitHeadNegationMethod. If that one failed, * then probably we didn't enter the error state simply because of the edge along which * we exited the loop; instead, it might have been because something which is actually * true of the program variables on loop exit was supposed not to be. For example, we might * have reached the error state because of a failed 'assert' statement, which simply asserts * something about the variables involved in the loop. Our hope is to build as invariant the * very statement that is asserted. */ private Template exitTailIndexOneFreeCombMethod(InfixReln relation) { // Get top-level terms. Set<TemplateTerm> terms = exitFormulaTail.getTopLevelTerms(); // Keep just those that have max index 1. Set<TemplateTerm> indexone = new HashSet<>(); int n; for (TemplateTerm t : terms) { n = t.getMaxIndex(); if (n == 1) { indexone.add(t); } } // Combine these for LHS. TemplateSum LHS = TemplateSum.freshParamLinComb(type, indexone); // Make RHS parameter. TemplateTerm RHS = makeRHSParameter(); // Build template formula as constraint. TemplateFormula formula = new TemplateConstraint(LHS, relation, RHS); formula.unindex(); // Make nonzero parameter clause. // Namely, we simply ask that not all of the top-level parameters on // the LHS be zero. Set<TemplateVariable> topLevelLHSparams = LHS.getTopLevelParameters(); TemplateFormula nzpc = makeBasicParamClause(topLevelLHSparams); Template choice = new Template(formula, nzpc); return choice; }