mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
improved and tested route level insertion
This commit is contained in:
parent
b3a186cc62
commit
5dae3ee528
7 changed files with 396 additions and 83 deletions
|
|
@ -42,11 +42,11 @@ final class AuxilliaryCostCalculator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param path
|
* @param path activity path to get the costs for
|
||||||
* @param depTime
|
* @param depTime departure time at first activity in path
|
||||||
* @param driver
|
* @param driver driver of vehicle
|
||||||
* @param vehicle
|
* @param vehicle vehicle running the path
|
||||||
* @return
|
* @return cost of path
|
||||||
*/
|
*/
|
||||||
public double costOfPath(final List<TourActivity> path, final double depTime, final Driver driver, final Vehicle vehicle){
|
public double costOfPath(final List<TourActivity> path, final double depTime, final Driver driver, final Vehicle vehicle){
|
||||||
if(path.isEmpty()){
|
if(path.isEmpty()){
|
||||||
|
|
@ -69,9 +69,7 @@ final class AuxilliaryCostCalculator {
|
||||||
double transportTime = routingCosts.getTransportTime(prevAct.getLocationId(), act.getLocationId(), departureTimePrevAct, driver, vehicle);
|
double transportTime = routingCosts.getTransportTime(prevAct.getLocationId(), act.getLocationId(), departureTimePrevAct, driver, vehicle);
|
||||||
cost += transportCost;
|
cost += transportCost;
|
||||||
double actStartTime = departureTimePrevAct + transportTime;
|
double actStartTime = departureTimePrevAct + transportTime;
|
||||||
double earliestOperationStartTime = Math.max(actStartTime, act.getTheoreticalEarliestOperationStartTime());
|
departureTimePrevAct = Math.max(actStartTime, act.getTheoreticalEarliestOperationStartTime()) + act.getOperationTime();
|
||||||
double actEndTime = earliestOperationStartTime + act.getOperationTime();
|
|
||||||
departureTimePrevAct = actEndTime;
|
|
||||||
cost += activityCosts.getActivityCost(act, actStartTime, driver, vehicle);
|
cost += activityCosts.getActivityCost(act, actStartTime, driver, vehicle);
|
||||||
prevAct = act;
|
prevAct = act;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -296,10 +296,11 @@ class CalculatorBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, RouteAndActivityStateGetter activityStates2, int forwardLooking, int solutionMemory){
|
private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, RouteAndActivityStateGetter activityStates2, int forwardLooking, int solutionMemory){
|
||||||
int after = forwardLooking;
|
|
||||||
ActivityInsertionCostsCalculator routeLevelCostEstimator;
|
ActivityInsertionCostsCalculator routeLevelCostEstimator;
|
||||||
if(activityInsertionCostCalculator == null && addDefaultCostCalc){
|
if(activityInsertionCostCalculator == null && addDefaultCostCalc){
|
||||||
routeLevelCostEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), activityStates2);
|
RouteLevelActivityInsertionCostsEstimator routeLevelActivityInsertionCostsEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), activityStates2);
|
||||||
|
routeLevelActivityInsertionCostsEstimator.setForwardLooking(forwardLooking);
|
||||||
|
routeLevelCostEstimator = routeLevelActivityInsertionCostsEstimator;
|
||||||
}
|
}
|
||||||
else if(activityInsertionCostCalculator == null && !addDefaultCostCalc){
|
else if(activityInsertionCostCalculator == null && !addDefaultCostCalc){
|
||||||
routeLevelCostEstimator = new ActivityInsertionCostsCalculator(){
|
routeLevelCostEstimator = new ActivityInsertionCostsCalculator(){
|
||||||
|
|
@ -318,7 +319,7 @@ class CalculatorBuilder {
|
||||||
routeLevelCostEstimator = activityInsertionCostCalculator;
|
routeLevelCostEstimator = activityInsertionCostCalculator;
|
||||||
}
|
}
|
||||||
JobInsertionCostsCalculator jobInsertionCalculator = new ServiceInsertionOnRouteLevelCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), routeLevelCostEstimator, constraintManager, constraintManager);
|
JobInsertionCostsCalculator jobInsertionCalculator = new ServiceInsertionOnRouteLevelCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), routeLevelCostEstimator, constraintManager, constraintManager);
|
||||||
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setNuOfActsForwardLooking(after);
|
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setNuOfActsForwardLooking(forwardLooking);
|
||||||
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setMemorySize(solutionMemory);
|
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setMemorySize(solutionMemory);
|
||||||
((ServiceInsertionOnRouteLevelCalculator) jobInsertionCalculator).setStates(activityStates2);
|
((ServiceInsertionOnRouteLevelCalculator) jobInsertionCalculator).setStates(activityStates2);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,14 +57,13 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost
|
||||||
path.add(prevAct); path.add(newAct); path.add(nextAct);
|
path.add(prevAct); path.add(newAct); path.add(nextAct);
|
||||||
int actIndex;
|
int actIndex;
|
||||||
if(prevAct instanceof Start) actIndex = 0;
|
if(prevAct instanceof Start) actIndex = 0;
|
||||||
else actIndex = iFacts.getRoute().getTourActivities().getActivities().indexOf(prevAct);
|
else actIndex = iFacts.getRoute().getTourActivities().getActivities().indexOf(nextAct);
|
||||||
if(nuOfActivities2LookForward > 0){ path.addAll(getForwardLookingPath(iFacts.getRoute(),actIndex)); }
|
if(nuOfActivities2LookForward > 0){ path.addAll(getForwardLookingPath(iFacts.getRoute(),actIndex)); }
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* calculates the path costs with new vehicle, c(forwardPath,newVehicle).
|
* calculates the path costs with new vehicle, c(forwardPath,newVehicle).
|
||||||
*/
|
*/
|
||||||
double forwardPathCost_newVehicle = auxilliaryPathCostCalculator.costOfPath(path, depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
double forwardPathCost_newVehicle = auxilliaryPathCostCalculator.costOfPath(path, depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||||
|
|
||||||
double additionalCosts = forwardPathCost_newVehicle - (actCostsOld(iFacts.getRoute(), path.get(path.size()-1)) - actCostsOld(iFacts.getRoute(), prevAct));
|
double additionalCosts = forwardPathCost_newVehicle - (actCostsOld(iFacts.getRoute(), path.get(path.size()-1)) - actCostsOld(iFacts.getRoute(), prevAct));
|
||||||
|
|
||||||
return new ActivityInsertionCosts(additionalCosts, 0.0);
|
return new ActivityInsertionCosts(additionalCosts, 0.0);
|
||||||
|
|
@ -93,4 +92,7 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost
|
||||||
return forwardLookingPath;
|
return forwardLookingPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setForwardLooking(int nActivities) {
|
||||||
|
this.nuOfActivities2LookForward = nActivities;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,31 +72,17 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsC
|
||||||
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
|
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
|
||||||
|
|
||||||
private int nuOfActsForwardLooking = 0;
|
private int nuOfActsForwardLooking = 0;
|
||||||
|
//
|
||||||
private int memorySize = 2;
|
private int memorySize = 2;
|
||||||
|
|
||||||
private Start start;
|
private Start start;
|
||||||
|
|
||||||
private End end;
|
private End end;
|
||||||
|
|
||||||
private Neighborhood neighborhood = new Neighborhood() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean areNeighbors(String location1, String location2) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
public void setTourActivityFactory(TourActivityFactory tourActivityFactory){
|
public void setTourActivityFactory(TourActivityFactory tourActivityFactory){
|
||||||
this.tourActivityFactory=tourActivityFactory;
|
this.tourActivityFactory=tourActivityFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNeighborhood(Neighborhood neighborhood) {
|
|
||||||
this.neighborhood = neighborhood;
|
|
||||||
logger.info("initialise neighborhood " + neighborhood);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMemorySize(int memorySize) {
|
public void setMemorySize(int memorySize) {
|
||||||
this.memorySize = memorySize;
|
this.memorySize = memorySize;
|
||||||
logger.info("set [solutionMemory="+memorySize+"]");
|
logger.info("set [solutionMemory="+memorySize+"]");
|
||||||
|
|
@ -182,9 +168,8 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsC
|
||||||
* k=serviceAct2Insert
|
* k=serviceAct2Insert
|
||||||
*/
|
*/
|
||||||
for(TourActivity nextAct : tour.getActivities()){
|
for(TourActivity nextAct : tour.getActivities()){
|
||||||
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
|
ConstraintsStatus hardActivityConstraintsStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
|
||||||
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
|
if(hardActivityConstraintsStatus.equals(ConstraintsStatus.FULFILLED)){
|
||||||
if(status.equals(ConstraintsStatus.FULFILLED)){
|
|
||||||
/**
|
/**
|
||||||
* builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking}
|
* builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking}
|
||||||
*/
|
*/
|
||||||
|
|
@ -202,11 +187,11 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsC
|
||||||
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
|
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
|
else if(hardActivityConstraintsStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
|
||||||
loopBroken = true;
|
loopBroken = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* calculate transport and activity costs with new vehicle (without inserting k)
|
* calculate transport and activity costs with new vehicle (without inserting k)
|
||||||
|
|
@ -237,9 +222,8 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsC
|
||||||
}
|
}
|
||||||
if(!loopBroken){
|
if(!loopBroken){
|
||||||
End nextAct = end;
|
End nextAct = end;
|
||||||
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
|
ConstraintsStatus hardActivityConstraintsStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
|
||||||
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
|
if(hardActivityConstraintsStatus.equals(ConstraintsStatus.FULFILLED)){
|
||||||
if(status.equals(ConstraintsStatus.FULFILLED)){
|
|
||||||
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
|
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
|
||||||
if(actInsertionCosts != null){
|
if(actInsertionCosts != null){
|
||||||
/**
|
/**
|
||||||
|
|
@ -256,7 +240,6 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
package jsprit.core.algorithm.recreate;
|
||||||
|
|
||||||
|
import jsprit.core.algorithm.state.StateManager;
|
||||||
|
import jsprit.core.algorithm.state.UpdateVariableCosts;
|
||||||
|
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||||
|
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
|
import jsprit.core.problem.driver.Driver;
|
||||||
|
import jsprit.core.problem.job.Job;
|
||||||
|
import jsprit.core.problem.job.Service;
|
||||||
|
import jsprit.core.problem.misc.JobInsertionContext;
|
||||||
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
|
import jsprit.core.problem.solution.route.activity.PickupActivity;
|
||||||
|
import jsprit.core.problem.solution.route.activity.PickupService;
|
||||||
|
import jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||||
|
import jsprit.core.problem.solution.route.activity.TourActivity;
|
||||||
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleImpl;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleType;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleTypeImpl;
|
||||||
|
import jsprit.core.util.CostFactory;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by schroeder on 02.07.14.
|
||||||
|
*/
|
||||||
|
public class TestRouteLevelActivityInsertionCostEstimator {
|
||||||
|
|
||||||
|
private VehicleRoute route;
|
||||||
|
|
||||||
|
private VehicleRoutingTransportCosts routingCosts;
|
||||||
|
|
||||||
|
private VehicleRoutingActivityCosts activityCosts;
|
||||||
|
|
||||||
|
private StateManager stateManager;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void doBefore(){
|
||||||
|
routingCosts = CostFactory.createEuclideanCosts();
|
||||||
|
|
||||||
|
activityCosts = new VehicleRoutingActivityCosts() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getActivityCost(TourActivity tourAct, double arrivalTime, Driver driver, Vehicle vehicle) {
|
||||||
|
return Math.max(0.,arrivalTime - tourAct.getTheoreticalLatestOperationStartTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
Service s1 = Service.Builder.newInstance("s1").setLocationId("10,0").setTimeWindow(TimeWindow.newInstance(10.,10.)).build();
|
||||||
|
Service s2 = Service.Builder.newInstance("s2").setLocationId("20,0").setTimeWindow(TimeWindow.newInstance(20.,20.)).build();
|
||||||
|
Service s3 = Service.Builder.newInstance("s3").setLocationId("30,0").setTimeWindow(TimeWindow.newInstance(30.,30.)).build();
|
||||||
|
|
||||||
|
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").build();
|
||||||
|
Vehicle vehicle = VehicleImpl.Builder.newInstance("vehicle").setStartLocationId("0,0").setType(type).build();
|
||||||
|
|
||||||
|
route = VehicleRoute.Builder.newInstance(vehicle).addService(s1).addService(s2).addService(s3).build();
|
||||||
|
|
||||||
|
stateManager = new StateManager(routingCosts);
|
||||||
|
stateManager.addStateUpdater(new UpdateVariableCosts(activityCosts,routingCosts,stateManager));
|
||||||
|
stateManager.informInsertionStarts(Arrays.asList(route), Collections.<Job>emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNewActInBetweenFirstAndSecond_and_forwardLookingIs0_itShouldReturnCorrectCosts(){
|
||||||
|
Service s4 = Service.Builder.newInstance("s4").setLocationId("5,0").build();
|
||||||
|
PickupActivity pickupService = new PickupService(s4);
|
||||||
|
JobInsertionContext context = new JobInsertionContext(route,s4,route.getVehicle(),route.getDriver(),0.);
|
||||||
|
RouteLevelActivityInsertionCostsEstimator estimator = new RouteLevelActivityInsertionCostsEstimator(routingCosts,activityCosts,stateManager);
|
||||||
|
estimator.setForwardLooking(0);
|
||||||
|
ActivityInsertionCostsCalculator.ActivityInsertionCosts iCosts = estimator.getCosts(context, route.getStart(), route.getActivities().get(0), pickupService, 0.);
|
||||||
|
assertEquals(0.,iCosts.getAdditionalCosts(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNewActWithTWInBetweenFirstAndSecond_and_forwardLookingIs0_itShouldReturnCorrectCosts(){
|
||||||
|
Service s4 = Service.Builder.newInstance("s4").setLocationId("5,0").setTimeWindow(TimeWindow.newInstance(5.,5.)).build();
|
||||||
|
PickupActivity pickupService = new PickupService(s4);
|
||||||
|
JobInsertionContext context = new JobInsertionContext(route,s4,route.getVehicle(),route.getDriver(),0.);
|
||||||
|
RouteLevelActivityInsertionCostsEstimator estimator = new RouteLevelActivityInsertionCostsEstimator(routingCosts,activityCosts,stateManager);
|
||||||
|
estimator.setForwardLooking(0);
|
||||||
|
ActivityInsertionCostsCalculator.ActivityInsertionCosts iCosts = estimator.getCosts(context, route.getStart(), route.getActivities().get(0), pickupService, 0.);
|
||||||
|
assertEquals(0.,iCosts.getAdditionalCosts(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNewActWithTWAndServiceTimeInBetweenFirstAndSecond_and_forwardLookingIs0_itShouldReturnCorrectCosts(){
|
||||||
|
Service s4 = Service.Builder.newInstance("s4").setLocationId("5,0").setServiceTime(10.).setTimeWindow(TimeWindow.newInstance(5.,5.)).build();
|
||||||
|
PickupActivity pickupService = new PickupService(s4);
|
||||||
|
JobInsertionContext context = new JobInsertionContext(route,s4,route.getVehicle(),route.getDriver(),0.);
|
||||||
|
RouteLevelActivityInsertionCostsEstimator estimator = new RouteLevelActivityInsertionCostsEstimator(routingCosts,activityCosts,stateManager);
|
||||||
|
estimator.setForwardLooking(0);
|
||||||
|
ActivityInsertionCostsCalculator.ActivityInsertionCosts iCosts = estimator.getCosts(context, route.getStart(), route.getActivities().get(0), pickupService, 0.);
|
||||||
|
double expectedTransportCosts = 0.;
|
||||||
|
double expectedActivityCosts = 10.;
|
||||||
|
assertEquals(expectedActivityCosts+expectedTransportCosts,iCosts.getAdditionalCosts(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNewActWithTWAndServiceTimeInBetweenFirstAndSecond_and_forwardLookingIs3_itShouldReturnCorrectCosts(){
|
||||||
|
Service s4 = Service.Builder.newInstance("s4").setLocationId("5,0").setServiceTime(10.).setTimeWindow(TimeWindow.newInstance(5.,5.)).build();
|
||||||
|
PickupActivity pickupService = new PickupService(s4);
|
||||||
|
JobInsertionContext context = new JobInsertionContext(route,s4,route.getVehicle(),route.getDriver(),0.);
|
||||||
|
RouteLevelActivityInsertionCostsEstimator estimator = new RouteLevelActivityInsertionCostsEstimator(routingCosts,activityCosts,stateManager);
|
||||||
|
estimator.setForwardLooking(3);
|
||||||
|
ActivityInsertionCostsCalculator.ActivityInsertionCosts iCosts = estimator.getCosts(context, route.getStart(), route.getActivities().get(0), pickupService, 0.);
|
||||||
|
double expectedTransportCosts = 0.;
|
||||||
|
double expectedActivityCosts = 30.;
|
||||||
|
assertEquals(expectedActivityCosts+expectedTransportCosts,iCosts.getAdditionalCosts(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNewActInBetweenSecondAndThird_and_forwardLookingIs0_itShouldReturnCorrectCosts(){
|
||||||
|
Service s4 = Service.Builder.newInstance("s4").setLocationId("5,0").build();
|
||||||
|
PickupActivity pickupService = new PickupService(s4);
|
||||||
|
JobInsertionContext context = new JobInsertionContext(route,s4,route.getVehicle(),route.getDriver(),0.);
|
||||||
|
RouteLevelActivityInsertionCostsEstimator estimator = new RouteLevelActivityInsertionCostsEstimator(routingCosts,activityCosts,stateManager);
|
||||||
|
estimator.setForwardLooking(0);
|
||||||
|
ActivityInsertionCostsCalculator.ActivityInsertionCosts iCosts =
|
||||||
|
estimator.getCosts(context, route.getActivities().get(0), route.getActivities().get(1), pickupService, 10.);
|
||||||
|
double expectedTransportCosts = 10.;
|
||||||
|
double expectedActivityCosts = 10.;
|
||||||
|
assertEquals(expectedTransportCosts+expectedActivityCosts,iCosts.getAdditionalCosts(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNewActInBetweenSecondAndThird_and_forwardLookingIs3_itShouldReturnCorrectCosts(){
|
||||||
|
Service s4 = Service.Builder.newInstance("s4").setLocationId("5,0").build();
|
||||||
|
PickupActivity pickupService = new PickupService(s4);
|
||||||
|
JobInsertionContext context = new JobInsertionContext(route,s4,route.getVehicle(),route.getDriver(),0.);
|
||||||
|
RouteLevelActivityInsertionCostsEstimator estimator = new RouteLevelActivityInsertionCostsEstimator(routingCosts,activityCosts,stateManager);
|
||||||
|
estimator.setForwardLooking(3);
|
||||||
|
ActivityInsertionCostsCalculator.ActivityInsertionCosts iCosts =
|
||||||
|
estimator.getCosts(context, route.getActivities().get(0), route.getActivities().get(1), pickupService, 10.);
|
||||||
|
double expectedTransportCosts = 10.;
|
||||||
|
double expectedActivityCosts = 10.+10.;
|
||||||
|
assertEquals(expectedTransportCosts+expectedActivityCosts,iCosts.getAdditionalCosts(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNewActWithTWInBetweenSecondAndThird_and_forwardLookingIs3_itShouldReturnCorrectCosts(){
|
||||||
|
Service s4 = Service.Builder.newInstance("s4").setLocationId("5,0").setTimeWindow(TimeWindow.newInstance(5.,5.)).build();
|
||||||
|
PickupActivity pickupService = new PickupService(s4);
|
||||||
|
JobInsertionContext context = new JobInsertionContext(route,s4,route.getVehicle(),route.getDriver(),0.);
|
||||||
|
RouteLevelActivityInsertionCostsEstimator estimator = new RouteLevelActivityInsertionCostsEstimator(routingCosts,activityCosts,stateManager);
|
||||||
|
estimator.setForwardLooking(3);
|
||||||
|
ActivityInsertionCostsCalculator.ActivityInsertionCosts iCosts =
|
||||||
|
estimator.getCosts(context, route.getActivities().get(0), route.getActivities().get(1), pickupService, 10.);
|
||||||
|
double expectedTransportCosts = 10.;
|
||||||
|
double expectedActivityCosts = 10.+10.+10.;
|
||||||
|
assertEquals(expectedTransportCosts+expectedActivityCosts,iCosts.getAdditionalCosts(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
package jsprit.core.algorithm.recreate;
|
||||||
|
|
||||||
|
import jsprit.core.algorithm.state.StateManager;
|
||||||
|
import jsprit.core.algorithm.state.UpdateVariableCosts;
|
||||||
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
|
import jsprit.core.problem.constraint.ConstraintManager;
|
||||||
|
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||||
|
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
|
import jsprit.core.problem.driver.Driver;
|
||||||
|
import jsprit.core.problem.job.Job;
|
||||||
|
import jsprit.core.problem.job.Service;
|
||||||
|
import jsprit.core.problem.misc.JobInsertionContext;
|
||||||
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
|
import jsprit.core.problem.solution.route.activity.PickupActivity;
|
||||||
|
import jsprit.core.problem.solution.route.activity.PickupService;
|
||||||
|
import jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||||
|
import jsprit.core.problem.solution.route.activity.TourActivity;
|
||||||
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleImpl;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleType;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleTypeImpl;
|
||||||
|
import jsprit.core.util.CostFactory;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by schroeder on 02.07.14.
|
||||||
|
*/
|
||||||
|
public class TestRouteLevelServiceInsertionCostEstimator {
|
||||||
|
|
||||||
|
private VehicleRoute route;
|
||||||
|
|
||||||
|
private VehicleRoutingTransportCosts routingCosts;
|
||||||
|
|
||||||
|
private VehicleRoutingActivityCosts activityCosts;
|
||||||
|
|
||||||
|
private StateManager stateManager;
|
||||||
|
|
||||||
|
private ConstraintManager constraintManager;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void doBefore(){
|
||||||
|
routingCosts = CostFactory.createEuclideanCosts();
|
||||||
|
|
||||||
|
activityCosts = new VehicleRoutingActivityCosts() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getActivityCost(TourActivity tourAct, double arrivalTime, Driver driver, Vehicle vehicle) {
|
||||||
|
return Math.max(0.,arrivalTime - tourAct.getTheoreticalLatestOperationStartTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
Service s1 = Service.Builder.newInstance("s1").setLocationId("10,0").setTimeWindow(TimeWindow.newInstance(10.,10.)).build();
|
||||||
|
Service s2 = Service.Builder.newInstance("s2").setLocationId("20,0").setTimeWindow(TimeWindow.newInstance(20.,20.)).build();
|
||||||
|
Service s3 = Service.Builder.newInstance("s3").setLocationId("30,0").setTimeWindow(TimeWindow.newInstance(30.,30.)).build();
|
||||||
|
|
||||||
|
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").build();
|
||||||
|
Vehicle vehicle = VehicleImpl.Builder.newInstance("vehicle").setStartLocationId("0,0").setType(type).build();
|
||||||
|
|
||||||
|
route = VehicleRoute.Builder.newInstance(vehicle).addService(s1).addService(s2).addService(s3).build();
|
||||||
|
|
||||||
|
stateManager = new StateManager(routingCosts);
|
||||||
|
stateManager.addStateUpdater(new UpdateVariableCosts(activityCosts,routingCosts,stateManager));
|
||||||
|
stateManager.informInsertionStarts(Arrays.asList(route), Collections.<Job>emptyList());
|
||||||
|
|
||||||
|
VehicleRoutingProblem vrp = mock(VehicleRoutingProblem.class);
|
||||||
|
when(vrp.getTransportCosts()).thenReturn(routingCosts);
|
||||||
|
|
||||||
|
constraintManager = new ConstraintManager(vrp,stateManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNewServiceNeedToBeInserted_itShouldReturnCorrectInsertionCosts(){
|
||||||
|
Service s4 = Service.Builder.newInstance("s4").setLocationId("5,0").setTimeWindow(TimeWindow.newInstance(5.,5.)).build();
|
||||||
|
// PickupActivity pickupService = new PickupService(s4);
|
||||||
|
JobInsertionContext context = new JobInsertionContext(route,s4,route.getVehicle(),route.getDriver(),0.);
|
||||||
|
RouteLevelActivityInsertionCostsEstimator estimator = new RouteLevelActivityInsertionCostsEstimator(routingCosts,activityCosts,stateManager);
|
||||||
|
estimator.setForwardLooking(0);
|
||||||
|
ServiceInsertionOnRouteLevelCalculator routeInserter = new ServiceInsertionOnRouteLevelCalculator(routingCosts,
|
||||||
|
activityCosts,estimator,constraintManager,constraintManager);
|
||||||
|
routeInserter.setStates(stateManager);
|
||||||
|
InsertionData iData = routeInserter.getInsertionData(route,s4,route.getVehicle(),route.getDepartureTime(),route.getDriver(),Double.MAX_VALUE);
|
||||||
|
assertEquals(0.,iData.getInsertionCost(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNewServiceNeedToBeInserted_itShouldReturnCorrectInsertionIndex(){
|
||||||
|
Service s4 = Service.Builder.newInstance("s4").setLocationId("5,0").setTimeWindow(TimeWindow.newInstance(5.,5.)).build();
|
||||||
|
// PickupActivity pickupService = new PickupService(s4);
|
||||||
|
JobInsertionContext context = new JobInsertionContext(route,s4,route.getVehicle(),route.getDriver(),0.);
|
||||||
|
RouteLevelActivityInsertionCostsEstimator estimator = new RouteLevelActivityInsertionCostsEstimator(routingCosts,activityCosts,stateManager);
|
||||||
|
estimator.setForwardLooking(0);
|
||||||
|
ServiceInsertionOnRouteLevelCalculator routeInserter = new ServiceInsertionOnRouteLevelCalculator(routingCosts,
|
||||||
|
activityCosts,estimator,constraintManager,constraintManager);
|
||||||
|
routeInserter.setStates(stateManager);
|
||||||
|
InsertionData iData = routeInserter.getInsertionData(route,s4,route.getVehicle(),route.getDepartureTime(),route.getDriver(),Double.MAX_VALUE);
|
||||||
|
assertEquals(0,iData.getDeliveryInsertionIndex(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNewServiceWithServiceTimeNeedToBeInserted_itShouldReturnCorrectInsertionData(){
|
||||||
|
Service s4 = Service.Builder.newInstance("s4").setServiceTime(10.).setLocationId("5,0").setTimeWindow(TimeWindow.newInstance(5.,5.)).build();
|
||||||
|
// PickupActivity pickupService = new PickupService(s4);
|
||||||
|
JobInsertionContext context = new JobInsertionContext(route,s4,route.getVehicle(),route.getDriver(),0.);
|
||||||
|
RouteLevelActivityInsertionCostsEstimator estimator = new RouteLevelActivityInsertionCostsEstimator(routingCosts,activityCosts,stateManager);
|
||||||
|
estimator.setForwardLooking(0);
|
||||||
|
ServiceInsertionOnRouteLevelCalculator routeInserter = new ServiceInsertionOnRouteLevelCalculator(routingCosts,
|
||||||
|
activityCosts,estimator,constraintManager,constraintManager);
|
||||||
|
routeInserter.setStates(stateManager);
|
||||||
|
InsertionData iData = routeInserter.getInsertionData(route,s4,route.getVehicle(),route.getDepartureTime(),route.getDriver(),Double.MAX_VALUE);
|
||||||
|
assertEquals(0,iData.getDeliveryInsertionIndex(),0.01);
|
||||||
|
assertEquals(30.,iData.getInsertionCost(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNewServiceWithServiceTimeNeedToBeInsertedAndRouteIsEmpty_itShouldReturnCorrectInsertionData(){
|
||||||
|
Service s4 = Service.Builder.newInstance("s4").setServiceTime(10.).setLocationId("5,0").setTimeWindow(TimeWindow.newInstance(5.,5.)).build();
|
||||||
|
// PickupActivity pickupService = new PickupService(s4);
|
||||||
|
VehicleRoute emptyroute = VehicleRoute.emptyRoute();
|
||||||
|
JobInsertionContext context = new JobInsertionContext(emptyroute,s4,route.getVehicle(),route.getDriver(),0.);
|
||||||
|
RouteLevelActivityInsertionCostsEstimator estimator = new RouteLevelActivityInsertionCostsEstimator(routingCosts,activityCosts,stateManager);
|
||||||
|
estimator.setForwardLooking(0);
|
||||||
|
ServiceInsertionOnRouteLevelCalculator routeInserter = new ServiceInsertionOnRouteLevelCalculator(routingCosts,
|
||||||
|
activityCosts,estimator,constraintManager,constraintManager);
|
||||||
|
routeInserter.setStates(stateManager);
|
||||||
|
InsertionData iData = routeInserter.getInsertionData(emptyroute,s4,route.getVehicle(),route.getDepartureTime(),route.getDriver(),Double.MAX_VALUE);
|
||||||
|
assertEquals(0,iData.getDeliveryInsertionIndex(),0.01);
|
||||||
|
assertEquals(10.,iData.getInsertionCost(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNewServiceWithServiceTimeAndTWNeedToBeInsertedAndRouteIsEmpty_itShouldReturnCorrectInsertionData(){
|
||||||
|
Service s4 = Service.Builder.newInstance("s4").setServiceTime(10.).setLocationId("5,0").setTimeWindow(TimeWindow.newInstance(3.,3.)).build();
|
||||||
|
// PickupActivity pickupService = new PickupService(s4);
|
||||||
|
VehicleRoute emptyroute = VehicleRoute.emptyRoute();
|
||||||
|
JobInsertionContext context = new JobInsertionContext(emptyroute,s4,route.getVehicle(),route.getDriver(),0.);
|
||||||
|
RouteLevelActivityInsertionCostsEstimator estimator = new RouteLevelActivityInsertionCostsEstimator(routingCosts,activityCosts,stateManager);
|
||||||
|
estimator.setForwardLooking(0);
|
||||||
|
ServiceInsertionOnRouteLevelCalculator routeInserter = new ServiceInsertionOnRouteLevelCalculator(routingCosts,
|
||||||
|
activityCosts,estimator,constraintManager,constraintManager);
|
||||||
|
routeInserter.setStates(stateManager);
|
||||||
|
InsertionData iData = routeInserter.getInsertionData(emptyroute,s4,route.getVehicle(),route.getDepartureTime(),route.getDriver(),Double.MAX_VALUE);
|
||||||
|
assertEquals(0,iData.getDeliveryInsertionIndex(),0.01);
|
||||||
|
assertEquals(10.+2.,iData.getInsertionCost(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,14 @@ import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
|
|
||||||
public class CostFactory {
|
public class CostFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return manhattanCosts.
|
||||||
|
* <p>
|
||||||
|
* This retrieves coordinates from locationIds. LocationId has to be locId="{x},{y}". For example,
|
||||||
|
* locId="10,10" is interpreted such that x=10 and y=10.
|
||||||
|
*
|
||||||
|
* @return manhattanCosts
|
||||||
|
*/
|
||||||
public static VehicleRoutingTransportCosts createManhattanCosts(){
|
public static VehicleRoutingTransportCosts createManhattanCosts(){
|
||||||
Locations locations = new Locations(){
|
Locations locations = new Locations(){
|
||||||
|
|
||||||
|
|
@ -19,6 +27,14 @@ public class CostFactory {
|
||||||
return new ManhattanCosts(locations);
|
return new ManhattanCosts(locations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return euclideanCosts.
|
||||||
|
* <p>
|
||||||
|
* This retrieves coordinates from locationIds. LocationId has to be locId="{x},{y}". For example,
|
||||||
|
* locId="10,10" is interpreted such that x=10 and y=10.
|
||||||
|
*
|
||||||
|
* @return euclidean
|
||||||
|
*/
|
||||||
public static VehicleRoutingTransportCosts createEuclideanCosts(){
|
public static VehicleRoutingTransportCosts createEuclideanCosts(){
|
||||||
Locations locations = new Locations(){
|
Locations locations = new Locations(){
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue