mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
improve route level insertion
This commit is contained in:
parent
4e99daeebf
commit
d2b896c104
4 changed files with 64 additions and 142 deletions
|
|
@ -13,7 +13,6 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -23,6 +22,7 @@ import java.util.PriorityQueue;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import util.Neighborhood;
|
import util.Neighborhood;
|
||||||
|
import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
|
||||||
import algorithms.HardConstraints.HardRouteLevelConstraint;
|
import algorithms.HardConstraints.HardRouteLevelConstraint;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
|
|
@ -90,11 +90,12 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
logger.info("set [solutionMemory="+memorySize+"]");
|
logger.info("set [solutionMemory="+memorySize+"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
public CalculatesServiceInsertionOnRouteLevel(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, HardRouteLevelConstraint hardRouteLevelConstraint) {
|
public CalculatesServiceInsertionOnRouteLevel(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, HardRouteLevelConstraint hardRouteLevelConstraint, ActivityInsertionCostsCalculator activityInsertionCostsCalculator) {
|
||||||
super();
|
super();
|
||||||
this.transportCosts = vehicleRoutingCosts;
|
this.transportCosts = vehicleRoutingCosts;
|
||||||
this.activityCosts = costFunc;
|
this.activityCosts = costFunc;
|
||||||
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
|
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
|
||||||
|
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
|
||||||
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(transportCosts, activityCosts);
|
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(transportCosts, activityCosts);
|
||||||
logger.info("initialise " + this);
|
logger.info("initialise " + this);
|
||||||
}
|
}
|
||||||
|
|
@ -170,23 +171,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
/**
|
/**
|
||||||
* 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}
|
||||||
*/
|
*/
|
||||||
|
InsertionContext iContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, prevActDepTime_newVehicle);
|
||||||
//---------------------------
|
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(iContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
|
||||||
//ActivityInsertionCostsEstimator
|
if(actInsertionCosts != null){
|
||||||
List<TourActivity> path = new ArrayList<TourActivity>();
|
|
||||||
path.add(prevAct); path.add(serviceAct2Insert); path.add(nextAct);
|
|
||||||
if(nuOfActsForwardLooking > 0){ path.addAll(getForwardLookingPath(currentRoute,actIndex)); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* calculates the path costs with new vehicle, c(forwardPath,newVehicle).
|
|
||||||
*/
|
|
||||||
double forwardPathCost_newVehicle = auxilliaryPathCostCalculator.costOfPath(path, prevActDepTime_newVehicle, newDriver, 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)
|
* 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 + forwardPathCost_newVehicle - pathCost_oldVehicle(currentRoute,path);
|
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* memorize it in insertion-queue
|
* memorize it in insertion-queue
|
||||||
|
|
@ -194,7 +185,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
if(insertion_cost_approximation < best_known_insertion_costs){
|
if(insertion_cost_approximation < best_known_insertion_costs){
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -227,19 +218,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
End nextAct = end;
|
End nextAct = end;
|
||||||
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
|
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
|
||||||
|
|
||||||
//----------------------------
|
InsertionContext iContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, prevActDepTime_newVehicle);
|
||||||
//ActivityInsertionCostsEstimator
|
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(iContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
|
||||||
/**
|
if(actInsertionCosts != null){
|
||||||
* calculates the path costs with new vehicle, c(forwardPath,newVehicle).
|
|
||||||
*/
|
|
||||||
List<TourActivity> path = Arrays.asList(prevAct,serviceAct2Insert,end);
|
|
||||||
double forwardPathCost_newVehicle = auxilliaryPathCostCalculator.costOfPath(path, prevActDepTime_newVehicle, newDriver, 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)
|
* 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 + forwardPathCost_newVehicle - pathCost_oldVehicle(currentRoute,path);
|
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* memorize it in insertion-queue
|
* memorize it in insertion-queue
|
||||||
|
|
@ -248,6 +233,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -256,14 +242,14 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(memorySize==0){
|
if(memorySize==0){ // return bestInsertion
|
||||||
InsertionData insertion = bestInsertionsQueue.poll();
|
InsertionData insertion = bestInsertionsQueue.poll();
|
||||||
if(insertion != null){
|
if(insertion != null){
|
||||||
best_insertion_index = insertion.getDeliveryInsertionIndex();
|
best_insertion_index = insertion.getDeliveryInsertionIndex();
|
||||||
best_insertion_costs = insertion.getInsertionCost();
|
best_insertion_costs = insertion.getInsertionCost();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
for(int i=0;i<memorySize;i++){
|
for(int i=0;i<memorySize;i++){
|
||||||
InsertionData data = bestInsertionsQueue.poll();
|
InsertionData data = bestInsertionsQueue.poll();
|
||||||
if(data == null){
|
if(data == null){
|
||||||
|
|
@ -291,6 +277,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
best_insertion_costs = insertion_costs;
|
best_insertion_costs = insertion_costs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.noInsertionFound();
|
if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.noInsertionFound();
|
||||||
return new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver);
|
return new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver);
|
||||||
}
|
}
|
||||||
|
|
@ -323,36 +310,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private double pathCost_oldVehicle(VehicleRoute vehicleRoute, List<TourActivity> path) {
|
private double sumOf_prevCosts_oldVehicle(VehicleRoute vehicleRoute, TourActivity act) {
|
||||||
TourActivity act = path.get(path.size()-1);
|
|
||||||
if(act instanceof End){
|
if(act instanceof End){
|
||||||
return stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble();
|
return stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble();
|
||||||
}
|
}
|
||||||
return stateManager.getActivityState(act,StateTypes.COSTS).toDouble();
|
return stateManager.getActivityState(act,StateTypes.COSTS).toDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* returns the path or the partial route r_partial = {j+1,j+2,...,j+nuOfActsForwardLooking}
|
|
||||||
*
|
|
||||||
* @param route
|
|
||||||
* @param actIndex
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private List<TourActivity> getForwardLookingPath(VehicleRoute route, int actIndex) {
|
|
||||||
List<TourActivity> forwardLookingPath = new ArrayList<TourActivity>();
|
|
||||||
int nuOfActsInPath = 0;
|
|
||||||
int index = actIndex + 1;
|
|
||||||
while(index < route.getTourActivities().getActivities().size() && nuOfActsInPath < nuOfActsForwardLooking){
|
|
||||||
forwardLookingPath.add(route.getTourActivities().getActivities().get(index));
|
|
||||||
index++;
|
|
||||||
nuOfActsInPath++;
|
|
||||||
}
|
|
||||||
if(nuOfActsInPath < nuOfActsForwardLooking){
|
|
||||||
forwardLookingPath.add(route.getEnd());
|
|
||||||
}
|
|
||||||
return forwardLookingPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a comparator to sort insertion-data in insertionQueue in ascending order according insertion costs.
|
* creates a comparator to sort insertion-data in insertionQueue in ascending order according insertion costs.
|
||||||
* @return
|
* @return
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,8 @@ class CalculatorBuilder {
|
||||||
|
|
||||||
private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, StateManager activityStates2, int forwardLooking, int solutionMemory){
|
private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, StateManager activityStates2, int forwardLooking, int solutionMemory){
|
||||||
int after = forwardLooking;
|
int after = forwardLooking;
|
||||||
JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts(), hardRouteLevelConstraint);
|
ActivityInsertionCostsCalculator routeLevelCostEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager, activityStates2);
|
||||||
|
JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager, routeLevelCostEstimator);
|
||||||
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNuOfActsForwardLooking(after);
|
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNuOfActsForwardLooking(after);
|
||||||
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setMemorySize(solutionMemory);
|
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setMemorySize(solutionMemory);
|
||||||
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood());
|
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood());
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,6 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost
|
||||||
|
|
||||||
private HardActivityLevelConstraint hardConstraint;
|
private HardActivityLevelConstraint hardConstraint;
|
||||||
|
|
||||||
private VehicleRoutingTransportCosts routingCosts;
|
|
||||||
|
|
||||||
private VehicleRoutingActivityCosts activityCosts;
|
private VehicleRoutingActivityCosts activityCosts;
|
||||||
|
|
||||||
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
|
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
|
||||||
|
|
@ -47,9 +45,9 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost
|
||||||
|
|
||||||
public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint, StateManager stateManager) {
|
public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint, StateManager stateManager) {
|
||||||
super();
|
super();
|
||||||
this.routingCosts = routingCosts;
|
|
||||||
this.activityCosts = actCosts;
|
this.activityCosts = actCosts;
|
||||||
this.hardConstraint = hardActivityLevelConstraint;
|
this.hardConstraint = hardActivityLevelConstraint;
|
||||||
|
this.stateManager = stateManager;
|
||||||
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(routingCosts, activityCosts);
|
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(routingCosts, activityCosts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,46 +73,6 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost
|
||||||
|
|
||||||
return new ActivityInsertionCosts(additionalCosts, 0.0);
|
return new ActivityInsertionCosts(additionalCosts, 0.0);
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
|
||||||
// double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
|
||||||
//
|
|
||||||
// double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct;
|
|
||||||
//
|
|
||||||
// double newAct_endTime = CalcUtils.getActivityEndTime(newAct_arrTime, newAct);
|
|
||||||
//
|
|
||||||
// double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
|
||||||
//
|
|
||||||
// double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
|
||||||
// double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
|
||||||
//
|
|
||||||
// double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct;
|
|
||||||
//
|
|
||||||
// double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
|
||||||
//
|
|
||||||
// double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct;
|
|
||||||
//
|
|
||||||
// double oldCosts;
|
|
||||||
// double oldTime;
|
|
||||||
// if(iFacts.getRoute().isEmpty()){
|
|
||||||
// oldCosts = 0.0;
|
|
||||||
// oldTime = 0.0;
|
|
||||||
// }
|
|
||||||
// else{
|
|
||||||
// double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
|
||||||
// double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getNewDriver(), iFacts.getNewVehicle());
|
|
||||||
//
|
|
||||||
// double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
|
||||||
// oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct;
|
|
||||||
// oldTime = (nextAct.getArrTime() - iFacts.getRoute().getDepartureTime());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// double additionalCosts = totalCosts - oldCosts;
|
|
||||||
// double additionalTime = (nextAct_arrTime - iFacts.getNewDepTime()) - oldTime;
|
|
||||||
//
|
|
||||||
// return new ActivityInsertionCosts(additionalCosts,additionalTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private double actCostsOld(VehicleRoute vehicleRoute, TourActivity act) {
|
private double actCostsOld(VehicleRoute vehicleRoute, TourActivity act) {
|
||||||
|
|
|
||||||
|
|
@ -147,14 +147,13 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
|
||||||
states = new StateManagerImpl();
|
states = new StateManagerImpl();
|
||||||
|
|
||||||
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
|
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
|
||||||
serviceInsertion = new CalculatesServiceInsertionOnRouteLevel(costs,activityCosts, hardRouteLevelConstraint);
|
ActivityInsertionCostsCalculator actInsertionCostCalculator = new RouteLevelActivityInsertionCostsEstimator(costs, activityCosts, new HardConstraints.HardTimeWindowActivityLevelConstraint(states, costs), states);
|
||||||
|
serviceInsertion = new CalculatesServiceInsertionOnRouteLevel(costs,activityCosts, new HardConstraints.HardLoadConstraint(states), actInsertionCostCalculator);
|
||||||
serviceInsertion.setNuOfActsForwardLooking(4);
|
serviceInsertion.setNuOfActsForwardLooking(4);
|
||||||
serviceInsertion.setStates(states);
|
serviceInsertion.setStates(states);
|
||||||
|
|
||||||
updateStates = new UpdateStates(states, costs, activityCosts);
|
updateStates = new UpdateStates(states, costs, activityCosts);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TourActivity getActivityMock(String id, double earliestOperationStart, double currCost){
|
public TourActivity getActivityMock(String id, double earliestOperationStart, double currCost){
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue