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 2bbf0fda0..5fd6456f8 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 @@ -22,10 +22,7 @@ import com.graphhopper.jsprit.core.algorithm.state.StateManager; import com.graphhopper.jsprit.core.problem.cost.TransportDistance; import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext; -import com.graphhopper.jsprit.core.problem.solution.route.activity.DeliverShipment; -import com.graphhopper.jsprit.core.problem.solution.route.activity.End; -import com.graphhopper.jsprit.core.problem.solution.route.activity.Start; -import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity; +import com.graphhopper.jsprit.core.problem.solution.route.activity.*; import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; import java.util.Collection; @@ -81,7 +78,7 @@ public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prev 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; @@ -89,27 +86,20 @@ public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prev double additionalDistance = distancePrevAct2NewAct + distanceNewAct2nextAct - distancePrevAct2NextAct; if(currentDistance + additionalDistance > maxDistance) return ConstraintsStatus.NOT_FULFILLED; - + StateId tempStateId = stateManager.createStateId("tempStateId"); double additionalDistanceOfPickup = 0; if(newAct instanceof DeliverShipment){ - int iIndexOfPickup = iFacts.getRelatedActivityContext().getInsertionIndex(); - TourActivity pickup = iFacts.getAssociatedActivities().get(0); - 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 - 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; + additionalDistanceOfPickup = stateManager.getActivityState( + iFacts.getAssociatedActivities().get(0), tempStateId, Double.class); } - if(currentDistance + additionalDistance + additionalDistanceOfPickup > maxDistance){ return ConstraintsStatus.NOT_FULFILLED; } + if (newAct instanceof PickupShipment) + stateManager.putActivityState(newAct, tempStateId, additionalDistance); + return ConstraintsStatus.FULFILLED; } 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 22c07de04..127521e81 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 @@ -36,14 +36,14 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl; import com.graphhopper.jsprit.core.util.ManhattanCosts; - import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import java.util.*; - -import static org.mockito.Mockito.mock; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; /** * Created by schroeder on 18/05/16. @@ -172,11 +172,11 @@ public double getDistance(Location from, Location to, double departureTime, Vehi JobInsertionContext context = new JobInsertionContext(route,newDelivery,vehicle2,null,0); Assert.assertTrue(maxDistanceConstraint.fulfilled(context,route.getStart(),newAct(),act(0),0).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED)); //additional distance: 20+35-15=40 - Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(0),newAct(),act(1),0).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED)); + Assert.assertTrue(maxDistanceConstraint.fulfilled(context, act(0), newAct(), act(1), 0).equals(HardActivityConstraint.ConstraintsStatus.FULFILLED)); //additional distance: 35+65-30=70 - Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(1),newAct(),act(2),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED)); + Assert.assertTrue(maxDistanceConstraint.fulfilled(context, act(1), newAct(), act(2), 0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED)); //additional distance: 65+100-35 - Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(2),newAct(),act(3),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED)); + Assert.assertTrue(maxDistanceConstraint.fulfilled(context, act(2), newAct(), act(3), 0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED)); //additional distance: 100+45-55 Assert.assertTrue(maxDistanceConstraint.fulfilled(context,act(3),newAct(),act(4),0).equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED)); //additional distance: 45+20-25 @@ -260,4 +260,85 @@ public void distanceToTravelShouldBeCorrectVehicle2(){ 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)); + 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)); + 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)); + } }