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 new file mode 100644 index 00000000..0cfb8c9f --- /dev/null +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/state/UpdateMaxTimeInVehicle.java @@ -0,0 +1,204 @@ +/* + * Licensed to GraphHopper GmbH under one or more contributor + * license agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + * + * GraphHopper GmbH licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.graphhopper.jsprit.core.algorithm.state; + +import com.graphhopper.jsprit.core.problem.Location; +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.solution.route.VehicleRoute; +import com.graphhopper.jsprit.core.problem.solution.route.activity.*; +import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; + +import java.util.*; + +/** + * Created by schroeder on 15/09/16. + */ +public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{ + + private Map> openPickupEndTimes = new HashMap<>(); + + private Map> slackTimes = new HashMap<>(); + + private Map> actStartTimes = new HashMap<>(); + + private VehicleRoute route; + + private final StateManager stateManager; + + private final StateId latestStartId; + + private double[] prevActEndTimes; + + private Location[] prevActLocations; + + private Collection vehicles; + + private final TransportTime transportTime; + + private final VehicleRoutingActivityCosts activityCosts; + + private UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate vehiclesToUpdate = new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() { + + @Override + public Collection get(VehicleRoute route) { + return Arrays.asList(route.getVehicle()); + } + + }; + + + public UpdateMaxTimeInVehicle(StateManager stateManager, StateId slackTimeId, TransportTime transportTime, VehicleRoutingActivityCosts activityCosts) { + this.stateManager = stateManager; + this.latestStartId = slackTimeId; + this.transportTime = transportTime; + prevActEndTimes = new double[stateManager.getMaxIndexOfVehicleTypeIdentifiers() + 1]; + prevActLocations = new Location[stateManager.getMaxIndexOfVehicleTypeIdentifiers() + 1]; + this.activityCosts = activityCosts; + } + + + public void setVehiclesToUpdate(UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate vehiclesToUpdate) { + this.vehiclesToUpdate = vehiclesToUpdate; + } + + + @Override + public void begin(VehicleRoute route) { + openPickupEndTimes.clear(); + slackTimes.clear(); + actStartTimes.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()); + prevActEndTimes[vehicleIndex] = v.getEarliestDeparture(); + prevActLocations[vehicleIndex] = v.getStartLocation(); + } + } + + @Override + public void visit(TourActivity activity) { + double maxTime = getMaxTimeInVehicle(activity); + + for(Vehicle v : vehicles) { + int vehicleIndex = v.getVehicleTypeIdentifier().getIndex(); + Location prevActLocation = prevActLocations[vehicleIndex]; + double prevActEndTime = prevActEndTimes[v.getVehicleTypeIdentifier().getIndex()]; + double activityArrival = prevActEndTimes[v.getVehicleTypeIdentifier().getIndex()] + transportTime.getTransportTime(prevActLocation,activity.getLocation(),prevActEndTime,route.getDriver(),v); + 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); + if (activity instanceof ServiceActivity || activity instanceof PickupActivity) { + openPickups.put(((TourActivity.JobActivity) activity).getJob(), activityEnd); + } else if (activity instanceof DeliveryActivity) { + Job job = ((TourActivity.JobActivity) activity).getJob(); + double pickupEnd; + if (openPickups.containsKey(job)) { + pickupEnd = openPickups.get(job); + openPickups.remove(job); + } else pickupEnd = v.getEarliestDeparture(); + double slackTime = maxTime - (activityStart - pickupEnd); + slackTimes.get(vehicleIndex).put(activity, slackTime); + } + prevActLocations[vehicleIndex] = activity.getLocation(); + prevActEndTimes[vehicleIndex] = activityEnd; + } + + } + + private double getMaxTimeInVehicle(TourActivity activity) { + double maxTime = Double.MAX_VALUE; + if(activity instanceof TourActivity.JobActivity){ + maxTime = ((TourActivity.JobActivity) activity).getJob().getMaxTimeInVehicle(); + } + 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); + } + + @Override + public void finish() { + for(Vehicle v : vehicles) { + int vehicleIndex = v.getVehicleTypeIdentifier().getIndex(); + + //!!! open routes !!! + double routeEnd; + 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); + double slackTime = job.getMaxTimeInVehicle() - (routeEnd - actEndTime); + openDeliveries.put(job.getId(), slackTime); + } + + double minSlackTimeAtEnd = minSlackTime(openDeliveries); + stateManager.putRouteState(route, v, latestStartId, routeEnd + minSlackTimeAtEnd); + List acts = new ArrayList<>(this.route.getActivities()); + Collections.reverse(acts); + for (TourActivity act : acts) { + if (act instanceof ServiceActivity || act instanceof PickupActivity) { + String jobId = ((TourActivity.JobActivity) act).getJob().getId(); + openDeliveries.remove(jobId); + double minSlackTime = minSlackTime(openDeliveries); + double latestStart = actStart(act, v) + minSlackTime; + stateManager.putActivityState(act, v, latestStartId, 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); + } + double minSlackTime = minSlackTime(openDeliveries); + double latestStart = actStart(act, v) + minSlackTime; + stateManager.putActivityState(act, v, latestStartId, latestStart); + } + } + } + } + + private double actStart(TourActivity act, Vehicle v) { + return actStartTimes.get(v.getVehicleTypeIdentifier().getIndex()).get(act); + } + + private double minSlackTime(Map openDeliveries) { + double min = Double.MAX_VALUE; + for(Double value : openDeliveries.values()){ + if(value < min) min = value; + } + return min; + } +} 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 new file mode 100644 index 00000000..0effe3e0 --- /dev/null +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/constraint/MaxTimeInVehicleConstraint.java @@ -0,0 +1,108 @@ +/* + * Licensed to GraphHopper GmbH under one or more contributor + * license agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + * + * GraphHopper GmbH licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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.problem.cost.TransportTime; +import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts; +import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext; +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 java.util.Map; + +/** + * Created by schroeder on 15/09/16. + */ +public class MaxTimeInVehicleConstraint implements HardActivityConstraint { + + private final TransportTime transportTime; + + private final VehicleRoutingActivityCosts activityCosts; + + private final StateId latestStartId; + + private final StateManager stateManager; + + public MaxTimeInVehicleConstraint(TransportTime transportTime, VehicleRoutingActivityCosts activityCosts, StateId latestStartId, StateManager stateManager) { + this.transportTime = transportTime; + this.latestStartId = latestStartId; + this.stateManager = stateManager; + this.activityCosts = activityCosts; + } + + @Override + public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { + /* + 1. check whether insertion of new shipment satisfies own max-in-vehicle-constraint + 2. check whether insertion of new shipment satisfies all other max-in-vehicle-constraints + */ + //************ 1. check whether insertion of new shipment satisfies own max-in-vehicle-constraint + double newActArrival = prevActDepTime + transportTime.getTransportTime(prevAct.getLocation(),newAct.getLocation(),prevActDepTime,iFacts.getNewDriver(),iFacts.getNewVehicle()); + double newActStart = Math.max(newActArrival, newAct.getTheoreticalEarliestOperationStartTime()); + double newActDeparture = newActStart + activityCosts.getActivityDuration(newAct, newActArrival, iFacts.getNewDriver(), iFacts.getNewVehicle()); + double nextActArrival = newActDeparture + transportTime.getTransportTime(newAct.getLocation(),nextAct.getLocation(),newActDeparture,iFacts.getNewDriver(),iFacts.getNewVehicle()); + double nextActStart = Math.max(nextActArrival,nextAct.getTheoreticalEarliestOperationStartTime()); + if(newAct instanceof DeliveryActivity){ + double pickupEnd; + if(iFacts.getAssociatedActivities().size() == 1){ + pickupEnd = iFacts.getNewDepTime(); + } + else { + pickupEnd = iFacts.getRelatedActivityContext().getEndTime(); + } + double timeInVehicle = newActStart - pickupEnd; + double maxTimeInVehicle = ((TourActivity.JobActivity)newAct).getJob().getMaxTimeInVehicle(); + if(timeInVehicle > maxTimeInVehicle) return ConstraintsStatus.NOT_FULFILLED; + + } + else if(newAct instanceof PickupActivity){ + if(iFacts.getAssociatedActivities().size() == 1){ + double maxTimeInVehicle = ((TourActivity.JobActivity)newAct).getJob().getMaxTimeInVehicle(); + //ToDo - estimate in vehicle time of pickups here - This seems to trickier than I thought + double nextActDeparture = nextActStart + activityCosts.getActivityDuration(nextAct, nextActArrival, iFacts.getNewDriver(), iFacts.getNewVehicle()); +// if(!nextAct instanceof End) + double timeToEnd = 0; //newAct.end + tt(newAct,nextAct) + t@nextAct + t_to_end + if(timeToEnd > maxTimeInVehicle) return ConstraintsStatus.NOT_FULFILLED; + } + } + + //************ 2. check whether insertion of new shipment satisfies all other max-in-vehicle-constraints + + 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; + } + return ConstraintsStatus.FULFILLED; + } + +// private double getMaxTime(String jobId) { +// if(maxTimes.containsKey(jobId)) return maxTimes.get(jobId); +// else return Double.MAX_VALUE; +// } +} diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Delivery.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Delivery.java index d99e3c3e..f31b25ef 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Delivery.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Delivery.java @@ -41,6 +41,13 @@ public class Delivery extends Service { super(id); } + + public Builder setMaxTimeInVehicle(double maxTimeInVehicle){ + if(maxTimeInVehicle < 0) throw new IllegalArgumentException("maxTimeInVehicle should be positive"); + this.maxTimeInVehicle = maxTimeInVehicle; + return this; + } + /** * Builds Delivery. * diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Job.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Job.java index 161e3ee7..55728235 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Job.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Job.java @@ -62,4 +62,6 @@ public interface Job extends HasId, HasIndex { */ public int getPriority(); + public double getMaxTimeInVehicle(); + } diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Pickup.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Pickup.java index a30ff92b..2a893d5f 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Pickup.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Pickup.java @@ -41,6 +41,13 @@ public class Pickup extends Service { super(id); } + public Builder setMaxTimeInVehicle(double maxTimeInVehicle){ + throw new UnsupportedOperationException("maxTimeInVehicle is not yet supported for Pickups and Services (only for Deliveries and Shipments)"); +// if(maxTimeInVehicle < 0) throw new IllegalArgumentException("maxTimeInVehicle should be positive"); +// this.maxTimeInVehicle = maxTimeInVehicle; +// return this; + } + /** * Builds Pickup. *

diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Service.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Service.java index 38a496b6..72b3f473 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Service.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Service.java @@ -40,6 +40,8 @@ import java.util.Collection; */ public class Service extends AbstractJob { + + /** * Builder that builds a service. * @@ -90,6 +92,8 @@ public class Service extends AbstractJob { private int priority = 2; + protected double maxTimeInVehicle = Double.MAX_VALUE; + Builder(String id){ this.id = id; timeWindows = new TimeWindowsImpl(); @@ -224,6 +228,13 @@ public class Service extends AbstractJob { this.priority = priority; return this; } + + public Builder setMaxTimeInVehicle(double maxTimeInVehicle){ + throw new UnsupportedOperationException("maxTimeInVehicle is not yet supported for Pickups and Services (only for Deliveries and Shipments)"); +// if(maxTimeInVehicle < 0) throw new IllegalArgumentException("maxTimeInVehicle should be positive"); +// this.maxTimeInVehicle = maxTimeInVehicle; +// return this; + } } private final String id; @@ -246,6 +257,8 @@ public class Service extends AbstractJob { private final int priority; + private final double maxTimeInVehicle; + Service(Builder builder) { id = builder.id; serviceTime = builder.serviceTime; @@ -257,6 +270,7 @@ public class Service extends AbstractJob { location = builder.location; timeWindowManager = builder.timeWindows; priority = builder.priority; + maxTimeInVehicle = builder.maxTimeInVehicle; } public Collection getTimeWindows(){ @@ -370,4 +384,9 @@ public class Service extends AbstractJob { return priority; } + @Override + public double getMaxTimeInVehicle() { + return this.maxTimeInVehicle; + } + } diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Shipment.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Shipment.java index 3275e901..fa11607a 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Shipment.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/job/Shipment.java @@ -89,6 +89,8 @@ public class Shipment extends AbstractJob { private int priority = 2; + public double maxTimeInVehicle = Double.MAX_VALUE; + /** * Returns new instance of this builder. * @@ -281,6 +283,18 @@ public class Shipment extends AbstractJob { this.priority = priority; return this; } + + /** + * Sets maximal time the job can be in vehicle. + * + * @param maxTimeInVehicle + * @return + */ + public Builder setMaxTimeInVehicle(double maxTimeInVehicle){ + if(maxTimeInVehicle < 0) throw new IllegalArgumentException("maxTimeInVehicle should be positive"); + this.maxTimeInVehicle = maxTimeInVehicle; + return this; + } } private final String id; @@ -309,6 +323,8 @@ public class Shipment extends AbstractJob { private final int priority; + private final double maxTimeInVehicle; + Shipment(Builder builder) { this.id = builder.id; this.pickupServiceTime = builder.pickupServiceTime; @@ -323,6 +339,7 @@ public class Shipment extends AbstractJob { this.deliveryTimeWindows = builder.deliveryTimeWindows; this.pickupTimeWindows = builder.pickupTimeWindows; this.priority = builder.priority; + this.maxTimeInVehicle = builder.maxTimeInVehicle; } @Override @@ -440,4 +457,9 @@ public class Shipment extends AbstractJob { public int getPriority() { return priority; } + + @Override + public double getMaxTimeInVehicle() { + return maxTimeInVehicle; + } } 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 new file mode 100644 index 00000000..2c5444b2 --- /dev/null +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/MaxTimeInVehicle_IT.java @@ -0,0 +1,69 @@ +/* + * Licensed to GraphHopper GmbH under one or more contributor + * license agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + * + * GraphHopper GmbH licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.graphhopper.jsprit.core.algorithm; + +import com.graphhopper.jsprit.core.algorithm.box.Jsprit; +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.problem.Location; +import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; +import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager; +import com.graphhopper.jsprit.core.problem.constraint.MaxTimeInVehicleConstraint; +import com.graphhopper.jsprit.core.problem.job.Shipment; +import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution; +import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl; +import com.graphhopper.jsprit.core.reporting.SolutionPrinter; +import com.graphhopper.jsprit.core.util.Solutions; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by schroeder on 20/09/16. + */ +public class MaxTimeInVehicle_IT { + + @Test + public void test(){ + + Shipment s1 = Shipment.Builder.newInstance("s1").setPickupLocation(Location.newInstance(0,0)).setDeliveryLocation(Location.newInstance(100,0)).setDeliveryServiceTime(10) + .setMaxTimeInVehicle(90d) + .build(); + Shipment s2 = Shipment.Builder.newInstance("s2").setPickupLocation(Location.newInstance(0,0)).setDeliveryLocation(Location.newInstance(100,0)).setDeliveryServiceTime(10) + .setMaxTimeInVehicle(90d) + .build(); + + VehicleImpl v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0,0)).build(); + + VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addVehicle(v).addJob(s1).addJob(s2).build(); + + StateManager stateManager = new StateManager(vrp); + StateId id = stateManager.createStateId("max-time"); + stateManager.addStateUpdater(new UpdateMaxTimeInVehicle(stateManager,id,vrp.getTransportCosts(),vrp.getActivityCosts())); + + ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager); + constraintManager.addConstraint(new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts(),id,stateManager), ConstraintManager.Priority.CRITICAL); + + VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp).setStateAndConstraintManager(stateManager,constraintManager).buildAlgorithm(); + VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions()); + + Assert.assertEquals(400, solution.getCost(), 0.001); +// SolutionPrinter.print(vrp,solution, SolutionPrinter.Print.VERBOSE); + } +} 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 new file mode 100644 index 00000000..f39164d1 --- /dev/null +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/algorithm/state/UpdateMaxTimeInVehicleTest.java @@ -0,0 +1,203 @@ +/* + * Licensed to GraphHopper GmbH under one or more contributor + * license agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + * + * GraphHopper GmbH licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.graphhopper.jsprit.core.algorithm.state; + +import com.graphhopper.jsprit.core.problem.Location; +import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; +import com.graphhopper.jsprit.core.problem.job.Delivery; +import com.graphhopper.jsprit.core.problem.job.Pickup; +import com.graphhopper.jsprit.core.problem.job.Shipment; +import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute; +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 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. + */ +public class UpdateMaxTimeInVehicleTest { + + private VehicleRoute route; + + private VehicleRoute route2; + + private VehicleImpl vehicle; + + private VehicleImpl v; + + private VehicleImpl vehicle2; + + private VehicleRoutingProblem vrp; + + private com.graphhopper.jsprit.core.algorithm.state.UpdateMaxTimeInVehicle maxTimeInVehicleConstraint; + + private StateManager stateManager; + + private StateId latestStartId; + + @Before + public void doBefore() { + VehicleType type = VehicleTypeImpl.Builder.newInstance("t").build(); + + v = VehicleImpl.Builder.newInstance("v0").setStartLocation(Location.newInstance(0, 0)) + .setType(type).build(); + + vehicle = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0,0)) + .setEndLocation(Location.newInstance(0,50)).setType(type).build(); + + vehicle2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance(0,10)) + .setEndLocation(Location.newInstance(0,40)).setType(type).build(); + + Pickup service = Pickup.Builder.newInstance("s").setLocation(Location.newInstance(0, 10)).build(); + Pickup service2 = Pickup.Builder.newInstance("s2").setLocation(Location.newInstance(0, 20)).build(); + + Pickup service3 = Pickup.Builder.newInstance("s3").setLocation(Location.newInstance(0, 30)).build(); + Pickup service4 = Pickup.Builder.newInstance("s4").setLocation(Location.newInstance(0, 40)).build(); + + Delivery d1 = Delivery.Builder.newInstance("d1").setLocation(Location.newInstance(10,0)).build(); + + Shipment shipment = Shipment.Builder.newInstance("shipment").setPickupLocation(Location.newInstance(20,0)) + .setDeliveryLocation(Location.newInstance(40,0)) + .setMaxTimeInVehicle(20d) + .build(); + + Delivery d2 = Delivery.Builder.newInstance("d2").setLocation(Location.newInstance(30,0)).setServiceTime(10).build(); + + + vrp = VehicleRoutingProblem.Builder.newInstance().addVehicle(v).addVehicle(vehicle).addVehicle(vehicle2).addJob(service) + .addJob(service2).addJob(service3).addJob(service4) + .addJob(d1).addJob(shipment).addJob(d2) + .build(); + + route = VehicleRoute.Builder.newInstance(vehicle).setJobActivityFactory(vrp.getJobActivityFactory()) + .addService(service).addService(service2).addService(service3).addService(service4).build(); + + route2 = VehicleRoute.Builder.newInstance(v).setJobActivityFactory(vrp.getJobActivityFactory()) + .addDelivery(d1).addPickup(shipment).addDelivery(shipment).build(); + + stateManager = new StateManager(vrp); + stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(),vrp.getActivityCosts())); + stateManager.informInsertionStarts(Arrays.asList(route), null); + + latestStartId = stateManager.createStateId("slack-time-id"); + +// Map maxTimes = new HashMap<>(); +// maxTimes.put("s",40d); +// maxTimes.put("shipment",20d); + maxTimeInVehicleConstraint = new UpdateMaxTimeInVehicle(stateManager, latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts()); + maxTimeInVehicleConstraint.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() { + @Override + public Collection get(VehicleRoute route) { + return Arrays.asList((Vehicle)vehicle,(Vehicle)vehicle2,v); + } + }); + stateManager.addStateUpdater(maxTimeInVehicleConstraint); + } + +// @Test +// public void testVehicle(){ +// stateManager.informInsertionStarts(Arrays.asList(route), null); +// 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); +// Assert.assertEquals(40, slackTime, 0.001); +// } +// if(jobId.equals("s3")){ +// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), latestStartId,Double.class); +// Assert.assertEquals(30, slackTime, 0.001); +// } +// if(jobId.equals("s2")){ +// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), latestStartId,Double.class); +// Assert.assertEquals(20, slackTime, 0.001); +// } +// if(jobId.equals("s")){ +// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), latestStartId,Double.class); +// Assert.assertEquals(Double.MAX_VALUE, slackTime, 0.001); +// } +// } +// Double slackTime = stateManager.getRouteState(route,route.getVehicle(), latestStartId,Double.class); +// Assert.assertNotNull(slackTime); +// Assert.assertEquals(50,slackTime,0.001); +// } +// +// @Test +// public void testVehicle2(){ +// stateManager.informInsertionStarts(Arrays.asList(route), null); +// 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); +// Assert.assertEquals(40, slackTime, 0.001); +// } +// if(jobId.equals("s3")){ +// Double slackTime = stateManager.getActivityState(act,vehicle2, latestStartId,Double.class); +// Assert.assertEquals(30, slackTime, 0.001); +// } +// if(jobId.equals("s2")){ +// Double slackTime = stateManager.getActivityState(act,vehicle2, latestStartId,Double.class); +// Assert.assertEquals(20, slackTime, 0.001); +// } +// if(jobId.equals("s")){ +// Double slackTime = stateManager.getActivityState(act,vehicle2, latestStartId,Double.class); +// Assert.assertEquals(Double.MAX_VALUE, slackTime, 0.001); +// } +// } +// Double slackTime = stateManager.getRouteState(route,vehicle2, latestStartId,Double.class); +// Assert.assertNotNull(slackTime); +// Assert.assertEquals(40,slackTime,0.001); +// } + + @Test + public void testWithShipment(){ + stateManager.informInsertionStarts(Arrays.asList(route2), null); + 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); + 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); + Assert.assertEquals(Double.MAX_VALUE, slackTime, 0.001); + } + else{ + Double slackTime = stateManager.getActivityState(act,v, latestStartId,Double.class); + Assert.assertEquals(40, 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 new file mode 100644 index 00000000..c3495570 --- /dev/null +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/constraint/MaxTimeInVehicleConstraintTest.java @@ -0,0 +1,246 @@ +/* + * Licensed to GraphHopper GmbH under one or more contributor + * license agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + * + * GraphHopper GmbH licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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.problem.AbstractActivity; +import com.graphhopper.jsprit.core.problem.Location; +import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; +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.vehicle.Vehicle; +import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.*; + +/** + * Created by schroeder on 19/09/16. + */ +public class MaxTimeInVehicleConstraintTest { + + Delivery d1; + + Shipment shipment; + + Delivery d2; + + Pickup p1; + + Pickup p2; + + Vehicle v; + + VehicleRoute route; + + VehicleRoutingProblem vrp; + + @Before + public void doBefore(){ + + } + + private void ini(double maxTime){ + d1 = Delivery.Builder.newInstance("d1").setLocation(Location.newInstance(10,0)).build(); + shipment = Shipment.Builder.newInstance("shipment").setPickupLocation(Location.newInstance(20,0)) + .setDeliveryLocation(Location.newInstance(40,0)).setMaxTimeInVehicle(maxTime).build(); + d2 = Delivery.Builder.newInstance("d2").setLocation(Location.newInstance(30,0)).setServiceTime(10).build(); + + p1 = Pickup.Builder.newInstance("p1").setLocation(Location.newInstance(10, 0)).build(); + p2 = Pickup.Builder.newInstance("p2").setLocation(Location.newInstance(20,0)).build(); + + v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0,0)).build(); + + vrp = VehicleRoutingProblem.Builder.newInstance().addJob(d1).addJob(shipment).addJob(d2).addJob(p1).addJob(p2) + .addVehicle(v).build(); + + route = VehicleRoute.Builder.newInstance(v).setJobActivityFactory(vrp.getJobActivityFactory()) + .addDelivery(d1).addPickup(shipment).addDelivery(shipment).build(); + } + + @Test + public void insertingDeliveryAtAnyPositionShouldWork(){ + ini(30d); + StateManager stateManager = new StateManager(vrp); + StateId latestStartId = stateManager.createStateId("latest-start-id"); + + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts()); + stateManager.addStateUpdater(updater); + stateManager.informInsertionStarts(Arrays.asList(route),new ArrayList()); + + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager); + JobInsertionContext c = new JobInsertionContext(route,d2,v,route.getDriver(),0.); + List acts = vrp.getActivities(d2); + c.getAssociatedActivities().add(acts.get(0)); + + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getStart(), acts.get(0), route.getActivities().get(0), 0)); + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getActivities().get(0), acts.get(0), route.getActivities().get(1), 10)); + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getActivities().get(1), acts.get(0), route.getActivities().get(2), 20)); + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getActivities().get(2), acts.get(0), route.getEnd(), 40)); + + } + + @Test + public void insertingDeliveryInBetweenShipmentShouldFail(){ + ini(25d); + StateManager stateManager = new StateManager(vrp); + StateId latestStartId = stateManager.createStateId("latest-start-id"); + + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(),vrp.getActivityCosts()); + stateManager.addStateUpdater(updater); + stateManager.informInsertionStarts(Arrays.asList(route),new ArrayList()); + + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager); + JobInsertionContext c = new JobInsertionContext(route,d2,v,route.getDriver(),0.); + List acts = vrp.getActivities(d2); + c.getAssociatedActivities().add(acts.get(0)); + + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getStart(), acts.get(0), route.getActivities().get(0), 0)); + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getActivities().get(0), acts.get(0), route.getActivities().get(1), 10)); + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, route.getActivities().get(1), acts.get(0), route.getActivities().get(2), 20)); + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getActivities().get(2), acts.get(0), route.getEnd(), 40)); + } + + + + @Test + public void insertingPickupShipmentAtAnyPositionShouldWork(){ + ini(25d); + VehicleRoute r = VehicleRoute.Builder.newInstance(v).setJobActivityFactory(vrp.getJobActivityFactory()) + .addDelivery(d1).addDelivery(d2).build(); + + StateManager stateManager = new StateManager(vrp); + StateId latestStartId = stateManager.createStateId("latest-start-id"); + + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts()); + stateManager.addStateUpdater(updater); + stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList()); + + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager); + JobInsertionContext c = new JobInsertionContext(r,shipment,v,r.getDriver(),0.); + List acts = vrp.getActivities(shipment); + c.getAssociatedActivities().add(acts.get(0)); + c.getAssociatedActivities().add(acts.get(1)); + + + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, r.getStart(), acts.get(0), r.getActivities().get(0), 0)); + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, r.getActivities().get(0), acts.get(0), r.getActivities().get(1), 10)); + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, r.getActivities().get(1), acts.get(0), r.getEnd(), 40)); + } + +// @Test +// public void insertingPickupBeforeDeliveryShouldFail(){ +// VehicleRoute r = VehicleRoute.Builder.newInstance(v).setJobActivityFactory(vrp.getJobActivityFactory()) +// .addPickup(p1).addDelivery(d2).build(); +// +// StateManager stateManager = new StateManager(vrp); +// StateId latestStartId = stateManager.createStateId("latest-start-id"); +// +// Map maxTimes = new HashMap<>(); +// maxTimes.put("p2",30d); +// UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(),vrp.getActivityCosts()); +// stateManager.addStateUpdater(updater); +// stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList()); +// +// MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager); +// JobInsertionContext c = new JobInsertionContext(r,shipment,v,r.getDriver(),0.); +// List acts = vrp.getActivities(shipment); +// c.getAssociatedActivities().add(acts.get(0)); +// c.getAssociatedActivities().add(acts.get(1)); +// +// +// Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, r.getStart(), acts.get(0), r.getActivities().get(0), 0)); +// Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, r.getActivities().get(0), acts.get(0), r.getActivities().get(1), 10)); +// Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, r.getActivities().get(1), acts.get(0), r.getEnd(), 30)); +//// Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, r.getActivities().get(0), acts.get(0), r.getActivities().get(1), 10)); +//// Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, r.getActivities().get(1), acts.get(0), r.getEnd(), 40)); +// } + + @Test + public void whenPickupIsInsertedAt0_insertingDeliveryShipmentShouldFailWhereConstraintIsBroken(){ + ini(25d); + VehicleRoute r = VehicleRoute.Builder.newInstance(v).setJobActivityFactory(vrp.getJobActivityFactory()) + .addDelivery(d1).addDelivery(d2).build(); + + StateManager stateManager = new StateManager(vrp); + StateId latestStartId = stateManager.createStateId("latest-start-id"); + + Map maxTimes = new HashMap<>(); + maxTimes.put("shipment",25d); + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts()); + stateManager.addStateUpdater(updater); + stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList()); + + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager); + JobInsertionContext c = new JobInsertionContext(r,shipment,v,r.getDriver(),0.); + List acts = vrp.getActivities(shipment); + c.getAssociatedActivities().add(acts.get(0)); + c.getAssociatedActivities().add(acts.get(1)); + + ActivityContext ac = new ActivityContext(); + ac.setArrivalTime(20); + ac.setEndTime(20); + c.setRelatedActivityContext(ac); + + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, acts.get(0), acts.get(1), r.getActivities().get(0), 20)); + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, r.getActivities().get(0), acts.get(1), r.getActivities().get(1), 30)); + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, r.getActivities().get(1), acts.get(1), r.getEnd(), 40)); + } + + @Test + public void whenPickupIsInsertedAt1_insertingDeliveryShipmentShouldFailWhereConstraintIsBroken(){ + ini(25d); + VehicleRoute r = VehicleRoute.Builder.newInstance(v).setJobActivityFactory(vrp.getJobActivityFactory()) + .addDelivery(d1).addDelivery(d2).build(); + + StateManager stateManager = new StateManager(vrp); + StateId latestStartId = stateManager.createStateId("latest-start-id"); + + Map maxTimes = new HashMap<>(); + maxTimes.put("shipment",25d); + UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts()); + stateManager.addStateUpdater(updater); + stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList()); + + MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager); + JobInsertionContext c = new JobInsertionContext(r,shipment,v,r.getDriver(),0.); + List acts = vrp.getActivities(shipment); + c.getAssociatedActivities().add(acts.get(0)); + c.getAssociatedActivities().add(acts.get(1)); + + ActivityContext ac = new ActivityContext(); + ac.setArrivalTime(20); + ac.setEndTime(20); + c.setRelatedActivityContext(ac); + + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, acts.get(0), acts.get(1), r.getActivities().get(1), 20)); + Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, r.getActivities().get(1), acts.get(1), r.getEnd(), 40)); +// Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, r.getActivities().get(1), acts.get(1), r.getEnd(), 40)); + } +} diff --git a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/DeliveryTest.java b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/DeliveryTest.java index 0ab568c6..9b616a67 100644 --- a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/DeliveryTest.java +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/DeliveryTest.java @@ -103,5 +103,20 @@ public class DeliveryTest { Assert.assertEquals(2, s.getPriority()); } + @Test + public void whenAddingMaxTimeInVehicle_itShouldBeSet(){ + Delivery s = Delivery.Builder.newInstance("s").setLocation(Location.newInstance("loc")) + .setMaxTimeInVehicle(10) + .build(); + Assert.assertEquals(10, s.getMaxTimeInVehicle(),0.001); + } + + @Test + public void whenNotAddingMaxTimeInVehicle_itShouldBeDefault(){ + Delivery s = Delivery.Builder.newInstance("s").setLocation(Location.newInstance("loc")) + .build(); + Assert.assertEquals(Double.MAX_VALUE, s.getMaxTimeInVehicle(),0.001); + } + } diff --git a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/PickupTest.java b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/PickupTest.java index 6236536c..6e066d07 100644 --- a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/PickupTest.java +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/PickupTest.java @@ -105,4 +105,18 @@ public class PickupTest { Assert.assertEquals(2, s.getPriority()); } + @Test(expected = UnsupportedOperationException.class) + public void whenAddingMaxTimeInVehicle_itShouldThrowEx(){ + Pickup s = Pickup.Builder.newInstance("s").setLocation(Location.newInstance("loc")) + .setMaxTimeInVehicle(10) + .build(); + } + + @Test + public void whenNotAddingMaxTimeInVehicle_itShouldBeDefault(){ + Pickup s = Pickup.Builder.newInstance("s").setLocation(Location.newInstance("loc")) + .build(); + Assert.assertEquals(Double.MAX_VALUE, s.getMaxTimeInVehicle(),0.001); + } + } diff --git a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/ServiceTest.java b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/ServiceTest.java index bec514e2..8deda4ba 100644 --- a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/ServiceTest.java +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/ServiceTest.java @@ -271,4 +271,18 @@ public class ServiceTest { } + @Test(expected = UnsupportedOperationException.class) + public void whenAddingMaxTimeInVehicle_itShouldThrowEx(){ + Service s = Service.Builder.newInstance("s").setLocation(Location.newInstance("loc")) + .setMaxTimeInVehicle(10) + .build(); + } + + @Test + public void whenNotAddingMaxTimeInVehicle_itShouldBeDefault(){ + Service s = Service.Builder.newInstance("s").setLocation(Location.newInstance("loc")) + .build(); + Assert.assertEquals(Double.MAX_VALUE, s.getMaxTimeInVehicle(),0.001); + } + } diff --git a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/ShipmentTest.java b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/ShipmentTest.java index 6c463d04..c9df07c5 100644 --- a/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/ShipmentTest.java +++ b/jsprit-core/src/test/java/com/graphhopper/jsprit/core/problem/job/ShipmentTest.java @@ -425,4 +425,19 @@ public class ShipmentTest { } + @Test + public void whenAddingMaxTimeInVehicle_itShouldBeSet(){ + Shipment s = Shipment.Builder.newInstance("s").setPickupLocation(Location.newInstance("loc")).setDeliveryLocation(Location.newInstance("loc")) + .setMaxTimeInVehicle(10) + .build(); + Assert.assertEquals(10, s.getMaxTimeInVehicle(),0.001); + } + + @Test + public void whenNotAddingMaxTimeInVehicle_itShouldBeDefault(){ + Shipment s = Shipment.Builder.newInstance("s").setPickupLocation(Location.newInstance("loc")).setDeliveryLocation(Location.newInstance("loc")) + .build(); + Assert.assertEquals(Double.MAX_VALUE, s.getMaxTimeInVehicle(),0.001); + } + }