I have a VRP problem I'm solving using timefold. It's working well but I want to be able to load in existing schedules for analysis and allow changes to the routes through a GUI. To do that I've written a ProblemChange, but it seems like the code must already exist in Timefold, or I'm doing it wrong. So, is there already a method like this? If not, will this allow for changing the previousStandStill of a Customer?
`public class PreviousStandstillChange implements ProblemChange {
private final TimeWindowedCustomer timeWindowedCustomer;
private final Standstill previousStandstill;
public PreviousStandstillChange(TimeWindowedCustomer timeWindowedCustomer, Standstill previousStandstill) {
this.timeWindowedCustomer = timeWindowedCustomer;
this.previousStandstill = previousStandstill;
}
@Override
public void doChange(VehicleRoutingSolution vehicleRoutingSolution,
ProblemChangeDirector problemChangeDirector) {
TimeWindowedCustomer workingTimeWindowedCustomer = problemChangeDirector
.lookUpWorkingObjectOrFail(timeWindowedCustomer);
Standstill currentPreviousStandstill = workingTimeWindowedCustomer.getPreviousStandstill();
TimeWindowedCustomer currentNexTimeWindowedCustomer = workingTimeWindowedCustomer.getNextCustomer();
// First find the TimeWindowedCustomer that points to the standstill
for (TimeWindowedCustomer timeWindowedCustomer : vehicleRoutingSolution.getCustomerList()) {
if (timeWindowedCustomer.getPreviousStandstill() == previousStandstill) {
timeWindowedCustomer.setPreviousStandstill(workingTimeWindowedCustomer);
workingTimeWindowedCustomer.setNextCustomer(timeWindowedCustomer);
workingTimeWindowedCustomer.setPreviousStandstill(previousStandstill);
previousStandstill.setNextCustomer(workingTimeWindowedCustomer);
break;
}
}
// Then connect the previous and next of the customer being moved
if (currentPreviousStandstill != null) {
if (currentNexTimeWindowedCustomer != null) {
currentNexTimeWindowedCustomer.setPreviousStandstill(currentPreviousStandstill);
currentPreviousStandstill.setNextCustomer(currentNexTimeWindowedCustomer);
} else {
currentPreviousStandstill.setNextCustomer(null);
}
}
}
}`
I'm trying to implement a ProblemChange properly.
When you change variables or properties, you need to call either changeVariable
or changeProblemProperty
respectively. I would change your code to:
public void doChange(VehicleRoutingSolution vehicleRoutingSolution,
ProblemChangeDirector problemChangeDirector) {
TimeWindowedCustomer workingTimeWindowedCustomer = problemChangeDirector
.lookUpWorkingObjectOrFail(timeWindowedCustomer);
Standstill currentPreviousStandstill = workingTimeWindowedCustomer.getPreviousStandstill();
TimeWindowedCustomer currentNexTimeWindowedCustomer = workingTimeWindowedCustomer.getNextCustomer();
// First find the TimeWindowedCustomer that points to the standstill
for (TimeWindowedCustomer timeWindowedCustomer : vehicleRoutingSolution.getCustomerList()) {
if (timeWindowedCustomer.getPreviousStandstill() == previousStandstill) {
problemChangeDirector.changeVariable(timeWindowedCustomer, "previousStandstill", entity -> entity.setPreviousStandstill(workingTimeWindowedCustomer));
problemChangeDirector.changeVariable(workingTimeWindowedCustomer, "nextCustomer", entity -> entity.setNextCustomer(timeWindowedCustomer));
problemChangeDirector.changeVariable(workingTimeWindowedCustomer, "previousStandstill", entity -> entity.setPreviousStandstill(previousStandstill));
problemChangeDirector.changeVariable(previousStandstill, "nextCustomer", entity -> entity.setNextCustomer(workingTimeWindowedCustomer));
break;
}
}
// Then connect the previous and next of the customer being moved
if (currentPreviousStandstill != null) {
if (currentNexTimeWindowedCustomer != null) {
problemChangeDirector.changeVariable(currentNexTimeWindowedCustomer, "previousStandstill", entity -> entity.setPreviousStandstill(currentPreviousStandstill));
problemChangeDirector.changeVariable(currentPreviousStandstill, "nextCustomer", entity -> entity.setNextCustomer(currentNexTimeWindowedCustomer));
} else {
problemChangeDirector.changeVariable(currentPreviousStandstill, "nextCustomer", entity -> entity.setNextCustomer(null));
}
}
}