package org.optaplanner.examples.nqueens.solver.tracking;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.optaplanner.core.api.solver.SolverFactory;
import org.optaplanner.core.config.heuristic.selector.common.SelectionOrder;
import org.optaplanner.core.config.heuristic.selector.move.generic.ChangeMoveSelectorConfig;
import org.optaplanner.core.config.localsearch.LocalSearchPhaseConfig;
import org.optaplanner.core.config.localsearch.decider.acceptor.AcceptorConfig;
import org.optaplanner.core.config.localsearch.decider.acceptor.AcceptorType;
import org.optaplanner.core.config.localsearch.decider.forager.LocalSearchForagerConfig;
import org.optaplanner.core.config.solver.SolverConfig;
import org.optaplanner.core.config.solver.termination.TerminationConfig;
import org.optaplanner.core.impl.solver.DefaultSolver;
import org.optaplanner.examples.nqueens.app.NQueensApp;
import org.optaplanner.examples.nqueens.domain.NQueens;
import org.optaplanner.examples.nqueens.persistence.NQueensGenerator;
import static org.junit.Assert.*;
@RunWith(Parameterized.class)
public class NQueensLocalSearchTrackingTest extends NQueensAbstractTrackingTest {
private static final int N = 6;
private final AcceptorConfig acceptorConfig;
private final LocalSearchForagerConfig localSearchForagerConfig;
private final List<NQueensStepTracking> expectedCoordinates;
public NQueensLocalSearchTrackingTest(AcceptorConfig acceptorConfig,
LocalSearchForagerConfig localSearchForagerConfig,
List<NQueensStepTracking> expectedCoordinates) {
this.expectedCoordinates = expectedCoordinates;
this.localSearchForagerConfig = localSearchForagerConfig;
this.acceptorConfig = acceptorConfig;
}
@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());
}
@Parameterized.Parameters(name = "AcceptorType: {0}")
public static Collection<Object[]> parameters() {
Collection<Object[]> params = new ArrayList<>();
AcceptorConfig acceptorConfig = new AcceptorConfig();
LocalSearchForagerConfig localSearchForagerConfig = new LocalSearchForagerConfig();
localSearchForagerConfig.setAcceptedCountLimit(N * N);
acceptorConfig.setAcceptorTypeList(Arrays.asList(AcceptorType.HILL_CLIMBING));
params.add(new Object[]{acceptorConfig, localSearchForagerConfig, Arrays.asList(
new NQueensStepTracking(1, 5), new NQueensStepTracking(0, 1),
new NQueensStepTracking(4, 3), new NQueensStepTracking(2, 2),
new NQueensStepTracking(3, 5), new NQueensStepTracking(1, 4),
new NQueensStepTracking(1, 5), new NQueensStepTracking(1, 4),
new NQueensStepTracking(1, 5)
)});
acceptorConfig = new AcceptorConfig();
acceptorConfig.setAcceptorTypeList(Arrays.asList(AcceptorType.ENTITY_TABU));
acceptorConfig.setEntityTabuSize(N - 1);
localSearchForagerConfig = new LocalSearchForagerConfig();
localSearchForagerConfig.setAcceptedCountLimit(N * N);
params.add(new Object[]{acceptorConfig, localSearchForagerConfig, Arrays.asList(
new NQueensStepTracking(1, 5), new NQueensStepTracking(0, 1),
new NQueensStepTracking(4, 3), new NQueensStepTracking(2, 2),
new NQueensStepTracking(3, 5), new NQueensStepTracking(5, 4),
new NQueensStepTracking(1, 4), new NQueensStepTracking(0, 0),
new NQueensStepTracking(4, 1)
)});
acceptorConfig = new AcceptorConfig();
acceptorConfig.setAcceptorTypeList(Arrays.asList(AcceptorType.LATE_ACCEPTANCE));
acceptorConfig.setLateAcceptanceSize(1);
localSearchForagerConfig = new LocalSearchForagerConfig();
localSearchForagerConfig.setAcceptedCountLimit(1);
params.add(new Object[]{acceptorConfig, localSearchForagerConfig, Arrays.asList(
new NQueensStepTracking(0, 1), new NQueensStepTracking(0, 2), // (0, 0) is rejected due to high score
new NQueensStepTracking(0, 1), new NQueensStepTracking(0, 2),
new NQueensStepTracking(0, 1), new NQueensStepTracking(0, 2)
)});
return params;
}
}