code: @SafeVarargs
      protected final Move<? super SolutionType> getBestMove(Collection<? extends Move<? super SolutionType>> moves,
                                                             boolean requireImprovement,
                                                             Predicate<? super Move<? super SolutionType>>... filters){
          return this.getBestMove(moves, requireImprovement, false, filters);
      }
docs: <p>
  Get the best valid move among a collection of possible moves. The best move is the one yielding the
  largest delta (see {@link #computeDelta(Evaluation, Evaluation)}) when being applied to the current
  solution, from all valid moves.
  </p>
  <p>
  If <code>requireImprovement</code> is set to <code>true</code>, only moves that improve the current solution
  are considered, i.e. moves that yield a positive delta (unless the current solution is invalid, then all
  valid moves are improvements). Any number of additional filters can be specified, where moves are only
  admitted if they pass through all filters. Each filter is a predicate that should return <code>true</code>
  if a given move is to be considered. If any filter returns <code>false</code> for a specific move, this
  move is discarded.
  </p>
  <p>
  Returns <code>null</code> if no move is found that satisfies all conditions.
  </p>
  <p>
  Note that all computed evaluations and validations are cached.
  Before returning the chosen move, if any, its evaluation and validation are re-cached
  to maximize the probability that these values will remain available in the cache for later retrieval.
  </p>
  
  @param moves collection of possible moves
  @param requireImprovement if set to <code>true</code>, only improving moves are considered
  @param filters additional move filters
  @return best valid move, may be <code>null</code>