From d628f23b4d709f22306e1e334bfb882db1f72b40 Mon Sep 17 00:00:00 2001 From: He Huang Date: Tue, 29 Nov 2016 11:52:52 +0800 Subject: [PATCH] fix deliverShipment insertion in max distance constraint --- .../constraint/MaxDistanceConstraint.java | 16 ++- .../VehicleDependentTraveledDistanceTest.java | 118 ++++++++++++++++-- 2 files changed, 118 insertions(+), 16 deletions(-) diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/constraint/MaxDistanceConstraint.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/constraint/MaxDistanceConstraint.java index 2bbf0fda..fac022db 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/constraint/MaxDistanceConstraint.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/constraint/MaxDistanceConstraint.java @@ -81,7 +81,7 @@ public class MaxDistanceConstraint implements HardActivityConstraint{ double distancePrevAct2NewAct = distanceCalculator.getDistance(prevAct.getLocation(), newAct.getLocation(), iFacts.getNewDepTime(), iFacts.getNewVehicle()); double distanceNewAct2nextAct = distanceCalculator.getDistance(newAct.getLocation(), nextAct.getLocation(), iFacts.getNewDepTime(), iFacts.getNewVehicle()); double distancePrevAct2NextAct = distanceCalculator.getDistance(prevAct.getLocation(), nextAct.getLocation(), prevActDepTime, iFacts.getNewVehicle()); - if(routeIsEmpty) distancePrevAct2NextAct = 0; + if(prevAct instanceof Start && nextAct instanceof End) distancePrevAct2NextAct = 0; if(nextAct instanceof End && !iFacts.getNewVehicle().isReturnToDepot()){ distanceNewAct2nextAct = 0; distancePrevAct2NextAct = 0; @@ -97,12 +97,20 @@ public class MaxDistanceConstraint implements HardActivityConstraint{ TourActivity actBeforePickup; if(iIndexOfPickup > 0) actBeforePickup = iFacts.getRoute().getActivities().get(iIndexOfPickup-1); else actBeforePickup = new Start(iFacts.getNewVehicle().getStartLocation(),0,Double.MAX_VALUE); - TourActivity actAfterPickup = iFacts.getRoute().getActivities().get(iIndexOfPickup); - //ToDo account here fore End and returnToDepot + TourActivity actAfterPickup; + if (iIndexOfPickup < iFacts.getRoute().getActivities().size()) + actAfterPickup = iFacts.getRoute().getActivities().get(iIndexOfPickup); + else + actAfterPickup = nextAct; double distanceActBeforePickup2Pickup = distanceCalculator.getDistance(actBeforePickup.getLocation(), pickup.getLocation(), actBeforePickup.getEndTime(), iFacts.getNewVehicle()); double distancePickup2ActAfterPickup = distanceCalculator.getDistance(pickup.getLocation(), actAfterPickup.getLocation(), iFacts.getRelatedActivityContext().getEndTime(), iFacts.getNewVehicle()); double distanceBeforePickup2AfterPickup = distanceCalculator.getDistance(actBeforePickup.getLocation(), actAfterPickup.getLocation(), actBeforePickup.getEndTime(), iFacts.getNewVehicle()); - additionalDistanceOfPickup = distanceActBeforePickup2Pickup + distancePickup2ActAfterPickup - distanceBeforePickup2AfterPickup; + if (routeIsEmpty) distanceBeforePickup2AfterPickup = 0; + if (actAfterPickup instanceof End && !iFacts.getNewVehicle().isReturnToDepot()) { + distancePickup2ActAfterPickup = 0; + distanceBeforePickup2AfterPickup = 0; + } + additionalDistanceOfPickup = distanceActBeforePickup2Pickup + distancePickup2ActAfterPickup - distanceBeforePickup2AfterPickup; } diff --git a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/constraint/VehicleDependentTraveledDistanceTest.java b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/constraint/VehicleDependentTraveledDistanceTest.java index 22c07de0..a1ed5145 100644 --- a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/constraint/VehicleDependentTraveledDistanceTest.java +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/constraint/VehicleDependentTraveledDistanceTest.java @@ -28,6 +28,7 @@ import com.graphhopper.jsprit.core.problem.job.Delivery; import com.graphhopper.jsprit.core.problem.job.Job; import com.graphhopper.jsprit.core.problem.job.Pickup; import com.graphhopper.jsprit.core.problem.job.Shipment; +import com.graphhopper.jsprit.core.problem.misc.ActivityContext; 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.End; @@ -214,50 +215,143 @@ vehicle2 (max distance): 180.0 @Test public void distanceOfShipmentInRoute(){ double traveledDistanceBeforePickup = stateManager.getActivityState(route.getActivities().get(2), vehicle,traveledDistanceId, Double.class); - double traveledDistanceBeforeDelivery = stateManager.getActivityState(route.getActivities().get(4), vehicle,traveledDistanceId, Double.class); + double traveledDistanceBeforeDelivery = stateManager.getActivityState(route.getActivities().get(4), vehicle, traveledDistanceId, Double.class); Assert.assertEquals(90d,traveledDistanceBeforeDelivery-traveledDistanceBeforePickup,0.01); } @Test public void distanceOfShipmentInRouteVehicle2(){ double traveledDistanceBeforePickup = stateManager.getActivityState(route.getActivities().get(2), vehicle2,traveledDistanceId, Double.class); - double traveledDistanceBeforeDelivery = stateManager.getActivityState(route.getActivities().get(4), vehicle2,traveledDistanceId, Double.class); + double traveledDistanceBeforeDelivery = stateManager.getActivityState(route.getActivities().get(4), vehicle2, traveledDistanceId, Double.class); Assert.assertEquals(90d,traveledDistanceBeforeDelivery-traveledDistanceBeforePickup,0.01); } @Test public void distanceOfPickupInRoute(){ - double traveledDistanceBeforePickup = stateManager.getActivityState(route.getActivities().get(3),vehicle, traveledDistanceId, Double.class); + double traveledDistanceBeforePickup = stateManager.getActivityState(route.getActivities().get(3), vehicle, traveledDistanceId, Double.class); double total = stateManager.getRouteState(route, vehicle,traveledDistanceId, Double.class); Assert.assertEquals(100d,total-traveledDistanceBeforePickup,0.01); } @Test public void distanceOfPickupInRouteVehicle2(){ - double traveledDistanceBeforePickup = stateManager.getActivityState(route.getActivities().get(3),vehicle2, traveledDistanceId, Double.class); + double traveledDistanceBeforePickup = stateManager.getActivityState(route.getActivities().get(3), vehicle2, traveledDistanceId, Double.class); double total = stateManager.getRouteState(route, vehicle2,traveledDistanceId, Double.class); Assert.assertEquals(80d,total-traveledDistanceBeforePickup,0.01); } @Test public void distanceToTravelShouldBeCorrect(){ - double total = stateManager.getRouteState(route,vehicle,traveledDistanceId,Double.class); + double total = stateManager.getRouteState(route, vehicle, traveledDistanceId, Double.class); Assert.assertEquals(180d,total - stateManager.getActivityState(route.getActivities().get(0),vehicle,traveledDistanceId,Double.class),0.01); - Assert.assertEquals(165d,total - stateManager.getActivityState(route.getActivities().get(1),vehicle,traveledDistanceId,Double.class),0.01); + Assert.assertEquals(165d, total - stateManager.getActivityState(route.getActivities().get(1), vehicle, traveledDistanceId, Double.class), 0.01); Assert.assertEquals(135d,total - stateManager.getActivityState(route.getActivities().get(2),vehicle,traveledDistanceId,Double.class),0.01); - Assert.assertEquals(100d,total - stateManager.getActivityState(route.getActivities().get(3),vehicle,traveledDistanceId,Double.class),0.01); - Assert.assertEquals(45d,total - stateManager.getActivityState(route.getActivities().get(4),vehicle,traveledDistanceId,Double.class),0.01); + Assert.assertEquals(100d, total - stateManager.getActivityState(route.getActivities().get(3), vehicle, traveledDistanceId, Double.class), 0.01); + Assert.assertEquals(45d, total - stateManager.getActivityState(route.getActivities().get(4), vehicle, traveledDistanceId, Double.class), 0.01); } @Test public void distanceToTravelShouldBeCorrectVehicle2(){ - double total = stateManager.getRouteState(route,vehicle2,traveledDistanceId,Double.class); + double total = stateManager.getRouteState(route, vehicle2, traveledDistanceId, Double.class); Assert.assertEquals(160d,total - stateManager.getActivityState(route.getActivities().get(0),vehicle2,traveledDistanceId,Double.class),0.01); - Assert.assertEquals(145d,total - stateManager.getActivityState(route.getActivities().get(1),vehicle2,traveledDistanceId,Double.class),0.01); + Assert.assertEquals(145d, total - stateManager.getActivityState(route.getActivities().get(1), vehicle2, traveledDistanceId, Double.class), 0.01); Assert.assertEquals(115d,total - stateManager.getActivityState(route.getActivities().get(2),vehicle2,traveledDistanceId,Double.class),0.01); - Assert.assertEquals(80d,total - stateManager.getActivityState(route.getActivities().get(3),vehicle2,traveledDistanceId,Double.class),0.01); - Assert.assertEquals(25d,total - stateManager.getActivityState(route.getActivities().get(4),vehicle2,traveledDistanceId,Double.class),0.01); + Assert.assertEquals(80d, total - stateManager.getActivityState(route.getActivities().get(3), vehicle2, traveledDistanceId, Double.class), 0.01); + Assert.assertEquals(25d, total - stateManager.getActivityState(route.getActivities().get(4), vehicle2, traveledDistanceId, Double.class), 0.01); } + + @Test + public void whenAddingDeliverShipment_constraintShouldWork() { + Shipment shipment = Shipment.Builder.newInstance("s") + .setPickupLocation(Location.newInstance(0, 3)) + .setDeliveryLocation(Location.newInstance(4, 0)) + .build(); + VehicleImpl vehicle = VehicleImpl.Builder.newInstance("v") + .setStartLocation(Location.newInstance(0, 0)) + .build(); + final VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance() + .addJob(shipment) + .addVehicle(vehicle) + .build(); + VehicleRoute route = VehicleRoute.emptyRoute(); + JobInsertionContext context = new JobInsertionContext(route, shipment, vehicle, null, 0); + context.getAssociatedActivities().add(vrp.getActivities(shipment).get(0)); + context.getAssociatedActivities().add(vrp.getActivities(shipment).get(1)); + maxDistanceMap = new HashMap<>(); + maxDistanceMap.put(vehicle,12d); + + StateManager stateManager = new StateManager(vrp); + MaxDistanceConstraint maxDistanceConstraint = + new MaxDistanceConstraint(stateManager, traveledDistanceId, new TransportDistance() { + @Override + public double getDistance(Location from, Location to, double departureTime, Vehicle vehicle) { + return vrp.getTransportCosts().getTransportTime(from,to,departureTime, null, vehicle); + } + },maxDistanceMap); + Assert.assertTrue(maxDistanceConstraint.fulfilled(context, + new Start(vehicle.getStartLocation(), 0, Double.MAX_VALUE), + vrp.getActivities(shipment).get(0), + new End(vehicle.getEndLocation(), 0, Double.MAX_VALUE), + 0).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED)); + + ActivityContext pickupContext = new ActivityContext(); + pickupContext.setArrivalTime(3); + pickupContext.setEndTime(3); + pickupContext.setInsertionIndex(0); + context.setRelatedActivityContext(pickupContext); + Assert.assertTrue(maxDistanceConstraint.fulfilled(context, + vrp.getActivities(shipment).get(0), + vrp.getActivities(shipment).get(1), + new End(vehicle.getEndLocation(), 0, Double.MAX_VALUE), + 3).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED)); + } + + @Test + public void whenAddingDeliverShipmentWithVehDiffStartEndLocs_constraintShouldWork() { + Shipment shipment = Shipment.Builder.newInstance("s") + .setPickupLocation(Location.newInstance(0, 1)) + .setDeliveryLocation(Location.newInstance(4, 1)) + .build(); + VehicleImpl vehicle = VehicleImpl.Builder.newInstance("v") + .setStartLocation(Location.newInstance(0, 0)) + .setEndLocation(Location.newInstance(0, 4)) + .build(); + final VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance() + .addJob(shipment) + .addVehicle(vehicle) + .build(); + VehicleRoute route = VehicleRoute.emptyRoute(); + JobInsertionContext context = new JobInsertionContext(route, shipment, vehicle, null, 0); + context.getAssociatedActivities().add(vrp.getActivities(shipment).get(0)); + context.getAssociatedActivities().add(vrp.getActivities(shipment).get(1)); + maxDistanceMap = new HashMap<>(); + maxDistanceMap.put(vehicle,10d); + + StateManager stateManager = new StateManager(vrp); + MaxDistanceConstraint maxDistanceConstraint = + new MaxDistanceConstraint(stateManager, traveledDistanceId, new TransportDistance() { + @Override + public double getDistance(Location from, Location to, double departureTime, Vehicle vehicle) { + return vrp.getTransportCosts().getTransportTime(from,to,departureTime, null, vehicle); + } + },maxDistanceMap); + Assert.assertTrue(maxDistanceConstraint.fulfilled(context, + new Start(vehicle.getStartLocation(), 0, Double.MAX_VALUE), + vrp.getActivities(shipment).get(0), + new End(vehicle.getEndLocation(), 0, Double.MAX_VALUE), + 0).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED)); + + ActivityContext pickupContext = new ActivityContext(); + pickupContext.setArrivalTime(1); + pickupContext.setEndTime(1); + pickupContext.setInsertionIndex(0); + context.setRelatedActivityContext(pickupContext); + Assert.assertTrue(maxDistanceConstraint.fulfilled(context, + vrp.getActivities(shipment).get(0), + vrp.getActivities(shipment).get(1), + new End(vehicle.getEndLocation(), 0, Double.MAX_VALUE), + 1).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED)); + } }