code: private Set<String> doResolveFeatures(Collection<String> rootFeatures, Set<String> preResolved, SelectionContext selectionContext) {
          // first pass; process the roots until we have selected all the candidates for multiple versions;
          // need to reset the initial black list count so we can recalculate it during the first pass
          selectionContext.resetInitialBlackListCount();
          Set<String> result = processCurrentPermutation(rootFeatures, preResolved, selectionContext);
  
          // if the first pass resulted in no conflicts return the results (optimistic)
          if (selectionContext.getResult().getConflicts().isEmpty()) {
              selectionContext.selectCurrentPermutation();
              return result;
          }
  
          // oh oh, we have conflicts;
          // NOTE, if the current solution has more conflicts than the initial count (black list)
          // then that means one of the toleration (postponed) choices we made introduced an
          // addition conflict.  That implies that a better solution may be available.
          // As long as there are more conflicts than the number of initial root conflicts
          // and there is a different permutation to try do another pass
          while (selectionContext.currentHasMoreThanInitialBlackListCount() && selectionContext.popPermutation()) {
              result = processCurrentPermutation(rootFeatures, preResolved, selectionContext);
          }
  
          // Return the best solution found
          selectionContext.restoreBestSolution();
          return selectionContext.getResult().getResolvedFeatures();
      }
docs: /*
  There are two phases to resolving the root features.
  1) Optimistically process all multiple candidate features to the end picking the most preferred features
  2) If this is successful then return the result with no conficts
  3) If conflicts were found then backtrack over the permutations and choose different candidates. Note this may create more permutations
  4) if a permutation is found that has not conflicts return the results
  5) Otherwise use the first permutation and report the original conflicts