Skip to content
Advertisement

Optaplanner chained variable corruption

Running into an issue with variable corruption on a chained variable model.

The entity (Delivery{id=’3′, tasks=[…], previousDeliveryOrShift=Delivery{id=’2′, tasks=[…], previousDeliveryOrShift=Shift{id=’1′, startTime=2022-10-03T16:00}, deliveryTime=2022-10-03T16:27}, deliveryTime=2022-10-03T17:12})’s shadow variable (Delivery.deliveryTime)’s corrupted value (2022-10-03T17:10) changed to uncorrupted value (2022-10-03T17:12) after all variable listeners were triggered without changes to the genuine variables.

I’ve tried using FULL_ASSERT with trace logging to see the move that is causing this but it’s erroring before the trace log shows me the move it is trying to make. I’ve tried running a debugger with breakpoints but it will solve correctly without any corruption when I do that. Not sure if this is some thread issue?

The code in the variableListener that is causing this is a while loop that’s needed to loop through the nextDelivery()s and sum together task times so I can add it to the deliveryTime of the FIRST delivery in the chain. Removing this loop fixes the corruption but now the deliveryTimes of all Deliveries in the chain will be off. I don’t understand why looping forwards and summing task times would cause corruption.

private void updateDeliveryTime(
      ScoreDirector<DeliveryRoutingSolution> scoreDirector, Delivery delivery) {
    Delivery shadowDelivery = delivery;

    while (shadowDelivery != null) {
      LocalDateTime deliveryTime = null;
      if (shadowDelivery.getPreviousDeliveryOrShift() != null) {
        PreviousDeliveryOrShift previousDeliveryOrShift =
            shadowDelivery.getPreviousDeliveryOrShift();

        if (previousDeliveryOrShift.getType() == PreviousDeliveryOrShift.Type.SHIFT) {
          Delivery nextDelivery = shadowDelivery;
          Duration taskTimeBeforeDelivery = Duration.ZERO;

          while (nextDelivery != null) { // the while loop causing the problem
            taskTimeBeforeDelivery =
                taskTimeBeforeDelivery.plus(
                    nextDelivery.getTaskTime());

            nextDelivery = nextDelivery.getNextDelivery();
          }

          deliveryTime =
              previousDeliveryOrShift
                  .getStartTime()
                  .plus(taskTimeBeforeDelivery);

        } else {
          ...
        }
      }

      scoreDirector.beforeVariableChanged(shadowDelivery, "deliveryTime");
      shadowDelivery.setDeliveryTime(deliveryTime);
      scoreDirector.afterVariableChanged(shadowDelivery, "deliveryTime");

      shadowDelivery = shadowDelivery.getNextDelivery();
    }
  }
}

I’ve tried looking at other stackoverflow threads on this issue but still can’t seem to get this working. Any suggestions are welcome. Thanks.

Advertisement

Answer

Solved this. I’ve learned that you do not want a shadow variable’s value to change depending on what is ahead of it in the chain. This is what was causing the corruption. I removed the while loop causing the problem and moved the calculations to a constraint instead.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement