docs: public List<Factor> getMinimalFactors() {
      // Sort factors in descending order of size.
      List<Factor> sortedFactors = Lists.newArrayList(factors);
      Collections.sort(sortedFactors, new Comparator<Factor>() {
        public int compare(Factor f1, Factor f2) {
          return f2.getVars().size() - f1.getVars().size();
        }
      });
  
      List<List<Factor>> factorsToMerge = Lists.newArrayList();
      Set<Integer> factorNums = Sets.newHashSet();
      Multimap<Integer, Integer> varFactorIndex = HashMultimap.create();
      for (Factor f : sortedFactors) {
        Set<Integer> mergeableFactors = Sets.newHashSet(factorNums);
        for (int varNum : f.getVars().getVariableNumsArray()) {
          mergeableFactors.retainAll(varFactorIndex.get(varNum));
        }
  
        if (mergeableFactors.size() > 0) {
          int factorIndex = Iterables.getFirst(mergeableFactors, -1);
          factorsToMerge.get(factorIndex).add(f);
        } else {
          for (int varNum : f.getVars().getVariableNumsArray()) {
            varFactorIndex.put(varNum, factorsToMerge.size());
          }
          factorNums.add(factorsToMerge.size());
          factorsToMerge.add(Lists.newArrayList(f));
        }
      }
  
      // Merge factors using size as a guideline
      List<Factor> finalFactors = Lists.newArrayListWithCapacity(factorsToMerge.size());
      for (List<Factor> toMerge : factorsToMerge) {
        // Sort the factors by their .size() attribute, sparsest factors
        // first.
        Collections.sort(toMerge, new Comparator<Factor>() {
          public int compare(Factor f1, Factor f2) {
            return (int) (f1.size() - f2.size());
          }
        });
        finalFactors.add(Factors.product(toMerge));
      }
      return finalFactors;
    }