Friday, June 21, 2013

Shadow variables, PlanningVariableListener and bi-directional variables

Most types of custom constraints are relatively straightforward to implement in OptaPlanner. There was one notorious exception: time windows for vehicle routing. But OptaPlanner 6.0.0.Beta4 supports shadow variables, which make that a lot easier to implement.

A shadow variable is a variables who's correct value can be deduced from the state of the genuine planning variables. Even though such a variable violates the principle of normalization by definition, in some use cases it can be very practical to use a shadow variable. For example in vehicle routing with time windows: the arrival time at a customer for a vehicle can be calculated based on the previously visited customers of that vehicle (and the known travel times between 2 locations).

PlanningVariableListener



To update the shadow variable(s) correctly, we can annotate a PlanningVariableListener on the genuine planning variable:

    @PlanningVariable(..., variableListenerClasses = {VehicleUpdatingVariableListener.class, ArrivalTimeUpdatingVariableListener.class})
    ...
    public Standstill getPreviousStandstill() {
        return previousStandstill;
    }



Bi-directional variables


OptaPlanner reuses that system internally to provide support for bi-directional variables (like JPA), currently only for chained variables:

    @PlanningVariable(mappedBy = "previousStandstill")
    Customer getNextCustomer();


So if OptaPlanner changes the previousStandstill side, it automatically also changes the nextCustomer side accordingly.

2 comments:

  1. Can't wait to see the examples Geoffrey!

    ReplyDelete
  2. It's already in master, in the vrp example, it works, but I am still improving the gui etc :)

    ReplyDelete