I'm trying to add a hand-made solution to OptaPlanner in Java code. I'm following the first way from this.
According the comments, I should somehow use ScoreDirector.triggerVariableListeners()
to initialize shadow variables.
I've found in OptaPlanner examples code like this:
private <Result_> Result_ applyScoreDirector(Function<InnerScoreDirector<Solution_, Score_>, Result_> function) {
try (InnerScoreDirector<Solution_, Score_> scoreDirector =
(InnerScoreDirector<Solution_, Score_>) solverFactory.getScoreDirectorFactory().buildScoreDirector(true,
true)) {
scoreDirector.setWorkingSolution(getSolution());
Result_ result = function.apply(scoreDirector);
scoreDirector.triggerVariableListeners();
scoreDirector.calculateScore();
setSolution(scoreDirector.getWorkingSolution());
return result;
}
}
I've tried to adapt it to my case (Table - my planning solution):
SolverConfig solverConfig = SolverConfig.createFromXmlFile(new File(url.getFile()));
solverManager = SolverManager.create(solverConfig, new SolverManagerConfig());
Table result = createInitialSolution(data);
DefaultSolverManager defaultSolverManager = (DefaultSolverManager) solverManager;
DefaultSolverFactory<Table> solverFactory = (DefaultSolverFactory<Table>) defaultSolverManager.getSolverFactory();
InnerScoreDirector<Table, HardSoftScore> scoreDirector = (InnerScoreDirector<Table, HardSoftScore>)
solverFactory.getScoreDirectorFactory().buildScoreDirector(true, true);
scoreDirector.setWorkingSolution(result);
scoreDirector.triggerVariableListeners();
scoreDirector.calculateScore();
result = scoreDirector.getWorkingSolution();
return result;
This doesn't work. All shadow variables are null. What am I doing wrong?
SolutionManager
provides an update(...)
method which serves just this purpose.
In OptaPlanner, there is a bug in that call which makes it not work with chained and list variables. Timefold Solver fixes that bug, among others.