/*
   * 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;
  }
  private Template topLevelTermFormsMethod(InfixReln relation) {
    Template choice = null;

    // Get all forms.
    Set<TermForm> forms = entryFormula.getTopLevelTermForms();
    forms.addAll(loopFormula.getTopLevelTermForms());
    forms.addAll(exitFormula.getTopLevelTermForms());

    // Convert to terms, and sum up for LHS.
    Vector<TemplateTerm> terms = new Vector<>();
    for (TermForm f : forms) {
      terms.add(f.getTemplate());
    }
    TemplateSum LHS = new TemplateSum(FormulaType.RationalType, terms);

    // Make RHS parameter.
    TemplateTerm RHS = makeRHSParameter();

    // Build template formula as constraint.
    TemplateFormula formula = new TemplateConstraint(LHS, relation, RHS);

    // 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);

    choice = new Template(formula, nzpc);
    return choice;
  }
 private Map<String, Integer> getTopLevelUIFnamesAndArities(TemplateFormula f) {
   Set<TemplateUIF> topLevelUIFs = f.getAllTopLevelUIFs();
   HashMap<String, Integer> map = new HashMap<>();
   String name;
   Integer arity;
   for (TemplateUIF u : topLevelUIFs) {
     name = u.getName();
     arity = Integer.valueOf(u.getArity());
     map.put(name, arity);
   }
   return map;
 }
 private Set<TemplateTerm> getUnindexedVarsAsTerms(TemplateFormula f) {
   Set<TemplateVariable> vars = f.getAllVariables();
   Set<String> varNames = new HashSet<>();
   for (TemplateVariable v : vars) {
     varNames.add(v.getName());
   }
   Set<TemplateTerm> terms = new HashSet<>();
   TemplateTerm t;
   for (String name : varNames) {
     t = new TemplateTerm(type);
     t.setVariable(new TemplateVariable(type, name));
     terms.add(t);
   }
   return terms;
 }