Here is the state of my implementation :
public class ReloadConstraint implements SoftActivityConstraint {
ArrayList<double[]> local_vehicle_windows;
public ReloadConstraint(ArrayList<double[]> local_vehicle_windows) {
super();
this.local_vehicle_windows = local_vehicle_windows;
}
@Override
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double depTimeAtPrevAct) {
double cost = 0;
// Add a new activity as first reloading activity
// new activity == depot and previous != depot
// d 'p'
double newActArrTime = depTimeAtPrevAct + costMatrix.getTransportTime(prevAct.getLocation(), newAct.getLocation(), 0.0, iFacts.getNewDriver(), iFacts.getNewVehicle());
if (newAct.getLocation() == iFacts.getNewVehicle().getStartLocation() && prevAct.getLocation() != iFacts.getNewVehicle().getStartLocation() && prevAct.getIndex() >= 0){
newActArrTime += local_vehicle_windows.get(Integer.parseInt(iFacts.getNewVehicle().getId()))[2];
}
newActArrTime = Math.max(newActArrTime, newAct.getTheoreticalEarliestOperationStartTime());
newAct.setArrTime(newActArrTime);
double newActEndTime = newActArrTime + newAct.getOperationTime();
VehicleRoute route = iFacts.getRoute();
List<TourActivity> tourActivities = route.getActivities();
if (!(nextAct instanceof End)) {
boolean actAfterNew = false;
for (TourActivity tourActivity : tourActivities) {
if (!actAfterNew && !tourActivity.equals(nextAct)){
continue;
}
actAfterNew = true;
prevAct = newAct;
newAct = tourActivity;
depTimeAtPrevAct = newActEndTime;
newActArrTime = depTimeAtPrevAct + costMatrix.getTransportTime(prevAct.getLocation(), newAct.getLocation(), 0.0, iFacts.getNewDriver(), iFacts.getNewVehicle());
if (newAct.getLocation() == iFacts.getNewVehicle().getStartLocation() && prevAct.getLocation() != iFacts.getNewVehicle().getStartLocation() && prevAct.getIndex() >= 0){
newActArrTime += local_vehicle_windows.get(Integer.parseInt(iFacts.getNewVehicle().getId()))[2];
}
newActArrTime = Math.max(newActArrTime, newAct.getTheoreticalEarliestOperationStartTime());
newAct.setArrTime(newActArrTime);
newActEndTime = newActArrTime + newAct.getOperationTime();
}
}
return cost;
}
}
I consider now only the case where I pickup after a delivery activity. That allow me to don’t shift at the first departure and to propagate easily.
By propagate, I consider to recompute the shift at each insertion, which make the computation heavier, but I have not find another way.
It works quite well, Except for one Activity after reloading which don’t take into account the shift.
I think i’m missing a case, but can’t find out which one it is.
Edit : I’m switching to use a HardActivityConstraint, seems to give well constrained results.