diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/state/UpdateMaxTimeInVehicle.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/state/UpdateMaxTimeInVehicle.java index cd80bc26..dc8fbcad 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/state/UpdateMaxTimeInVehicle.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/state/UpdateMaxTimeInVehicle.java @@ -33,17 +33,19 @@ import java.util.*; */ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{ - private Map> openPickupEndTimes = new HashMap<>(); + private Map> openPickupEndTimesPerVehicle = new HashMap<>(); - private Map> slackTimes = new HashMap<>(); + private Map> slackTimesPerVehicle = new HashMap<>(); - private Map> actStartTimes = new HashMap<>(); + private Map> actStartTimesPerVehicle = new HashMap<>(); private VehicleRoute route; private final StateManager stateManager; - private final StateId latestStartId; + private final StateId minSlackId; + + private final StateId openJobsId; private double[] prevActEndTimes; @@ -65,9 +67,10 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{ }; - public UpdateMaxTimeInVehicle(StateManager stateManager, StateId slackTimeId, TransportTime transportTime, VehicleRoutingActivityCosts activityCosts) { + public UpdateMaxTimeInVehicle(StateManager stateManager, StateId slackTimeId, TransportTime transportTime, VehicleRoutingActivityCosts activityCosts, StateId openJobsId) { this.stateManager = stateManager; - this.latestStartId = slackTimeId; + this.minSlackId = slackTimeId; + this.openJobsId = openJobsId; this.transportTime = transportTime; prevActEndTimes = new double[stateManager.getMaxIndexOfVehicleTypeIdentifiers() + 1]; prevActLocations = new Location[stateManager.getMaxIndexOfVehicleTypeIdentifiers() + 1]; @@ -82,16 +85,16 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{ @Override public void begin(VehicleRoute route) { - openPickupEndTimes.clear(); - slackTimes.clear(); - actStartTimes.clear(); + openPickupEndTimesPerVehicle.clear(); + slackTimesPerVehicle.clear(); + actStartTimesPerVehicle.clear(); vehicles = vehiclesToUpdate.get(route); this.route = route; for(Vehicle v : vehicles){ int vehicleIndex = v.getVehicleTypeIdentifier().getIndex(); - openPickupEndTimes.put(vehicleIndex,new HashMap()); - slackTimes.put(vehicleIndex,new HashMap()); - actStartTimes.put(vehicleIndex,new HashMap()); + openPickupEndTimesPerVehicle.put(vehicleIndex, new HashMap()); + slackTimesPerVehicle.put(vehicleIndex, new HashMap()); + actStartTimesPerVehicle.put(vehicleIndex, new HashMap()); prevActEndTimes[vehicleIndex] = v.getEarliestDeparture(); prevActLocations[vehicleIndex] = v.getStartLocation(); } @@ -109,7 +112,7 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{ double activityStart = Math.max(activityArrival,activity.getTheoreticalEarliestOperationStartTime()); memorizeActStart(activity,v,activityStart); double activityEnd = activityStart + activityCosts.getActivityDuration(activity, activityArrival, route.getDriver(), v); - Map openPickups = openPickupEndTimes.get(vehicleIndex); + Map openPickups = openPickupEndTimesPerVehicle.get(vehicleIndex); if (activity instanceof ServiceActivity || activity instanceof PickupActivity) { openPickups.put(((TourActivity.JobActivity) activity).getJob(), activityEnd); } else if (activity instanceof DeliveryActivity) { @@ -120,7 +123,7 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{ openPickups.remove(job); } else pickupEnd = v.getEarliestDeparture(); double slackTime = maxTime - (activityStart - pickupEnd); - slackTimes.get(vehicleIndex).put(activity, slackTime); + slackTimesPerVehicle.get(vehicleIndex).put(activity, slackTime); } prevActLocations[vehicleIndex] = activity.getLocation(); prevActEndTimes[vehicleIndex] = activityEnd; @@ -136,16 +139,8 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{ return maxTime; } -// private double getMaxTimeInVehicle(String jobId) { -// double maxTime = Double.MAX_VALUE; -// if(maxTimes.containsKey(jobId)){ -// maxTime = maxTimes.get(jobId); -// } -// return maxTime; -// } - private void memorizeActStart(TourActivity activity, Vehicle v, double activityStart) { - actStartTimes.get(v.getVehicleTypeIdentifier().getIndex()).put(activity,activityStart); + actStartTimesPerVehicle.get(v.getVehicleTypeIdentifier().getIndex()).put(activity, activityStart); } @Override @@ -158,33 +153,35 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{ if(!v.isReturnToDepot()) routeEnd = prevActEndTimes[vehicleIndex]; else routeEnd = prevActEndTimes[vehicleIndex] + transportTime.getTransportTime(prevActLocations[vehicleIndex],v.getEndLocation(),prevActEndTimes[vehicleIndex],route.getDriver(),v); - Map openDeliveries = new HashMap<>(); - for (Job job : openPickupEndTimes.get(vehicleIndex).keySet()) { - double actEndTime = openPickupEndTimes.get(vehicleIndex).get(job); + Map openDeliveries = new HashMap<>(); + for (Job job : openPickupEndTimesPerVehicle.get(vehicleIndex).keySet()) { + double actEndTime = openPickupEndTimesPerVehicle.get(vehicleIndex).get(job); double slackTime = job.getMaxTimeInVehicle() - (routeEnd - actEndTime); - openDeliveries.put(job.getId(), slackTime); + openDeliveries.put(job, slackTime); } double minSlackTimeAtEnd = minSlackTime(openDeliveries); - stateManager.putRouteState(route, v, latestStartId, routeEnd + minSlackTimeAtEnd); + stateManager.putRouteState(route, v, minSlackId, minSlackTimeAtEnd); + stateManager.putRouteState(route, v, openJobsId, new HashMap<>(openDeliveries)); List acts = new ArrayList<>(this.route.getActivities()); Collections.reverse(acts); for (TourActivity act : acts) { + Job job = ((TourActivity.JobActivity) act).getJob(); if (act instanceof ServiceActivity || act instanceof PickupActivity) { - String jobId = ((TourActivity.JobActivity) act).getJob().getId(); - openDeliveries.remove(jobId); + openDeliveries.remove(job); double minSlackTime = minSlackTime(openDeliveries); - double latestStart = actStart(act, v) + minSlackTime; - stateManager.putActivityState(act, v, latestStartId, latestStart); +// double latestStart = actStart(act, v) + minSlackTime; + stateManager.putActivityState(act, v, openJobsId, new HashMap<>(openDeliveries)); + stateManager.putActivityState(act, v, minSlackId, minSlackTime); } else { - String jobId = ((TourActivity.JobActivity) act).getJob().getId(); - if(slackTimes.get(vehicleIndex).containsKey(act)){ - double slackTime = slackTimes.get(vehicleIndex).get(act); - openDeliveries.put(jobId,slackTime); + if (slackTimesPerVehicle.get(vehicleIndex).containsKey(act)) { + double slackTime = slackTimesPerVehicle.get(vehicleIndex).get(act); + openDeliveries.put(job, slackTime); } double minSlackTime = minSlackTime(openDeliveries); - double latestStart = actStart(act, v) + minSlackTime; - stateManager.putActivityState(act, v, latestStartId, latestStart); +// double latestStart = actStart(act, v) + minSlackTime; + stateManager.putActivityState(act, v, openJobsId, new HashMap<>(openDeliveries)); + stateManager.putActivityState(act, v, minSlackId, minSlackTime); } } } @@ -200,44 +197,44 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{ else routeEnd = prevActEndTimes[vehicleIndex] + transportTime.getTransportTime(prevActLocations[vehicleIndex], v.getEndLocation(), prevActEndTimes[vehicleIndex], route.getDriver(), v); - Map openDeliveries = new HashMap<>(); - for (Job job : openPickupEndTimes.get(vehicleIndex).keySet()) { + Map openDeliveries = new HashMap<>(); + for (Job job : openPickupEndTimesPerVehicle.get(vehicleIndex).keySet()) { if (job == ignore) continue; - double actEndTime = openPickupEndTimes.get(vehicleIndex).get(job); + double actEndTime = openPickupEndTimesPerVehicle.get(vehicleIndex).get(job); double slackTime = job.getMaxTimeInVehicle() - (routeEnd - actEndTime); - openDeliveries.put(job.getId(), slackTime); + openDeliveries.put(job, slackTime); } double minSlackTimeAtEnd = minSlackTime(openDeliveries); - stateManager.putRouteState(route, v, latestStartId, routeEnd + minSlackTimeAtEnd); + stateManager.putRouteState(route, v, minSlackId, routeEnd + minSlackTimeAtEnd); List acts = new ArrayList<>(activities); Collections.reverse(acts); for (TourActivity act : acts) { + Job job = ((TourActivity.JobActivity) act).getJob(); if (act instanceof ServiceActivity || act instanceof PickupActivity) { - String jobId = ((TourActivity.JobActivity) act).getJob().getId(); + String jobId = job.getId(); openDeliveries.remove(jobId); double minSlackTime = minSlackTime(openDeliveries); double latestStart = actStart(act, v) + minSlackTime; - stateManager.putActivityState(act, v, latestStartId, latestStart); + stateManager.putActivityState(act, v, minSlackId, latestStart); } else { - String jobId = ((TourActivity.JobActivity) act).getJob().getId(); - if (slackTimes.get(vehicleIndex).containsKey(act)) { - double slackTime = slackTimes.get(vehicleIndex).get(act); - openDeliveries.put(jobId, slackTime); + if (slackTimesPerVehicle.get(vehicleIndex).containsKey(act)) { + double slackTime = slackTimesPerVehicle.get(vehicleIndex).get(act); + openDeliveries.put(job, slackTime); } double minSlackTime = minSlackTime(openDeliveries); double latestStart = actStart(act, v) + minSlackTime; - stateManager.putActivityState(act, v, latestStartId, latestStart); + stateManager.putActivityState(act, v, minSlackId, latestStart); } } } } private double actStart(TourActivity act, Vehicle v) { - return actStartTimes.get(v.getVehicleTypeIdentifier().getIndex()).get(act); + return actStartTimesPerVehicle.get(v.getVehicleTypeIdentifier().getIndex()).get(act); } - private double minSlackTime(Map openDeliveries) { + private double minSlackTime(Map openDeliveries) { double min = Double.MAX_VALUE; for(Double value : openDeliveries.values()){ if(value < min) min = value; diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/constraint/MaxTimeInVehicleConstraint.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/constraint/MaxTimeInVehicleConstraint.java index fa23b277..31a57e16 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/constraint/MaxTimeInVehicleConstraint.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/constraint/MaxTimeInVehicleConstraint.java @@ -20,23 +20,19 @@ package com.graphhopper.jsprit.core.problem.constraint; import com.graphhopper.jsprit.core.algorithm.state.StateId; import com.graphhopper.jsprit.core.algorithm.state.StateManager; -import com.graphhopper.jsprit.core.algorithm.state.UpdateMaxTimeInVehicle; -import com.graphhopper.jsprit.core.algorithm.state.UpdateVehicleDependentPracticalTimeWindows; import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; import com.graphhopper.jsprit.core.problem.cost.TransportTime; import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts; +import com.graphhopper.jsprit.core.problem.job.Job; +import com.graphhopper.jsprit.core.problem.job.Shipment; import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext; -import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute; import com.graphhopper.jsprit.core.problem.solution.route.activity.DeliveryActivity; import com.graphhopper.jsprit.core.problem.solution.route.activity.End; import com.graphhopper.jsprit.core.problem.solution.route.activity.PickupActivity; import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity; -import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import java.util.Collections; +import java.util.Map; /** * Created by schroeder on 15/09/16. @@ -49,16 +45,19 @@ public class MaxTimeInVehicleConstraint implements HardActivityConstraint { private final VehicleRoutingActivityCosts activityCosts; - private final StateId latestStartId; + private final StateId minSlackId; + + private final StateId openJobsId; private final StateManager stateManager; - public MaxTimeInVehicleConstraint(TransportTime transportTime, VehicleRoutingActivityCosts activityCosts, StateId latestStartId, StateManager stateManager, VehicleRoutingProblem vrp) { + public MaxTimeInVehicleConstraint(TransportTime transportTime, VehicleRoutingActivityCosts activityCosts, StateId minSlackId, StateManager stateManager, VehicleRoutingProblem vrp, StateId openJobsId) { this.transportTime = transportTime; - this.latestStartId = latestStartId; + this.minSlackId = minSlackId; this.stateManager = stateManager; this.activityCosts = activityCosts; this.vrp = vrp; + this.openJobsId = openJobsId; } @Override @@ -102,53 +101,101 @@ public class MaxTimeInVehicleConstraint implements HardActivityConstraint { //************ 2. check whether insertion of new shipment satisfies all other max-in-vehicle-constraints - if(newActIsPickup || iFacts.getAssociatedActivities().size() == 1) { - double latest; - if (iFacts.getRoute().isEmpty()) latest = Double.MAX_VALUE; - else if (nextAct instanceof End) { - latest = stateManager.getRouteState(iFacts.getRoute(), iFacts.getNewVehicle(), latestStartId, Double.class); - } else latest = stateManager.getActivityState(nextAct, iFacts.getNewVehicle(), latestStartId, Double.class); - - if (nextActStart > latest) { - return ConstraintsStatus.NOT_FULFILLED; - } - - } else { - boolean isShipment = iFacts.getAssociatedActivities().size() == 2; - if (newActIsDelivery && isShipment) { - StateManager localStateManager = new StateManager(vrp); - StateId stateId = localStateManager.createStateId("local-slack"); - UpdateMaxTimeInVehicle updateMaxTimeInVehicle = new UpdateMaxTimeInVehicle(localStateManager, stateId, transportTime, activityCosts); - updateMaxTimeInVehicle.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() { - @Override - public Collection get(VehicleRoute route) { - return Arrays.asList(iFacts.getNewVehicle()); + double minSlack = Double.MAX_VALUE; + if (!(nextAct instanceof End)) { + minSlack = stateManager.getActivityState(nextAct, iFacts.getNewVehicle(), minSlackId, Double.class); + } + double directArrTimeNextAct = prevActDepTime + transportTime.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); + double directNextActStart = Math.max(directArrTimeNextAct, nextAct.getTheoreticalEarliestOperationStartTime()); + double additionalTimeOfNewAct = (nextActStart - prevActDepTime) - (directNextActStart - prevActDepTime); + if (additionalTimeOfNewAct > minSlack) { + if (newActIsPickup) return ConstraintsStatus.NOT_FULFILLED_BREAK; + else return ConstraintsStatus.NOT_FULFILLED; + } + if (newActIsDelivery) { + Map openJobsAtNext; + if (nextAct instanceof End) + openJobsAtNext = stateManager.getRouteState(iFacts.getRoute(), iFacts.getNewVehicle(), openJobsId, Map.class); + else openJobsAtNext = stateManager.getActivityState(nextAct, iFacts.getNewVehicle(), openJobsId, Map.class); + if (openJobsAtNext == null) openJobsAtNext = Collections.emptyMap(); + for (Job openJob : openJobsAtNext.keySet()) { + double slack = openJobsAtNext.get(openJob); + double additionalTimeOfNewJob = additionalTimeOfNewAct; + if (openJob instanceof Shipment) { + Map openJobsAtNextOfPickup = Collections.emptyMap(); + TourActivity nextAfterPickup; + if (iFacts.getAssociatedActivities().size() == 1 && !iFacts.getRoute().isEmpty()) + nextAfterPickup = iFacts.getRoute().getActivities().get(0); + else + nextAfterPickup = iFacts.getRoute().getActivities().get(iFacts.getRelatedActivityContext().getInsertionIndex()); + if (nextAfterPickup != null) + openJobsAtNextOfPickup = stateManager.getActivityState(nextAfterPickup, iFacts.getNewVehicle(), openJobsId, Map.class); + if (openJobsAtNextOfPickup.containsKey(openJob)) { + TourActivity pickupAct = iFacts.getAssociatedActivities().get(0); + double pickupActArrTime = iFacts.getRelatedActivityContext().getArrivalTime(); + double pickupActEndTime = startOf(pickupAct, pickupActArrTime) + activityCosts.getActivityDuration(pickupAct, pickupActArrTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); + double nextAfterPickupArr = pickupActEndTime + transportTime.getTransportTime(pickupAct.getLocation(), nextAfterPickup.getLocation(), pickupActArrTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); + additionalTimeOfNewJob += startOf(nextAfterPickup, nextAfterPickupArr) - startOf(nextAfterPickup, nextAfterPickup.getArrTime()); } - }); - updateMaxTimeInVehicle.begin(iFacts.getRoute()); - List tourActivities = new ArrayList<>(iFacts.getRoute().getActivities()); - tourActivities.add(iFacts.getRelatedActivityContext().getInsertionIndex(), iFacts.getAssociatedActivities().get(0)); - for (TourActivity act : tourActivities) { - updateMaxTimeInVehicle.visit(act); } - updateMaxTimeInVehicle.finish(tourActivities, iFacts.getJob()); - - double latest; - if (iFacts.getRoute().isEmpty()) latest = Double.MAX_VALUE; - else if (nextAct instanceof End) { - latest = localStateManager.getRouteState(iFacts.getRoute(), iFacts.getNewVehicle(), stateId, Double.class); - } else - latest = localStateManager.getActivityState(nextAct, iFacts.getNewVehicle(), stateId, Double.class); - - if (nextActStart > latest) { + if (additionalTimeOfNewJob > slack) { return ConstraintsStatus.NOT_FULFILLED; } - } } + + +// if(newActIsPickup || iFacts.getAssociatedActivities().size() == 1) { +// double latest; +// if (iFacts.getRoute().isEmpty()) latest = Double.MAX_VALUE; +// else if (nextAct instanceof End) { +// latest = stateManager.getRouteState(iFacts.getRoute(), iFacts.getNewVehicle(), latestStartId, Double.class); +// } else latest = stateManager.getActivityState(nextAct, iFacts.getNewVehicle(), latestStartId, Double.class); +// +// if (nextActStart > latest) { +// return ConstraintsStatus.NOT_FULFILLED; +// } +// +// } else { +// boolean isShipment = iFacts.getAssociatedActivities().size() == 2; +// if (newActIsDelivery && isShipment) { +// StateManager localStateManager = new StateManager(vrp); +// StateId stateId = localStateManager.createStateId("local-slack"); +// UpdateMaxTimeInVehicle updateMaxTimeInVehicle = new UpdateMaxTimeInVehicle(localStateManager, stateId, transportTime, activityCosts); +// updateMaxTimeInVehicle.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() { +// @Override +// public Collection get(VehicleRoute route) { +// return Arrays.asList(iFacts.getNewVehicle()); +// } +// }); +// updateMaxTimeInVehicle.begin(iFacts.getRoute()); +// List tourActivities = new ArrayList<>(iFacts.getRoute().getActivities()); +// tourActivities.add(iFacts.getRelatedActivityContext().getInsertionIndex(), iFacts.getAssociatedActivities().get(0)); +// for (TourActivity act : tourActivities) { +// updateMaxTimeInVehicle.visit(act); +// } +// updateMaxTimeInVehicle.finish(tourActivities, iFacts.getJob()); +// +// double latest; +// if (iFacts.getRoute().isEmpty()) latest = Double.MAX_VALUE; +// else if (nextAct instanceof End) { +// latest = localStateManager.getRouteState(iFacts.getRoute(), iFacts.getNewVehicle(), stateId, Double.class); +// } else +// latest = localStateManager.getActivityState(nextAct, iFacts.getNewVehicle(), stateId, Double.class); +// +// if (nextActStart > latest) { +// return ConstraintsStatus.NOT_FULFILLED; +// } +// +// } +// } return ConstraintsStatus.FULFILLED; } + private double startOf(TourActivity act, double arrTime) { + return Math.max(arrTime, act.getTheoreticalEarliestOperationStartTime()); + } + // private double getMaxTime(String jobId) { // if(maxTimes.containsKey(jobId)) return maxTimes.get(jobId); // else return Double.MAX_VALUE; diff --git a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/MaxTimeInVehicle_IT.java b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/MaxTimeInVehicle_IT.java index 18285a11..a592b9da 100644 --- a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/MaxTimeInVehicle_IT.java +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/MaxTimeInVehicle_IT.java @@ -54,10 +54,11 @@ public class MaxTimeInVehicle_IT { StateManager stateManager = new StateManager(vrp); StateId id = stateManager.createStateId("max-time"); - stateManager.addStateUpdater(new UpdateMaxTimeInVehicle(stateManager,id,vrp.getTransportCosts(),vrp.getActivityCosts())); + StateId openJobsId = stateManager.createStateId("open-jobs-id"); + stateManager.addStateUpdater(new UpdateMaxTimeInVehicle(stateManager, id, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId)); ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager); - constraintManager.addConstraint(new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts(),id,stateManager, vrp), ConstraintManager.Priority.CRITICAL); + constraintManager.addConstraint(new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), id, stateManager, vrp, openJobsId), ConstraintManager.Priority.CRITICAL); VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp).setStateAndConstraintManager(stateManager,constraintManager).buildAlgorithm(); VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions()); diff --git a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/state/UpdateMaxTimeInVehicleTest.java b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/state/UpdateMaxTimeInVehicleTest.java index f39164d1..75aaf145 100644 --- a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/state/UpdateMaxTimeInVehicleTest.java +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/state/UpdateMaxTimeInVehicleTest.java @@ -30,15 +30,12 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl; import com.graphhopper.jsprit.core.problem.vehicle.VehicleType; import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeImpl; - import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; -import java.util.Map; /** * Created by schroeder on 15/09/16. @@ -61,7 +58,9 @@ public class UpdateMaxTimeInVehicleTest { private StateManager stateManager; - private StateId latestStartId; + private StateId minSlackId; + + private StateId openJobsId; @Before public void doBefore() { @@ -107,12 +106,13 @@ public class UpdateMaxTimeInVehicleTest { stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(),vrp.getActivityCosts())); stateManager.informInsertionStarts(Arrays.asList(route), null); - latestStartId = stateManager.createStateId("slack-time-id"); + minSlackId = stateManager.createStateId("min-slack-id"); + openJobsId = stateManager.createStateId("open-jobs-id"); // Map maxTimes = new HashMap<>(); // maxTimes.put("s",40d); // maxTimes.put("shipment",20d); - maxTimeInVehicleConstraint = new UpdateMaxTimeInVehicle(stateManager, latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts()); + maxTimeInVehicleConstraint = new UpdateMaxTimeInVehicle(stateManager, minSlackId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId); maxTimeInVehicleConstraint.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() { @Override public Collection get(VehicleRoute route) { @@ -128,23 +128,23 @@ public class UpdateMaxTimeInVehicleTest { // for(TourActivity act : route.getActivities()){ // String jobId = ((TourActivity.JobActivity)act).getJob().getId(); // if(jobId.equals("s4")){ -// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), latestStartId,Double.class); +// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), minSlackId,Double.class); // Assert.assertEquals(40, slackTime, 0.001); // } // if(jobId.equals("s3")){ -// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), latestStartId,Double.class); +// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), minSlackId,Double.class); // Assert.assertEquals(30, slackTime, 0.001); // } // if(jobId.equals("s2")){ -// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), latestStartId,Double.class); +// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), minSlackId,Double.class); // Assert.assertEquals(20, slackTime, 0.001); // } // if(jobId.equals("s")){ -// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), latestStartId,Double.class); +// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), minSlackId,Double.class); // Assert.assertEquals(Double.MAX_VALUE, slackTime, 0.001); // } // } -// Double slackTime = stateManager.getRouteState(route,route.getVehicle(), latestStartId,Double.class); +// Double slackTime = stateManager.getRouteState(route,route.getVehicle(), minSlackId,Double.class); // Assert.assertNotNull(slackTime); // Assert.assertEquals(50,slackTime,0.001); // } @@ -155,23 +155,23 @@ public class UpdateMaxTimeInVehicleTest { // for(TourActivity act : route.getActivities()){ // String jobId = ((TourActivity.JobActivity)act).getJob().getId(); // if(jobId.equals("s4")){ -// Double slackTime = stateManager.getActivityState(act,vehicle2, latestStartId,Double.class); +// Double slackTime = stateManager.getActivityState(act,vehicle2, minSlackId,Double.class); // Assert.assertEquals(40, slackTime, 0.001); // } // if(jobId.equals("s3")){ -// Double slackTime = stateManager.getActivityState(act,vehicle2, latestStartId,Double.class); +// Double slackTime = stateManager.getActivityState(act,vehicle2, minSlackId,Double.class); // Assert.assertEquals(30, slackTime, 0.001); // } // if(jobId.equals("s2")){ -// Double slackTime = stateManager.getActivityState(act,vehicle2, latestStartId,Double.class); +// Double slackTime = stateManager.getActivityState(act,vehicle2, minSlackId,Double.class); // Assert.assertEquals(20, slackTime, 0.001); // } // if(jobId.equals("s")){ -// Double slackTime = stateManager.getActivityState(act,vehicle2, latestStartId,Double.class); +// Double slackTime = stateManager.getActivityState(act,vehicle2, minSlackId,Double.class); // Assert.assertEquals(Double.MAX_VALUE, slackTime, 0.001); // } // } -// Double slackTime = stateManager.getRouteState(route,vehicle2, latestStartId,Double.class); +// Double slackTime = stateManager.getRouteState(route,vehicle2, minSlackId,Double.class); // Assert.assertNotNull(slackTime); // Assert.assertEquals(40,slackTime,0.001); // } @@ -182,17 +182,17 @@ public class UpdateMaxTimeInVehicleTest { for(TourActivity act : route2.getActivities()){ String jobId = ((TourActivity.JobActivity)act).getJob().getId(); if(jobId.equals("d1")){ - Double slackTime = stateManager.getActivityState(act,v, latestStartId,Double.class); + Double slackTime = stateManager.getActivityState(act, v, minSlackId, Double.class); Assert.assertEquals(Double.MAX_VALUE, slackTime, 0.001); } if(jobId.equals("shipment")){ if(act instanceof PickupActivity){ - Double slackTime = stateManager.getActivityState(act,v, latestStartId,Double.class); + Double slackTime = stateManager.getActivityState(act, v, minSlackId, Double.class); Assert.assertEquals(Double.MAX_VALUE, slackTime, 0.001); } else{ - Double slackTime = stateManager.getActivityState(act,v, latestStartId,Double.class); - Assert.assertEquals(40, slackTime, 0.001); + Double slackTime = stateManager.getActivityState(act, v, minSlackId, Double.class); + Assert.assertEquals(0, slackTime, 0.001); } } diff --git a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/constraint/MaxTimeInVehicleConstraintTest.java b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/constraint/MaxTimeInVehicleConstraintTest.java index 3e96ef7c..87070df1 100644 --- a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/constraint/MaxTimeInVehicleConstraintTest.java +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/constraint/MaxTimeInVehicleConstraintTest.java @@ -20,6 +20,7 @@ package com.graphhopper.jsprit.core.problem.constraint; import com.graphhopper.jsprit.core.algorithm.state.StateId; import com.graphhopper.jsprit.core.algorithm.state.StateManager; +import com.graphhopper.jsprit.core.algorithm.state.UpdateActivityTimes; import com.graphhopper.jsprit.core.algorithm.state.UpdateMaxTimeInVehicle; import com.graphhopper.jsprit.core.problem.AbstractActivity; import com.graphhopper.jsprit.core.problem.Location; @@ -112,13 +113,15 @@ public class MaxTimeInVehicleConstraintTest { .addPickup(s1).addDelivery(s1).build(); StateManager stateManager = new StateManager(vrp); - StateId latestStartId = stateManager.createStateId("latest-start-id"); + StateId minSlackId = stateManager.createStateId("min-slack-id"); + StateId openJobsId = stateManager.createStateId("open-jobs-id"); - UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts()); + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, minSlackId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId); stateManager.addStateUpdater(updater); + stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts())); stateManager.informInsertionStarts(Arrays.asList(route),new ArrayList()); - MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp); + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), minSlackId, stateManager, vrp, openJobsId); JobInsertionContext c = new JobInsertionContext(route,s2,v,route.getDriver(),0.); List acts = vrp.getActivities(s2); @@ -126,7 +129,7 @@ public class MaxTimeInVehicleConstraintTest { c.getAssociatedActivities().add(acts.get(1)); Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getStart(), acts.get(0), route.getActivities().get(0), 0)); - Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, act(route,0), acts.get(0), act(route,1), 20)); + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED_BREAK, constraint.fulfilled(c, act(route, 0), acts.get(0), act(route, 1), 20)); Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, act(route,1), acts.get(0), route.getEnd(), 40)); //insert pickup at 0 @@ -148,12 +151,14 @@ public class MaxTimeInVehicleConstraintTest { ini(30d, Double.MAX_VALUE, Double.MAX_VALUE); StateManager stateManager = new StateManager(vrp); StateId latestStartId = stateManager.createStateId("latest-start-id"); + StateId openJobsId = stateManager.createStateId("open-jobs-id"); - UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts()); + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId); stateManager.addStateUpdater(updater); + stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts())); stateManager.informInsertionStarts(Arrays.asList(route),new ArrayList()); - MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp); + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId); JobInsertionContext c = new JobInsertionContext(route,d2,v,route.getDriver(),0.); List acts = vrp.getActivities(d2); c.getAssociatedActivities().add(acts.get(0)); @@ -165,24 +170,67 @@ public class MaxTimeInVehicleConstraintTest { } + @Test + public void insertingD2JustAfterStartShouldWork() { + ini(20d, 30, Double.MAX_VALUE); + + StateManager stateManager = new StateManager(vrp); + StateId latestStartId = stateManager.createStateId("latest-start-id"); + StateId openJobsId = stateManager.createStateId("open-jobs-id"); + + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId); + stateManager.addStateUpdater(updater); + stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts())); + stateManager.informInsertionStarts(Arrays.asList(route), new ArrayList()); + + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId); + JobInsertionContext c = new JobInsertionContext(route, d2, v, route.getDriver(), 0.); + List acts = vrp.getActivities(d2); + c.getAssociatedActivities().add(acts.get(0)); + + Assert.assertEquals("inserting d2 just after start should work", HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getStart(), acts.get(0), route.getActivities().get(0), 0)); + } + + @Test + public void insertingD2AfterFirstDeliveryShouldWork() { + ini(20d, 30, Double.MAX_VALUE); + + StateManager stateManager = new StateManager(vrp); + StateId latestStartId = stateManager.createStateId("latest-start-id"); + StateId openJobsId = stateManager.createStateId("open-jobs-id"); + + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId); + stateManager.addStateUpdater(updater); + stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts())); + stateManager.informInsertionStarts(Arrays.asList(route), new ArrayList()); + + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId); + JobInsertionContext c = new JobInsertionContext(route, d2, v, route.getDriver(), 0.); + List acts = vrp.getActivities(d2); + c.getAssociatedActivities().add(acts.get(0)); + + + Assert.assertEquals("inserting d2 after first delivery should work", HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getActivities().get(0), acts.get(0), route.getActivities().get(1), 10)); + } + @Test public void insertingDeliveryInBetweenShipmentShouldFail(){ ini(20d, 30, Double.MAX_VALUE); StateManager stateManager = new StateManager(vrp); StateId latestStartId = stateManager.createStateId("latest-start-id"); + StateId openJobsId = stateManager.createStateId("open-jobs-id"); - UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(),vrp.getActivityCosts()); + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId); stateManager.addStateUpdater(updater); + stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts())); stateManager.informInsertionStarts(Arrays.asList(route),new ArrayList()); - MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp); + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId); JobInsertionContext c = new JobInsertionContext(route,d2,v,route.getDriver(),0.); List acts = vrp.getActivities(d2); c.getAssociatedActivities().add(acts.get(0)); - Assert.assertEquals("inserting d2 just after start should work", HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getStart(), acts.get(0), route.getActivities().get(0), 0)); - Assert.assertEquals("inserting d2 after first delivery should work", HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getActivities().get(0), acts.get(0), route.getActivities().get(1), 10)); Assert.assertEquals("inserting d2 between pickup and delivery shipment should fail due to max-in-vehicle constraint of shipment", HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, route.getActivities().get(1), acts.get(0), route.getActivities().get(2), 20)); Assert.assertEquals("inserting d2 at end should fail", HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, route.getActivities().get(2), acts.get(0), route.getEnd(), 40)); } @@ -197,12 +245,14 @@ public class MaxTimeInVehicleConstraintTest { StateManager stateManager = new StateManager(vrp); StateId latestStartId = stateManager.createStateId("latest-start-id"); + StateId openJobsId = stateManager.createStateId("open-jobs-id"); - UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts()); + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId); stateManager.addStateUpdater(updater); + stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts())); stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList()); - MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp); + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId); JobInsertionContext c = new JobInsertionContext(r, s1,v,r.getDriver(),0.); List acts = vrp.getActivities(s1); c.getAssociatedActivities().add(acts.get(0)); @@ -223,12 +273,14 @@ public class MaxTimeInVehicleConstraintTest { StateManager stateManager = new StateManager(vrp); StateId latestStartId = stateManager.createStateId("latest-start-id"); + StateId openJobsId = stateManager.createStateId("open-jobs-id"); - UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts()); + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId); stateManager.addStateUpdater(updater); + stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts())); stateManager.informInsertionStarts(Arrays.asList(r), new ArrayList()); - MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp); + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId); JobInsertionContext c = new JobInsertionContext(r, s1, v, r.getDriver(), 0.); List acts = vrp.getActivities(s1); c.getAssociatedActivities().add(acts.get(0)); @@ -250,18 +302,20 @@ public class MaxTimeInVehicleConstraintTest { StateManager stateManager = new StateManager(vrp); StateId latestStartId = stateManager.createStateId("latest-start-id"); + StateId openJobsId = stateManager.createStateId("open-jobs-id"); - UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts()); + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId); stateManager.addStateUpdater(updater); + stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts())); stateManager.informInsertionStarts(Arrays.asList(r), new ArrayList()); - MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp); + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId); JobInsertionContext c = new JobInsertionContext(r, s1, v, r.getDriver(), 0.); List acts = vrp.getActivities(s1); c.getAssociatedActivities().add(acts.get(0)); c.getAssociatedActivities().add(acts.get(1)); - Assert.assertEquals("pickup shipment cannot happen at first pos. since d2 has max in-vehicle time", HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, r.getStart(), acts.get(0), r.getActivities().get(0), 0)); + Assert.assertEquals("pickup shipment cannot happen at first pos. since d2 has max in-vehicle time", HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED_BREAK, constraint.fulfilled(c, r.getStart(), acts.get(0), r.getActivities().get(0), 0)); Assert.assertEquals("pickup shipment can happen at second pos.", HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, r.getActivities().get(0), acts.get(0), r.getActivities().get(1), 10)); Assert.assertEquals("d2 has been delivered so pickup shipment is possible", HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, r.getActivities().get(1), acts.get(0), r.getEnd(), 30)); } @@ -308,12 +362,14 @@ public class MaxTimeInVehicleConstraintTest { StateManager stateManager = new StateManager(vrp); StateId latestStartId = stateManager.createStateId("latest-start-id"); + StateId openJobsId = stateManager.createStateId("open-jobs-id"); - UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts()); + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId); stateManager.addStateUpdater(updater); + stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts())); stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList()); - MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp); + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId); JobInsertionContext c = new JobInsertionContext(r, s1,v,r.getDriver(),0.); List acts = vrp.getActivities(s1); c.getAssociatedActivities().add(acts.get(0)); @@ -337,14 +393,16 @@ public class MaxTimeInVehicleConstraintTest { StateManager stateManager = new StateManager(vrp); StateId latestStartId = stateManager.createStateId("latest-start-id"); + StateId openJobsId = stateManager.createStateId("open-jobs-id"); Map maxTimes = new HashMap<>(); maxTimes.put("s1",25d); - UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts()); + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId); stateManager.addStateUpdater(updater); + stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts())); stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList()); - MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp); + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId); JobInsertionContext c = new JobInsertionContext(r, s1,v,r.getDriver(),0.); List acts = vrp.getActivities(s1); c.getAssociatedActivities().add(acts.get(0));