public static Term min(Iterable<? extends Term> iterable) {
   Term min = null;
   for (Term t : iterable) {
     if (min == null || t.name().compareTo(min.name()) < 0) {
       min = t;
     }
   }
   return min;
 }
 public static void addDomainConstants(
     Iterable<Term> constants, MultiList<Object, Set<Term>> interchangeable) {
   MultiMap<Object, Term> typed = new MultiMap<Object, Term>();
   for (Term t : constants) {
     typed.put(t.type() == null ? Sugar.NIL : t.type(), t);
   }
   for (Map.Entry<Object, Set<Term>> entry : typed.entrySet()) {
     interchangeable.put(entry.getKey(), entry.getValue());
   }
 }
  private static MultiList<Object, Set<Constant>> partitionExchangeable_impl(
      Iterable<DefaultRule> rules) {
    MultiMap<Term, Term> partitioning = new MultiMap<Term, Term>();

    List<Term> constants = Sugar.arrayListFromCollections(constants(rules));
    Set<Term> closed = new HashSet<Term>();

    // checking interchangeability pairwise
    for (int i = 0; i < constants.size(); i++) {
      if (!closed.contains(constants.get(i))) {
        partitioning.put(constants.get(i), constants.get(i));
        for (int j = i + 1; j < constants.size(); j++) {
          if (areExchangeable(constants.get(i), constants.get(j), rules)) {
            partitioning.put(constants.get(i), constants.get(j));
            closed.add(constants.get(j));
          }
        }
      }
    }
    Map<Constant, Constant> map = new HashMap<Constant, Constant>();
    for (Map.Entry<Term, Set<Term>> entry : partitioning.entrySet()) {
      Constant lexmin = null;
      for (Term t : entry.getValue()) {
        if (t instanceof Constant) {
          if (lexmin == null || t.toString().compareTo(lexmin.toString()) < 0) {
            lexmin = (Constant) t;
          }
        }
      }
      for (Term t : entry.getValue()) {
        if (t instanceof Constant) {
          map.put((Constant) t, lexmin);
        }
      }
    }

    MultiMap<Pair<Object, Constant>, Constant> mm =
        new MultiMap<Pair<Object, Constant>, Constant>();
    for (Map.Entry<Constant, Constant> entry : map.entrySet()) {
      mm.put(
          new Pair<Object, Constant>(
              entry.getValue().type() == null ? Sugar.NIL : entry.getValue().type(),
              entry.getValue()),
          entry.getKey());
    }

    MultiList<Object, Set<Constant>> retVal = new MultiList<Object, Set<Constant>>();
    for (Map.Entry<Pair<Object, Constant>, Set<Constant>> entry : mm.entrySet()) {
      retVal.put(entry.getKey().r, entry.getValue());
    }
    return retVal;
  }
 private static boolean sameType(Term a, Term b) {
   if (a.type() == null && b.type() == null) {
     return true;
   } else if ((a.type() == null && b.type() != null) || (a.type() != null && b.type() == null)) {
     return false;
   } else {
     return a.type().equals(b.type());
   }
 }