OptaPlanner: Chained Through Timing, Automatic Delay Until Last Paradigm

Viewed 43

The OptaPlanner docs suggest using a custom variable listener to implement an automatic delay when, for example, more than one person must be at a job site at the same time:

https://www.optaplanner.org/docs/optaplanner/latest/design-patterns/design-patterns.html#chainedThroughTimeAutomaticDelayUntilLast

This requires that the planning entities must know about each other regardless of anchor, however, and in a chained timing scenario, the entities in a chain only know about previous, next, and the anchor. At least by default.

This means that the shadow variables that are being updated depend on the planning and shadow variables of entities in chains other than their own.

So, is there a standard to handling this? I could have the entities hold references to the other entities, but that doesn't explain how one can prevent variable listener or score corruption.

I'd imagine that this requires specifying sources on other chains, but I'm not sure how to go about that.

1 Answers

You can access the whole solution in your custom shadow variable listener through the score director:

public class MyDelayedStarTimeVariableListener implements VariableListener<MySolution, MyEntity> {

    // ...other before/after methods omitted...

    @Override
    public void afterVariableChanged(ScoreDirector<MySolution> scoreDirector, MyEntity entity) {
        MySolution solution = scoreDirector.getWorkingSolution();

        // Next, get any entity from the solution.
    }
}

and use it like this:

@PlanningEntity
public class MyEntity {
    @PlanningVariable(valueRangeProviderRefs = { "myAnchorRange", "myEntityRange" }, graphType = PlanningVariableGraphType.CHAINED)
    private MyEntityOrAnchor previous;

    @CustomShadowVariable(variableListenerClass = MyDelayedStarTimeVariableListener.class, sources = {
            @PlanningVariableReference(variableName = "previous") })
    private LocalTime startTime;

    // Rest of the class omitted for brevity.
}
  1. The listener's before/afterVariableChanged() method will be called each time an entity's previous planning variable changes.

  2. When that happens, the listener can not only update the startTime shadow variable of the entity object passed as the second argument, but also any other MyEntity instance in the solution, either by navigating through the chain the entity argument is part of or by getting the score director's working solution to access other chains.

See https://www.optaplanner.org/docs/optaplanner/latest/shadow-variable/shadow-variable.html for further information about shadow variables.

Related