@Test
  public void trackLocalSearch() {
    SolverFactory<NQueens> solverFactory =
        SolverFactory.createFromXmlResource(NQueensApp.SOLVER_CONFIG);
    SolverConfig solverConfig = solverFactory.getSolverConfig();

    NQueensGenerator generator = new NQueensGenerator();
    NQueens planningProblem = NQueensSolutionInitializer.initialize(generator.createNQueens(N));

    LocalSearchPhaseConfig localSearchPhaseConfig = new LocalSearchPhaseConfig();
    localSearchPhaseConfig.setAcceptorConfig(acceptorConfig);
    localSearchPhaseConfig.setForagerConfig(localSearchForagerConfig);
    localSearchPhaseConfig.getForagerConfig().setBreakTieRandomly(false);
    localSearchPhaseConfig.setMoveSelectorConfig(new ChangeMoveSelectorConfig());
    localSearchPhaseConfig.getMoveSelectorConfig().setSelectionOrder(SelectionOrder.ORIGINAL);
    localSearchPhaseConfig.setTerminationConfig(new TerminationConfig());
    localSearchPhaseConfig.getTerminationConfig().setStepCountLimit(20);
    solverConfig.getPhaseConfigList().set(1, localSearchPhaseConfig);

    NQueensStepTracker listener = new NQueensStepTracker();
    DefaultSolver<NQueens> solver = (DefaultSolver<NQueens>) solverFactory.buildSolver();
    solver.addPhaseLifecycleListener(listener);
    NQueens bestSolution = solver.solve(planningProblem);

    assertNotNull(bestSolution);
    assertTrackingList(expectedCoordinates, listener.getTrackingList());
  }
 public void fireBestSolutionChanged(Solution newBestSolution, int newUninitializedVariableCount) {
   final Iterator<SolverEventListener> it = getEventListenersIterator();
   if (it.hasNext()) {
     final BestSolutionChangedEvent event =
         new BestSolutionChangedEvent(
             solver,
             solver.getSolverScope().calculateTimeMillisSpent(),
             newBestSolution,
             newUninitializedVariableCount);
     do {
       it.next().bestSolutionChanged(event);
     } while (it.hasNext());
   }
 }
 public Solver buildSolver() {
   DefaultSolver solver = new DefaultSolver();
   BasicPlumbingTermination basicPlumbingTermination = new BasicPlumbingTermination();
   solver.setBasicPlumbingTermination(basicPlumbingTermination);
   EnvironmentMode environmentMode =
       this.environmentMode == null ? EnvironmentMode.REPRODUCIBLE : this.environmentMode;
   if (randomSeed != null) {
     solver.setRandomSeed(randomSeed);
   } else {
     if (environmentMode != EnvironmentMode.PRODUCTION) {
       solver.setRandomSeed(DEFAULT_RANDOM_SEED);
     }
   }
   SolutionDescriptor solutionDescriptor = buildSolutionDescriptor();
   ScoreDirectorFactoryConfig scoreDirectorFactoryConfig_ =
       scoreDirectorFactoryConfig == null
           ? new ScoreDirectorFactoryConfig()
           : scoreDirectorFactoryConfig;
   ScoreDirectorFactory scoreDirectorFactory =
       scoreDirectorFactoryConfig_.buildScoreDirectorFactory(environmentMode, solutionDescriptor);
   solver.setScoreDirectorFactory(scoreDirectorFactory);
   ScoreDefinition scoreDefinition = scoreDirectorFactory.getScoreDefinition();
   TerminationConfig terminationConfig_ =
       terminationConfig == null ? new TerminationConfig() : terminationConfig;
   Termination termination =
       terminationConfig_.buildTermination(scoreDefinition, basicPlumbingTermination);
   solver.setTermination(termination);
   BestSolutionRecaller bestSolutionRecaller = buildBestSolutionRecaller(environmentMode);
   solver.setBestSolutionRecaller(bestSolutionRecaller);
   if (CollectionUtils.isEmpty(solverPhaseConfigList)) {
     throw new IllegalArgumentException(
         "Configure at least 1 phase (for example <localSearch>) in the solver configuration.");
   }
   List<SolverPhase> solverPhaseList = new ArrayList<SolverPhase>(solverPhaseConfigList.size());
   int phaseIndex = 0;
   for (SolverPhaseConfig solverPhaseConfig : solverPhaseConfigList) {
     SolverPhase solverPhase =
         solverPhaseConfig.buildSolverPhase(
             phaseIndex, environmentMode, solutionDescriptor, scoreDefinition, termination);
     ((AbstractSolverPhase) solverPhase).setBestSolutionRecaller(bestSolutionRecaller);
     solverPhaseList.add(solverPhase);
     phaseIndex++;
   }
   solver.setSolverPhaseList(solverPhaseList);
   return solver;
 }
 public void close(Solver solver) {
   ((DefaultSolver) solver).removePhaseLifecycleListener(listener);
 }
 public void open(Solver solver) {
   DefaultSolver defaultSolver = (DefaultSolver) solver;
   defaultSolver.setConstraintMatchEnabledPreference(true);
   defaultSolver.addPhaseLifecycleListener(listener);
 }