Search code examples
javaoptaplanner

OptaPlanner plans entities even though there are no moves available


I am trying to use a MoveSelectionFilter to exclude some planning entitiy instances from being planned.

However, even if I reject all moves, the instances still get initially planned in the construction heuristic phase, according to the debug output. I am using the WEAKEST_FIT heuristic, two custom MoveListFactories (which, at the moment, do not generate any moves at all) and no default MoveListFactory.

How do I keep OptaPlanner from planning these entities? I have looked at the nurse rostering example which does exactly what I want to do if you advance the date but was not able to reproduce the behavior.

Edit: The Filter is definitely being applied. I have checked the sizes of the MoveLists and they are both empty.

My filter looks like this:

public boolean accept(PatientAdmissionSchedule patientAdmissionSchedule, BedDesignation bedDesignation) {
    return false;
}

And is applied like so:

if (filter.accept(patientAdmissionSchedule, bedDesignation)) {
            for (Bed bed : bedList) {
                moveList.add(new BedChangeMove(bedDesignation, bed));
            }
        }

and

for (ListIterator<BedDesignation> it = bedDesignationList.listIterator(); it.hasNext();) {
        BedDesignation bedDesignation = it.next();
        if (!filter.accept(patientAdmissionSchedule, bedDesignation)) {
            it.remove();
        }
    }

In the debug, I have the following lines

2017-03-14 19:40:59,305 [SwingWorker-pool-4-thread-1] DEBUG     CH step (31), time spent (173), score (0hard/0medium/0soft), selected move count (7), picked move (Patient6(Night(7),null) {null -> 15(0)}).
2017-03-14 19:40:59,306 [SwingWorker-pool-4-thread-1] INFO  Construction Heuristic phase (0) ended: step total (32), time spent (174), best score (0hard/0medium/0soft).
2017-03-14 19:40:59,313 [SwingWorker-pool-4-thread-1] WARN      No doable selected move at step index (0), time spent (181). Terminating phase early.

which I think further demonstrates that there are no moves to select.

The planning entity is essentially identical to the one from the patient admission scheduling example:

@PlanningEntity(difficultyWeightFactoryClass = BedDesignationDifficultyWeightFactory.class)
@XStreamAlias("BedDesignation")
public class BedDesignation extends AbstractPersistable {

private Admission admission;
private Bed bed;
private Night night;

@PlanningVariable(nullable = true, valueRangeProviderRefs = {"bedRange"},
        strengthComparatorClass = BedStrengthComparator.class)
public Bed getBed() {
    return bed;
}

I also tried using only a single MoveListFactory which returns an empty MoveList. But there are still somehow moves like this

2017-03-14 19:40:59,305 [SwingWorker-pool-4-thread-1] DEBUG     CH step (31), time spent (173), score (0hard/0medium/0soft), selected move count (7), picked move (Patient6(Night(7),null) {null -> 15(0)})

which get picked during the construction heuristic phase.


Solution

  • You're missing the movableEntitySelectionFilter attribute in @PlanningEntity

    @PlanningEntity(movableEntitySelectionFilter = MovableLectureSelectionFilter.class, ...)
    public class Lecture ...