1
0
Fork 0
mirror of https://github.com/graphhopper/jsprit.git synced 2020-01-24 07:45:05 +01:00

improve max-time-in-vehicle

This commit is contained in:
oblonski 2017-11-08 16:10:39 +01:00
parent 3a5e42691b
commit e8fe642e16
No known key found for this signature in database
GPG key ID: 179DE487285680D1
5 changed files with 247 additions and 144 deletions

View file

@ -33,17 +33,19 @@ import java.util.*;
*/
public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{
private Map<Integer,Map<Job,Double>> openPickupEndTimes = new HashMap<>();
private Map<Integer, Map<Job, Double>> openPickupEndTimesPerVehicle = new HashMap<>();
private Map<Integer,Map<TourActivity,Double>> slackTimes = new HashMap<>();
private Map<Integer, Map<TourActivity, Double>> slackTimesPerVehicle = new HashMap<>();
private Map<Integer,Map<TourActivity,Double>> actStartTimes = new HashMap<>();
private Map<Integer, Map<TourActivity, Double>> actStartTimesPerVehicle = new HashMap<>();
private VehicleRoute route;
private final StateManager stateManager;
private final StateId latestStartId;
private final StateId minSlackId;
private final StateId openJobsId;
private double[] prevActEndTimes;
@ -65,9 +67,10 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{
};
public UpdateMaxTimeInVehicle(StateManager stateManager, StateId slackTimeId, TransportTime transportTime, VehicleRoutingActivityCosts activityCosts) {
public UpdateMaxTimeInVehicle(StateManager stateManager, StateId slackTimeId, TransportTime transportTime, VehicleRoutingActivityCosts activityCosts, StateId openJobsId) {
this.stateManager = stateManager;
this.latestStartId = slackTimeId;
this.minSlackId = slackTimeId;
this.openJobsId = openJobsId;
this.transportTime = transportTime;
prevActEndTimes = new double[stateManager.getMaxIndexOfVehicleTypeIdentifiers() + 1];
prevActLocations = new Location[stateManager.getMaxIndexOfVehicleTypeIdentifiers() + 1];
@ -82,16 +85,16 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{
@Override
public void begin(VehicleRoute route) {
openPickupEndTimes.clear();
slackTimes.clear();
actStartTimes.clear();
openPickupEndTimesPerVehicle.clear();
slackTimesPerVehicle.clear();
actStartTimesPerVehicle.clear();
vehicles = vehiclesToUpdate.get(route);
this.route = route;
for(Vehicle v : vehicles){
int vehicleIndex = v.getVehicleTypeIdentifier().getIndex();
openPickupEndTimes.put(vehicleIndex,new HashMap<Job, Double>());
slackTimes.put(vehicleIndex,new HashMap<TourActivity, Double>());
actStartTimes.put(vehicleIndex,new HashMap<TourActivity, Double>());
openPickupEndTimesPerVehicle.put(vehicleIndex, new HashMap<Job, Double>());
slackTimesPerVehicle.put(vehicleIndex, new HashMap<TourActivity, Double>());
actStartTimesPerVehicle.put(vehicleIndex, new HashMap<TourActivity, Double>());
prevActEndTimes[vehicleIndex] = v.getEarliestDeparture();
prevActLocations[vehicleIndex] = v.getStartLocation();
}
@ -109,7 +112,7 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{
double activityStart = Math.max(activityArrival,activity.getTheoreticalEarliestOperationStartTime());
memorizeActStart(activity,v,activityStart);
double activityEnd = activityStart + activityCosts.getActivityDuration(activity, activityArrival, route.getDriver(), v);
Map<Job, Double> openPickups = openPickupEndTimes.get(vehicleIndex);
Map<Job, Double> openPickups = openPickupEndTimesPerVehicle.get(vehicleIndex);
if (activity instanceof ServiceActivity || activity instanceof PickupActivity) {
openPickups.put(((TourActivity.JobActivity) activity).getJob(), activityEnd);
} else if (activity instanceof DeliveryActivity) {
@ -120,7 +123,7 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{
openPickups.remove(job);
} else pickupEnd = v.getEarliestDeparture();
double slackTime = maxTime - (activityStart - pickupEnd);
slackTimes.get(vehicleIndex).put(activity, slackTime);
slackTimesPerVehicle.get(vehicleIndex).put(activity, slackTime);
}
prevActLocations[vehicleIndex] = activity.getLocation();
prevActEndTimes[vehicleIndex] = activityEnd;
@ -136,16 +139,8 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{
return maxTime;
}
// private double getMaxTimeInVehicle(String jobId) {
// double maxTime = Double.MAX_VALUE;
// if(maxTimes.containsKey(jobId)){
// maxTime = maxTimes.get(jobId);
// }
// return maxTime;
// }
private void memorizeActStart(TourActivity activity, Vehicle v, double activityStart) {
actStartTimes.get(v.getVehicleTypeIdentifier().getIndex()).put(activity,activityStart);
actStartTimesPerVehicle.get(v.getVehicleTypeIdentifier().getIndex()).put(activity, activityStart);
}
@Override
@ -158,33 +153,35 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{
if(!v.isReturnToDepot()) routeEnd = prevActEndTimes[vehicleIndex];
else routeEnd = prevActEndTimes[vehicleIndex] + transportTime.getTransportTime(prevActLocations[vehicleIndex],v.getEndLocation(),prevActEndTimes[vehicleIndex],route.getDriver(),v);
Map<String, Double> openDeliveries = new HashMap<>();
for (Job job : openPickupEndTimes.get(vehicleIndex).keySet()) {
double actEndTime = openPickupEndTimes.get(vehicleIndex).get(job);
Map<Job, Double> openDeliveries = new HashMap<>();
for (Job job : openPickupEndTimesPerVehicle.get(vehicleIndex).keySet()) {
double actEndTime = openPickupEndTimesPerVehicle.get(vehicleIndex).get(job);
double slackTime = job.getMaxTimeInVehicle() - (routeEnd - actEndTime);
openDeliveries.put(job.getId(), slackTime);
openDeliveries.put(job, slackTime);
}
double minSlackTimeAtEnd = minSlackTime(openDeliveries);
stateManager.putRouteState(route, v, latestStartId, routeEnd + minSlackTimeAtEnd);
stateManager.putRouteState(route, v, minSlackId, minSlackTimeAtEnd);
stateManager.putRouteState(route, v, openJobsId, new HashMap<>(openDeliveries));
List<TourActivity> acts = new ArrayList<>(this.route.getActivities());
Collections.reverse(acts);
for (TourActivity act : acts) {
Job job = ((TourActivity.JobActivity) act).getJob();
if (act instanceof ServiceActivity || act instanceof PickupActivity) {
String jobId = ((TourActivity.JobActivity) act).getJob().getId();
openDeliveries.remove(jobId);
openDeliveries.remove(job);
double minSlackTime = minSlackTime(openDeliveries);
double latestStart = actStart(act, v) + minSlackTime;
stateManager.putActivityState(act, v, latestStartId, latestStart);
// double latestStart = actStart(act, v) + minSlackTime;
stateManager.putActivityState(act, v, openJobsId, new HashMap<>(openDeliveries));
stateManager.putActivityState(act, v, minSlackId, minSlackTime);
} else {
String jobId = ((TourActivity.JobActivity) act).getJob().getId();
if(slackTimes.get(vehicleIndex).containsKey(act)){
double slackTime = slackTimes.get(vehicleIndex).get(act);
openDeliveries.put(jobId,slackTime);
if (slackTimesPerVehicle.get(vehicleIndex).containsKey(act)) {
double slackTime = slackTimesPerVehicle.get(vehicleIndex).get(act);
openDeliveries.put(job, slackTime);
}
double minSlackTime = minSlackTime(openDeliveries);
double latestStart = actStart(act, v) + minSlackTime;
stateManager.putActivityState(act, v, latestStartId, latestStart);
// double latestStart = actStart(act, v) + minSlackTime;
stateManager.putActivityState(act, v, openJobsId, new HashMap<>(openDeliveries));
stateManager.putActivityState(act, v, minSlackId, minSlackTime);
}
}
}
@ -200,44 +197,44 @@ public class UpdateMaxTimeInVehicle implements StateUpdater, ActivityVisitor{
else
routeEnd = prevActEndTimes[vehicleIndex] + transportTime.getTransportTime(prevActLocations[vehicleIndex], v.getEndLocation(), prevActEndTimes[vehicleIndex], route.getDriver(), v);
Map<String, Double> openDeliveries = new HashMap<>();
for (Job job : openPickupEndTimes.get(vehicleIndex).keySet()) {
Map<Job, Double> openDeliveries = new HashMap<>();
for (Job job : openPickupEndTimesPerVehicle.get(vehicleIndex).keySet()) {
if (job == ignore) continue;
double actEndTime = openPickupEndTimes.get(vehicleIndex).get(job);
double actEndTime = openPickupEndTimesPerVehicle.get(vehicleIndex).get(job);
double slackTime = job.getMaxTimeInVehicle() - (routeEnd - actEndTime);
openDeliveries.put(job.getId(), slackTime);
openDeliveries.put(job, slackTime);
}
double minSlackTimeAtEnd = minSlackTime(openDeliveries);
stateManager.putRouteState(route, v, latestStartId, routeEnd + minSlackTimeAtEnd);
stateManager.putRouteState(route, v, minSlackId, routeEnd + minSlackTimeAtEnd);
List<TourActivity> acts = new ArrayList<>(activities);
Collections.reverse(acts);
for (TourActivity act : acts) {
Job job = ((TourActivity.JobActivity) act).getJob();
if (act instanceof ServiceActivity || act instanceof PickupActivity) {
String jobId = ((TourActivity.JobActivity) act).getJob().getId();
String jobId = job.getId();
openDeliveries.remove(jobId);
double minSlackTime = minSlackTime(openDeliveries);
double latestStart = actStart(act, v) + minSlackTime;
stateManager.putActivityState(act, v, latestStartId, latestStart);
stateManager.putActivityState(act, v, minSlackId, latestStart);
} else {
String jobId = ((TourActivity.JobActivity) act).getJob().getId();
if (slackTimes.get(vehicleIndex).containsKey(act)) {
double slackTime = slackTimes.get(vehicleIndex).get(act);
openDeliveries.put(jobId, slackTime);
if (slackTimesPerVehicle.get(vehicleIndex).containsKey(act)) {
double slackTime = slackTimesPerVehicle.get(vehicleIndex).get(act);
openDeliveries.put(job, slackTime);
}
double minSlackTime = minSlackTime(openDeliveries);
double latestStart = actStart(act, v) + minSlackTime;
stateManager.putActivityState(act, v, latestStartId, latestStart);
stateManager.putActivityState(act, v, minSlackId, latestStart);
}
}
}
}
private double actStart(TourActivity act, Vehicle v) {
return actStartTimes.get(v.getVehicleTypeIdentifier().getIndex()).get(act);
return actStartTimesPerVehicle.get(v.getVehicleTypeIdentifier().getIndex()).get(act);
}
private double minSlackTime(Map<String, Double> openDeliveries) {
private double minSlackTime(Map<Job, Double> openDeliveries) {
double min = Double.MAX_VALUE;
for(Double value : openDeliveries.values()){
if(value < min) min = value;

View file

@ -20,23 +20,19 @@ package com.graphhopper.jsprit.core.problem.constraint;
import com.graphhopper.jsprit.core.algorithm.state.StateId;
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
import com.graphhopper.jsprit.core.algorithm.state.UpdateMaxTimeInVehicle;
import com.graphhopper.jsprit.core.algorithm.state.UpdateVehicleDependentPracticalTimeWindows;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.cost.TransportTime;
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import com.graphhopper.jsprit.core.problem.job.Job;
import com.graphhopper.jsprit.core.problem.job.Shipment;
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
import com.graphhopper.jsprit.core.problem.solution.route.activity.DeliveryActivity;
import com.graphhopper.jsprit.core.problem.solution.route.activity.End;
import com.graphhopper.jsprit.core.problem.solution.route.activity.PickupActivity;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Collections;
import java.util.Map;
/**
* Created by schroeder on 15/09/16.
@ -49,16 +45,19 @@ public class MaxTimeInVehicleConstraint implements HardActivityConstraint {
private final VehicleRoutingActivityCosts activityCosts;
private final StateId latestStartId;
private final StateId minSlackId;
private final StateId openJobsId;
private final StateManager stateManager;
public MaxTimeInVehicleConstraint(TransportTime transportTime, VehicleRoutingActivityCosts activityCosts, StateId latestStartId, StateManager stateManager, VehicleRoutingProblem vrp) {
public MaxTimeInVehicleConstraint(TransportTime transportTime, VehicleRoutingActivityCosts activityCosts, StateId minSlackId, StateManager stateManager, VehicleRoutingProblem vrp, StateId openJobsId) {
this.transportTime = transportTime;
this.latestStartId = latestStartId;
this.minSlackId = minSlackId;
this.stateManager = stateManager;
this.activityCosts = activityCosts;
this.vrp = vrp;
this.openJobsId = openJobsId;
}
@Override
@ -102,53 +101,101 @@ public class MaxTimeInVehicleConstraint implements HardActivityConstraint {
//************ 2. check whether insertion of new shipment satisfies all other max-in-vehicle-constraints
if(newActIsPickup || iFacts.getAssociatedActivities().size() == 1) {
double latest;
if (iFacts.getRoute().isEmpty()) latest = Double.MAX_VALUE;
else if (nextAct instanceof End) {
latest = stateManager.getRouteState(iFacts.getRoute(), iFacts.getNewVehicle(), latestStartId, Double.class);
} else latest = stateManager.getActivityState(nextAct, iFacts.getNewVehicle(), latestStartId, Double.class);
if (nextActStart > latest) {
return ConstraintsStatus.NOT_FULFILLED;
}
} else {
boolean isShipment = iFacts.getAssociatedActivities().size() == 2;
if (newActIsDelivery && isShipment) {
StateManager localStateManager = new StateManager(vrp);
StateId stateId = localStateManager.createStateId("local-slack");
UpdateMaxTimeInVehicle updateMaxTimeInVehicle = new UpdateMaxTimeInVehicle(localStateManager, stateId, transportTime, activityCosts);
updateMaxTimeInVehicle.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() {
@Override
public Collection<Vehicle> get(VehicleRoute route) {
return Arrays.asList(iFacts.getNewVehicle());
double minSlack = Double.MAX_VALUE;
if (!(nextAct instanceof End)) {
minSlack = stateManager.getActivityState(nextAct, iFacts.getNewVehicle(), minSlackId, Double.class);
}
double directArrTimeNextAct = prevActDepTime + transportTime.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double directNextActStart = Math.max(directArrTimeNextAct, nextAct.getTheoreticalEarliestOperationStartTime());
double additionalTimeOfNewAct = (nextActStart - prevActDepTime) - (directNextActStart - prevActDepTime);
if (additionalTimeOfNewAct > minSlack) {
if (newActIsPickup) return ConstraintsStatus.NOT_FULFILLED_BREAK;
else return ConstraintsStatus.NOT_FULFILLED;
}
if (newActIsDelivery) {
Map<Job, Double> openJobsAtNext;
if (nextAct instanceof End)
openJobsAtNext = stateManager.getRouteState(iFacts.getRoute(), iFacts.getNewVehicle(), openJobsId, Map.class);
else openJobsAtNext = stateManager.getActivityState(nextAct, iFacts.getNewVehicle(), openJobsId, Map.class);
if (openJobsAtNext == null) openJobsAtNext = Collections.emptyMap();
for (Job openJob : openJobsAtNext.keySet()) {
double slack = openJobsAtNext.get(openJob);
double additionalTimeOfNewJob = additionalTimeOfNewAct;
if (openJob instanceof Shipment) {
Map<Job, Double> openJobsAtNextOfPickup = Collections.emptyMap();
TourActivity nextAfterPickup;
if (iFacts.getAssociatedActivities().size() == 1 && !iFacts.getRoute().isEmpty())
nextAfterPickup = iFacts.getRoute().getActivities().get(0);
else
nextAfterPickup = iFacts.getRoute().getActivities().get(iFacts.getRelatedActivityContext().getInsertionIndex());
if (nextAfterPickup != null)
openJobsAtNextOfPickup = stateManager.getActivityState(nextAfterPickup, iFacts.getNewVehicle(), openJobsId, Map.class);
if (openJobsAtNextOfPickup.containsKey(openJob)) {
TourActivity pickupAct = iFacts.getAssociatedActivities().get(0);
double pickupActArrTime = iFacts.getRelatedActivityContext().getArrivalTime();
double pickupActEndTime = startOf(pickupAct, pickupActArrTime) + activityCosts.getActivityDuration(pickupAct, pickupActArrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double nextAfterPickupArr = pickupActEndTime + transportTime.getTransportTime(pickupAct.getLocation(), nextAfterPickup.getLocation(), pickupActArrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
additionalTimeOfNewJob += startOf(nextAfterPickup, nextAfterPickupArr) - startOf(nextAfterPickup, nextAfterPickup.getArrTime());
}
});
updateMaxTimeInVehicle.begin(iFacts.getRoute());
List<TourActivity> tourActivities = new ArrayList<>(iFacts.getRoute().getActivities());
tourActivities.add(iFacts.getRelatedActivityContext().getInsertionIndex(), iFacts.getAssociatedActivities().get(0));
for (TourActivity act : tourActivities) {
updateMaxTimeInVehicle.visit(act);
}
updateMaxTimeInVehicle.finish(tourActivities, iFacts.getJob());
double latest;
if (iFacts.getRoute().isEmpty()) latest = Double.MAX_VALUE;
else if (nextAct instanceof End) {
latest = localStateManager.getRouteState(iFacts.getRoute(), iFacts.getNewVehicle(), stateId, Double.class);
} else
latest = localStateManager.getActivityState(nextAct, iFacts.getNewVehicle(), stateId, Double.class);
if (nextActStart > latest) {
if (additionalTimeOfNewJob > slack) {
return ConstraintsStatus.NOT_FULFILLED;
}
}
}
// if(newActIsPickup || iFacts.getAssociatedActivities().size() == 1) {
// double latest;
// if (iFacts.getRoute().isEmpty()) latest = Double.MAX_VALUE;
// else if (nextAct instanceof End) {
// latest = stateManager.getRouteState(iFacts.getRoute(), iFacts.getNewVehicle(), latestStartId, Double.class);
// } else latest = stateManager.getActivityState(nextAct, iFacts.getNewVehicle(), latestStartId, Double.class);
//
// if (nextActStart > latest) {
// return ConstraintsStatus.NOT_FULFILLED;
// }
//
// } else {
// boolean isShipment = iFacts.getAssociatedActivities().size() == 2;
// if (newActIsDelivery && isShipment) {
// StateManager localStateManager = new StateManager(vrp);
// StateId stateId = localStateManager.createStateId("local-slack");
// UpdateMaxTimeInVehicle updateMaxTimeInVehicle = new UpdateMaxTimeInVehicle(localStateManager, stateId, transportTime, activityCosts);
// updateMaxTimeInVehicle.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() {
// @Override
// public Collection<Vehicle> get(VehicleRoute route) {
// return Arrays.asList(iFacts.getNewVehicle());
// }
// });
// updateMaxTimeInVehicle.begin(iFacts.getRoute());
// List<TourActivity> tourActivities = new ArrayList<>(iFacts.getRoute().getActivities());
// tourActivities.add(iFacts.getRelatedActivityContext().getInsertionIndex(), iFacts.getAssociatedActivities().get(0));
// for (TourActivity act : tourActivities) {
// updateMaxTimeInVehicle.visit(act);
// }
// updateMaxTimeInVehicle.finish(tourActivities, iFacts.getJob());
//
// double latest;
// if (iFacts.getRoute().isEmpty()) latest = Double.MAX_VALUE;
// else if (nextAct instanceof End) {
// latest = localStateManager.getRouteState(iFacts.getRoute(), iFacts.getNewVehicle(), stateId, Double.class);
// } else
// latest = localStateManager.getActivityState(nextAct, iFacts.getNewVehicle(), stateId, Double.class);
//
// if (nextActStart > latest) {
// return ConstraintsStatus.NOT_FULFILLED;
// }
//
// }
// }
return ConstraintsStatus.FULFILLED;
}
private double startOf(TourActivity act, double arrTime) {
return Math.max(arrTime, act.getTheoreticalEarliestOperationStartTime());
}
// private double getMaxTime(String jobId) {
// if(maxTimes.containsKey(jobId)) return maxTimes.get(jobId);
// else return Double.MAX_VALUE;

View file

@ -54,10 +54,11 @@ public class MaxTimeInVehicle_IT {
StateManager stateManager = new StateManager(vrp);
StateId id = stateManager.createStateId("max-time");
stateManager.addStateUpdater(new UpdateMaxTimeInVehicle(stateManager,id,vrp.getTransportCosts(),vrp.getActivityCosts()));
StateId openJobsId = stateManager.createStateId("open-jobs-id");
stateManager.addStateUpdater(new UpdateMaxTimeInVehicle(stateManager, id, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId));
ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
constraintManager.addConstraint(new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts(),id,stateManager, vrp), ConstraintManager.Priority.CRITICAL);
constraintManager.addConstraint(new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), id, stateManager, vrp, openJobsId), ConstraintManager.Priority.CRITICAL);
VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp).setStateAndConstraintManager(stateManager,constraintManager).buildAlgorithm();
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());

View file

@ -30,15 +30,12 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleType;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeImpl;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* Created by schroeder on 15/09/16.
@ -61,7 +58,9 @@ public class UpdateMaxTimeInVehicleTest {
private StateManager stateManager;
private StateId latestStartId;
private StateId minSlackId;
private StateId openJobsId;
@Before
public void doBefore() {
@ -107,12 +106,13 @@ public class UpdateMaxTimeInVehicleTest {
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(),vrp.getActivityCosts()));
stateManager.informInsertionStarts(Arrays.asList(route), null);
latestStartId = stateManager.createStateId("slack-time-id");
minSlackId = stateManager.createStateId("min-slack-id");
openJobsId = stateManager.createStateId("open-jobs-id");
// Map<String,Double> maxTimes = new HashMap<>();
// maxTimes.put("s",40d);
// maxTimes.put("shipment",20d);
maxTimeInVehicleConstraint = new UpdateMaxTimeInVehicle(stateManager, latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts());
maxTimeInVehicleConstraint = new UpdateMaxTimeInVehicle(stateManager, minSlackId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId);
maxTimeInVehicleConstraint.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() {
@Override
public Collection<Vehicle> get(VehicleRoute route) {
@ -128,23 +128,23 @@ public class UpdateMaxTimeInVehicleTest {
// for(TourActivity act : route.getActivities()){
// String jobId = ((TourActivity.JobActivity)act).getJob().getId();
// if(jobId.equals("s4")){
// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), latestStartId,Double.class);
// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), minSlackId,Double.class);
// Assert.assertEquals(40, slackTime, 0.001);
// }
// if(jobId.equals("s3")){
// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), latestStartId,Double.class);
// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), minSlackId,Double.class);
// Assert.assertEquals(30, slackTime, 0.001);
// }
// if(jobId.equals("s2")){
// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), latestStartId,Double.class);
// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), minSlackId,Double.class);
// Assert.assertEquals(20, slackTime, 0.001);
// }
// if(jobId.equals("s")){
// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), latestStartId,Double.class);
// Double slackTime = stateManager.getActivityState(act,route.getVehicle(), minSlackId,Double.class);
// Assert.assertEquals(Double.MAX_VALUE, slackTime, 0.001);
// }
// }
// Double slackTime = stateManager.getRouteState(route,route.getVehicle(), latestStartId,Double.class);
// Double slackTime = stateManager.getRouteState(route,route.getVehicle(), minSlackId,Double.class);
// Assert.assertNotNull(slackTime);
// Assert.assertEquals(50,slackTime,0.001);
// }
@ -155,23 +155,23 @@ public class UpdateMaxTimeInVehicleTest {
// for(TourActivity act : route.getActivities()){
// String jobId = ((TourActivity.JobActivity)act).getJob().getId();
// if(jobId.equals("s4")){
// Double slackTime = stateManager.getActivityState(act,vehicle2, latestStartId,Double.class);
// Double slackTime = stateManager.getActivityState(act,vehicle2, minSlackId,Double.class);
// Assert.assertEquals(40, slackTime, 0.001);
// }
// if(jobId.equals("s3")){
// Double slackTime = stateManager.getActivityState(act,vehicle2, latestStartId,Double.class);
// Double slackTime = stateManager.getActivityState(act,vehicle2, minSlackId,Double.class);
// Assert.assertEquals(30, slackTime, 0.001);
// }
// if(jobId.equals("s2")){
// Double slackTime = stateManager.getActivityState(act,vehicle2, latestStartId,Double.class);
// Double slackTime = stateManager.getActivityState(act,vehicle2, minSlackId,Double.class);
// Assert.assertEquals(20, slackTime, 0.001);
// }
// if(jobId.equals("s")){
// Double slackTime = stateManager.getActivityState(act,vehicle2, latestStartId,Double.class);
// Double slackTime = stateManager.getActivityState(act,vehicle2, minSlackId,Double.class);
// Assert.assertEquals(Double.MAX_VALUE, slackTime, 0.001);
// }
// }
// Double slackTime = stateManager.getRouteState(route,vehicle2, latestStartId,Double.class);
// Double slackTime = stateManager.getRouteState(route,vehicle2, minSlackId,Double.class);
// Assert.assertNotNull(slackTime);
// Assert.assertEquals(40,slackTime,0.001);
// }
@ -182,17 +182,17 @@ public class UpdateMaxTimeInVehicleTest {
for(TourActivity act : route2.getActivities()){
String jobId = ((TourActivity.JobActivity)act).getJob().getId();
if(jobId.equals("d1")){
Double slackTime = stateManager.getActivityState(act,v, latestStartId,Double.class);
Double slackTime = stateManager.getActivityState(act, v, minSlackId, Double.class);
Assert.assertEquals(Double.MAX_VALUE, slackTime, 0.001);
}
if(jobId.equals("shipment")){
if(act instanceof PickupActivity){
Double slackTime = stateManager.getActivityState(act,v, latestStartId,Double.class);
Double slackTime = stateManager.getActivityState(act, v, minSlackId, Double.class);
Assert.assertEquals(Double.MAX_VALUE, slackTime, 0.001);
}
else{
Double slackTime = stateManager.getActivityState(act,v, latestStartId,Double.class);
Assert.assertEquals(40, slackTime, 0.001);
Double slackTime = stateManager.getActivityState(act, v, minSlackId, Double.class);
Assert.assertEquals(0, slackTime, 0.001);
}
}

View file

@ -20,6 +20,7 @@ package com.graphhopper.jsprit.core.problem.constraint;
import com.graphhopper.jsprit.core.algorithm.state.StateId;
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
import com.graphhopper.jsprit.core.algorithm.state.UpdateActivityTimes;
import com.graphhopper.jsprit.core.algorithm.state.UpdateMaxTimeInVehicle;
import com.graphhopper.jsprit.core.problem.AbstractActivity;
import com.graphhopper.jsprit.core.problem.Location;
@ -112,13 +113,15 @@ public class MaxTimeInVehicleConstraintTest {
.addPickup(s1).addDelivery(s1).build();
StateManager stateManager = new StateManager(vrp);
StateId latestStartId = stateManager.createStateId("latest-start-id");
StateId minSlackId = stateManager.createStateId("min-slack-id");
StateId openJobsId = stateManager.createStateId("open-jobs-id");
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts());
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, minSlackId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId);
stateManager.addStateUpdater(updater);
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts()));
stateManager.informInsertionStarts(Arrays.asList(route),new ArrayList<Job>());
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp);
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), minSlackId, stateManager, vrp, openJobsId);
JobInsertionContext c = new JobInsertionContext(route,s2,v,route.getDriver(),0.);
List<AbstractActivity> acts = vrp.getActivities(s2);
@ -126,7 +129,7 @@ public class MaxTimeInVehicleConstraintTest {
c.getAssociatedActivities().add(acts.get(1));
Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getStart(), acts.get(0), route.getActivities().get(0), 0));
Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, act(route,0), acts.get(0), act(route,1), 20));
Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED_BREAK, constraint.fulfilled(c, act(route, 0), acts.get(0), act(route, 1), 20));
Assert.assertEquals(HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, act(route,1), acts.get(0), route.getEnd(), 40));
//insert pickup at 0
@ -148,12 +151,14 @@ public class MaxTimeInVehicleConstraintTest {
ini(30d, Double.MAX_VALUE, Double.MAX_VALUE);
StateManager stateManager = new StateManager(vrp);
StateId latestStartId = stateManager.createStateId("latest-start-id");
StateId openJobsId = stateManager.createStateId("open-jobs-id");
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts());
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId);
stateManager.addStateUpdater(updater);
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts()));
stateManager.informInsertionStarts(Arrays.asList(route),new ArrayList<Job>());
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp);
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId);
JobInsertionContext c = new JobInsertionContext(route,d2,v,route.getDriver(),0.);
List<AbstractActivity> acts = vrp.getActivities(d2);
c.getAssociatedActivities().add(acts.get(0));
@ -165,24 +170,67 @@ public class MaxTimeInVehicleConstraintTest {
}
@Test
public void insertingD2JustAfterStartShouldWork() {
ini(20d, 30, Double.MAX_VALUE);
StateManager stateManager = new StateManager(vrp);
StateId latestStartId = stateManager.createStateId("latest-start-id");
StateId openJobsId = stateManager.createStateId("open-jobs-id");
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId);
stateManager.addStateUpdater(updater);
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts()));
stateManager.informInsertionStarts(Arrays.asList(route), new ArrayList<Job>());
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId);
JobInsertionContext c = new JobInsertionContext(route, d2, v, route.getDriver(), 0.);
List<AbstractActivity> acts = vrp.getActivities(d2);
c.getAssociatedActivities().add(acts.get(0));
Assert.assertEquals("inserting d2 just after start should work", HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getStart(), acts.get(0), route.getActivities().get(0), 0));
}
@Test
public void insertingD2AfterFirstDeliveryShouldWork() {
ini(20d, 30, Double.MAX_VALUE);
StateManager stateManager = new StateManager(vrp);
StateId latestStartId = stateManager.createStateId("latest-start-id");
StateId openJobsId = stateManager.createStateId("open-jobs-id");
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId);
stateManager.addStateUpdater(updater);
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts()));
stateManager.informInsertionStarts(Arrays.asList(route), new ArrayList<Job>());
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId);
JobInsertionContext c = new JobInsertionContext(route, d2, v, route.getDriver(), 0.);
List<AbstractActivity> acts = vrp.getActivities(d2);
c.getAssociatedActivities().add(acts.get(0));
Assert.assertEquals("inserting d2 after first delivery should work", HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getActivities().get(0), acts.get(0), route.getActivities().get(1), 10));
}
@Test
public void insertingDeliveryInBetweenShipmentShouldFail(){
ini(20d, 30, Double.MAX_VALUE);
StateManager stateManager = new StateManager(vrp);
StateId latestStartId = stateManager.createStateId("latest-start-id");
StateId openJobsId = stateManager.createStateId("open-jobs-id");
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(),vrp.getActivityCosts());
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId);
stateManager.addStateUpdater(updater);
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts()));
stateManager.informInsertionStarts(Arrays.asList(route),new ArrayList<Job>());
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp);
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId);
JobInsertionContext c = new JobInsertionContext(route,d2,v,route.getDriver(),0.);
List<AbstractActivity> acts = vrp.getActivities(d2);
c.getAssociatedActivities().add(acts.get(0));
Assert.assertEquals("inserting d2 just after start should work", HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getStart(), acts.get(0), route.getActivities().get(0), 0));
Assert.assertEquals("inserting d2 after first delivery should work", HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, route.getActivities().get(0), acts.get(0), route.getActivities().get(1), 10));
Assert.assertEquals("inserting d2 between pickup and delivery shipment should fail due to max-in-vehicle constraint of shipment", HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, route.getActivities().get(1), acts.get(0), route.getActivities().get(2), 20));
Assert.assertEquals("inserting d2 at end should fail", HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, route.getActivities().get(2), acts.get(0), route.getEnd(), 40));
}
@ -197,12 +245,14 @@ public class MaxTimeInVehicleConstraintTest {
StateManager stateManager = new StateManager(vrp);
StateId latestStartId = stateManager.createStateId("latest-start-id");
StateId openJobsId = stateManager.createStateId("open-jobs-id");
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts());
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId);
stateManager.addStateUpdater(updater);
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts()));
stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList<Job>());
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp);
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId);
JobInsertionContext c = new JobInsertionContext(r, s1,v,r.getDriver(),0.);
List<AbstractActivity> acts = vrp.getActivities(s1);
c.getAssociatedActivities().add(acts.get(0));
@ -223,12 +273,14 @@ public class MaxTimeInVehicleConstraintTest {
StateManager stateManager = new StateManager(vrp);
StateId latestStartId = stateManager.createStateId("latest-start-id");
StateId openJobsId = stateManager.createStateId("open-jobs-id");
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts());
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId);
stateManager.addStateUpdater(updater);
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts()));
stateManager.informInsertionStarts(Arrays.asList(r), new ArrayList<Job>());
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp);
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId);
JobInsertionContext c = new JobInsertionContext(r, s1, v, r.getDriver(), 0.);
List<AbstractActivity> acts = vrp.getActivities(s1);
c.getAssociatedActivities().add(acts.get(0));
@ -250,18 +302,20 @@ public class MaxTimeInVehicleConstraintTest {
StateManager stateManager = new StateManager(vrp);
StateId latestStartId = stateManager.createStateId("latest-start-id");
StateId openJobsId = stateManager.createStateId("open-jobs-id");
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts());
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId);
stateManager.addStateUpdater(updater);
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts()));
stateManager.informInsertionStarts(Arrays.asList(r), new ArrayList<Job>());
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp);
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId);
JobInsertionContext c = new JobInsertionContext(r, s1, v, r.getDriver(), 0.);
List<AbstractActivity> acts = vrp.getActivities(s1);
c.getAssociatedActivities().add(acts.get(0));
c.getAssociatedActivities().add(acts.get(1));
Assert.assertEquals("pickup shipment cannot happen at first pos. since d2 has max in-vehicle time", HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED, constraint.fulfilled(c, r.getStart(), acts.get(0), r.getActivities().get(0), 0));
Assert.assertEquals("pickup shipment cannot happen at first pos. since d2 has max in-vehicle time", HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED_BREAK, constraint.fulfilled(c, r.getStart(), acts.get(0), r.getActivities().get(0), 0));
Assert.assertEquals("pickup shipment can happen at second pos.", HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, r.getActivities().get(0), acts.get(0), r.getActivities().get(1), 10));
Assert.assertEquals("d2 has been delivered so pickup shipment is possible", HardActivityConstraint.ConstraintsStatus.FULFILLED, constraint.fulfilled(c, r.getActivities().get(1), acts.get(0), r.getEnd(), 30));
}
@ -308,12 +362,14 @@ public class MaxTimeInVehicleConstraintTest {
StateManager stateManager = new StateManager(vrp);
StateId latestStartId = stateManager.createStateId("latest-start-id");
StateId openJobsId = stateManager.createStateId("open-jobs-id");
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts());
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId);
stateManager.addStateUpdater(updater);
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts()));
stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList<Job>());
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp);
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId);
JobInsertionContext c = new JobInsertionContext(r, s1,v,r.getDriver(),0.);
List<AbstractActivity> acts = vrp.getActivities(s1);
c.getAssociatedActivities().add(acts.get(0));
@ -337,14 +393,16 @@ public class MaxTimeInVehicleConstraintTest {
StateManager stateManager = new StateManager(vrp);
StateId latestStartId = stateManager.createStateId("latest-start-id");
StateId openJobsId = stateManager.createStateId("open-jobs-id");
Map<String,Double> maxTimes = new HashMap<>();
maxTimes.put("s1",25d);
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager,latestStartId,vrp.getTransportCosts(), vrp.getActivityCosts());
UpdateMaxTimeInVehicle updater = new UpdateMaxTimeInVehicle(stateManager, latestStartId, vrp.getTransportCosts(), vrp.getActivityCosts(), openJobsId);
stateManager.addStateUpdater(updater);
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), vrp.getActivityCosts()));
stateManager.informInsertionStarts(Arrays.asList(r),new ArrayList<Job>());
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(),vrp.getActivityCosts() , latestStartId, stateManager, vrp);
MaxTimeInVehicleConstraint constraint = new MaxTimeInVehicleConstraint(vrp.getTransportCosts(), vrp.getActivityCosts(), latestStartId, stateManager, vrp, openJobsId);
JobInsertionContext c = new JobInsertionContext(r, s1,v,r.getDriver(),0.);
List<AbstractActivity> acts = vrp.getActivities(s1);
c.getAssociatedActivities().add(acts.get(0));