code: private void retainOnly(int columns) {
          LOGGER.info("Sorting the columns by entropy and computing the top " + 
                      columns + " columns to retain");
  
          int words = termToIndex.numDimensions();
          MultiMap<Double,Integer> entropyToIndex =
              new BoundedSortedMultiMap<Double,Integer>(
                      columns, false, true, true);
  
          // Compute the entropy of each row and column.
          EntropyStats stats = MatrixEntropy.entropy(cooccurrenceMatrix);
  
          // Add the entropy values for each column.  Since the rows will be
          // concatenated as columns, they represent currently non-existing
          // columns beyond the number of words.
          for (int col = 0; col < words; ++col)
              entropyToIndex.put(stats.colEntropy[col], col);
          for (int row = 0; row < words; ++row)
              entropyToIndex.put(stats.rowEntropy[row], row+words);
  
          Set<Integer> indicesToKeep =
              new HashSet<Integer>(entropyToIndex.values());
  
          LOGGER.info("Reducing to " + columns + " highest entropy columns.");
          
          reduced = retainColumns(indicesToKeep);
          cooccurrenceMatrix = null;
      }
docs: Drops all but the specified number of columns, retaining those that have
  the highest information theoretic entropy.
  
  @param columns the number of columns to keep