code: @Override
      public List<SubsetMove> getAllMoves(SubsetSolution solution) {
          // create empty list to store generated moves
          List<SubsetMove> moves = new ArrayList<>();
          // get set of candidate IDs for deletion and addition
          Set<Integer> removeCandidates = getRemoveCandidates(solution);
          Set<Integer> addCandidates = getAddCandidates(solution);
          // possible to perform desired number of swaps?
          int curNumSwaps = numSwaps(addCandidates, removeCandidates);
          if(curNumSwaps == 0){
              // impossible: return empty set
              return moves;
          }
          // create all moves performing numSwaps swaps
          SubsetIterator<Integer> itDel, itAdd;
          Set<Integer> del, add;
          itDel = new SubsetIterator<>(removeCandidates, curNumSwaps);
          while(itDel.hasNext()){
              del = itDel.next();
              itAdd = new SubsetIterator<>(addCandidates, curNumSwaps);
              while(itAdd.hasNext()){
                  add = itAdd.next();
                  // create and add move
                  moves.add(new GeneralSubsetMove(add, del));
              }
          }
          // return all moves
          return moves;
      }
docs: <p>
  Generates the list of all possible moves that perform exactly \(k\) swaps, where \(k\) is the desired number
  of swaps specified at construction. Possible fixed IDs are not considered to be swapped. If \(m &lt; k\)
  IDs are currently selected or unselected (excluding any fixed IDs), no swaps can be performed and the
  returned list will be empty.
  
  @param solution solution for which all possible multi swap moves are generated
  @return list of all multi swap moves, may be empty