// ************************************************************************
// Worker methods
// ************************************************************************
public void solve(DefaultSolverScope solverScope) {
LocalSearchSolverPhaseScope phaseScope = new LocalSearchSolverPhaseScope(solverScope);
phaseStarted(phaseScope);
LocalSearchStepScope stepScope = createNextStepScope(phaseScope, null);
while (!termination.isPhaseTerminated(phaseScope)) {
stepScope.setTimeGradient(termination.calculatePhaseTimeGradient(phaseScope));
stepStarted(stepScope);
decider.decideNextStep(stepScope);
Move nextStep = stepScope.getStep();
if (nextStep == null) {
if (termination.isPhaseTerminated(phaseScope)) {
logger.trace(" Step index ({}), time spend ({}) terminated without picking a nextStep.",
stepScope.getStepIndex(),
stepScope.getPhaseScope().calculateSolverTimeMillisSpend());
} else if (stepScope.getSelectedMoveCount() == 0L) {
logger.warn(" No doable selected move at step index ({}), time spend ({})."
+ " Terminating phase early.",
stepScope.getStepIndex(),
stepScope.getPhaseScope().calculateSolverTimeMillisSpend());
} else {
throw new IllegalStateException("The step index (" + stepScope.getStepIndex()
+ ") has accepted/selected move count (" + stepScope.getAcceptedMoveCount() + "/"
+ stepScope.getSelectedMoveCount() + ") but failed to pick a nextStep (" + nextStep + ").");
}
// Although stepStarted has been called, stepEnded is not called for this step
break;
}
nextStep.doMove(stepScope.getScoreDirector());
// there is no need to recalculate the score, but we still need to set it
phaseScope.getWorkingSolution().setScore(stepScope.getScore());
if (assertStepScoreIsUncorrupted) {
phaseScope.assertWorkingScore(stepScope.getScore());
}
stepEnded(stepScope);
stepScope = createNextStepScope(phaseScope, stepScope);
}
phaseEnded(phaseScope);