Multiple breaks for vehicles. Feature #211



I’m working on feature #211, I changed the “informJobInserted” and “informInsertionStarts” methods of the BreakScheduling class to perform an insertion of more than one break:

public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
    List<Break> aBreakList = inRoute.getVehicle().getBreak(); // HERE
    if(aBreakList != null){
    	for(int i=aBreakList.size()-1; i >= 0; i--) {
		Break aBreak = aBreakList.get(i);		
    		boolean removed = inRoute.getTourActivities().removeJob(aBreak);
                    logger.trace("ruin: {}", aBreak.getId());
    		if(inRoute.getEnd().getArrTime() > aBreak.getTimeWindow().getEnd()){
                    InsertionData iData = breakInsertionCalculator.getInsertionData(inRoute, aBreak, inRoute.getVehicle(), inRoute.getDepartureTime(), inRoute.getDriver(), Double.MAX_VALUE);
                    if(!(iData instanceof InsertionData.NoInsertionFound)){
                        //logger.trace("insert: [jobId={}]{}", aBreak.getId(), iData);
                        for(Event e : iData.getEvents()){

However, in some cases the break is not being inserted because of the following rule of the VehicleDependentTimeWindowConstraints class:

double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocation(), newAct.getLocation(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double endTimeAtNewAct = Math.max(arrTimeAtNewAct, newAct.getTheoreticalEarliestOperationStartTime()) + activityCosts.getActivityDuration(newAct, arrTimeAtNewAct,iFacts.getNewDriver(),iFacts.getNewVehicle());
double latestArrTimeAtNewAct =
            latestArrTimeAtNextAct -
                routingCosts.getBackwardTransportTime(newAct.getLocation(), nextActLocation, latestArrTimeAtNextAct, iFacts.getNewDriver(), iFacts.getNewVehicle())
                - activityCosts.getActivityDuration(newAct, arrTimeAtNewAct, iFacts.getNewDriver(), iFacts.getNewVehicle())
*  |--- prevAct ---|
*                       		                 |--- vehicle's arrival @newAct
*        latest arrival of vehicle @newAct ---|
if (arrTimeAtNewAct > latestArrTimeAtNewAct) {
    return ConstraintsStatus.NOT_FULFILLED;

I would like to understand this rule.

Best regards,


Let’s say we have route

prevAct -> nextAct

and we are trying to insert newAct, so the route will look like this:

prevAct -> newAct -> nextAct

Now we need to make sure that we have enough time to perform the activity at newAct, and then travel to nextAct, before the latest arrival time at nextAct.

Therefore this condition must be satisfied:

latest arrival at newAct <= latest arrival at next act - travel time from newAct to nextAct - duration of newAct