I try to use jsprit to solve a VRP with multiple TimeWindows
. Therefore I created a new Constraint-Class which contains a Map that relates a "TimeWindowsNotAvailable"-class to a Service.
The "TimeWindowsNotAvailable"-class contains a List of TimeWindows
where the Service can't be done (e.g. customer is not at home etc.).
The main problem is, that the newAct.getArrTime()
is always 0.0, although you can see in the solution of the VRP that the arrTime
is not 0.0.
Does anybody have an idea how I can fix this issue or are multiple TimeWindows
much harder to implement?
public class TimeConstraint implements HardActivityStateLevelConstraint {
private Map<Service, TimeWindowsNotAvailable> notAvailableMap;
private RouteAndActivityStateGetter states;
private VehicleRoutingTransportCosts routingCosts;
public TimeConstraint() {
super();
}
public boolean checkDepTime(Service service, Double depTime){
TimeWindowsNotAvailable timeWindowsNotAvailable = notAvailableMap.get(service);
if(timeWindowsNotAvailable == null) return true;
System.out.println(depTime);
return timeWindowsNotAvailable.isAvailable(depTime);
}
public void setNotAvailableMap(Map<Service, TimeWindowsNotAvailable> notAvailableMap){
this.notAvailableMap = notAvailableMap;
}
@Override
public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
Service currentService = (Service)iFacts.getJob();
if(checkDepTime(currentService, **newAct.getArrTime()**)) return ConstraintsStatus.FULFILLED;
return ConstraintsStatus.NOT_FULFILLED;
}
}
You cannot yet model multiple time windows out-of-the box but it is going to be implemented. For the time being, you can implement your own. Assume you have for example the following two time windows for a service: (e1,l1), (e2,l2) where e means earliest operation start and l latest. If l1 < e2, it is comparably "easy" to implement. Just look at how I implemented single hard time windows. Look at which is the TimeWindowConstraint and which is the practical time window state updater. You probably only need minor modifications of these classes, so just copy them and add multiple time windows, and add these two new classes to your State- and ConstraintManager (do not forget to deactivate the default time window constraints/stateUpdater).
The newAct does not have any arrTime since it is not yet inserted into the route and the best insertion position is still to be determined (by checking constraints and calculating marginal insertion costs). But you can easily calculate it as follows:
double newActArrTime = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevActDepTime,iFacts.getNewDriver(),iFacts.getNewVehicle);