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
|
|
@ -39,15 +39,15 @@ final class AuxilliaryCostCalculator {
|
|||
this.routingCosts = routingCosts;
|
||||
this.activityCosts = actCosts;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path
|
||||
* @param depTime
|
||||
* @param driver
|
||||
* @param vehicle
|
||||
* @return
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path activity path to get the costs for
|
||||
* @param depTime departure time at first activity in path
|
||||
* @param driver driver of vehicle
|
||||
* @param vehicle vehicle running the path
|
||||
* @return cost of path
|
||||
*/
|
||||
public double costOfPath(final List<TourActivity> path, final double depTime, final Driver driver, final Vehicle vehicle){
|
||||
if(path.isEmpty()){
|
||||
return 0.0;
|
||||
|
|
@ -69,9 +69,7 @@ final class AuxilliaryCostCalculator {
|
|||
double transportTime = routingCosts.getTransportTime(prevAct.getLocationId(), act.getLocationId(), departureTimePrevAct, driver, vehicle);
|
||||
cost += transportCost;
|
||||
double actStartTime = departureTimePrevAct + transportTime;
|
||||
double earliestOperationStartTime = Math.max(actStartTime, act.getTheoreticalEarliestOperationStartTime());
|
||||
double actEndTime = earliestOperationStartTime + act.getOperationTime();
|
||||
departureTimePrevAct = actEndTime;
|
||||
departureTimePrevAct = Math.max(actStartTime, act.getTheoreticalEarliestOperationStartTime()) + act.getOperationTime();
|
||||
cost += activityCosts.getActivityCost(act, actStartTime, driver, vehicle);
|
||||
prevAct = act;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,10 +296,11 @@ class CalculatorBuilder {
|
|||
}
|
||||
|
||||
private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, RouteAndActivityStateGetter activityStates2, int forwardLooking, int solutionMemory){
|
||||
int after = forwardLooking;
|
||||
ActivityInsertionCostsCalculator routeLevelCostEstimator;
|
||||
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){
|
||||
routeLevelCostEstimator = new ActivityInsertionCostsCalculator(){
|
||||
|
|
@ -318,7 +319,7 @@ class CalculatorBuilder {
|
|||
routeLevelCostEstimator = activityInsertionCostCalculator;
|
||||
}
|
||||
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).setStates(activityStates2);
|
||||
|
||||
|
|
|
|||
|
|
@ -57,14 +57,13 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost
|
|||
path.add(prevAct); path.add(newAct); path.add(nextAct);
|
||||
int actIndex;
|
||||
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)); }
|
||||
|
||||
/**
|
||||
/*
|
||||
* 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));
|
||||
|
||||
return new ActivityInsertionCosts(additionalCosts, 0.0);
|
||||
|
|
@ -93,4 +92,7 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost
|
|||
return forwardLookingPath;
|
||||
}
|
||||
|
||||
public void setForwardLooking(int nActivities) {
|
||||
this.nuOfActivities2LookForward = nActivities;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,31 +72,17 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsC
|
|||
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
|
||||
|
||||
private int nuOfActsForwardLooking = 0;
|
||||
|
||||
//
|
||||
private int memorySize = 2;
|
||||
|
||||
private Start start;
|
||||
|
||||
private End end;
|
||||
|
||||
private Neighborhood neighborhood = new Neighborhood() {
|
||||
|
||||
@Override
|
||||
public boolean areNeighbors(String location1, String location2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
public void setTourActivityFactory(TourActivityFactory tourActivityFactory){
|
||||
this.tourActivityFactory=tourActivityFactory;
|
||||
}
|
||||
|
||||
public void setNeighborhood(Neighborhood neighborhood) {
|
||||
this.neighborhood = neighborhood;
|
||||
logger.info("initialise neighborhood " + neighborhood);
|
||||
}
|
||||
|
||||
|
||||
public void setMemorySize(int memorySize) {
|
||||
this.memorySize = memorySize;
|
||||
logger.info("set [solutionMemory="+memorySize+"]");
|
||||
|
|
@ -182,35 +168,34 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsC
|
|||
* k=serviceAct2Insert
|
||||
*/
|
||||
for(TourActivity nextAct : tour.getActivities()){
|
||||
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
|
||||
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
|
||||
if(status.equals(ConstraintsStatus.FULFILLED)){
|
||||
/**
|
||||
* builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking}
|
||||
*/
|
||||
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
|
||||
ConstraintsStatus hardActivityConstraintsStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
|
||||
if(hardActivityConstraintsStatus.equals(ConstraintsStatus.FULFILLED)){
|
||||
/**
|
||||
* builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking}
|
||||
*/
|
||||
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
|
||||
|
||||
/**
|
||||
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
|
||||
*/
|
||||
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts();
|
||||
/**
|
||||
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
|
||||
*/
|
||||
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts();
|
||||
|
||||
/**
|
||||
* memorize it in insertion-queue
|
||||
*/
|
||||
if(insertion_cost_approximation < best_known_insertion_costs){
|
||||
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
|
||||
}
|
||||
}
|
||||
else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
|
||||
loopBroken = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* memorize it in insertion-queue
|
||||
*/
|
||||
if(insertion_cost_approximation < best_known_insertion_costs){
|
||||
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
|
||||
}
|
||||
}
|
||||
else if(hardActivityConstraintsStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
|
||||
loopBroken = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate transport and activity costs with new vehicle (without inserting k)
|
||||
*/
|
||||
|
||||
/**
|
||||
* calculate transport and activity costs with new vehicle (without inserting k)
|
||||
*/
|
||||
double transportCost_prevAct_nextAct_newVehicle = transportCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), prevActDepTime_newVehicle, newDriver, newVehicle);
|
||||
double transportTime_prevAct_nextAct_newVehicle = transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActDepTime_newVehicle, newDriver, newVehicle);
|
||||
double arrTime_nextAct_newVehicle = prevActDepTime_newVehicle + transportTime_prevAct_nextAct_newVehicle;
|
||||
|
|
@ -237,26 +222,24 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsC
|
|||
}
|
||||
if(!loopBroken){
|
||||
End nextAct = end;
|
||||
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
|
||||
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
|
||||
if(status.equals(ConstraintsStatus.FULFILLED)){
|
||||
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
|
||||
if(actInsertionCosts != null){
|
||||
/**
|
||||
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
|
||||
*/
|
||||
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts();
|
||||
ConstraintsStatus hardActivityConstraintsStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
|
||||
if(hardActivityConstraintsStatus.equals(ConstraintsStatus.FULFILLED)){
|
||||
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
|
||||
if(actInsertionCosts != null){
|
||||
/**
|
||||
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
|
||||
*/
|
||||
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts();
|
||||
|
||||
/**
|
||||
* memorize it in insertion-queue
|
||||
*/
|
||||
if(insertion_cost_approximation < best_known_insertion_costs){
|
||||
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* memorize it in insertion-queue
|
||||
*/
|
||||
if(insertion_cost_approximation < best_known_insertion_costs){
|
||||
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue