public static DefaultRule representativeSubstitution(
      DefaultRule rule, List<Set<Constant>> interchangeable) {
    if (rule.antecedent().variables().isEmpty()) {
      return rule;
    } else {
      // a bit naive (but not too much), it can be improved later...
      List<Literal> auxLiteralsC = new ArrayList<Literal>();
      for (Variable v : rule.antecedent().variables()) {
        auxLiteralsC.add(new Literal("v", v));
      }

      List<Literal> auxLiteralsE = new ArrayList<Literal>();

      int typeIndex = 0;
      for (Set<Constant> interch : interchangeable) {
        int counter = 0;
        for (Term t : interch) {
          auxLiteralsE.add(new Literal("v", t));
          if (++counter >= rule.antecedent().variables().size()) {
            break;
          }
        }
      }
      Matching m = new Matching();
      m.setSubsumptionMode(Matching.OI_SUBSUMPTION);
      Pair<Term[], List<Term[]>> substitutions =
          m.allSubstitutions(new Clause(auxLiteralsC), new Clause(auxLiteralsE), 1);
      return DefaultTransformationUtils.substitute(rule, substitutions.r, substitutions.s.get(0));
    }
  }