Search code examples
optaplanner

Custom VariableListener updating more than one shadow variables


I am reading in the documentation about shadow variables and custom variable listeners and i was wondering if i am on the right track in understanding how they work.

Copied from the OptaPlanner Documentation in section 4.3.6.4. "Custom VariableListener"

If one VariableListener changes two shadow variables (because having two separate VariableListeners would be inefficient), then annotate only the first shadow variable with the variableListenerClass and let the other shadow variable(s) reference the first shadow variable:

@PlanningVariable(...)
public Standstill getPreviousStandstill() {
    return previousStandstill;
}

@CustomShadowVariable(variableListenerClass = TransportTimeAndCapacityUpdatingVariableListener.class,
        sources = {@CustomShadowVariable.Source(variableName = "previousStandstill")})
public Integer getTransportTime() {
    return transportTime;
}

@CustomShadowVariable(variableListenerRef = @PlanningVariableReference(variableName = "transportTime"))
public Integer getCapacity() {
    return capacity;
}

So as i understand from this when the genuine planning variable gets changed and we have more shadow variables that need to be updated in another planning entity accordingly, we can do this in the same variable listener for the genuine planning entity.

If this is so then would something like this be valid?

Here are the annotated methods for the shadow variables in the shadow planning entity.

//shadow variables
protected Integer variable;
protected Integer shadowVariable2;

@CustomShadowVariable(variableListenerClass = CustomVariableListener.class,
    sources = {@CustomShadowVariable.Source(variableName = "variable")})
public Integer getVariable() {
return variable;
}

@CustomShadowVariable(variableListenerRef =     @PlanningVariableReference(variableName = "variable"))
public Integer getShadowVariable2() {
return shadowVariable2;
}

and the code of the VariableListener of the genuine planning entity

public class CustomVariableListener implements VariableListener<GenuinePlanningEntity> {

@Override
public void afterEntityAdded(ScoreDirector scoreDirector, GenuinePlanningEntity genuinePlanningEntity) {

}

@Override
public void afterEntityRemoved(ScoreDirector scoreDirector, GenuinePlanningEntity genuinePlanningEntity) {

}

@Override
public void afterVariableChanged(ScoreDirector scoreDirector, GenuinePlanningEntity genuinePlanningEntity) {
    List<ShadowPlanningEntity> shadowPlanningEntities = genuinePlanningEntity.getShadowPlanningEntities();
    Integer variable = genuinePlanningEntity.getVariable();
    for(ShadowPlanningEntity shadowPlanningEntity : shadowPlanningEntities){
        scoreDirector.beforeVariableChanged(shadowPlanningEntity,"variable");
        shadowPlanningEntity.setVariable(variable);
        scoreDirector.afterVariableChanged(shadowPlanningEntity,"variable");

        scoreDirector.beforeVariableChanged(shadowPlanningEntity,"shadowVariable2");
        shadowPlanningEntity.setshadowVariable2(shadowPlanningEntity.getshadowVariable2() + 1);
        scoreDirector.afterVariableChanged(shadowPlanningEntity,"shadowVariable2");

    }

}

@Override
public void beforeEntityAdded(ScoreDirector scoreDirector, GenuinePlanningEntity genuinePlanningEntity) {

}

@Override
public void beforeEntityRemoved(ScoreDirector scoreDirector, GenuinePlanningEntity genuinePlanningEntity) {

}

@Override
public void beforeVariableChanged(ScoreDirector scoreDirector, GenuinePlanningEntity genuinePlanningEntity) {

}



}

If that is not ok then how to properly update all the shadow variables from the shadow planning entity? Should the beforeVariableChanged and afterVariableChanged methods of the shadow variables be called like that?


Solution

  • Yes, that seems ok on first sight. Look at for example ArrivalTimeUpdatingVariableListener for a good example on how changing 1 Customer in a VRP chain can affect the arrival time of all other customers in the chain after that customer.