@Override
    protected void searchStep() {
        // get list of possible moves
        List<? extends Move<? super SolutionType>> moves = getNeighbourhood().getAllMoves(getCurrentSolution());
        // shuffle moves
        Collections.shuffle(moves);
        // find best admissible move, or first admissible improvement (if any)
        Move<? super SolutionType> move = getBestMove(
            // inspect all moves
            moves,
            // not necessarily an improvement
            false,
            // return first improvement move, if any
            true,
            // filter tabu moves (with aspiration criterion)
            getTabuFilter()
        );
        // process chosen move
        if (move != null) {
            // accept move (automatically updates tabu memory)
            accept(move);
        } else {
            // no valid non-tabu neighbour found: terminate search
            stop();
        }
    }
@ Override protected void searchStep ( ) { List < ? extends Move < ? super SolutionType > > moves = getNeighbourhood ( ) . getAllMoves ( getCurrentSolution ( ) ) ; Collections . shuffle ( moves ) ; Move < ? super SolutionType > move = getBestMove ( moves , false , true , getTabuFilter ( ) ) ; if ( move != null ) { accept ( move ) ; } else { stop ( ) ; } }
One step of the first-best-admissible tabu search algorithm.
All possible moves are inspected in random order, and either the first admissible improvement,
if any, or, else, the best admissible move, is applied to the current solution.

@throws IncompatibleTabuMemoryException if the applied tabu memory is not compatible with the type of moves
generated by the applied neighbourhood
@throws JamesRuntimeException if depending on malfunctioning components (problem, neighbourhood, ...)