I have a @PlanningEntity
called a Participation
, where the @PlanningVariable
enrolled
indicates whether Student
is attending the Appointment
in question:
@PlanningEntity
public class Participation {
private Student student;
private Appointment appointment;
@PlanningVariable
private Boolean enrolled = false;
}
In my specific use-case, the best solution is usually one where most (but not all) of the Participation
are attended. In fact, if I initialize my PlanningVariable
to null
instead of false
and start with a FIRST_FIT
construction phase, I get a performance improvement of around 3-4x to find the same solution (or the same score at least). I imagine because most enrolled
values are set to true
more efficiently than is possible during a LocalSearchPhase
.
The data-model backing my PlanningSolution
currently does not differentiate between a Participation
not being attended (enrolled = false
) and a choice not yet having been made (enrolled = null
). So even though this is a possible solution, ideally I would like to prevent changing the underlying data by initializing my PlanningEntity
s with a fake enrolled
value (setting it to null
preemptively).
I have tried experimenting with a custom Forager config, fox example by using .withPickEarlyType(LocalSearchPickEarlyType.FIRST_BEST_SCORE_IMPROVING)
and implementing a custom SelectionFilter
that only selects entities with enrolled==false
, but this does not seem to make a lot of difference.
So, the question: is it possible to do a FIRST_FIT
-like construction on a solution where the current solution is already initialized? I would basically like to tell Timefold to look at each entity exactly once, and greedily set enrolled=true
if this results in a better solution score.
EDIT: Another attempt was implementing a CustomPhaseCommand
as the first phase of my solver. This intuitively seems as a logical way to go, however I don't know how to check the impact of a change on the score of my solution. If I implement changeWorkingSolution
to set all enrolled
values to true
, the Phase is not executed since setting every value to true does not improve the solution score. Is there a way to check for an improvement from within a CustomPhaseCommand
?
EDIT2: See my 'answer' below