private LocalSearchDecider buildDecider(
     HeuristicConfigPolicy configPolicy, Termination termination) {
   LocalSearchDecider decider = new LocalSearchDecider();
   decider.setTermination(termination);
   MoveSelector moveSelector = buildMoveSelector(configPolicy);
   decider.setMoveSelector(moveSelector);
   AcceptorConfig acceptorConfig_ = acceptorConfig == null ? new AcceptorConfig() : acceptorConfig;
   decider.setAcceptor(acceptorConfig_.buildAcceptor(configPolicy));
   ForagerConfig foragerConfig_ = foragerConfig == null ? new ForagerConfig() : foragerConfig;
   Forager forager = foragerConfig_.buildForager(configPolicy);
   decider.setForager(forager);
   if (moveSelector.isNeverEnding() && !forager.supportsNeverEndingMoveSelector()) {
     throw new IllegalStateException(
         "The moveSelector ("
             + moveSelector
             + ") has neverEnding ("
             + moveSelector.isNeverEnding()
             + "), but the forager ("
             + forager
             + ") does not support it."
             + " Configure the <forager> with <acceptedCountLimit>.");
   }
   EnvironmentMode environmentMode = configPolicy.getEnvironmentMode();
   if (environmentMode.isNonIntrusiveFullAsserted()) {
     decider.setAssertMoveScoreFromScratch(true);
   }
   if (environmentMode.isIntrusiveFastAsserted()) {
     decider.setAssertExpectedUndoMoveScore(true);
   }
   return decider;
 }
 @Override
 public CustomPhase buildPhase(
     int phaseIndex,
     HeuristicConfigPolicy solverConfigPolicy,
     BestSolutionRecaller bestSolutionRecaller,
     Termination solverTermination) {
   HeuristicConfigPolicy phaseConfigPolicy = solverConfigPolicy.createPhaseConfigPolicy();
   DefaultCustomPhase customPhase = new DefaultCustomPhase();
   configurePhase(
       customPhase, phaseIndex, phaseConfigPolicy, bestSolutionRecaller, solverTermination);
   if (ConfigUtils.isEmptyCollection(customPhaseCommandClassList)) {
     throw new IllegalArgumentException(
         "Configure at least 1 <customPhaseCommandClass> in the <customPhase> configuration.");
   }
   List<CustomPhaseCommand> customPhaseCommandList =
       new ArrayList<>(customPhaseCommandClassList.size());
   Map<String, String> customProperties_ =
       customProperties != null ? customProperties : Collections.<String, String>emptyMap();
   for (Class<? extends CustomPhaseCommand> customPhaseCommandClass :
       customPhaseCommandClassList) {
     CustomPhaseCommand customPhaseCommand =
         ConfigUtils.newInstance(this, "customPhaseCommandClass", customPhaseCommandClass);
     customPhaseCommand.applyCustomProperties(customProperties_);
     customPhaseCommandList.add(customPhaseCommand);
   }
   customPhase.setCustomPhaseCommandList(customPhaseCommandList);
   customPhase.setForceUpdateBestSolution(
       forceUpdateBestSolution == null ? false : forceUpdateBestSolution);
   EnvironmentMode environmentMode = phaseConfigPolicy.getEnvironmentMode();
   if (environmentMode.isNonIntrusiveFullAsserted()) {
     customPhase.setAssertStepScoreFromScratch(true);
   }
   return customPhase;
 }
 public LocalSearchSolverPhase buildSolverPhase(
     int phaseIndex, HeuristicConfigPolicy solverConfigPolicy, Termination solverTermination) {
   HeuristicConfigPolicy phaseConfigPolicy = solverConfigPolicy.createPhaseConfigPolicy();
   DefaultLocalSearchSolverPhase phase = new DefaultLocalSearchSolverPhase();
   configureSolverPhase(phase, phaseIndex, phaseConfigPolicy, solverTermination);
   phase.setDecider(buildDecider(phaseConfigPolicy, phase.getTermination()));
   EnvironmentMode environmentMode = phaseConfigPolicy.getEnvironmentMode();
   if (environmentMode.isNonIntrusiveFullAsserted()) {
     phase.setAssertStepScoreFromScratch(true);
   }
   if (environmentMode.isIntrusiveFastAsserted()) {
     phase.setAssertExpectedStepScore(true);
   }
   return phase;
 }