private Template loopVarsAndHeadFreeCombMethod(InfixReln relation) {
    Template choice = null;
    // Get all loop head and loop tail variables.
    Set<TemplateTerm> headVars = getUnindexedVarsAsTerms(loopFormulaHead);
    Set<TemplateTerm> tailVars = getUnindexedVarsAsTerms(loopFormulaTail);

    // Declare a list of terms for each conjunct.
    List<TemplateTerm> headTerms = new Vector<>();
    List<TemplateTerm> tailTerms = new Vector<>();

    // Add the loop vars.
    headTerms.addAll(headVars);
    tailTerms.addAll(tailVars);

    // Create a fresh parameter linear combination of the terms for each conjunct.
    TemplateSum headLHS = TemplateSum.freshParamLinComb(type, headTerms);
    TemplateSum tailLHS = TemplateSum.freshParamLinComb(type, tailTerms);

    // Make RHS parameters.
    TemplateVariable param = TemplateTerm.getNextFreshParameter(type);
    TemplateTerm headRHS = new TemplateTerm(type);
    headRHS.setParameter(param);
    param = TemplateTerm.getNextFreshParameter(type);
    TemplateTerm tailRHS = new TemplateTerm(type);
    tailRHS.setParameter(param);

    // Build the conjuncts as constraints.
    TemplateFormula headFormula = new TemplateConstraint(headLHS, InfixReln.LEQ, headRHS);
    TemplateFormula tailFormula = new TemplateConstraint(tailLHS, InfixReln.EQUAL, tailRHS);

    // Form the conjunction.
    TemplateFormula formula =
        TemplateConjunction.conjoin((TemplateBoolean) headFormula, (TemplateBoolean) tailFormula);

    // Make nonzero parameter clause.
    // Namely, we simply ask that not all of the top-level parameters on
    // the LHS be zero.
    Set<TemplateVariable> topLevelLHSparams = headLHS.getTopLevelParameters();
    topLevelLHSparams.addAll(tailLHS.getTopLevelParameters());
    TemplateFormula nzpc = makeBasicParamClause(topLevelLHSparams);

    choice = new Template(formula, nzpc);
    return choice;
  }
  private Template loopVarsFreeCombMethod(InfixReln relation) {
    Template choice = null;
    // Get all loop variables.
    Set<TemplateTerm> loopVars = getUnindexedVarsAsTerms(loopFormula);

    // Get all distinct UIF names occurring at the top level in the loop formula,
    // and their arities.
    Map<String, Integer> uifNA = getTopLevelUIFnamesAndArities(loopFormula);

    // Declare the list of terms for the template.
    List<TemplateTerm> templateTerms = new Vector<>();

    // First add one term for each UIF name.
    int arity;
    TemplateUIF uif;
    for (String name : uifNA.keySet()) {
      arity = uifNA.get(name).intValue();
      TemplateSum[] args = new TemplateSum[arity];
      // each arg is a fresh parameter linear combination over loopVars
      for (int i = 0; i < arity; i++) {
        args[i] = TemplateSum.freshParamLinComb(type, loopVars);
      }
      // create the uif
      uif = new TemplateUIF(name, type, new TemplateSumList(args));
      // put it in a term
      templateTerms.add(new TemplateTerm(uif));
    }

    // Now add the loop vars themselves.
    templateTerms.addAll(loopVars);

    // Finally create a fresh parameter linear combination of all the terms.
    TemplateSum LHS = TemplateSum.freshParamLinComb(type, templateTerms);

    // Make RHS parameter.
    TemplateVariable param = TemplateTerm.getNextFreshParameter(type);
    TemplateTerm RHS = new TemplateTerm(type);
    RHS.setParameter(param);

    // 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 TemplateTerm makeRHSParameter() {
   TemplateVariable param = TemplateTerm.getNextFreshParameter(type);
   TemplateTerm RHS = new TemplateTerm(type);
   RHS.setParameter(param);
   return RHS;
 }