From f6bf46ca9a8397a897da32bf318ed90fc283e5bb Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Sat, 1 Mar 2014 12:17:00 +0100 Subject: [PATCH] tested and redesigned StateManager and UpdateLoads --- .../core/algorithm/state/StateManager.java | 16 +- .../core/algorithm/state/UpdateLoads.java | 66 ++--- ....java => UpdateMaxLoadForwardLooking.java} | 18 +- .../java/jsprit/core/problem/Capacity.java | 34 +++ .../core/algorithm/state/UpdateLoadsTest.java | 259 ++++++++++++++---- .../jsprit/core/problem/CapacityTest.java | 47 ++++ 6 files changed, 338 insertions(+), 102 deletions(-) rename jsprit-core/src/main/java/jsprit/core/algorithm/state/{UpdateMaxLoad.java => UpdateMaxLoadForwardLooking.java} (75%) diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/state/StateManager.java b/jsprit-core/src/main/java/jsprit/core/algorithm/state/StateManager.java index 1ac74fe3..2eb3c605 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/state/StateManager.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/state/StateManager.java @@ -30,6 +30,7 @@ import jsprit.core.algorithm.recreate.listener.InsertionStartsListener; import jsprit.core.algorithm.recreate.listener.JobInsertedListener; import jsprit.core.algorithm.ruin.listener.RuinListener; import jsprit.core.algorithm.ruin.listener.RuinListeners; +import jsprit.core.problem.Capacity; import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.cost.VehicleRoutingTransportCosts; import jsprit.core.problem.job.Job; @@ -113,20 +114,25 @@ public class StateManager implements RouteAndActivityStateGetter, IterationStart } private void addDefaultStates() { - defaultActivityStates_.put(StateFactory.LOAD, StateFactory.createState(0)); + defaultActivityStates_.put(StateFactory.LOAD, Capacity.Builder.newInstance().build()); + + defaultActivityStates_.put(StateFactory.COSTS, StateFactory.createState(0)); defaultActivityStates_.put(StateFactory.DURATION, StateFactory.createState(0)); defaultActivityStates_.put(StateFactory.FUTURE_MAXLOAD, StateFactory.createState(0)); defaultActivityStates_.put(StateFactory.PAST_MAXLOAD, StateFactory.createState(0)); - defaultRouteStates_.put(StateFactory.LOAD, StateFactory.createState(0)); + defaultRouteStates_.put(StateFactory.LOAD, Capacity.Builder.newInstance().build()); + defaultRouteStates_.put(StateFactory.COSTS, StateFactory.createState(0)); defaultRouteStates_.put(StateFactory.DURATION, StateFactory.createState(0)); defaultRouteStates_.put(StateFactory.FUTURE_MAXLOAD, StateFactory.createState(0)); defaultRouteStates_.put(StateFactory.PAST_MAXLOAD, StateFactory.createState(0)); - defaultRouteStates_.put(StateFactory.LOAD_AT_END, StateFactory.createState(0)); + defaultRouteStates_.put(StateFactory.MAXLOAD, StateFactory.createState(0)); - defaultRouteStates_.put(StateFactory.LOAD_AT_BEGINNING, StateFactory.createState(0)); + + defaultRouteStates_.put(StateFactory.LOAD_AT_END, Capacity.Builder.newInstance().build()); + defaultRouteStates_.put(StateFactory.LOAD_AT_BEGINNING, Capacity.Builder.newInstance().build()); } @@ -423,7 +429,7 @@ public class StateManager implements RouteAndActivityStateGetter, IterationStart addActivityVisitor(updateLoads); addListener(updateLoads); addActivityVisitor(new UpdatePrevMaxLoad(this)); - addActivityVisitor(new UpdateMaxLoad(this)); + addActivityVisitor(new UpdateMaxLoadForwardLooking(this)); addActivityVisitor(new UpdateMaxLoad_(this)); } } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateLoads.java b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateLoads.java index 394ed994..f99d6db8 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateLoads.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateLoads.java @@ -4,6 +4,7 @@ import java.util.Collection; import jsprit.core.algorithm.recreate.listener.InsertionStartsListener; import jsprit.core.algorithm.recreate.listener.JobInsertedListener; +import jsprit.core.problem.Capacity; import jsprit.core.problem.job.Delivery; import jsprit.core.problem.job.Job; import jsprit.core.problem.job.Pickup; @@ -15,34 +16,27 @@ import jsprit.core.problem.solution.route.state.StateFactory; /** - * Updates load at activity level. + * Updates load at start and end of route as well as at each activity. And update is triggered when either + * activityVisitor has been started, the insertion process has been started or a job has been inserted. * - *

Note that this assumes that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT. - * If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot. - * - *

Thus it DEPENDS on StateTypes.LOAD_AT_DEPOT + *

Note that this only works properly if you register this class as ActivityVisitor AND InsertionStartsListener AND JobInsertedListener. + * The reason behind is that activity states are dependent on route-level states and vice versa. If this is properly registered, + * this dependency is solved automatically. * * @author stefan * */ class UpdateLoads implements ActivityVisitor, StateUpdater, InsertionStartsListener, JobInsertedListener { + private StateManager stateManager; - private int currentLoad = 0; - private VehicleRoute route; - /** - * Updates load at activity level. - * - *

Note that this assumes that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT. - * If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot. - * - *

Thus it DEPENDS on StateTypes.LOAD_AT_DEPOT - * - *

The loads can be retrieved by
- * stateManager.getActivityState(activity,StateTypes.LOAD); - * - * @author stefan - * + + /* + * default has one dimension with a value of zero */ + private Capacity currentLoad = Capacity.Builder.newInstance().build(); + + private VehicleRoute route; + public UpdateLoads(StateManager stateManager) { super(); this.stateManager = stateManager; @@ -50,36 +44,36 @@ class UpdateLoads implements ActivityVisitor, StateUpdater, InsertionStartsListe @Override public void begin(VehicleRoute route) { - currentLoad = (int) stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble(); + currentLoad = stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class); this.route = route; } @Override public void visit(TourActivity act) { - currentLoad += act.getCapacityDemand(); - stateManager.putInternalActivityState(act, StateFactory.LOAD, StateFactory.createState(currentLoad)); - assert currentLoad <= route.getVehicle().getCapacity() : "currentLoad at activity must not be > vehicleCapacity"; - assert currentLoad >= 0 : "currentLoad at act must not be < 0"; + currentLoad = Capacity.addup(currentLoad, act.getCapacity()); + stateManager.putInternalActivityState_(act, StateFactory.LOAD, Capacity.class, currentLoad); + assert currentLoad.isLessOrEqual(route.getVehicle().getType().getCapacityDimensions()) : "currentLoad at activity must not be > vehicleCapacity"; + assert currentLoad.isGreaterOrEqual(Capacity.Builder.newInstance().build()) : "currentLoad at act must not be < 0 in one of the applied dimensions"; } @Override public void finish() { - currentLoad = 0; + currentLoad = Capacity.Builder.newInstance().build(); } void insertionStarts(VehicleRoute route) { - int loadAtDepot = 0; - int loadAtEnd = 0; + Capacity loadAtDepot = Capacity.Builder.newInstance().build(); + Capacity loadAtEnd = Capacity.Builder.newInstance().build(); for(Job j : route.getTourActivities().getJobs()){ if(j instanceof Delivery){ - loadAtDepot += j.getCapacityDemand(); + loadAtDepot = Capacity.addup(loadAtDepot, j.getSize()); } else if(j instanceof Pickup || j instanceof Service){ - loadAtEnd += j.getCapacityDemand(); + loadAtEnd = Capacity.addup(loadAtEnd, j.getSize()); } } - stateManager.putInternalRouteState(route, StateFactory.LOAD_AT_BEGINNING, StateFactory.createState(loadAtDepot)); - stateManager.putInternalRouteState(route, StateFactory.LOAD_AT_END, StateFactory.createState(loadAtEnd)); + stateManager.putInternalRouteState_(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class, loadAtDepot); + stateManager.putInternalRouteState_(route, StateFactory.LOAD_AT_END, Capacity.class, loadAtEnd); } @Override @@ -90,12 +84,12 @@ class UpdateLoads implements ActivityVisitor, StateUpdater, InsertionStartsListe @Override public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { if(job2insert instanceof Delivery){ - int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING).toDouble(); - stateManager.putInternalRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING, StateFactory.createState(loadAtDepot + job2insert.getCapacityDemand())); + Capacity loadAtDepot = stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING, Capacity.class); + stateManager.putInternalRouteState_(inRoute, StateFactory.LOAD_AT_BEGINNING, Capacity.class, Capacity.addup(loadAtDepot, job2insert.getSize())); } else if(job2insert instanceof Pickup || job2insert instanceof Service){ - int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_END).toDouble(); - stateManager.putInternalRouteState(inRoute, StateFactory.LOAD_AT_END, StateFactory.createState(loadAtEnd + job2insert.getCapacityDemand())); + Capacity loadAtEnd = stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_END, Capacity.class); + stateManager.putInternalRouteState_(inRoute, StateFactory.LOAD_AT_END, Capacity.class, Capacity.addup(loadAtEnd, job2insert.getSize())); } } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxLoad.java b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxLoadForwardLooking.java similarity index 75% rename from jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxLoad.java rename to jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxLoadForwardLooking.java index 8ea51264..97d03e7f 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxLoad.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxLoadForwardLooking.java @@ -5,12 +5,24 @@ import jsprit.core.problem.solution.route.activity.ReverseActivityVisitor; import jsprit.core.problem.solution.route.activity.TourActivity; import jsprit.core.problem.solution.route.state.StateFactory; - -class UpdateMaxLoad implements ReverseActivityVisitor, StateUpdater { +/** + * A {@link ReverseActivityVisitor} that looks forward in the vehicle route and determines + * the maximum load for subsequent activities. + * + *

+ * + * @author schroeder + * + */ +class UpdateMaxLoadForwardLooking implements ReverseActivityVisitor, StateUpdater { + private StateManager stateManager; + private VehicleRoute route; + private double maxLoad; - public UpdateMaxLoad(StateManager stateManager) { + + public UpdateMaxLoadForwardLooking(StateManager stateManager) { super(); this.stateManager = stateManager; } diff --git a/jsprit-core/src/main/java/jsprit/core/problem/Capacity.java b/jsprit-core/src/main/java/jsprit/core/problem/Capacity.java index 294d1fb0..096996a1 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/Capacity.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/Capacity.java @@ -202,6 +202,22 @@ public class Capacity { return true; } + /** + * Returns true if this capacity is greater or equal than the capacity toCompare + * + * @param toCompare + * @return + * @throws NullPointerException if one of the args is null + + */ + public boolean isGreaterOrEqual(Capacity toCompare) { + if(toCompare == null) throw new NullPointerException(); + for(int i=0;iemptyList()); - assertEquals(0.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble(),0.1); - assertEquals(0.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END).toDouble(),0.1); + Capacity loadAtBeginning = stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class); + assertEquals(0.,loadAtBeginning.get(0),0.1); + assertEquals(0.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(0),0.1); } - @SuppressWarnings("deprecation") @Test public void whenVehcicleRouteIsNotEmpty_loadsAtBeginningAndEndShouldBeCalculatedCorrectly(){ - StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); UpdateLoads updateLoads = new UpdateLoads(stateManager); Service service = mock(Service.class); - - when(service.getCapacityDemand()).thenReturn(1); Capacity capacity = Capacity.Builder.newInstance().addDimension(0, 1).build(); when(service.getSize()).thenReturn(capacity); @@ -51,13 +49,13 @@ public class UpdateLoadsTest { .addService(service).build(); updateLoads.informInsertionStarts(Arrays.asList(route), Collections.emptyList()); - assertEquals(0.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble(),0.1); - assertEquals(1.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END).toDouble(),0.1); + assertEquals(0.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class).get(0),0.1); + assertEquals(1.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(0),0.1); } @Test public void whenVehcicleRouteIsNotEmpty_multipleLoadsAtBeginningAndEndShouldBeCalculatedCorrectly(){ - StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); UpdateLoads updateLoads = new UpdateLoads(stateManager); Service service = mock(Service.class); @@ -68,90 +66,152 @@ public class UpdateLoadsTest { .addService(service).build(); updateLoads.informInsertionStarts(Arrays.asList(route), Collections.emptyList()); - assertEquals(0.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble(),0.1); - assertEquals(1.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END).toDouble(),0.1); + assertEquals(0.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class).get(0),0.1); + assertEquals(0.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class).get(1),0.1); + assertEquals(1.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(0),0.1); + assertEquals(2.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(1),0.1); } - @SuppressWarnings("deprecation") @Test public void whenVehcicleRouteHasTwoActivities_loadsAtBeginningAndEndShouldBeCalculatedCorrectly(){ - StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); UpdateLoads updateLoads = new UpdateLoads(stateManager); Service service = mock(Service.class); - when(service.getCapacityDemand()).thenReturn(1); + when(service.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 1).build()); Service service2 = mock(Service.class); - when(service2.getCapacityDemand()).thenReturn(10); + when(service2.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 10).build()); VehicleRoute route = VehicleRoute.Builder.newInstance(mock(Vehicle.class), mock(Driver.class)) .addService(service).addService(service2).build(); updateLoads.informInsertionStarts(Arrays.asList(route), Collections.emptyList()); - assertEquals(0.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble(),0.1); - assertEquals(11.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END).toDouble(),0.1); + assertEquals(0.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class).get(0),0.1); + assertEquals(11.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(0),0.1); } - @SuppressWarnings("deprecation") @Test - public void whenVehcicleRouteHasTwoActivities_loadsAtActivitiesShouldBeCalculatedCorrectly(){ - StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); + public void whenVehcicleRouteHasTwoActivitiesWithMultipleCapDims_loadsAtBeginningAndEndShouldBeCalculatedCorrectly(){ + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); + UpdateLoads updateLoads = new UpdateLoads(stateManager); + + Service service = mock(Service.class); + when(service.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 3).build()); + + Service service2 = mock(Service.class); + when(service2.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 10).addDimension(1, 14).build()); + + VehicleRoute route = VehicleRoute.Builder.newInstance(mock(Vehicle.class), mock(Driver.class)) + .addService(service).addService(service2).build(); + + updateLoads.informInsertionStarts(Arrays.asList(route), Collections.emptyList()); + assertEquals(0.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class).get(0),0.1); + assertEquals(0.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class).get(1),0.1); + assertEquals(11.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(0),0.1); + assertEquals(17.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(1),0.1); + } + + @Test + public void whenVehicleRouteHasTwoActivities_loadsAtActivitiesShouldBeCalculatedCorrectly(){ + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); UpdateLoads updateLoads = new UpdateLoads(stateManager); RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor(); routeActivityVisitor.addActivityVisitor(updateLoads); Service service = mock(Service.class); - when(service.getCapacityDemand()).thenReturn(1); + when(service.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 1).build()); Service service2 = mock(Service.class); - when(service2.getCapacityDemand()).thenReturn(10); + when(service2.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 10).build()); VehicleRoute route = VehicleRoute.Builder.newInstance(mock(Vehicle.class), mock(Driver.class)) .addService(service).addService(service2).build(); routeActivityVisitor.visit(route); - assertEquals(1.,stateManager.getActivityState(route.getActivities().get(0), StateFactory.LOAD).toDouble(),0.1); - assertEquals(11.,stateManager.getActivityState(route.getActivities().get(1), StateFactory.LOAD).toDouble(),0.1); + assertEquals(1.,stateManager.getActivityState(route.getActivities().get(0), StateFactory.LOAD, Capacity.class).get(0),0.1); + assertEquals(11.,stateManager.getActivityState(route.getActivities().get(1), StateFactory.LOAD, Capacity.class).get(0),0.1); } - @SuppressWarnings("deprecation") + @Test + public void whenVehicleRouteHasTwoActivitiesWithMultipleCapDims_loadsAtActivitiesShouldBeCalculatedCorrectly(){ + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); + UpdateLoads updateLoads = new UpdateLoads(stateManager); + + RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor(); + routeActivityVisitor.addActivityVisitor(updateLoads); + + Service service = mock(Service.class); + when(service.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 3).build()); + + Service service2 = mock(Service.class); + when(service2.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 10).addDimension(1, 13).build()); + + VehicleRoute route = VehicleRoute.Builder.newInstance(mock(Vehicle.class), mock(Driver.class)) + .addService(service).addService(service2).build(); + + routeActivityVisitor.visit(route); + + assertEquals(1.,stateManager.getActivityState(route.getActivities().get(0), StateFactory.LOAD, Capacity.class).get(0),0.1); + assertEquals(3.,stateManager.getActivityState(route.getActivities().get(0), StateFactory.LOAD, Capacity.class).get(1),0.1); + assertEquals(11.,stateManager.getActivityState(route.getActivities().get(1), StateFactory.LOAD, Capacity.class).get(0),0.1); + assertEquals(16.,stateManager.getActivityState(route.getActivities().get(1), StateFactory.LOAD, Capacity.class).get(1),0.1); + } + @Test public void whenVehcicleRouteHasPickupAndDelivery_loadsAtBeginningAndEndShouldBeCalculatedCorrectly(){ - StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); UpdateLoads updateLoads = new UpdateLoads(stateManager); Pickup pickup = mock(Pickup.class); - when(pickup.getCapacityDemand()).thenReturn(1); + when(pickup.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 1).build()); Delivery delivery = mock(Delivery.class); - when(delivery.getCapacityDemand()).thenReturn(10); - Capacity capacity2 = Capacity.Builder.newInstance().addDimension(0, 10).build(); - when(delivery.getSize()).thenReturn(capacity2); + when(delivery.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 10).build()); VehicleRoute route = VehicleRoute.Builder.newInstance(mock(Vehicle.class), mock(Driver.class)) .addService(pickup).addService(delivery).build(); updateLoads.informInsertionStarts(Arrays.asList(route), Collections.emptyList()); - assertEquals(10.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble(),0.1); - assertEquals(1.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END).toDouble(),0.1); + assertEquals(10.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class).get(0),0.1); + assertEquals(1.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(0),0.1); + } + + @Test + public void whenVehcicleRouteHasPickupAndDeliveryWithMultipleCapDims_loadsAtBeginningAndEndShouldBeCalculatedCorrectly(){ + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); + UpdateLoads updateLoads = new UpdateLoads(stateManager); + + Pickup pickup = mock(Pickup.class); + when(pickup.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 4).build()); + + Delivery delivery = mock(Delivery.class); + when(delivery.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 10).addDimension(1, 13).build()); + + VehicleRoute route = VehicleRoute.Builder.newInstance(mock(Vehicle.class), mock(Driver.class)) + .addService(pickup).addService(delivery).build(); + + updateLoads.informInsertionStarts(Arrays.asList(route), Collections.emptyList()); + assertEquals(10.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class).get(0),0.1); + assertEquals(13.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class).get(1),0.1); + assertEquals(1.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(0),0.1); + assertEquals(4.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(1),0.1); } - @SuppressWarnings("deprecation") @Test public void whenVehcicleRouteHasPickupAndDelivery_loadsAtActivitiesShouldBeCalculatedCorrectly(){ - StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); UpdateLoads updateLoads = new UpdateLoads(stateManager); RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor(); routeActivityVisitor.addActivityVisitor(updateLoads); Pickup pickup = mock(Pickup.class); - when(pickup.getCapacityDemand()).thenReturn(1); + when(pickup.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 1).build()); Delivery delivery = mock(Delivery.class); - when(delivery.getCapacityDemand()).thenReturn(10); Capacity capacity2 = Capacity.Builder.newInstance().addDimension(0, 10).build(); when(delivery.getSize()).thenReturn(capacity2); @@ -161,29 +221,54 @@ public class UpdateLoadsTest { updateLoads.informInsertionStarts(Arrays.asList(route), Collections.emptyList()); routeActivityVisitor.visit(route); - assertEquals(11.,stateManager.getActivityState(route.getActivities().get(0), StateFactory.LOAD).toDouble(),0.1); - assertEquals(1.,stateManager.getActivityState(route.getActivities().get(1), StateFactory.LOAD).toDouble(),0.1); + assertEquals(11.,stateManager.getActivityState(route.getActivities().get(0), StateFactory.LOAD, Capacity.class).get(0),0.1); + assertEquals(1.,stateManager.getActivityState(route.getActivities().get(1), StateFactory.LOAD, Capacity.class).get(0),0.1); } - @SuppressWarnings("deprecation") @Test - public void whenPickupIsInsertedIntoVehcicleRouteWithPickupAndDelivery_loadsAtBeginningAndEndShouldBeCalculatedCorrectly(){ - StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); + public void whenVehcicleRouteHasPickupAndDeliveryWithMultipleCapDims_loadsAtActivitiesShouldBeCalculatedCorrectly(){ + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); UpdateLoads updateLoads = new UpdateLoads(stateManager); RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor(); routeActivityVisitor.addActivityVisitor(updateLoads); Pickup pickup = mock(Pickup.class); - when(pickup.getCapacityDemand()).thenReturn(1); + when(pickup.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 4).build()); + + Delivery delivery = mock(Delivery.class); + Capacity capacity2 = Capacity.Builder.newInstance().addDimension(0, 10).addDimension(1, 14).build(); + when(delivery.getSize()).thenReturn(capacity2); + + VehicleRoute route = VehicleRoute.Builder.newInstance(mock(Vehicle.class), mock(Driver.class)) + .addService(pickup).addService(delivery).build(); + + updateLoads.informInsertionStarts(Arrays.asList(route), Collections.emptyList()); + routeActivityVisitor.visit(route); + + assertEquals(11.,stateManager.getActivityState(route.getActivities().get(0), StateFactory.LOAD, Capacity.class).get(0),0.1); + assertEquals(18.,stateManager.getActivityState(route.getActivities().get(0), StateFactory.LOAD, Capacity.class).get(1),0.1); + assertEquals(1.,stateManager.getActivityState(route.getActivities().get(1), StateFactory.LOAD, Capacity.class).get(0),0.1); + assertEquals(4.,stateManager.getActivityState(route.getActivities().get(1), StateFactory.LOAD, Capacity.class).get(1),0.1); + } + + @Test + public void whenPickupIsInsertedIntoVehcicleRouteWithPickupAndDelivery_loadsAtBeginningAndEndShouldBeCalculatedCorrectly(){ + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); + UpdateLoads updateLoads = new UpdateLoads(stateManager); + + RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor(); + routeActivityVisitor.addActivityVisitor(updateLoads); + + Pickup pickup = mock(Pickup.class); + when(pickup.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 1).build()); Delivery delivery = mock(Delivery.class); - when(delivery.getCapacityDemand()).thenReturn(10); Capacity capacity2 = Capacity.Builder.newInstance().addDimension(0, 10).build(); when(delivery.getSize()).thenReturn(capacity2); Pickup pickup2insert = mock(Pickup.class); - when(pickup2insert.getCapacityDemand()).thenReturn(2); + when(pickup2insert.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 2).build()); VehicleRoute route = VehicleRoute.Builder.newInstance(mock(Vehicle.class), mock(Driver.class)) .addService(pickup).addService(delivery).build(); @@ -191,29 +276,56 @@ public class UpdateLoadsTest { updateLoads.informInsertionStarts(Arrays.asList(route), Collections.emptyList()); updateLoads.informJobInserted(pickup2insert, route, 0., 0.); - assertEquals(10.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble(),0.1); - assertEquals(3.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END).toDouble(),0.1); + assertEquals(10.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class).get(0),0.1); + assertEquals(3.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(0),0.1); } - - @SuppressWarnings("deprecation") + @Test - public void whenDeliveryIsInsertedIntoVehcicleRouteWithPickupAndDelivery_loadsAtBeginningAndEndShouldBeCalculatedCorrectly(){ - StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); + public void whenPickupIsInsertedIntoVehcicleRouteWithPickupAndDeliveryWithMultipleCapDims_loadsAtBeginningAndEndShouldBeCalculatedCorrectly(){ + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); UpdateLoads updateLoads = new UpdateLoads(stateManager); RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor(); routeActivityVisitor.addActivityVisitor(updateLoads); Pickup pickup = mock(Pickup.class); - when(pickup.getCapacityDemand()).thenReturn(1); + when(pickup.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 3).build()); + + Delivery delivery = mock(Delivery.class); + Capacity capacity2 = Capacity.Builder.newInstance().addDimension(0, 10).addDimension(1, 15).build(); + when(delivery.getSize()).thenReturn(capacity2); + + Pickup pickup2insert = mock(Pickup.class); + when(pickup2insert.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 4).build()); + + VehicleRoute route = VehicleRoute.Builder.newInstance(mock(Vehicle.class), mock(Driver.class)) + .addService(pickup).addService(delivery).build(); + + updateLoads.informInsertionStarts(Arrays.asList(route), Collections.emptyList()); + updateLoads.informJobInserted(pickup2insert, route, 0., 0.); + + assertEquals(10.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class).get(0),0.1); + assertEquals(15.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class).get(1),0.1); + assertEquals(3.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(0),0.1); + assertEquals(7.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class).get(1),0.1); + } + + @Test + public void whenDeliveryIsInsertedIntoVehcicleRouteWithPickupAndDelivery_loadsAtBeginningAndEndShouldBeCalculatedCorrectly(){ + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); + UpdateLoads updateLoads = new UpdateLoads(stateManager); + + RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor(); + routeActivityVisitor.addActivityVisitor(updateLoads); + + Pickup pickup = mock(Pickup.class); + when(pickup.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 1).build()); Delivery delivery = mock(Delivery.class); - when(delivery.getCapacityDemand()).thenReturn(10); Capacity size = Capacity.Builder.newInstance().addDimension(0, 10).build(); when(delivery.getSize()).thenReturn(size); Delivery delivery2insert = mock(Delivery.class); - when(delivery2insert.getCapacityDemand()).thenReturn(20); Capacity size2 = Capacity.Builder.newInstance().addDimension(0, 20).build(); when(delivery2insert.getSize()).thenReturn(size2); @@ -223,8 +335,39 @@ public class UpdateLoadsTest { updateLoads.informInsertionStarts(Arrays.asList(route), Collections.emptyList()); updateLoads.informJobInserted(delivery2insert, route, 0., 0.); - assertEquals(30.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble(),0.1); - assertEquals(1.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END).toDouble(),0.1); + assertEquals(30.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING,Capacity.class).get(0),0.1); + assertEquals(1.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END,Capacity.class).get(0),0.1); } - + + @Test + public void whenDeliveryIsInsertedIntoVehcicleRouteWithPickupAndDeliveryWithMultipleCapDims_loadsAtBeginningAndEndShouldBeCalculatedCorrectly(){ + StateManager stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); + UpdateLoads updateLoads = new UpdateLoads(stateManager); + + RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor(); + routeActivityVisitor.addActivityVisitor(updateLoads); + + Pickup pickup = mock(Pickup.class); + when(pickup.getSize()).thenReturn(Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 3).build()); + + Delivery delivery = mock(Delivery.class); + Capacity size = Capacity.Builder.newInstance().addDimension(0, 10).addDimension(1, 14).build(); + when(delivery.getSize()).thenReturn(size); + + Delivery delivery2insert = mock(Delivery.class); + Capacity size2 = Capacity.Builder.newInstance().addDimension(0, 20).addDimension(1, 25).build(); + when(delivery2insert.getSize()).thenReturn(size2); + + VehicleRoute route = VehicleRoute.Builder.newInstance(mock(Vehicle.class), mock(Driver.class)) + .addService(pickup).addService(delivery).build(); + + updateLoads.informInsertionStarts(Arrays.asList(route), Collections.emptyList()); + updateLoads.informJobInserted(delivery2insert, route, 0., 0.); + + assertEquals(30.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING,Capacity.class).get(0),0.1); + assertEquals(39.,stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING,Capacity.class).get(1),0.1); + assertEquals(1.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END,Capacity.class).get(0),0.1); + assertEquals(3.,stateManager.getRouteState(route, StateFactory.LOAD_AT_END,Capacity.class).get(1),0.1); + } + } diff --git a/jsprit-core/src/test/java/jsprit/core/problem/CapacityTest.java b/jsprit-core/src/test/java/jsprit/core/problem/CapacityTest.java index 361f6f6e..86d62446 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/CapacityTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/CapacityTest.java @@ -230,6 +230,28 @@ public class CapacityTest { assertFalse(cap2.isLessOrEqual(cap1)); } + @Test + public void whenOneCapIsBiggerThanAnother_greaterOrEqualShouldReturnTrue(){ + Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build(); + Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 4).addDimension(2, 4).build(); + assertTrue(cap2.isGreaterOrEqual(cap1)); + } + + @Test + public void whenOneCapIsBiggerThanAnother_greaterOrEqualShouldReturnTrue_v2(){ + Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build(); + //which is zero-cap + Capacity cap2 = Capacity.Builder.newInstance().build(); + assertTrue(cap1.isGreaterOrEqual(cap2)); + } + + @Test + public void whenOneCapIsEqualToAnother_greaterOrEqualShouldReturnTrue(){ + Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build(); + Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 3).addDimension(2, 4).build(); + assertTrue(cap2.isGreaterOrEqual(cap1)); + } + @Test public void whenAddingTwo_itShouldReturnCorrectCap(){ int wheelChairSpace = 0; @@ -267,4 +289,29 @@ public class CapacityTest { assertEquals(-4,inverted.get(2)); } + @Test + public void whenDeterminingTheMaximumOfTwoCapacities_itShouldReturnCapWithMaxOfEachDimension(){ + Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 3).addDimension(1, 3).build(); + Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 4).build(); + assertEquals(3,Capacity.max(cap1,cap2).get(0)); + assertEquals(4,Capacity.max(cap1,cap2).get(1)); + } + + @Test + public void whenDeterminingTheMaximumOfTwoCapacities_itShouldReturnCapWithMaxOfEachDimension_v2(){ + Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 3).build(); + Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 4).build(); + assertEquals(2,Capacity.max(cap1,cap2).get(0)); + assertEquals(4,Capacity.max(cap1,cap2).get(1)); + } + + @Test + public void whenDeterminingTheMaximumOfTwoCapacities_itShouldReturnCapWithMaxOfEachDimension_v3(){ + Capacity cap1 = Capacity.Builder.newInstance().addDimension(0, 1).addDimension(1, 3).addDimension(2, 3).build(); + Capacity cap2 = Capacity.Builder.newInstance().addDimension(0, 2).addDimension(1, 4).build(); + assertEquals(2,Capacity.max(cap1,cap2).get(0)); + assertEquals(4,Capacity.max(cap1,cap2).get(1)); + assertEquals(3,Capacity.max(cap1,cap2).get(2)); + } + }