Show Table of Contents
6.11. Custom Solver Phase
Between phases or before the first phase, you might want to execute a custom action on the
Solution to get a better score. Yet you'll still want to reuse the score calculation. For example, to implement a custom construction heuristic without implementing an entire Phase.
Note
Most of the time, a custom solver phase is not worth the hassle. The supported Constructions Heuristics are configurable (use the Benchmarker to tweak them),
Termination aware and support partially initialized solutions too.
Implement the
CustomPhaseCommand interface:
public interface CustomPhaseCommand {
void changeWorkingSolution(ScoreDirector scoreDirector);
}
For example:
public class ToOriginalMachineSolutionInitializer implements CustomPhaseCommand {
public void changeWorkingSolution(ScoreDirector scoreDirector) {
MachineReassignment machineReassignment = (MachineReassignment) scoreDirector.getWorkingSolution();
for (MrProcessAssignment processAssignment : machineReassignment.getProcessAssignmentList()) {
scoreDirector.beforeVariableChanged(processAssignment, "machine");
processAssignment.setMachine(processAssignment.getOriginalMachine());
scoreDirector.afterVariableChanged(processAssignment, "machine");
scoreDirector.triggerVariableListeners();
}
}
}Warning
Any change on the planning entities in a
CustomPhaseCommand must be notified to the ScoreDirector.
Warning
Do not change any of the problem facts in a
CustomPhaseCommand. That will corrupt the Solver because any previous score or solution was for a different problem. To do that, read about repeated planning and do it with a ProblemFactChange instead.
Configure your
CustomPhaseCommand like this:
<solver>
...
<customPhase>
<customPhaseCommandClass>org.optaplanner.examples.machinereassignment.solver.solution.initializer.ToOriginalMachineSolutionInitializer</customPhaseCommandClass>
</customPhase>
... <!-- Other phases -->
</solver>
Configure multiple
customPhaseCommandClass instances to run them in sequence.
Important
If the changes of a
CustomPhaseCommand don't result in a better score, the best solution won't be changed (so effectively nothing will have changed for the next Phase or CustomPhaseCommand). To force such changes anyway, use forceUpdateBestSolution:
<customPhase>
<customPhaseCommandClass>...MyUninitializer</customPhaseCommandClass>
<forceUpdateBestSolution>true</forceUpdateBestSolution>
</customPhase>Note
If the
Solver or a Phase wants to terminate while a CustomPhaseCommand is still running, it will wait to terminate until the CustomPhaseCommand is done, however long that takes. The build-in solver phases don't suffer from this problem.

Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.