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

Merge pull request #16 from bringg/merge_gh1

Merge gh1
This commit is contained in:
kobyb 2018-01-21 10:12:48 +02:00 committed by GitHub
commit 6750969700
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 305 additions and 204 deletions

View file

@ -13,11 +13,11 @@ jsprit is a multi-module project and consists of:
If you want to use the latest release of jsprit-core, add the following lines to your pom:
```
<dependency>
<groupId>com.graphhopper</groupId>
<artifactId>jsprit-core</artifactId>
<version>{version}</version>
</dependency>
<dependency>
<groupId>com.graphhopper</groupId>
<artifactId>jsprit-core</artifactId>
<version>{version}</version>
</dependency>
```
Find the latest versions here: [mvn repository](https://mvnrepository.com/artifact/com.graphhopper/jsprit-core)

View file

@ -15,6 +15,9 @@ VROOM is an optimization engine written in C++14 that aim at providing good solu
#### [Hipster4j](http://www.hipster4j.org/)
Hipster is an easy to use yet powerful and flexible type-safe library for heuristic search, written in pure Java. It relies on a flexible model with generic operators to define search problems. So you can also model and solve vehicle routing problems.
#### [OscaR](https://bitbucket.org/oscarlib/oscar/wiki/Home)
OscaR, an Open Source Toolbox for Optimising Logistics and Supply Chain Systems.
### Territory Design
#### [OpenDoorLogistics](http://www.opendoorlogistics.com)
@ -23,4 +26,4 @@ standalone open source application for performing geographic analysis of your cu
If you know another promising open source implementation, report it.
If you know another promising open source implementation, report it.

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(null, 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

@ -232,9 +232,9 @@ public class VehicleRoutingProblem {
*/
public Builder addJob(AbstractJob job) {
if (tentativeJobs.containsKey(job.getId()))
throw new IllegalArgumentException("vehicle routing problem already contains a service or shipment with id " + job.getId() + ". make sure you use unique ids for all services and shipments");
throw new IllegalArgumentException("The vehicle routing problem already contains a service or shipment with id " + job.getId() + ". Please make sure you use unique ids for all services and shipments.");
if (!(job instanceof Service || job instanceof Shipment))
throw new IllegalArgumentException("job must be either a service or a shipment");
throw new IllegalArgumentException("Job must be either a service or a shipment.");
job.setIndex(jobIndexCounter);
incJobIndexCounter();
tentativeJobs.put(job.getId(), job);
@ -285,10 +285,11 @@ public class VehicleRoutingProblem {
for (Vehicle v : uniqueVehicles) {
if (v.getBreak() != null) {
if (!uniqueBreakIds.add(v.getBreak().getId()))
throw new IllegalArgumentException("problem already contains a vehicle break with id " + v.getBreak().getId() + ". choose unique ids for each vehicle break.");
throw new IllegalArgumentException("The vehicle routing roblem already contains a vehicle break with id " + v.getBreak().getId() + ". Please choose unique ids for each vehicle break.");
hasBreaks = true;
List<AbstractActivity> breakActivities = jobActivityFactory.createActivities(v.getBreak());
if(breakActivities.isEmpty()) throw new IllegalArgumentException("at least one activity for break needs to be created by activityFactory");
if (breakActivities.isEmpty())
throw new IllegalArgumentException("At least one activity for break needs to be created by activityFactory.");
for(AbstractActivity act : breakActivities){
act.setIndex(activityIndexCounter);
incActivityIndexCounter();
@ -351,7 +352,7 @@ public class VehicleRoutingProblem {
private void addShipment(Shipment job) {
if (jobs.containsKey(job.getId())) {
logger.warn("job " + job + " already in job list. overrides existing job.");
logger.warn("The job " + job + " has already been added to the job list. This overrides the existing job.");
}
addLocationToTentativeLocations(job);
// tentative_coordinates.put(job.getPickupLocation().getId(), job.getPickupLocation().getCoordinate());
@ -367,7 +368,7 @@ public class VehicleRoutingProblem {
* */
public Builder addVehicle(Vehicle vehicle) {
if (!(vehicle instanceof AbstractVehicle))
throw new IllegalArgumentException("vehicle must be an AbstractVehicle");
throw new IllegalArgumentException("A vehicle must be an AbstractVehicle.");
return addVehicle((AbstractVehicle) vehicle);
}
@ -379,7 +380,7 @@ public class VehicleRoutingProblem {
*/
public Builder addVehicle(AbstractVehicle vehicle) {
if(addedVehicleIds.contains(vehicle.getId())){
throw new IllegalArgumentException("problem already contains a vehicle with id " + vehicle.getId() + ". choose unique ids for each vehicle.");
throw new IllegalArgumentException("The vehicle routing problem already contains a vehicle with id " + vehicle.getId() + ". Please choose unique ids for each vehicle.");
}
else addedVehicleIds.add(vehicle.getId());
if (!uniqueVehicles.contains(vehicle)) {
@ -443,7 +444,7 @@ public class VehicleRoutingProblem {
}
boolean hasBreaks = addBreaksToActivityMap();
if (hasBreaks && fleetSize.equals(FleetSize.INFINITE))
throw new UnsupportedOperationException("breaks are not yet supported when dealing with infinite fleet. either set it to finite or omit breaks.");
throw new UnsupportedOperationException("Breaks are not yet supported when dealing with infinite fleet. Either set it to finite or omit breaks.");
return new VehicleRoutingProblem(this);
}
@ -510,7 +511,7 @@ public class VehicleRoutingProblem {
// tentative_coordinates.put(service.getLocation().getId(), service.getLocation().getCoordinate());
addLocationToTentativeLocations(service);
if (jobs.containsKey(service.getId())) {
logger.warn("service " + service + " already in job list. overrides existing job.");
logger.warn("The service " + service + " has already been added to job list. This overrides existing job.");
}
jobs.put(service.getId(), service);
return this;

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,55 +101,53 @@ 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;
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(prevAct, 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;
}
}
}
return ConstraintsStatus.FULFILLED;
}
// private double getMaxTime(String jobId) {
// if(maxTimes.containsKey(jobId)) return maxTimes.get(jobId);
// else return Double.MAX_VALUE;
// }
private double startOf(TourActivity act, double arrTime) {
return Math.max(arrTime, act.getTheoreticalEarliestOperationStartTime());
}
}

View file

@ -30,6 +30,7 @@ import com.graphhopper.jsprit.core.problem.Skills;
*/
public interface Job extends HasId, HasIndex {
/**
* Returns the unique identifier (id) of a job.
*

View file

@ -92,7 +92,7 @@ public class Service extends AbstractJob {
protected Object userData;
protected double maxTimeInVehicle = Double.MAX_VALUE;
Builder(String id){
this.id = id;
timeWindows = new TimeWindowsImpl();
@ -135,7 +135,7 @@ public class Service extends AbstractJob {
*/
public Builder<T> setServiceTime(double serviceTime) {
if (serviceTime < 0)
throw new IllegalArgumentException("serviceTime must be greater than or equal to zero");
throw new IllegalArgumentException("The service time of a service must be greater than or equal to zero.");
this.serviceTime = serviceTime;
return this;
}
@ -167,20 +167,20 @@ public class Service extends AbstractJob {
* @throws IllegalArgumentException if dimensionValue < 0
*/
public Builder<T> addSizeDimension(int dimensionIndex, int dimensionValue) {
if (dimensionValue < 0) throw new IllegalArgumentException("capacity value cannot be negative");
if (dimensionValue < 0) throw new IllegalArgumentException("The capacity value must not be negative.");
capacityBuilder.addDimension(dimensionIndex, dimensionValue);
return this;
}
public Builder<T> setTimeWindow(TimeWindow tw){
if(tw == null) throw new IllegalArgumentException("time-window arg must not be null");
if (tw == null) throw new IllegalArgumentException("The time window must not be null.");
this.timeWindows = new TimeWindowsImpl();
timeWindows.add(tw);
return this;
}
public Builder<T> addTimeWindow(TimeWindow timeWindow) {
if(timeWindow == null) throw new IllegalArgumentException("time-window arg must not be null");
if (timeWindow == null) throw new IllegalArgumentException("The time window must not be null.");
if(!twAdded){
timeWindows = new TimeWindowsImpl();
twAdded = true;
@ -205,7 +205,7 @@ public class Service extends AbstractJob {
* @throws IllegalArgumentException if neither locationId nor coordinate is set.
*/
public T build() {
if (location == null) throw new IllegalArgumentException("location is missing");
if (location == null) throw new IllegalArgumentException("The location of service " + id + " is missing.");
this.setType("service");
capacity = capacityBuilder.build();
skills = skillBuilder.build();
@ -222,10 +222,13 @@ public class Service extends AbstractJob {
return this;
}
public Builder<T> addAllRequiredSkills(Collection<String> skills) {
skillBuilder.addAllSkills(skills);
return this;
}
public Builder<T> addAllRequiredSkills(Skills skills){
for(String s : skills.values()){
skillBuilder.addSkill(s);
}
skillBuilder.addAllSkills(skills.values());
return this;
}
@ -246,13 +249,13 @@ public class Service extends AbstractJob {
*/
public Builder<T> setPriority(int priority) {
if (priority < 1 || priority > 10)
throw new IllegalArgumentException("incorrect priority. only priority values from 1 to 10 are allowed where 1 = high and 10 is low");
throw new IllegalArgumentException("The priority value is not valid. Only 1 (very high) to 10 (very low) are allowed.");
this.priority = priority;
return this;
}
public Builder<T> setMaxTimeInVehicle(double maxTimeInVehicle){
throw new UnsupportedOperationException("maxTimeInVehicle is not yet supported for Pickups and Services (only for Deliveries and Shipments)");
throw new UnsupportedOperationException("The maximum time in vehicle 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;

View file

@ -148,7 +148,8 @@ public class Shipment extends AbstractJob {
* @throws IllegalArgumentException if servicTime < 0.0
*/
public Builder setPickupServiceTime(double serviceTime) {
if (serviceTime < 0.0) throw new IllegalArgumentException("serviceTime must not be < 0.0");
if (serviceTime < 0.0)
throw new IllegalArgumentException("The service time of a shipment must not be < 0.0.");
this.pickupServiceTime = serviceTime;
return this;
}
@ -164,7 +165,7 @@ public class Shipment extends AbstractJob {
* @throws IllegalArgumentException if timeWindow is null
*/
public Builder setPickupTimeWindow(TimeWindow timeWindow) {
if (timeWindow == null) throw new IllegalArgumentException("delivery time-window must not be null");
if (timeWindow == null) throw new IllegalArgumentException("The delivery time window must not be null.");
this.pickupTimeWindows = new TimeWindowsImpl();
this.pickupTimeWindows.add(timeWindow);
return this;
@ -193,7 +194,8 @@ public class Shipment extends AbstractJob {
* @throws IllegalArgumentException if serviceTime < 0.0
*/
public Builder setDeliveryServiceTime(double deliveryServiceTime) {
if (deliveryServiceTime < 0.0) throw new IllegalArgumentException("deliveryServiceTime must not be < 0.0");
if (deliveryServiceTime < 0.0)
throw new IllegalArgumentException("The service time of a delivery must not be < 0.0.");
this.deliveryServiceTime = deliveryServiceTime;
return this;
}
@ -209,7 +211,7 @@ public class Shipment extends AbstractJob {
* @throws IllegalArgumentException if timeWindow is null
*/
public Builder setDeliveryTimeWindow(TimeWindow timeWindow) {
if (timeWindow == null) throw new IllegalArgumentException("delivery time-window must not be null");
if (timeWindow == null) throw new IllegalArgumentException("The delivery time window must not be null.");
this.deliveryTimeWindows = new TimeWindowsImpl();
this.deliveryTimeWindows.add(timeWindow);
return this;
@ -224,7 +226,8 @@ public class Shipment extends AbstractJob {
* @throws IllegalArgumentException if dimVal < 0
*/
public Builder addSizeDimension(int dimensionIndex, int dimensionValue) {
if (dimensionValue < 0) throw new IllegalArgumentException("capacity value cannot be negative");
if (dimensionValue < 0)
throw new IllegalArgumentException("The capacity value must not be negative, but is " + dimensionValue + ".");
capacityBuilder.addDimension(dimensionIndex, dimensionValue);
return this;
}
@ -245,8 +248,8 @@ public class Shipment extends AbstractJob {
* is set
*/
public Shipment build() {
if (pickupLocation_ == null) throw new IllegalArgumentException("pickup location is missing");
if (deliveryLocation_ == null) throw new IllegalArgumentException("delivery location is missing");
if (pickupLocation_ == null) throw new IllegalArgumentException("The pickup location is missing.");
if (deliveryLocation_ == null) throw new IllegalArgumentException("The delivery location is missing.");
capacity = capacityBuilder.build();
skills = skillBuilder.build();
return new Shipment(this);
@ -258,10 +261,13 @@ public class Shipment extends AbstractJob {
return this;
}
public Builder addAllRequiredSkills(Collection<String> skills) {
skillBuilder.addAllSkills(skills);
return this;
}
public Builder addAllRequiredSkills(Skills skills) {
for (String s : skills.values()) {
addRequiredSkill(s);
}
addAllRequiredSkills(skills.values());
return this;
}
@ -271,7 +277,7 @@ public class Shipment extends AbstractJob {
}
public Builder addDeliveryTimeWindow(TimeWindow timeWindow) {
if(timeWindow == null) throw new IllegalArgumentException("time-window arg must not be null");
if (timeWindow == null) throw new IllegalArgumentException("The time window must not be null.");
if(!deliveryTimeWindowAdded){
deliveryTimeWindows = new TimeWindowsImpl();
deliveryTimeWindowAdded = true;
@ -291,7 +297,7 @@ public class Shipment extends AbstractJob {
}
public Builder addPickupTimeWindow(TimeWindow timeWindow) {
if(timeWindow == null) throw new IllegalArgumentException("time-window arg must not be null");
if (timeWindow == null) throw new IllegalArgumentException("The time window must not be null.");
if(!pickupTimeWindowAdded){
pickupTimeWindows = new TimeWindowsImpl();
pickupTimeWindowAdded = true;
@ -319,7 +325,7 @@ public class Shipment extends AbstractJob {
*/
public Builder setPriority(int priority) {
if (priority < 1 || priority > 10)
throw new IllegalArgumentException("incorrect priority. only 1 (very high) to 10 (very low) are allowed");
throw new IllegalArgumentException("The priority value is not valid. Only 1 (very high) to 10 (very low) are allowed.");
this.priority = priority;
return this;
}
@ -331,7 +337,8 @@ public class Shipment extends AbstractJob {
* @return
*/
public Builder setMaxTimeInVehicle(double maxTimeInVehicle){
if(maxTimeInVehicle < 0) throw new IllegalArgumentException("maxTimeInVehicle should be positive");
if (maxTimeInVehicle < 0)
throw new IllegalArgumentException("The maximum time in vehicle must be positive.");
this.maxTimeInVehicle = maxTimeInVehicle;
return this;
}
@ -436,7 +443,7 @@ public class Shipment extends AbstractJob {
return pickupTimeWindows.getTimeWindows();
}
/**
* Returns a string with the shipment's attributes.
* <p>

View file

@ -24,6 +24,8 @@ import com.graphhopper.jsprit.core.problem.job.Break;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
/**
* Implementation of {@link Vehicle}.
@ -135,6 +137,7 @@ public class VehicleImpl extends AbstractVehicle {
private Builder(String id) {
super();
this.id = id;
if (id == null) throw new IllegalArgumentException("Vehicle id must not be null.");
}
/**
@ -145,7 +148,7 @@ public class VehicleImpl extends AbstractVehicle {
* @throws IllegalArgumentException if type is null
*/
public Builder setType(VehicleType type) {
if (type == null) throw new IllegalArgumentException("type cannot be null.");
if (type == null) throw new IllegalArgumentException("Vehicle type must not be null.");
this.type = type;
return this;
}
@ -196,6 +199,8 @@ public class VehicleImpl extends AbstractVehicle {
* @return start location
*/
public Builder setStartLocation(Location startLocation) {
if (startLocation == null)
throw new IllegalArgumentException("Start location of vehicle " + id + " must not be null.");
this.startLocation = startLocation;
return this;
}
@ -213,7 +218,7 @@ public class VehicleImpl extends AbstractVehicle {
*/
public Builder setEarliestStart(double earliest_startTime) {
if (earliest_startTime < 0)
throw new IllegalArgumentException("earliest start of vehicle " + id + " must not be negative");
throw new IllegalArgumentException("The earliest start time of vehicle " + id + " must not be negative.");
this.earliestStart = earliest_startTime;
return this;
}
@ -226,12 +231,19 @@ public class VehicleImpl extends AbstractVehicle {
*/
public Builder setLatestArrival(double latest_arrTime) {
if (latest_arrTime < 0)
throw new IllegalArgumentException("latest arrival time of vehicle " + id + " must not be negative");
throw new IllegalArgumentException("The latest arrival time of vehicle " + id + " must not be negative.");
this.latestArrival = latest_arrTime;
return this;
}
public Builder addAllSkills(Collection<String> skills) {
if (skills == null) throw new IllegalArgumentException("Skills of vehicle " + id + " must not be null");
skillBuilder.addAllSkills(skills);
return this;
}
public Builder addSkill(String skill) {
if (skill == null) throw new IllegalArgumentException("Skill of vehicle " + id + " must not be null");
skillBuilder.addSkill(skill);
return this;
}
@ -254,17 +266,17 @@ public class VehicleImpl extends AbstractVehicle {
*/
public VehicleImpl build() {
if (latestArrival < earliestStart)
throw new IllegalArgumentException("latest arrival of vehicle " + id + " must not be smaller than its start time");
throw new IllegalArgumentException("The latest arrival time of vehicle " + id + " must not be smaller than its start time.");
if (startLocation != null && endLocation != null) {
if (!startLocation.getId().equals(endLocation.getId()) && !returnToDepot)
throw new IllegalArgumentException("this must not be. you specified both endLocationId and open-routes. this is contradictory. <br>" +
"if you set endLocation, returnToDepot must be true. if returnToDepot is false, endLocationCoord must not be specified.");
throw new IllegalArgumentException("You specified both the end location and that the vehicle " + id + " does not need to return to its end location. This must not be. " +
"Either specify end location and return to depot or leave end location unspecified.");
}
if (startLocation != null && endLocation == null) {
endLocation = startLocation;
}
if (startLocation == null && endLocation == null)
throw new IllegalArgumentException("vehicle requires startLocation. but neither locationId nor locationCoord nor startLocationId nor startLocationCoord has been set");
throw new IllegalArgumentException("Every vehicle requires a start location, but vehicle " + id + " does not have one.");
skills = skillBuilder.build();
return new VehicleImpl(this);
}

View file

@ -151,7 +151,8 @@ public class VehicleTypeImpl implements VehicleType {
* if velocity is smaller than zero
*/
public VehicleTypeImpl.Builder setMaxVelocity(double inMeterPerSeconds) {
if (inMeterPerSeconds < 0.0) throw new IllegalArgumentException("velocity cannot be smaller than zero");
if (inMeterPerSeconds < 0.0)
throw new IllegalArgumentException("The velocity of a vehicle (type) cannot be smaller than zero.");
this.maxVelo = inMeterPerSeconds;
return this;
}
@ -166,7 +167,7 @@ public class VehicleTypeImpl implements VehicleType {
* @throws IllegalArgumentException if fixedCost is smaller than zero
*/
public VehicleTypeImpl.Builder setFixedCost(double fixedCost) {
if (fixedCost < 0.0) throw new IllegalArgumentException("fixed costs cannot be smaller than zero");
if (fixedCost < 0.0) throw new IllegalArgumentException("Fixed costs must not be smaller than zero.");
this.fixedCost = fixedCost;
return this;
}
@ -181,7 +182,8 @@ public class VehicleTypeImpl implements VehicleType {
* @throws IllegalArgumentException if perDistance is smaller than zero
*/
public VehicleTypeImpl.Builder setCostPerDistance(double perDistance) {
if (perDistance < 0.0) throw new IllegalArgumentException("cost per distance must not be smaller than zero");
if (perDistance < 0.0)
throw new IllegalArgumentException("Cost per distance must not be smaller than zero.");
this.perDistance = perDistance;
return this;
}
@ -260,9 +262,9 @@ public class VehicleTypeImpl implements VehicleType {
* @throws IllegalArgumentException if capacity dimension is already set
*/
public Builder addCapacityDimension(int dimIndex, int dimVal) {
if (dimVal < 0) throw new IllegalArgumentException("capacity value cannot be negative");
if (dimVal < 0) throw new IllegalArgumentException("The capacity value must not be negative.");
if (capacityDimensions != null)
throw new IllegalArgumentException("either build your dimension with build your dimensions with " +
throw new IllegalArgumentException("Either build your dimension with build your dimensions with " +
"addCapacityDimension(int dimIndex, int dimVal) or set the already built dimensions with .setCapacityDimensions(Capacity capacity)." +
"You used both methods.");
dimensionAdded = true;
@ -283,7 +285,7 @@ public class VehicleTypeImpl implements VehicleType {
*/
public Builder setCapacityDimensions(Capacity capacity) {
if (dimensionAdded)
throw new IllegalArgumentException("either build your dimension with build your dimensions with " +
throw new IllegalArgumentException("Either build your dimension with build your dimensions with " +
"addCapacityDimension(int dimIndex, int dimVal) or set the already built dimensions with .setCapacityDimensions(Capacity capacity)." +
"You used both methods.");
this.capacityDimensions = capacity;

View file

@ -29,15 +29,19 @@ import java.util.*;
*/
public class UnassignedJobReasonTracker implements JobUnassignedListener {
private final static String NO_REASON = "cannot determine a particular reason";
public static String getMostLikelyFailedConstraintName(Frequency failedConstraintNamesFrequency) {
if (failedConstraintNamesFrequency == null) return "no reason found";
if (failedConstraintNamesFrequency == null || failedConstraintNamesFrequency.getUniqueCount() == 0)
return NO_REASON;
Iterator<Map.Entry<Comparable<?>, Long>> entryIterator = failedConstraintNamesFrequency.entrySetIterator();
int maxCount = 0;
long maxCount = 0;
String mostLikely = null;
while (entryIterator.hasNext()) {
Map.Entry<Comparable<?>, Long> entry = entryIterator.next();
if (entry.getValue() > maxCount) {
Comparable<?> key = entry.getKey();
maxCount = entry.getValue();
mostLikely = key.toString();
}
}
@ -53,6 +57,7 @@ public class UnassignedJobReasonTracker implements JobUnassignedListener {
Set<String> failedConstraintNamesToBeIgnored = new HashSet<>();
public UnassignedJobReasonTracker() {
codesToHumanReadableReason.put(-1, NO_REASON);
codesToHumanReadableReason.put(1, "cannot serve required skill");
codesToHumanReadableReason.put(2, "cannot be visited within time window");
codesToHumanReadableReason.put(3, "does not fit into any vehicle due to capacity");
@ -164,8 +169,9 @@ public class UnassignedJobReasonTracker implements JobUnassignedListener {
* @return
*/
public String getMostLikelyReason(String jobId) {
if (!this.failedConstraintNamesFrequencyMapping.containsKey(jobId)) return "no reason found";
if (!this.failedConstraintNamesFrequencyMapping.containsKey(jobId)) return codesToHumanReadableReason.get(-1);
Frequency reasons = this.failedConstraintNamesFrequencyMapping.get(jobId);
String mostLikelyReason = getMostLikelyFailedConstraintName(reasons);
int code = toCode(mostLikelyReason);
if (code == -1) return mostLikelyReason;

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, 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,12 +302,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));
@ -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));

View file

@ -134,6 +134,19 @@ public class UnassignedJobReasonTrackerTest {
Assert.assertEquals(4, reasonTracker.getMostLikelyReasonCode(solution.getUnassignedJobs().iterator().next().getId()));
}
@Test
public void getMostLikelyTest() {
Frequency frequency = new Frequency();
frequency.addValue("a");
frequency.addValue("b");
frequency.addValue("a");
frequency.addValue("a");
frequency.addValue("a");
frequency.addValue("a");
frequency.addValue("a");
Assert.assertEquals("a", UnassignedJobReasonTracker.getMostLikelyFailedConstraintName(frequency));
}
@Test
public void testFreq() {
Frequency frequency = new Frequency();