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

experiment with insertionCalcs

This commit is contained in:
Stefan Schroeder 2013-08-21 13:53:27 +02:00
parent 50ca0971a5
commit 099d01ddd8
47 changed files with 1711 additions and 1343 deletions

View file

@ -0,0 +1,50 @@
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class BackwardInTimeListeners {
interface BackwardInTimeListener{
public void start(VehicleRoute route);
public void prevActivity(TourActivity act, double latestDepartureTime, double latestOperationStartTime);
public void finnish();
}
private Collection<BackwardInTimeListener> listeners = new ArrayList<BackwardInTimeListener>();
public void addListener(BackwardInTimeListener l){
listeners.add(l);
}
public void start(VehicleRoute route){
for(BackwardInTimeListener l : listeners){ l.start(route); }
}
/**
* Informs listener about nextActivity.
*
* <p>LatestDepartureTime is the theoretical latest departureTime to meet the latestOperationStartTimeWindow at the nextActivity (forward in time), i.e.
* assume act_i and act_j are two successive activities and the latestDepTime of act_j is 10pm. With a travelTime from act_i to act_j of 1h the latestDepartureTime at act_i is 9pm.
* However, the latestOperationStartTime of act_i is 8pm, then (with a serviceTime of 0) the latestOperationStartTime at act_i amounts to 8pm.
*
* @param act
* @param latestDepartureTime
* @param latestOperationStartTime
*/
public void prevActivity(TourActivity act, double latestDepartureTime, double latestOperationStartTime){
for(BackwardInTimeListener l : listeners){ l.prevActivity(act,latestDepartureTime,latestOperationStartTime); }
}
public void finnish(){
for(BackwardInTimeListener l : listeners){ l.finnish(); }
}
}

View file

@ -33,182 +33,182 @@ import basics.Job;
import basics.algo.InsertionListener; import basics.algo.InsertionListener;
import basics.route.VehicleRoute; import basics.route.VehicleRoute;
//
//
/** ///**
* // *
* @author stefan schroeder // * @author stefan schroeder
* // *
*/ // */
//
final class BestInsertionConcurrent implements InsertionStrategy{ //final class BestInsertionConcurrent implements InsertionStrategy{
//
public static BestInsertionConcurrent newInstance(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads){ // public static BestInsertionConcurrent newInstance(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads){
return new BestInsertionConcurrent(routeAlgorithm, executor, nuOfThreads); // return new BestInsertionConcurrent(routeAlgorithm, executor, nuOfThreads);
} // }
//
static class Batch { // static class Batch {
List<VehicleRoute> routes = new ArrayList<VehicleRoute>(); // List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
//
} // }
//
private static Logger logger = Logger.getLogger(BestInsertionConcurrent.class); // private static Logger logger = Logger.getLogger(BestInsertionConcurrent.class);
//
private Random random = RandomNumberGeneration.getRandom(); // private Random random = RandomNumberGeneration.getRandom();
//
private RouteAlgorithm routeAlgorithm; // private RouteAlgorithm routeAlgorithm;
//
// private ExecutorService executor; //// private ExecutorService executor;
//
private int nuOfBatches; // private int nuOfBatches;
//
private ExecutorCompletionService<Insertion> completionService; // private ExecutorCompletionService<Insertion> completionService;
//
public void setRandom(Random random) { // public void setRandom(Random random) {
this.random = random; // this.random = random;
} // }
//
private BestInsertionConcurrent(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads) { // private BestInsertionConcurrent(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads) {
super(); // super();
this.routeAlgorithm = routeAlgorithm; // this.routeAlgorithm = routeAlgorithm;
// this.executor = executor; //// this.executor = executor;
logger.info("initialise " + this); // logger.info("initialise " + this);
this.nuOfBatches = nuOfThreads; // this.nuOfBatches = nuOfThreads;
completionService = new ExecutorCompletionService<Insertion>(executor); // completionService = new ExecutorCompletionService<Insertion>(executor);
} // }
//
@Override // @Override
public String toString() { // public String toString() {
return "[name=concurrentBestInsertion]"; // return "[name=concurrentBestInsertion]";
} // }
//
@Override // @Override
public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) { // public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs); // List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
Collections.shuffle(unassignedJobList, random); // Collections.shuffle(unassignedJobList, random);
// informInsertionStarts(vehicleRoutes,unassignedJobs.size()); //// informInsertionStarts(vehicleRoutes,unassignedJobs.size());
int inserted = 0; // int inserted = 0;
for(final Job unassignedJob : unassignedJobList){ // for(final Job unassignedJob : unassignedJobList){
VehicleRoute insertIn = null; // VehicleRoute insertIn = null;
Insertion bestInsertion = null; // Insertion bestInsertion = null;
double bestInsertionCost = Double.MAX_VALUE; // double bestInsertionCost = Double.MAX_VALUE;
//
List<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches); // List<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches);
//
for(final Batch batch : batches){ // for(final Batch batch : batches){
completionService.submit(new Callable<Insertion>() { // completionService.submit(new Callable<Insertion>() {
//
@Override // @Override
public Insertion call() throws Exception { // public Insertion call() throws Exception {
return getBestInsertion(batch,unassignedJob); // return getBestInsertion(batch,unassignedJob);
} // }
//
}); // });
//
} // }
//
try{ // try{
for(int i=0;i<batches.size();i++){ // for(int i=0;i<batches.size();i++){
Future<Insertion> futureIData = completionService.take(); // Future<Insertion> futureIData = completionService.take();
Insertion insertion = futureIData.get(); // Insertion insertion = futureIData.get();
if(insertion == null) continue; // if(insertion == null) continue;
if(insertion.getInsertionData().getInsertionCost() < bestInsertionCost){ // if(insertion.getInsertionData().getInsertionCost() < bestInsertionCost){
bestInsertion = insertion; // bestInsertion = insertion;
bestInsertionCost = insertion.getInsertionData().getInsertionCost(); // bestInsertionCost = insertion.getInsertionData().getInsertionCost();
} // }
} // }
} // }
catch(InterruptedException e){ // catch(InterruptedException e){
Thread.currentThread().interrupt(); // Thread.currentThread().interrupt();
} // }
catch (ExecutionException e) { // catch (ExecutionException e) {
e.printStackTrace(); // e.printStackTrace();
logger.error(e.getCause().toString()); // logger.error(e.getCause().toString());
System.exit(1); // System.exit(1);
} // }
//
if(bestInsertion != null){ // if(bestInsertion != null){
// informBeforeJobInsertion(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute()); //// informBeforeJobInsertion(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
insertIn = bestInsertion.getRoute(); // insertIn = bestInsertion.getRoute();
// logger.debug("insert job="+unassignedJob+" at index=" + bestInsertion.getInsertionData().getInsertionIndex() + " delta cost=" + bestInsertion.getInsertionData().getInsertionCost()); //// logger.debug("insert job="+unassignedJob+" at index=" + bestInsertion.getInsertionData().getInsertionIndex() + " delta cost=" + bestInsertion.getInsertionData().getInsertionCost());
routeAlgorithm.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute()); // routeAlgorithm.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
} // }
else { // else {
// VehicleRoute newRoute = VehicleRoute.emptyRoute(); //// VehicleRoute newRoute = VehicleRoute.emptyRoute();
// InsertionData bestI = routeAlgorithm.calculateBestInsertion(newRoute, unassignedJob, Double.MAX_VALUE); //// InsertionData bestI = routeAlgorithm.calculateBestInsertion(newRoute, unassignedJob, Double.MAX_VALUE);
// if(bestI instanceof InsertionData.NoInsertionFound) //// if(bestI instanceof InsertionData.NoInsertionFound)
throw new IllegalStateException("given the vehicles, could not create a valid solution.\n\tthe reason might be" + // throw new IllegalStateException("given the vehicles, could not create a valid solution.\n\tthe reason might be" +
" inappropriate vehicle capacity.\n\tthe job that does not fit in any vehicle anymore is \n\t" + unassignedJob); // " inappropriate vehicle capacity.\n\tthe job that does not fit in any vehicle anymore is \n\t" + unassignedJob);
// insertIn = newRoute; //// insertIn = newRoute;
// informBeforeJobInsertion(unassignedJob,bestI,newRoute); //// informBeforeJobInsertion(unassignedJob,bestI,newRoute);
// routeAlgorithm.insertJob(unassignedJob,bestI,newRoute); //// routeAlgorithm.insertJob(unassignedJob,bestI,newRoute);
// vehicleRoutes.add(newRoute); //// vehicleRoutes.add(newRoute);
} // }
inserted++; // inserted++;
// informJobInserted((unassignedJobList.size()-inserted), unassignedJob, insertIn); //// informJobInserted((unassignedJobList.size()-inserted), unassignedJob, insertIn);
} // }
// informInsertionEndsListeners(vehicleRoutes); //// informInsertionEndsListeners(vehicleRoutes);
} // }
//
private Insertion getBestInsertion(Batch batch, Job unassignedJob) { // private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
Insertion bestInsertion = null; // Insertion bestInsertion = null;
double bestInsertionCost = Double.MAX_VALUE; // double bestInsertionCost = Double.MAX_VALUE;
for(VehicleRoute vehicleRoute : batch.routes){ // for(VehicleRoute vehicleRoute : batch.routes){
InsertionData iData = routeAlgorithm.calculateBestInsertion(vehicleRoute, unassignedJob, bestInsertionCost); // InsertionData iData = routeAlgorithm.calculateBestInsertion(vehicleRoute, unassignedJob, bestInsertionCost);
if(iData instanceof NoInsertionFound) continue; // if(iData instanceof NoInsertionFound) continue;
if(iData.getInsertionCost() < bestInsertionCost){ // if(iData.getInsertionCost() < bestInsertionCost){
bestInsertion = new Insertion(vehicleRoute,iData); // bestInsertion = new Insertion(vehicleRoute,iData);
bestInsertionCost = iData.getInsertionCost(); // bestInsertionCost = iData.getInsertionCost();
}
}
return bestInsertion;
}
private List<Batch> distributeRoutes(Collection<VehicleRoute> vehicleRoutes, int nuOfBatches) {
List<Batch> batches = new ArrayList<Batch>();
for(int i=0;i<nuOfBatches;i++) batches.add(new Batch());
/*
* if route.size < nuOfBatches add as much routes as empty batches are available
* else add one empty route anyway
*/
// if(vehicleRoutes.size()<nuOfBatches){
// int nOfNewRoutes = nuOfBatches-vehicleRoutes.size();
// for(int i=0;i<nOfNewRoutes;i++){
// vehicleRoutes.add(VehicleRoute.emptyRoute());
// } // }
// } // }
// else{ // return bestInsertion;
vehicleRoutes.add(VehicleRoute.emptyRoute()); // }
//
// private List<Batch> distributeRoutes(Collection<VehicleRoute> vehicleRoutes, int nuOfBatches) {
// List<Batch> batches = new ArrayList<Batch>();
// for(int i=0;i<nuOfBatches;i++) batches.add(new Batch());
// /*
// * if route.size < nuOfBatches add as much routes as empty batches are available
// * else add one empty route anyway
// */
//// if(vehicleRoutes.size()<nuOfBatches){
//// int nOfNewRoutes = nuOfBatches-vehicleRoutes.size();
//// for(int i=0;i<nOfNewRoutes;i++){
//// vehicleRoutes.add(VehicleRoute.emptyRoute());
//// }
//// }
//// else{
// vehicleRoutes.add(VehicleRoute.emptyRoute());
//// }
// /*
// * distribute routes to batches equally
// */
// int count = 0;
// for(VehicleRoute route : vehicleRoutes){
// if(count == nuOfBatches) count=0;
// batches.get(count).routes.add(route);
// count++;
// } // }
/* // return batches;
* distribute routes to batches equally // }
*/ //
int count = 0; //
for(VehicleRoute route : vehicleRoutes){ // @Override
if(count == nuOfBatches) count=0; // public void removeListener(InsertionListener insertionListener) {
batches.get(count).routes.add(route); // // TODO Auto-generated method stub
count++; //
} // }
return batches; //
} // @Override
// public Collection<InsertionListener> getListeners() {
// // TODO Auto-generated method stub
@Override // return null;
public void removeListener(InsertionListener insertionListener) { // }
// TODO Auto-generated method stub //
// @Override
} // public void addListener(InsertionListener insertionListener) {
// // TODO Auto-generated method stub
@Override //
public Collection<InsertionListener> getListeners() { // }
// TODO Auto-generated method stub //
return null; //}
}
@Override
public void addListener(InsertionListener insertionListener) {
// TODO Auto-generated method stub
}
}

View file

@ -15,8 +15,7 @@ package algorithms;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import util.Neighborhood; import util.Neighborhood;
import algorithms.StatesContainer.State;
import algorithms.RouteStates.ActivityState;
import basics.Job; import basics.Job;
import basics.Service; import basics.Service;
import basics.costs.VehicleRoutingActivityCosts; import basics.costs.VehicleRoutingActivityCosts;
@ -28,8 +27,8 @@ import basics.route.Start;
import basics.route.TourActivities; import basics.route.TourActivities;
import basics.route.TourActivity; import basics.route.TourActivity;
import basics.route.Vehicle; import basics.route.Vehicle;
import basics.route.VehicleRoute;
import basics.route.VehicleImpl.NoVehicle; import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
@ -37,7 +36,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertion.class); private static final Logger logger = Logger.getLogger(CalculatesServiceInsertion.class);
private RouteStates routeStates; private StatesContainer states;
private VehicleRoutingTransportCosts routingCosts; private VehicleRoutingTransportCosts routingCosts;
@ -62,12 +61,8 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
logger.info("initialise neighborhood " + neighborhood); logger.info("initialise neighborhood " + neighborhood);
} }
public void setActivityStates(RouteStates actStates){ public void setActivityStates(StatesContainer activityStates2){
this.routeStates = actStates; this.states = activityStates2;
}
public ActivityState state(TourActivity act){
return routeStates.getState(act);
} }
public CalculatesServiceInsertion(VehicleRoutingTransportCosts vehicleRoutingTransportCosts, VehicleRoutingActivityCosts vehicleRoutingActivityCosts) { public CalculatesServiceInsertion(VehicleRoutingTransportCosts vehicleRoutingTransportCosts, VehicleRoutingActivityCosts vehicleRoutingActivityCosts) {
@ -96,21 +91,25 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
double bestCost = bestKnownCosts; double bestCost = bestKnownCosts;
Service service = (Service)jobToInsert; Service service = (Service)jobToInsert;
if(routeStates.getRouteState(currentRoute).getLoad() + service.getCapacityDemand() > newVehicle.getCapacity()){ int currentLoad = (int) states.getRouteState(currentRoute, StateTypes.LOAD).toDouble();
if(currentLoad + service.getCapacityDemand() > newVehicle.getCapacity()){
return InsertionData.noInsertionFound(); return InsertionData.noInsertionFound();
} }
int insertionIndex = InsertionData.NO_INDEX; int insertionIndex = InsertionData.NO_INDEX;
TourActivity deliveryAct2Insert = ServiceActivity.newInstance(service); TourActivity deliveryAct2Insert = ServiceActivity.newInstance(service);
// TourActivity deliveryAct2Insert = actStates.getActivity(service, true);
initialiseStartAndEnd(newVehicle, newVehicleDepartureTime); initialiseStartAndEnd(newVehicle, newVehicleDepartureTime);
TourActivity prevAct = start; TourActivity prevAct = start;
double prevCostInOriginalTour = 0.0; double prevCostInOriginalTour = 0.0;
int actIndex = 0; int actIndex = 0;
// logger.debug(prevAct.toString());
for(TourActivity nextAct : tour.getActivities()){ for(TourActivity nextAct : tour.getActivities()){
double nextCostInOriginalTour = state(nextAct).getCurrentCost(); // logger.debug(prevAct.toString() + " arrTime=" + prevAct.getArrTime() + " endTime=" + prevAct.getEndTime());
// logger.debug(deliveryAct2Insert.toString() + " arrTime=" + deliveryAct2Insert.getArrTime() + " endTime=" + deliveryAct2Insert.getEndTime());
// logger.debug(nextAct.toString() + " arrTime=" + nextAct.getArrTime() + " endTime=" + nextAct.getEndTime());
double nextCostInOriginalTour = states.getActivityState(nextAct,StateTypes.COSTS).toDouble();
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){ if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
double mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle, bestCost, nextCostInOriginalTour - prevCostInOriginalTour); double mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle, bestCost, nextCostInOriginalTour - prevCostInOriginalTour);
if(mc < bestCost){ if(mc < bestCost){
@ -123,8 +122,12 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
actIndex++; actIndex++;
} }
End nextAct = end; End nextAct = end;
// logger.debug(prevAct.toString() + " arrTime=" + prevAct.getArrTime() + " endTime=" + prevAct.getEndTime());
// logger.debug(deliveryAct2Insert.toString() + " arrTime=" + deliveryAct2Insert.getArrTime() + " endTime=" + deliveryAct2Insert.getEndTime());
// logger.debug(nextAct.toString() + " arrTime=" + nextAct.getArrTime() + " endTime=" + nextAct.getEndTime());
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){ if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
double mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle, bestCost, routeStates.getRouteState(currentRoute).getCosts() - prevCostInOriginalTour); double oldRouteCosts = states.getRouteState(currentRoute, StateTypes.COSTS).toDouble();
double mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle, bestCost, oldRouteCosts - prevCostInOriginalTour);
if(mc < bestCost){ if(mc < bestCost){
bestCost = mc; bestCost = mc;
insertionIndex = actIndex; insertionIndex = actIndex;
@ -139,8 +142,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
return insertionData; return insertionData;
} }
private void initialiseStartAndEnd(final Vehicle newVehicle, private void initialiseStartAndEnd(final Vehicle newVehicle, double newVehicleDepartureTime) {
double newVehicleDepartureTime) {
if(start == null){ if(start == null){
start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival()); start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
start.setEndTime(newVehicleDepartureTime); start.setEndTime(newVehicleDepartureTime);
@ -159,6 +161,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
end.setLocationId(newVehicle.getLocationId()); end.setLocationId(newVehicle.getLocationId());
end.setTheoreticalEarliestOperationStartTime(newVehicleDepartureTime); end.setTheoreticalEarliestOperationStartTime(newVehicleDepartureTime);
end.setTheoreticalLatestOperationStartTime(newVehicle.getLatestArrival()); end.setTheoreticalLatestOperationStartTime(newVehicle.getLatestArrival());
end.setEndTime(newVehicle.getLatestArrival());
} }
} }
@ -174,9 +177,9 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, driver, vehicle); double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, driver, vehicle);
if((tp_costs_prevAct_newAct + act_costs_newAct - costWithoutNewJob) > bestKnownCosts){ // if((tp_costs_prevAct_newAct + act_costs_newAct - costWithoutNewJob) > bestKnownCosts){
return Double.MAX_VALUE; // return Double.MAX_VALUE;
} // }
double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, driver, vehicle); double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, driver, vehicle);
double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, driver, vehicle); double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, driver, vehicle);
@ -184,26 +187,25 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct; double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct;
double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, driver, vehicle); double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, driver, vehicle);
double activityInsertionCosts; // logger.debug("nextActArrTime="+nextAct_arrTime);
double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct; double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct;
if(totalCosts - costWithoutNewJob > bestKnownCosts){ if(totalCosts - costWithoutNewJob > bestKnownCosts){
activityInsertionCosts = Double.MAX_VALUE; return Double.MAX_VALUE;
} }
if(nextAct_arrTime > getLatestOperationStart(nextAct)){ if(nextAct_arrTime > getLatestOperationStart(nextAct)){
activityInsertionCosts = Double.MAX_VALUE; return Double.MAX_VALUE;
} }
else{ return totalCosts - costWithoutNewJob;
activityInsertionCosts = totalCosts - costWithoutNewJob;
}
return activityInsertionCosts;
} }
private double getLatestOperationStart(TourActivity act) { private double getLatestOperationStart(TourActivity act) {
if(state(act) != null){ if(act instanceof End) {
return state(act).getLatestOperationStart(); return end.getTheoreticalLatestOperationStartTime();
} }
return act.getTheoreticalLatestOperationStartTime(); return states.getActivityState(act, StateTypes.LATEST_OPERATION_START_TIME).toDouble();
} }
} }

View file

@ -23,6 +23,8 @@ package algorithms;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import algorithms.InsertionData.NoInsertionFound; import algorithms.InsertionData.NoInsertionFound;
import algorithms.StatesContainer.State;
import algorithms.StatesContainer.States;
import basics.Job; import basics.Job;
import basics.route.Driver; import basics.route.Driver;
import basics.route.Vehicle; import basics.route.Vehicle;
@ -41,12 +43,12 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
private double solution_completeness_ratio = 0.5; private double solution_completeness_ratio = 0.5;
private RouteStates routeStates; private StatesContainer states;
public CalculatesServiceInsertionConsideringFixCost(final JobInsertionCalculator standardInsertionCalculator, RouteStates routeStates) { public CalculatesServiceInsertionConsideringFixCost(final JobInsertionCalculator standardInsertionCalculator, StatesContainer activityStates2) {
super(); super();
this.standardServiceInsertion = standardInsertionCalculator; this.standardServiceInsertion = standardInsertionCalculator;
this.routeStates = routeStates; this.states = activityStates2;
logger.info("inialise " + this); logger.info("inialise " + this);
} }
@ -84,7 +86,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
} }
private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job) { private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
double load = routeStates.getRouteState(route).getLoad() + job.getCapacityDemand(); double load = getCurrentLoad(route) + job.getCapacityDemand();
double currentFix = 0.0; double currentFix = 0.0;
if(route.getVehicle() != null){ if(route.getVehicle() != null){
if(!(route.getVehicle() instanceof NoVehicle)){ if(!(route.getVehicle() instanceof NoVehicle)){
@ -98,7 +100,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
} }
private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) { private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
int currentLoad = routeStates.getRouteState(route).getLoad(); int currentLoad = getCurrentLoad(route);
double load = currentLoad + job.getCapacityDemand(); double load = currentLoad + job.getCapacityDemand();
double currentRelFix = 0.0; double currentRelFix = 0.0;
if(route.getVehicle() != null){ if(route.getVehicle() != null){
@ -113,4 +115,8 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
return relativeFixCost; return relativeFixCost;
} }
private int getCurrentLoad(VehicleRoute route) {
return (int) states.getRouteState(route, StateTypes.LOAD).toDouble();
}
} }

View file

@ -31,6 +31,7 @@ import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts; import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver; import basics.route.Driver;
import basics.route.End; import basics.route.End;
import basics.route.ServiceActivity;
import basics.route.Start; import basics.route.Start;
import basics.route.TourActivities; import basics.route.TourActivities;
import basics.route.TourActivity; import basics.route.TourActivity;
@ -50,7 +51,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
private AuxilliaryCostCalculator auxilliaryPathCostCalculator; private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
private RouteStates routeStates; private StatesContainer states;
private int nuOfActsForwardLooking = 0; private int nuOfActsForwardLooking = 0;
@ -89,15 +90,10 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
logger.info("initialise " + this); logger.info("initialise " + this);
} }
public void setActivityStates(RouteStates actStates){ public void setActivityStates(StatesContainer activityStates2){
this.routeStates = actStates; this.states = activityStates2;
} }
public ActivityState state(TourActivity act){
return routeStates.getState(act);
}
void setNuOfActsForwardLooking(int nOfActsForwardLooking) { void setNuOfActsForwardLooking(int nOfActsForwardLooking) {
this.nuOfActsForwardLooking = nOfActsForwardLooking; this.nuOfActsForwardLooking = nOfActsForwardLooking;
logger.info("set [forwardLooking="+nOfActsForwardLooking+"]"); logger.info("set [forwardLooking="+nOfActsForwardLooking+"]");
@ -138,14 +134,14 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
/** /**
* pre-check whether vehicle-capacity of new vehicle is sufficient to load service. * pre-check whether vehicle-capacity of new vehicle is sufficient to load service.
*/ */
if(routeStates.getRouteState(currentRoute).getLoad() + service.getCapacityDemand() > newVehicle.getCapacity()){ if(states.getRouteState(currentRoute, StateTypes.LOAD).toDouble() + service.getCapacityDemand() > newVehicle.getCapacity()){
return InsertionData.noInsertionFound(); return InsertionData.noInsertionFound();
} }
/** /**
* some inis * some inis
*/ */
TourActivity serviceAct2Insert = routeStates.getActivity(service, true); TourActivity serviceAct2Insert = ServiceActivity.newInstance(service);
int best_insertion_index = InsertionData.NO_INDEX; int best_insertion_index = InsertionData.NO_INDEX;
initialiseStartAndEnd(newVehicle, newVehicleDepartureTime); initialiseStartAndEnd(newVehicle, newVehicleDepartureTime);
@ -262,7 +258,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
/** /**
* compute cost-diff of tour with and without new activity --> insertion_costs * compute cost-diff of tour with and without new activity --> insertion_costs
*/ */
double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - routeStates.getRouteState(currentRoute).getCosts(); double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - states.getRouteState(currentRoute,StateTypes.COSTS).toDouble();
/** /**
* if better than best known, make it the best known * if better than best known, make it the best known
@ -307,9 +303,9 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
private double pathCost_oldVehicle(VehicleRoute vehicleRoute, List<TourActivity> path) { private double pathCost_oldVehicle(VehicleRoute vehicleRoute, List<TourActivity> path) {
TourActivity act = path.get(path.size()-1); TourActivity act = path.get(path.size()-1);
if(act instanceof End){ if(act instanceof End){
return routeStates.getRouteState(vehicleRoute).getCosts(); return states.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble();
} }
return state(act).getCurrentCost(); return states.getActivityState(act,StateTypes.COSTS).toDouble();
} }
/** /**

View file

@ -0,0 +1,211 @@
/*******************************************************************************
* Copyright (c) 2011 Stefan Schroeder.
* eMail: stefan.schroeder@kit.edu
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import org.apache.log4j.Logger;
import util.Neighborhood;
import algorithms.RouteStates.ActivityState;
import algorithms.StatesContainer.State;
import algorithms.StatesContainer.States;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver;
import basics.route.End;
import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import basics.route.VehicleImpl.NoVehicle;
final class CalculatesServiceInsertionWithTriangleInequality implements JobInsertionCalculator{
class Marginals {
private double marginalCosts;
private double marginalTime;
public Marginals(double marginalCosts, double marginalTime) {
super();
this.marginalCosts = marginalCosts;
this.marginalTime = marginalTime;
}
/**
* @return the marginalCosts
*/
public double getMarginalCosts() {
return marginalCosts;
}
/**
* @return the marginalTime
*/
public double getMarginalTime() {
return marginalTime;
}
}
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertionWithTriangleInequality.class);
private StatesContainer routeStates;
private VehicleRoutingTransportCosts routingCosts;
private Start start;
private End end;
private HardConstraint hardConstraint = new HardConstraint() {
@Override
public boolean fulfilled() { return true; }
};
public void setHardConstraint(HardConstraint hardConstraint){
this.hardConstraint = hardConstraint;
}
private Neighborhood neighborhood = new Neighborhood() {
@Override
public boolean areNeighbors(String location1, String location2) {
return true;
}
};
public void setNeighborhood(Neighborhood neighborhood) {
this.neighborhood = neighborhood;
logger.info("initialise neighborhood " + neighborhood);
}
public void setActivityStates(StatesContainer activityStates2){
this.routeStates = activityStates2;
}
public CalculatesServiceInsertionWithTriangleInequality(VehicleRoutingTransportCosts vehicleRoutingTransportCosts, VehicleRoutingActivityCosts vehicleRoutingActivityCosts) {
super();
this.routingCosts = vehicleRoutingTransportCosts;
logger.info("initialise " + this);
}
@Override
public String toString() {
return "[name=calculatesServiceInsertion]";
}
/**
* Calculates the marginal cost of inserting job i locally. This is based on the
* assumption that cost changes can entirely covered by only looking at the predecessor i-1 and its successor i+1.
*
*/
@Override
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing.");
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing.");
TourActivities tour = currentRoute.getTourActivities();
Marginals bestMarginals = new Marginals(bestKnownCosts,Double.MAX_VALUE);
Service service = (Service)jobToInsert;
if(getCurrentLoad(currentRoute) + service.getCapacityDemand() > newVehicle.getCapacity()){
return InsertionData.noInsertionFound();
}
int insertionIndex = InsertionData.NO_INDEX;
TourActivity deliveryAct2Insert = ServiceActivity.newInstance(service);
initialiseStartAndEnd(newVehicle, newVehicleDepartureTime);
TourActivity prevAct = start;
int actIndex = 0;
for(TourActivity nextAct : tour.getActivities()){
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
Marginals mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle);
if(mc.getMarginalCosts() < bestMarginals.getMarginalCosts()){
bestMarginals = mc;
insertionIndex = actIndex;
}
}
prevAct = nextAct;
actIndex++;
}
End nextAct = end;
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
Marginals mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle);
if(mc.getMarginalCosts() < bestMarginals.getMarginalCosts()){
bestMarginals = mc;
insertionIndex = actIndex;
}
}
if(insertionIndex == InsertionData.NO_INDEX) {
return InsertionData.noInsertionFound();
}
InsertionData insertionData = new InsertionData(bestMarginals.getMarginalCosts(), InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
insertionData.setAdditionalTime(bestMarginals.getMarginalTime());
return insertionData;
}
private int getCurrentLoad(VehicleRoute currentRoute) {
States thisRoutesStates = routeStates.getRouteStates().get(currentRoute);
if(routeStates.getRouteStates().containsKey(currentRoute)){
int load = (int) thisRoutesStates.getState(StateTypes.LOAD).toDouble();
return load;
}
else return 0;
}
private void initialiseStartAndEnd(final Vehicle newVehicle, double newVehicleDepartureTime) {
if(start == null){
start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
start.setEndTime(newVehicleDepartureTime);
}
else{
start.setLocationId(newVehicle.getLocationId());
start.setTheoreticalEarliestOperationStartTime(newVehicle.getEarliestDeparture());
start.setTheoreticalLatestOperationStartTime(newVehicle.getLatestArrival());
start.setEndTime(newVehicleDepartureTime);
}
if(end == null){
end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival());
}
else{
end.setLocationId(newVehicle.getLocationId());
end.setTheoreticalEarliestOperationStartTime(newVehicleDepartureTime);
end.setTheoreticalLatestOperationStartTime(newVehicle.getLatestArrival());
}
}
public Marginals calculate(TourActivity prevAct, TourActivity nextAct, TourActivity newAct, Driver driver, Vehicle vehicle) {
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle);
double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle);
double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), 0.0, driver, vehicle);
double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), 0.0, driver, vehicle);
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), 0.0, driver, vehicle);
double tp_time_prevAct_nextAct = routingCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), 0.0, driver, vehicle);
return new Marginals(tp_costs_prevAct_newAct + tp_costs_newAct_nextAct - tp_costs_prevAct_nextAct, tp_time_prevAct_newAct + tp_time_newAct_nextAct - tp_time_prevAct_nextAct);
}
}

View file

@ -67,16 +67,7 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
else{ else{
relevantVehicles.addAll(fleetManager.getAvailableVehicles()); relevantVehicles.addAll(fleetManager.getAvailableVehicles());
} }
//
// for(TypeKey typeKey : fleetManager.getAvailableVehicleTypes()){
// if(!(currentRoute.getVehicle() instanceof NoVehicle)){
// TypeKey key = makeTypeKey(currentRoute.getVehicle().getType(),currentRoute.getVehicle().getLocationId());
// if(typeKey.equals(key)){
// continue;
// }
// }
// relevantVehicles.add(fleetManager.getEmptyVehicle(typeKey));
// }
for(Vehicle v : relevantVehicles){ for(Vehicle v : relevantVehicles){
double depTime = v.getEarliestDeparture(); double depTime = v.getEarliestDeparture();
InsertionData iData = insertionCalculator.calculate(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_); InsertionData iData = insertionCalculator.calculate(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
@ -92,8 +83,4 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
return bestIData; return bestIData;
} }
// private TypeKey makeTypeKey(VehicleType type, String locationId) {
// return new TypeKey(type,locationId);
// }
} }

View file

@ -70,7 +70,7 @@ class CalculatorBuilder {
private VehicleRoutingProblem vrp; private VehicleRoutingProblem vrp;
private RouteStates activityStates; private StatesContainer states;
private boolean local = true; private boolean local = true;
@ -107,12 +107,12 @@ class CalculatorBuilder {
/** /**
* Sets activityStates. MUST be set. * Sets activityStates. MUST be set.
* @param states TODO
* *
* @param activityStates
* @return * @return
*/ */
public CalculatorBuilder setActivityStates(RouteStates activityStates){ public CalculatorBuilder setStates(StatesContainer states){
this.activityStates = activityStates; this.states = states;
return this; return this;
} }
@ -184,21 +184,21 @@ class CalculatorBuilder {
*/ */
public JobInsertionCalculator build(){ public JobInsertionCalculator build(){
if(vrp == null) throw new IllegalStateException("vehicle-routing-problem is null, but it must be set (this.setVehicleRoutingProblem(vrp))"); if(vrp == null) throw new IllegalStateException("vehicle-routing-problem is null, but it must be set (this.setVehicleRoutingProblem(vrp))");
if(activityStates == null) throw new IllegalStateException("activity states is null, but is must be set (this.setActivityStates(states))"); if(states == null) throw new IllegalStateException("states is null, but is must be set (this.setStates(states))");
if(fleetManager == null) throw new IllegalStateException("fleetManager is null, but it must be set (this.setVehicleFleetManager(fleetManager))"); if(fleetManager == null) throw new IllegalStateException("fleetManager is null, but it must be set (this.setVehicleFleetManager(fleetManager))");
JobInsertionCalculator baseCalculator = null; JobInsertionCalculator baseCalculator = null;
CalculatorPlusListeners standardLocal = null; CalculatorPlusListeners standardLocal = null;
if(local){ if(local){
standardLocal = createStandardLocal(vrp, activityStates); standardLocal = createStandardLocal(vrp, states);
} }
else{ else{
standardLocal = createStandardRoute(vrp, activityStates,forwardLooking,memory); standardLocal = createStandardRoute(vrp, states,forwardLooking,memory);
} }
baseCalculator = standardLocal.getCalculator(); baseCalculator = standardLocal.getCalculator();
addAlgorithmListeners(standardLocal.getAlgorithmListener()); addAlgorithmListeners(standardLocal.getAlgorithmListener());
addInsertionListeners(standardLocal.getInsertionListener()); addInsertionListeners(standardLocal.getInsertionListener());
if(considerFixedCost){ if(considerFixedCost){
CalculatorPlusListeners withFixed = createCalculatorConsideringFixedCosts(vrp, baseCalculator, activityStates, weightOfFixedCost); CalculatorPlusListeners withFixed = createCalculatorConsideringFixedCosts(vrp, baseCalculator, states, weightOfFixedCost);
baseCalculator = withFixed.getCalculator(); baseCalculator = withFixed.getCalculator();
addAlgorithmListeners(withFixed.getAlgorithmListener()); addAlgorithmListeners(withFixed.getAlgorithmListener());
addInsertionListeners(withFixed.getInsertionListener()); addInsertionListeners(withFixed.getInsertionListener());
@ -206,7 +206,7 @@ class CalculatorBuilder {
if(timeScheduling){ if(timeScheduling){
baseCalculator = new CalculatesServiceInsertionWithTimeScheduling(baseCalculator,timeSlice,neighbors); baseCalculator = new CalculatesServiceInsertionWithTimeScheduling(baseCalculator,timeSlice,neighbors);
} }
return createFinalInsertion(fleetManager, baseCalculator, activityStates); return createFinalInsertion(fleetManager, baseCalculator, states);
} }
private void addInsertionListeners(List<InsertionListener> list) { private void addInsertionListeners(List<InsertionListener> list) {
@ -221,35 +221,39 @@ class CalculatorBuilder {
} }
} }
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, RouteStates activityStates){ private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StatesContainer activityStates2){
JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), vrp.getActivityCosts()); JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), vrp.getActivityCosts());
((CalculatesServiceInsertion) standardServiceInsertion).setActivityStates(activityStates); // JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertionWithTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts());
// ((CalculatesServiceInsertionWithTriangleInequality) standardServiceInsertion).setActivityStates(activityStates2);
// ((CalculatesServiceInsertionWithTriangleInequality) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
//
((CalculatesServiceInsertion) standardServiceInsertion).setActivityStates(activityStates2);
((CalculatesServiceInsertion) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood()); ((CalculatesServiceInsertion) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion); CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion);
return calcPlusListeners; return calcPlusListeners;
} }
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCalculator baseCalculator, RouteStates activityStates, double weightOfFixedCosts){ private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCalculator baseCalculator, StatesContainer activityStates2, double weightOfFixedCosts){
final CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(baseCalculator, activityStates); final CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(baseCalculator, activityStates2);
withFixCost.setWeightOfFixCost(weightOfFixedCosts); withFixCost.setWeightOfFixCost(weightOfFixedCosts);
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost); CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost);
calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost)); calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost));
return calcPlusListeners; return calcPlusListeners;
} }
private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, RouteStates activityStates, int forwardLooking, int solutionMemory){ private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, StatesContainer activityStates2, int forwardLooking, int solutionMemory){
int after = forwardLooking; int after = forwardLooking;
JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts()); JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts());
((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());
((CalculatesServiceInsertionOnRouteLevel) jobInsertionCalculator).setActivityStates(activityStates); ((CalculatesServiceInsertionOnRouteLevel) jobInsertionCalculator).setActivityStates(activityStates2);
CalculatorPlusListeners calcPlusListener = new CalculatorPlusListeners(jobInsertionCalculator); CalculatorPlusListeners calcPlusListener = new CalculatorPlusListeners(jobInsertionCalculator);
return calcPlusListener; return calcPlusListener;
} }
private JobInsertionCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCalculator baseCalc, RouteStates routeStates){ private JobInsertionCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCalculator baseCalc, StatesContainer activityStates2){
return new CalculatesVehTypeDepServiceInsertion(fleetManager, baseCalc); return new CalculatesVehTypeDepServiceInsertion(fleetManager, baseCalc);
} }

View file

@ -65,7 +65,7 @@ final class ConfigureFixCostCalculator implements InsertionStartsListener, JobIn
} }
@Override @Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute) { public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
nuOfJobsToRecreate--; nuOfJobsToRecreate--;
double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)vrp.getJobs().values().size())); double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)vrp.getJobs().values().size()));
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio); calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);

View file

@ -106,7 +106,7 @@ final class FindCheaperVehicleAlgo {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
TourActivities newTour = TourActivities.copyOf(vehicleRoute.getTourActivities()); TourActivities newTour = TourActivities.copyOf(vehicleRoute.getTourActivities());
tourStateCalculator.updateRoute(vehicleRoute); tourStateCalculator.iterate(vehicleRoute);
return VehicleRoute.newInstance(newTour,vehicleRoute.getDriver(),bestVehicle); return VehicleRoute.newInstance(newTour,vehicleRoute.getDriver(),bestVehicle);
} }
return vehicleRoute; return vehicleRoute;

View file

@ -0,0 +1,39 @@
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class ForwardInTimeListeners {
interface ForwardInTimeListener{
public void start(VehicleRoute route);
public void nextActivity(TourActivity act, double arrTime,double endTime);
public void finnish();
}
private Collection<ForwardInTimeListener> listeners = new ArrayList<ForwardInTimeListeners.ForwardInTimeListener>();
public void addListener(ForwardInTimeListener l){
listeners.add(l);
}
public void start(VehicleRoute route){
for(ForwardInTimeListener l : listeners){ l.start(route); }
}
public void nextActivity(TourActivity act, double arrTime, double endTime){
for(ForwardInTimeListener l : listeners){ l.nextActivity(act,arrTime,endTime); }
}
public void finnish(){
for(ForwardInTimeListener l : listeners){ l.finnish(); }
}
}

View file

@ -0,0 +1,7 @@
package algorithms;
interface HardConstraint {
public boolean fulfilled();
}

View file

@ -30,7 +30,7 @@ class Inserter {
} }
else throw new IllegalStateException("neither service nor shipment. this is not supported."); else throw new IllegalStateException("neither service nor shipment. this is not supported.");
insertionListeners.informJobInserted(job, vehicleRoute); insertionListeners.informJobInserted(job, vehicleRoute, insertionData.getInsertionCost(), insertionData.getAdditionalTime());
// updateTour(vehicleRoute); // updateTour(vehicleRoute);
} }
} }

View file

@ -55,6 +55,22 @@ class InsertionData {
private double departureTime; private double departureTime;
private double additionalTime;
/**
* @return the additionalTime
*/
public double getAdditionalTime() {
return additionalTime;
}
/**
* @param additionalTime the additionalTime to set
*/
public void setAdditionalTime(double additionalTime) {
this.additionalTime = additionalTime;
}
public InsertionData(double insertionCost, int pickupInsertionIndex, int deliveryInsertionIndex, Vehicle vehicle, Driver driver){ public InsertionData(double insertionCost, int pickupInsertionIndex, int deliveryInsertionIndex, Vehicle vehicle, Driver driver){
this.insertionCost = insertionCost; this.insertionCost = insertionCost;
this.pickupInsertionIndex = pickupInsertionIndex; this.pickupInsertionIndex = pickupInsertionIndex;

View file

@ -38,7 +38,7 @@ class InsertionFactory {
private static Logger log = Logger.getLogger(InsertionFactory.class); private static Logger log = Logger.getLogger(InsertionFactory.class);
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config, public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
VehicleFleetManager vehicleFleetManager, RouteStates activityStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads){ VehicleFleetManager vehicleFleetManager, StatesContainerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads){
boolean concurrentInsertion = false; boolean concurrentInsertion = false;
if(executorService != null) concurrentInsertion = true; if(executorService != null) concurrentInsertion = true;
if(config.containsKey("[@name]")){ if(config.containsKey("[@name]")){
@ -51,7 +51,7 @@ class InsertionFactory {
List<PrioritizedVRAListener> algoListeners = new ArrayList<PrioritizedVRAListener>(); List<PrioritizedVRAListener> algoListeners = new ArrayList<PrioritizedVRAListener>();
CalculatorBuilder calcBuilder = new CalculatorBuilder(insertionListeners, algorithmListeners); CalculatorBuilder calcBuilder = new CalculatorBuilder(insertionListeners, algorithmListeners);
calcBuilder.setActivityStates(activityStates); calcBuilder.setStates(routeStates);
calcBuilder.setVehicleRoutingProblem(vrp); calcBuilder.setVehicleRoutingProblem(vrp);
calcBuilder.setVehicleFleetManager(vehicleFleetManager); calcBuilder.setVehicleFleetManager(vehicleFleetManager);
@ -94,27 +94,22 @@ class InsertionFactory {
} }
JobInsertionCalculator jic = calcBuilder.build(); JobInsertionCalculator jic = calcBuilder.build();
TourStateUpdater tourStateCalculator = new TourStateUpdater(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts());
RouteAlgorithm routeAlgorithm = RouteAlgorithmImpl.newInstance(jic, tourStateCalculator);
// routeAlgorithm.getListeners().add(new VehicleSwitched(vehicleFleetManager));
((RouteAlgorithmImpl) routeAlgorithm).setStates(activityStates);
if(insertionName.equals("bestInsertion")){ if(insertionName.equals("bestInsertion")){
if(concurrentInsertion){ insertionStrategy = new BestInsertion(jic);
insertionStrategy = BestInsertionConcurrent.newInstance(routeAlgorithm,executorService,nuOfThreads);
}
else{
insertionStrategy = new BestInsertion(jic);
}
}
else if(insertionName.equals("regretInsertion")){
insertionStrategy = RegretInsertion.newInstance(routeAlgorithm);
} }
// else if(insertionName.equals("regretInsertion")){
// insertionStrategy = RegretInsertion.newInstance(routeAlgorithm);
// }
insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager)); insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager));
insertionStrategy.addListener(new ResetAndIniFleetManager(vehicleFleetManager)); insertionStrategy.addListener(new ResetAndIniFleetManager(vehicleFleetManager));
insertionStrategy.addListener(new VehicleSwitched(vehicleFleetManager)); insertionStrategy.addListener(new VehicleSwitched(vehicleFleetManager));
insertionStrategy.addListener(new UpdateRoute(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
// insertionStrategy.addListener(new UpdateLoadAtRouteLevel(routeStates));
insertionStrategy.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
for(InsertionListener l : insertionListeners) insertionStrategy.addListener(l); for(InsertionListener l : insertionListeners) insertionStrategy.addListener(l);
// insertionStrategy.addListener(new FindCheaperVehicle( // insertionStrategy.addListener(new FindCheaperVehicle(
// new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator))); // new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator)));

View file

@ -19,10 +19,10 @@ class InsertionListeners {
return listeners; return listeners;
} }
public void informJobInserted(Job insertedJob, VehicleRoute inRoute){ public void informJobInserted(Job insertedJob, VehicleRoute inRoute, double additionalCosts, double additionalTime){
for(InsertionListener l : listeners){ for(InsertionListener l : listeners){
if(l instanceof JobInsertedListener){ if(l instanceof JobInsertedListener){
((JobInsertedListener)l).informJobInserted(insertedJob, inRoute); ((JobInsertedListener)l).informJobInserted(insertedJob, inRoute, additionalCosts, additionalTime);
} }
} }
} }

View file

@ -0,0 +1,69 @@
/*******************************************************************************
* Copyright (c) 2011 Stefan Schroeder.
* eMail: stefan.schroeder@kit.edu
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.util.Iterator;
import org.apache.log4j.Logger;
import algorithms.BackwardInTimeListeners.BackwardInTimeListener;
import basics.costs.BackwardTransportTime;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
/**
*
* @author stefan schroeder
*
*/
class IterateRouteBackwardInTime implements VehicleRouteUpdater{
private static Logger log = Logger.getLogger(IterateRouteBackwardInTime.class);
private BackwardTransportTime transportTime;
private BackwardInTimeListeners listeners;
public IterateRouteBackwardInTime(BackwardTransportTime transportTime) {
super();
this.transportTime = transportTime;
listeners = new BackwardInTimeListeners();
}
/*
*
*/
public void iterate(VehicleRoute vehicleRoute) {
listeners.start(vehicleRoute);
Iterator<TourActivity> reverseActIter = vehicleRoute.getTourActivities().reverseActivityIterator();
TourActivity prevAct;
prevAct = vehicleRoute.getEnd();
double startAtPrevAct = prevAct.getTheoreticalLatestOperationStartTime();
listeners.prevActivity(prevAct, startAtPrevAct, startAtPrevAct);
while(reverseActIter.hasNext()){
TourActivity currAct = reverseActIter.next();
double latestDepTimeAtCurrAct = startAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), startAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle());
double potentialLatestOperationStartTimeAtCurrAct = latestDepTimeAtCurrAct - currAct.getOperationTime();
double latestOperationStartTime = Math.min(currAct.getTheoreticalLatestOperationStartTime(), potentialLatestOperationStartTimeAtCurrAct);
listeners.prevActivity(currAct, latestDepTimeAtCurrAct, latestOperationStartTime);
prevAct = currAct;
startAtPrevAct = latestOperationStartTime;
}
listeners.finnish();
}
public void addListener(BackwardInTimeListener l){ listeners.addListener(l); }
}

View file

@ -0,0 +1,85 @@
/*******************************************************************************
* Copyright (c) 2011 Stefan Schroeder.
* eMail: stefan.schroeder@kit.edu
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import org.apache.log4j.Logger;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import basics.costs.ForwardTransportTime;
import basics.route.Driver;
import basics.route.End;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
/**
*
* @author sschroeder
*
*/
class IterateRouteForwardInTime implements VehicleRouteUpdater{
private static Logger log = Logger.getLogger(IterateRouteForwardInTime.class);
private ForwardTransportTime transportTime;
private ForwardInTimeListeners listeners;
public IterateRouteForwardInTime(ForwardTransportTime transportTime) {
super();
this.transportTime = transportTime;
listeners = new ForwardInTimeListeners();
}
/**
*
*
*/
public void iterate(VehicleRoute vehicleRoute) {
listeners.start(vehicleRoute);
Vehicle vehicle = vehicleRoute.getVehicle();
Driver driver = vehicleRoute.getDriver();
TourActivity prevAct = vehicleRoute.getStart();
double startAtPrevAct = prevAct.getEndTime();
listeners.nextActivity(prevAct,startAtPrevAct,startAtPrevAct);
for(TourActivity currentAct : vehicleRoute.getTourActivities().getActivities()){
double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
double operationStartTime = Math.max(currentAct.getTheoreticalEarliestOperationStartTime(), arrivalTimeAtCurrAct);
double operationEndTime = operationStartTime + currentAct.getOperationTime();
listeners.nextActivity(currentAct,arrivalTimeAtCurrAct,operationEndTime);
prevAct = currentAct;
startAtPrevAct = operationEndTime;
}
End currentAct = vehicleRoute.getEnd();
double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
listeners.nextActivity(currentAct,arrivalTimeAtCurrAct,arrivalTimeAtCurrAct);
listeners.finnish();
}
public void addListener(ForwardInTimeListener l){
listeners.addListener(l);
}
}

View file

@ -76,7 +76,7 @@ class JobObserver implements JobInsertedListener, BeforeJobInsertionListener, Al
Collection<Info> infos = new ArrayList<Info>(); Collection<Info> infos = new ArrayList<Info>();
@Override @Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute) { public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
if(job2insert instanceof Service){ if(job2insert instanceof Service){
if(((Service) job2insert).getLocationId().equals(locationId)){ if(((Service) job2insert).getLocationId().equals(locationId)){
double actualMC = inRoute.getCost()-routeCostBefore; double actualMC = inRoute.getCost()-routeCostBefore;

View file

@ -1,229 +1,229 @@
/******************************************************************************* ///*******************************************************************************
* Copyright (c) 2011 Stefan Schroeder. // * Copyright (c) 2011 Stefan Schroeder.
* eMail: stefan.schroeder@kit.edu // * eMail: stefan.schroeder@kit.edu
* // *
* All rights reserved. This program and the accompanying materials // * All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0 // * are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at // * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html // * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* // *
* Contributors: // * Contributors:
* Stefan Schroeder - initial API and implementation // * Stefan Schroeder - initial API and implementation
******************************************************************************/ // ******************************************************************************/
package algorithms; //package algorithms;
//
import java.util.ArrayList; //import java.util.ArrayList;
import java.util.Collection; //import java.util.Collection;
import java.util.List; //import java.util.List;
//
import org.apache.log4j.Logger; //import org.apache.log4j.Logger;
//
import algorithms.InsertionData.NoInsertionFound; //import algorithms.InsertionData.NoInsertionFound;
import basics.Job; //import basics.Job;
import basics.Service; //import basics.Service;
import basics.algo.InsertionListener; //import basics.algo.InsertionListener;
import basics.route.VehicleRoute; //import basics.route.VehicleRoute;
//
//
/** ///**
* Insertion based an regret approach. // * Insertion based an regret approach.
* // *
* <p>Basically calculates the insertion cost of the firstBest and the secondBest alternative. The score is then calculated as difference // * <p>Basically calculates the insertion cost of the firstBest and the secondBest alternative. The score is then calculated as difference
* between secondBest and firstBest, plus additional scoring variables that can defined in this.ScoringFunction. // * between secondBest and firstBest, plus additional scoring variables that can defined in this.ScoringFunction.
* The idea is that if the cost of the secondBest alternative is way higher than the first best, it seems to be important to insert this // * The idea is that if the cost of the secondBest alternative is way higher than the first best, it seems to be important to insert this
* customer immediatedly. If difference is not that high, it might not impact solution if this customer is inserted later. // * customer immediatedly. If difference is not that high, it might not impact solution if this customer is inserted later.
* // *
* @author stefan schroeder // * @author stefan schroeder
* // *
*/ // */
final class RegretInsertion implements InsertionStrategy{ //final class RegretInsertion implements InsertionStrategy{
//
/** // /**
* Scorer to include other impacts on score such as time-window length or distance to depot. // * Scorer to include other impacts on score such as time-window length or distance to depot.
* // *
* @author schroeder // * @author schroeder
* // *
*/ // */
static interface ScoringFunction { // static interface ScoringFunction {
//
public double score(Job job); // public double score(Job job);
//
} // }
//
/** // /**
* Scorer that includes the length of the time-window when scoring a job. The wider the time-window, the lower the score. // * Scorer that includes the length of the time-window when scoring a job. The wider the time-window, the lower the score.
* // *
* <p>This is the default scorer, i.e.: score = (secondBest - firstBest) + this.TimeWindowScorer.score(job) // * <p>This is the default scorer, i.e.: score = (secondBest - firstBest) + this.TimeWindowScorer.score(job)
* // *
* @author schroeder // * @author schroeder
* // *
*/ // */
static class TimeWindowScorer implements ScoringFunction { // static class TimeWindowScorer implements ScoringFunction {
//
private double tw_scoringParam = - 0.1; // private double tw_scoringParam = - 0.1;
//
@Override // @Override
public double score(Job job) { // public double score(Job job) {
double twStart = 0.0; // double twStart = 0.0;
double twEnd = 0.0; // double twEnd = 0.0;
// if(job instanceof Shipment){ //// if(job instanceof Shipment){
// twStart = ((Shipment) job).getDeliveryTW().getStart(); //// twStart = ((Shipment) job).getDeliveryTW().getStart();
// twEnd = ((Shipment) job).getDeliveryTW().getEnd(); //// twEnd = ((Shipment) job).getDeliveryTW().getEnd();
//// }
//// else
// if(job instanceof Service){
// twStart = ((Service) job).getTimeWindow().getStart();
// twEnd = ((Service) job).getTimeWindow().getEnd();
// } // }
// else // return (twEnd-twStart)*tw_scoringParam;
if(job instanceof Service){ // }
twStart = ((Service) job).getTimeWindow().getStart(); //
twEnd = ((Service) job).getTimeWindow().getEnd(); // @Override
} // public String toString() {
return (twEnd-twStart)*tw_scoringParam; // return "[name=timeWindowScorer][scoringParam="+tw_scoringParam+"]";
} // }
//
@Override // }
public String toString() { //
return "[name=timeWindowScorer][scoringParam="+tw_scoringParam+"]"; // public static RegretInsertion newInstance(RouteAlgorithm routeAlgorithm) {
} // return new RegretInsertion(routeAlgorithm);
// }
} //
// private Logger logger = Logger.getLogger(RegretInsertion.class);
public static RegretInsertion newInstance(RouteAlgorithm routeAlgorithm) { //
return new RegretInsertion(routeAlgorithm); // private RouteAlgorithm routeAlgorithm;
} //
// private ScoringFunction scoringFunction = new TimeWindowScorer();
private Logger logger = Logger.getLogger(RegretInsertion.class); //
// /**
private RouteAlgorithm routeAlgorithm; // * Sets the scoring function.
// *
private ScoringFunction scoringFunction = new TimeWindowScorer(); // * <p>By default, the this.TimeWindowScorer is used.
// *
/** // * @param scoringFunction
* Sets the scoring function. // */
* // public void setScoringFunction(ScoringFunction scoringFunction) {
* <p>By default, the this.TimeWindowScorer is used. // this.scoringFunction = scoringFunction;
* // }
* @param scoringFunction //
*/ // public RegretInsertion(RouteAlgorithm routeAlgorithm) {
public void setScoringFunction(ScoringFunction scoringFunction) { // super();
this.scoringFunction = scoringFunction; // this.routeAlgorithm = routeAlgorithm;
} // logger.info("initialise " + this);
// }
public RegretInsertion(RouteAlgorithm routeAlgorithm) { //
super(); // @Override
this.routeAlgorithm = routeAlgorithm; // public String toString() {
logger.info("initialise " + this); // return "[name=regretInsertion][additionalScorer="+scoringFunction+"]";
} // }
//
@Override // public RouteAlgorithm getRouteAlgorithm(){
public String toString() { // return routeAlgorithm;
return "[name=regretInsertion][additionalScorer="+scoringFunction+"]"; // }
} //
// /**
public RouteAlgorithm getRouteAlgorithm(){ // * Runs insertion.
return routeAlgorithm; // *
} // * <p>Before inserting a job, all unassigned jobs are scored according to its best- and secondBest-insertion plus additional scoring variables.
// *
/** // */
* Runs insertion. // @Override
* // public void insertJobs(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
* <p>Before inserting a job, all unassigned jobs are scored according to its best- and secondBest-insertion plus additional scoring variables. // List<Job> jobs = new ArrayList<Job>(unassignedJobs);
* //// informInsertionStarts(routes,unassignedJobs);
*/ // int inserted = 0;
@Override // while(!jobs.isEmpty()){
public void insertJobs(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) { // List<Job> unassignedJobList = new ArrayList<Job>(jobs);
List<Job> jobs = new ArrayList<Job>(unassignedJobs); // ScoredJob bestScoredJob = null;
// informInsertionStarts(routes,unassignedJobs); // double bestScore = -1*Double.MAX_VALUE;
int inserted = 0; // VehicleRoute insertIn = null;
while(!jobs.isEmpty()){ //
List<Job> unassignedJobList = new ArrayList<Job>(jobs); // for(Job unassignedJob : unassignedJobList){
ScoredJob bestScoredJob = null; // InsertionData best = null;
double bestScore = -1*Double.MAX_VALUE; // InsertionData secondBest = null;
VehicleRoute insertIn = null; // VehicleRoute bestRoute = null;
//
for(Job unassignedJob : unassignedJobList){ // double benchmark = Double.MAX_VALUE;
InsertionData best = null; // for(VehicleRoute route : routes){
InsertionData secondBest = null; // if(secondBest != null){
VehicleRoute bestRoute = null; // benchmark = secondBest.getInsertionCost();
// }
double benchmark = Double.MAX_VALUE; // InsertionData iData = routeAlgorithm.calculateBestInsertion(route, unassignedJob, benchmark);
for(VehicleRoute route : routes){ // if(iData instanceof NoInsertionFound) continue;
if(secondBest != null){ // if(best == null){
benchmark = secondBest.getInsertionCost(); // best = iData;
} // bestRoute = route;
InsertionData iData = routeAlgorithm.calculateBestInsertion(route, unassignedJob, benchmark); // }
if(iData instanceof NoInsertionFound) continue; // else if(iData.getInsertionCost() < best.getInsertionCost()){
if(best == null){ // secondBest = best;
best = iData; // best = iData;
bestRoute = route; // bestRoute = route;
} // }
else if(iData.getInsertionCost() < best.getInsertionCost()){ // else if(secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())){
secondBest = best; // secondBest = iData;
best = iData; // }
bestRoute = route; // }
} // if(best == null){
else if(secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())){ // break;
secondBest = iData; // }
} // double score = score(unassignedJob,best,secondBest);
} // if(score > bestScore){
if(best == null){ // bestScoredJob = new ScoredJob(unassignedJob,score,best,bestRoute);
break; // bestScore = score;
} // }
double score = score(unassignedJob,best,secondBest); // }
if(score > bestScore){ // Job assignedJob;
bestScoredJob = new ScoredJob(unassignedJob,score,best,bestRoute); // if(bestScoredJob == null){
bestScore = score; // Job job = unassignedJobList.get(0);
} // VehicleRoute newRoute = VehicleRoute.emptyRoute();
} // InsertionData bestI = routeAlgorithm.calculateBestInsertion(newRoute, job, Double.MAX_VALUE);
Job assignedJob; // if(bestI instanceof InsertionData.NoInsertionFound) throw new IllegalStateException("given the vehicles, could not create a valid solution");
if(bestScoredJob == null){ // insertIn=newRoute;
Job job = unassignedJobList.get(0); // assignedJob=job;
VehicleRoute newRoute = VehicleRoute.emptyRoute(); // routeAlgorithm.insertJob(job,bestI,newRoute);
InsertionData bestI = routeAlgorithm.calculateBestInsertion(newRoute, job, Double.MAX_VALUE); // routes.add(newRoute);
if(bestI instanceof InsertionData.NoInsertionFound) throw new IllegalStateException("given the vehicles, could not create a valid solution"); // jobs.remove(job);
insertIn=newRoute; //
assignedJob=job; // }
routeAlgorithm.insertJob(job,bestI,newRoute); // else{
routes.add(newRoute); // routeAlgorithm.insertJob(bestScoredJob.getJob(),bestScoredJob.getInsertionData(), bestScoredJob.getRoute());
jobs.remove(job); // insertIn=bestScoredJob.getRoute();
// assignedJob=bestScoredJob.getJob();
} // jobs.remove(bestScoredJob.getJob());
else{ // }
routeAlgorithm.insertJob(bestScoredJob.getJob(),bestScoredJob.getInsertionData(), bestScoredJob.getRoute()); // inserted++;
insertIn=bestScoredJob.getRoute(); //// informJobInserted(assignedJob, insertIn);
assignedJob=bestScoredJob.getJob(); //
jobs.remove(bestScoredJob.getJob()); // }
} // }
inserted++; //
// informJobInserted(assignedJob, insertIn); // private double score(Job unassignedJob, InsertionData best, InsertionData secondBest) {
// if(best == null){
} // throw new IllegalStateException("cannot insert job " + unassignedJob.getId());
} // }
// if(secondBest == null){
private double score(Job unassignedJob, InsertionData best, InsertionData secondBest) { // return Double.MAX_VALUE;
if(best == null){ // }
throw new IllegalStateException("cannot insert job " + unassignedJob.getId()); // return (secondBest.getInsertionCost()-best.getInsertionCost()) + scoringFunction.score(unassignedJob);
} //
if(secondBest == null){ // }
return Double.MAX_VALUE; //
} // @Override
return (secondBest.getInsertionCost()-best.getInsertionCost()) + scoringFunction.score(unassignedJob); // public void removeListener(InsertionListener insertionListener) {
// // TODO Auto-generated method stub
} //
// }
@Override //
public void removeListener(InsertionListener insertionListener) { // @Override
// TODO Auto-generated method stub // public Collection<InsertionListener> getListeners() {
// // TODO Auto-generated method stub
} // return null;
// }
@Override //
public Collection<InsertionListener> getListeners() { // @Override
// TODO Auto-generated method stub // public void addListener(InsertionListener insertionListener) {
return null; // // TODO Auto-generated method stub
} //
// }
@Override //
public void addListener(InsertionListener insertionListener) { //}
// TODO Auto-generated method stub
}
}

View file

@ -4,4 +4,10 @@ class StateTypes {
final static String LOAD = "load"; final static String LOAD = "load";
final static String DURATION = "duration"; final static String DURATION = "duration";
final static String LATEST_OPERATION_START_TIME = "latestOST";
final static String EARLIEST_OPERATION_START_TIME = "earliestOST";
public static final String COSTS = "costs";
} }

View file

@ -8,7 +8,7 @@ import basics.route.VehicleRoute;
interface StatesContainer { interface StatesContainer {
interface State { interface State {
double getState(); double toDouble();
} }
class StateImpl implements State{ class StateImpl implements State{
@ -20,7 +20,7 @@ interface StatesContainer {
} }
@Override @Override
public double getState() { public double toDouble() {
return state; return state;
} }
@ -47,4 +47,8 @@ interface StatesContainer {
// void put(TourActivity act, States states); // void put(TourActivity act, States states);
State getActivityState(TourActivity act, String stateType);
State getRouteState(VehicleRoute route, String stateType);
} }

View file

@ -7,9 +7,9 @@ import java.util.Map;
import basics.route.TourActivity; import basics.route.TourActivity;
import basics.route.VehicleRoute; import basics.route.VehicleRoute;
public class StatesContainerImpl implements StatesContainer{ class StatesContainerImpl implements StatesContainer{
class StatesImpl implements States{ static class StatesImpl implements States{
private Map<String,State> states = new HashMap<String, State>(); private Map<String,State> states = new HashMap<String, State>();
@ -24,26 +24,100 @@ public class StatesContainerImpl implements StatesContainer{
} }
private Map<VehicleRoute,States> vehicleRoutes = new HashMap<VehicleRoute, StatesContainer.States>(); private Map<VehicleRoute,States> vehicleRouteStates = new HashMap<VehicleRoute, StatesContainer.States>();
private Map<TourActivity,States> tourActivities = new HashMap<TourActivity, StatesContainer.States>(); private Map<TourActivity,States> activityStates = new HashMap<TourActivity, StatesContainer.States>();
@Override @Override
public Map<VehicleRoute, States> getRouteStates() { public Map<VehicleRoute, States> getRouteStates() {
return Collections.unmodifiableMap(vehicleRoutes); return Collections.unmodifiableMap(vehicleRouteStates);
}
public States getRouteStates(VehicleRoute route){
return vehicleRouteStates.get(route);
} }
public void put(VehicleRoute route, States states) { public void put(VehicleRoute route, States states) {
vehicleRoutes.put(route, states); vehicleRouteStates.put(route, states);
} }
@Override @Override
public Map<TourActivity, States> getActivityStates() { public Map<TourActivity, States> getActivityStates() {
return Collections.unmodifiableMap(tourActivities); return Collections.unmodifiableMap(activityStates);
}
public States getActivityStates(TourActivity act){
return activityStates.get(act);
} }
public void put(TourActivity act, States states) { public void put(TourActivity act, States states) {
tourActivities.put(act, states); activityStates.put(act, states);
} }
public void clear(){
vehicleRouteStates.clear();
activityStates.clear();
}
@Override
public State getActivityState(TourActivity act, String stateType) {
if(!activityStates.containsKey(act)){
return getDefaultActState(stateType,act);
}
StatesImpl actStates = (StatesImpl) activityStates.get(act);
State state = actStates.getState(stateType);
if(state == null){
return getDefaultActState(stateType,act);
}
return state;
}
public void putActivityState(TourActivity act, String stateType, State state){
if(!activityStates.containsKey(act)){
activityStates.put(act, new StatesImpl());
}
StatesImpl actStates = (StatesImpl) activityStates.get(act);
actStates.putState(stateType, state);
}
private State getDefaultActState(String stateType, TourActivity act){
if(stateType.equals(StateTypes.LOAD)) return new StateImpl(0);
if(stateType.equals(StateTypes.COSTS)) return new StateImpl(0);
if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0);
if(stateType.equals(StateTypes.EARLIEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalEarliestOperationStartTime());
if(stateType.equals(StateTypes.LATEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalLatestOperationStartTime());
return null;
}
private State getDefaultRouteState(String stateType, VehicleRoute route){
if(stateType.equals(StateTypes.LOAD)) return new StateImpl(0);
if(stateType.equals(StateTypes.COSTS)) return new StateImpl(0);
if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0);
return null;
}
@Override
public State getRouteState(VehicleRoute route, String stateType) {
if(!vehicleRouteStates.containsKey(route)){
return getDefaultRouteState(stateType,route);
}
StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route);
State state = routeStates.getState(stateType);
if(state == null){
return getDefaultRouteState(stateType, route);
}
return state;
}
public void putRouteState(VehicleRoute route, String stateType, State state){
if(!vehicleRouteStates.containsKey(route)){
vehicleRouteStates.put(route, new StatesImpl());
}
StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route);
routeStates.putState(stateType, state);
}
} }

View file

@ -1,91 +0,0 @@
/*******************************************************************************
* Copyright (c) 2011 Stefan Schroeder.
* eMail: stefan.schroeder@kit.edu
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import org.apache.log4j.Logger;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.VehicleRoute;
/**
* Updates tour state, i.e. the tour as well as each activity in that tour has a state such as currentLoad, currentCost, earliestOperationTime and
* latestOperationTime. Each time the tour is changed (for instance by removing or adding an activity), tour and activity states
* might change, thus this updater updates activity states.
* This includes:
* - update load and totalCost at tour-level
* - update currentLoad and currentCost at activity-level
* - update earliest- and latestOperationStart values at activity-level
*
* If ensureFeasibility is true, then it additionally checks whether the earliestOperationStartTime is higher than the latestOperationStartTime.
* If it is, it returns a false value to indicate that the tour is not feasible. This makes only sense for hard-timewindows.
*
* If softTimeWindow is set to true, latestOperationStartTimes are not updated and the tour is always feasible.
*
* @author stefan schroeder
*
*/
class TourStateUpdater implements VehicleRouteUpdater{
// public final static Counter counter = new Counter("#updateTWProcesses: ");
private static Logger logger = Logger.getLogger(TourStateUpdater.class);
private boolean ensureFeasibility = true;
private UpdateTourStatesForwardInTime forwardUpdate;
private UpdateTourStatesBackwardInTime backwardUpdate;
private boolean updateTimeWindows = true;
private RouteStates actStates;
public TourStateUpdater(RouteStates activityStates, VehicleRoutingTransportCosts costs, VehicleRoutingActivityCosts costFunction) {
super();
forwardUpdate = new UpdateTourStatesForwardInTime(costs, costs, costFunction);
backwardUpdate = new UpdateTourStatesBackwardInTime(costs);
actStates=activityStates;
forwardUpdate.setStates(actStates);
backwardUpdate.setStates(actStates);
}
/*
*
*/
public boolean updateRoute(VehicleRoute vehicleRoute) {
if(updateTimeWindows){
backwardUpdate.checkFeasibility = ensureFeasibility;
backwardUpdate.updateRoute(vehicleRoute);
}
forwardUpdate.updateRoute(vehicleRoute);
boolean tourIsFeasible = true;
return tourIsFeasible;
}
public void setTimeWindowUpdate(boolean updateTimeWindows) {
this.updateTimeWindows = updateTimeWindows;
logger.info("set timeWindowUpdate to " + updateTimeWindows);
}
public void setEnsureFeasibility(boolean ensureFeasibility) {
this.ensureFeasibility = ensureFeasibility;
}
}

View file

@ -0,0 +1,53 @@
package algorithms;
import java.util.Collection;
import basics.Job;
import basics.algo.InsertionEndsListener;
import basics.algo.InsertionStartsListener;
import basics.algo.JobInsertedListener;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.VehicleRoute;
class UdateCostsAtRouteLevel implements JobInsertedListener, InsertionStartsListener, InsertionEndsListener{
private StatesContainerImpl states;
private VehicleRoutingTransportCosts tpCosts;
private VehicleRoutingActivityCosts actCosts;
public UdateCostsAtRouteLevel(StatesContainerImpl states, VehicleRoutingTransportCosts tpCosts, VehicleRoutingActivityCosts actCosts) {
super();
this.states = states;
this.tpCosts = tpCosts;
this.actCosts = actCosts;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
inRoute.getVehicleRouteCostCalculator().addTransportCost(additionalCosts);
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts);
forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
for(VehicleRoute route : vehicleRoutes){
forwardInTime.iterate(route);
}
}
@Override
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts);
forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
for(VehicleRoute route : vehicleRoutes){
forwardInTime.iterate(route);
}
}
}

View file

@ -0,0 +1,26 @@
package algorithms;
import org.apache.log4j.Logger;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
class UpdateActivityTimes implements ForwardInTimeListener{
private Logger log = Logger.getLogger(UpdateActivityTimes.class);
@Override
public void start(VehicleRoute route) {}
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
// log.debug(act.toString() + " arrTime="+ arrTime + " endTime=" + endTime);
act.setArrTime(arrTime);
act.setEndTime(endTime);
}
@Override
public void finnish() {}
}

View file

@ -0,0 +1,81 @@
package algorithms;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import algorithms.StatesContainer.StateImpl;
import basics.costs.ForwardTransportCost;
import basics.costs.VehicleRoutingActivityCosts;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class UpdateCostsAtAllLevels implements ForwardInTimeListener{
private VehicleRoutingActivityCosts activityCost;
private ForwardTransportCost transportCost;
private StatesContainerImpl states;
private double totalOperationCost = 0.0;
private VehicleRoute vehicleRoute = null;
private TourActivity prevAct = null;
private double startTimeAtPrevAct = 0.0;
public UpdateCostsAtAllLevels(VehicleRoutingActivityCosts activityCost, ForwardTransportCost transportCost, StatesContainerImpl states) {
super();
this.activityCost = activityCost;
this.transportCost = transportCost;
this.states = states;
}
@Override
public void start(VehicleRoute route) {
vehicleRoute = route;
vehicleRoute.getVehicleRouteCostCalculator().reset();
}
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
if(prevAct == null){
prevAct = act;
startTimeAtPrevAct = endTime;
}
else{
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), act.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
double actCost = activityCost.getActivityCost(act, arrTime, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
totalOperationCost += transportCost;
totalOperationCost += actCost;
if(!(act instanceof End)){
states.putActivityState(act, StateTypes.COSTS, new StateImpl(totalOperationCost));
}
prevAct = act;
startTimeAtPrevAct = endTime;
}
}
@Override
public void finnish() {
states.putRouteState(vehicleRoute, StateTypes.COSTS, new StateImpl(totalOperationCost));
//this is rather strange and likely to change
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver());
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().finish();
startTimeAtPrevAct = 0.0;
prevAct = null;
vehicleRoute = null;
totalOperationCost = 0.0;
}
}

View file

@ -0,0 +1,31 @@
package algorithms;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import algorithms.StatesContainer.StateImpl;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class UpdateEarliestStartTimeWindowAtActLocations implements ForwardInTimeListener{
private StatesContainerImpl states;
public UpdateEarliestStartTimeWindowAtActLocations(StatesContainerImpl states) {
super();
this.states = states;
}
@Override
public void start(VehicleRoute route) {}
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
if(act instanceof Start || act instanceof End) return;
states.putActivityState(act, StateTypes.EARLIEST_OPERATION_START_TIME, new StateImpl(Math.max(arrTime, act.getTheoreticalEarliestOperationStartTime())));
}
@Override
public void finnish() {}
}

View file

@ -0,0 +1,32 @@
package algorithms;
import algorithms.BackwardInTimeListeners.BackwardInTimeListener;
import algorithms.StatesContainer.StateImpl;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class UpdateLatestOperationStartTimeAtActLocations implements BackwardInTimeListener{
private StatesContainerImpl states;
public UpdateLatestOperationStartTimeAtActLocations(StatesContainerImpl states) {
super();
this.states = states;
}
@Override
public void start(VehicleRoute route) {}
@Override
public void prevActivity(TourActivity act,double latestDepartureTime, double latestOperationStartTime) {
// if(latestOperationStartTime < act.getArrTime()) throw new IllegalStateException(act.toString() + "; latestStart="+latestOperationStartTime+";actArrTime="+act.getArrTime());
if(act instanceof Start || act instanceof End) return;
states.putActivityState(act, StateTypes.LATEST_OPERATION_START_TIME, new StateImpl(latestOperationStartTime));
}
@Override
public void finnish() {}
}

View file

@ -0,0 +1,46 @@
package algorithms;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import algorithms.StatesContainer.StateImpl;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
/**
* It does not update start and end activities.
*
* @author stefan
*
*/
class UpdateLoadAtAllLevels implements ForwardInTimeListener{
private double load = 0.0;
private StatesContainerImpl states;
private VehicleRoute vehicleRoute;
public UpdateLoadAtAllLevels(StatesContainerImpl states) {
super();
this.states = states;
}
@Override
public void start(VehicleRoute route) { vehicleRoute = route; }
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
if(act instanceof Start || act instanceof End){ return; }
load += (double)act.getCapacityDemand();
states.putActivityState(act, StateTypes.LOAD, new StateImpl(load));
}
@Override
public void finnish() {
states.putRouteState(vehicleRoute, StateTypes.LOAD, new StateImpl(load));
load=0;
vehicleRoute = null;
}
}

View file

@ -0,0 +1,42 @@
package algorithms;
import java.util.Collection;
import algorithms.StatesContainer.StateImpl;
import basics.Job;
import basics.Service;
import basics.algo.InsertionStartsListener;
import basics.algo.JobInsertedListener;
import basics.route.VehicleRoute;
class UpdateLoadAtRouteLevel implements JobInsertedListener, InsertionStartsListener{
private StatesContainerImpl states;
public UpdateLoadAtRouteLevel(StatesContainerImpl states) {
super();
this.states = states;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
if(!(job2insert instanceof Service)){
return;
}
double oldLoad = states.getRouteState(inRoute, StateTypes.LOAD).toDouble();
states.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(oldLoad + job2insert.getCapacityDemand()));
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
int load = 0;
for(Job j : route.getTourActivities().getJobs()){
load += j.getCapacityDemand();
}
states.putRouteState(route, StateTypes.LOAD, new StateImpl(load));
}
}
}

View file

@ -1,36 +0,0 @@
package algorithms;
import java.util.Collection;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.algo.JobInsertedListener;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.VehicleRoute;
public class UpdateRoute implements JobInsertedListener, RuinListener{
private TourStateUpdater routeStateUpdater;
public UpdateRoute(RouteStates routeStates, VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts) {
routeStateUpdater = new TourStateUpdater(routeStates, routingCosts, activityCosts);
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute) {
routeStateUpdater.updateRoute(inRoute);
}
@Override
public void ruinStarts(Collection<VehicleRoute> routes) {}
@Override
public void ruinEnds(Collection<VehicleRoute> routes,Collection<Job> unassignedJobs) {
for(VehicleRoute route : routes) routeStateUpdater.updateRoute(route);
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {}
}

View file

@ -0,0 +1,55 @@
package algorithms;
import java.util.Collection;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.algo.JobInsertedListener;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.VehicleRoute;
public class UpdateStates implements JobInsertedListener, RuinListener{
private IterateRouteForwardInTime iterateForward;
private IterateRouteBackwardInTime iterateBackward;
public UpdateStates(StatesContainerImpl states, VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts) {
iterateForward = new IterateRouteForwardInTime(routingCosts);
iterateForward.addListener(new UpdateActivityTimes());
iterateForward.addListener(new UpdateCostsAtAllLevels(activityCosts, routingCosts, states));
iterateForward.addListener(new UpdateLoadAtAllLevels(states));
// iterateForward.addListener(new UpdateEarliestStartTimeWindowAtActLocations(states));
iterateBackward = new IterateRouteBackwardInTime(routingCosts);
iterateBackward.addListener(new UpdateLatestOperationStartTimeAtActLocations(states));
}
public void update(VehicleRoute route){
iterateForward.iterate(route);
iterateBackward.iterate(route);
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
iterateForward.iterate(inRoute);
iterateBackward.iterate(inRoute);
}
@Override
public void ruinStarts(Collection<VehicleRoute> routes) {}
@Override
public void ruinEnds(Collection<VehicleRoute> routes,Collection<Job> unassignedJobs) {
for(VehicleRoute route : routes) {
iterateForward.iterate(route);
iterateBackward.iterate(route);
}
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {}
}

View file

@ -1,105 +0,0 @@
/*******************************************************************************
* Copyright (c) 2011 Stefan Schroeder.
* eMail: stefan.schroeder@kit.edu
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.util.Iterator;
import org.apache.log4j.Logger;
import algorithms.RouteStates.ActivityState;
import basics.costs.BackwardTransportTime;
import basics.route.Start;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
/**
*
* @author stefan schroeder
*
*/
class UpdateTourStatesBackwardInTime implements VehicleRouteUpdater{
// public static Counter counter = new Counter("#updateTWProcesses: ");
private static Logger log = Logger.getLogger(UpdateTourStatesBackwardInTime.class);
public boolean checkFeasibility = true;
private BackwardTransportTime transportTime;
private RouteStates actStates;
public void setStates(RouteStates actStates){
this.actStates = actStates;
}
public ActivityState state(TourActivity act){
return actStates.getState(act);
}
public UpdateTourStatesBackwardInTime(BackwardTransportTime transportTime) {
super();
this.transportTime = transportTime;
}
/*
*
*/
public boolean updateRoute(VehicleRoute vehicleRoute) {
boolean ok = update(vehicleRoute);
return ok;
}
private boolean update(VehicleRoute vehicleRoute) {
TourActivities tour = vehicleRoute.getTourActivities();
int tourSize = tour.getActivities().size();
Iterator<TourActivity> reverseActIter = vehicleRoute.getTourActivities().reverseActivityIterator();
TourActivity prevAct;
boolean feasible = true;
prevAct = vehicleRoute.getEnd();
double startAtPrevAct = prevAct.getTheoreticalLatestOperationStartTime();
int count = 0;
while(reverseActIter.hasNext()){
TourActivity currAct = reverseActIter.next();
double latestOperationStartTime = latestOperationStartTime(vehicleRoute, prevAct, currAct, startAtPrevAct);
ActivityState state = state(currAct);
state.setLatestOperationStart(latestOperationStartTime);
prevAct = currAct;
startAtPrevAct = latestOperationStartTime;
count++;
}
// Start start = vehicleRoute.getStart();
// double latestOperationStartTime = latestOperationStartTime(vehicleRoute, prevAct, start, startAtPrevAct);
assert count == tourSize;
return feasible;
}
private double latestOperationStartTime(VehicleRoute vehicleRoute,
TourActivity prevAct, TourActivity currAct, double startAtPrevAct) {
double latestDepTimeAtCurrAct = startAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), startAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle());
double potentialLatestOperationStartTimeAtCurrAct = latestDepTimeAtCurrAct - currAct.getOperationTime();
double latestOperationStartTime = Math.min(currAct.getTheoreticalLatestOperationStartTime(), potentialLatestOperationStartTimeAtCurrAct);
return latestOperationStartTime;
}
}

View file

@ -1,156 +0,0 @@
/*******************************************************************************
* Copyright (c) 2011 Stefan Schroeder.
* eMail: stefan.schroeder@kit.edu
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import org.apache.log4j.Logger;
import algorithms.RouteStates.ActivityState;
import basics.costs.ForwardTransportCost;
import basics.costs.ForwardTransportTime;
import basics.costs.VehicleRoutingActivityCosts;
import basics.route.Driver;
import basics.route.End;
import basics.route.ServiceActivity;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
/**
*
* @author sschroeder
*
*/
class UpdateTourStatesForwardInTime implements VehicleRouteUpdater{
// public static Counter counter = new Counter("#updateTWProcesses: ");
private static Logger log = Logger.getLogger(UpdateTourStatesForwardInTime.class);
public boolean checkFeasibility = true;
private VehicleRoutingActivityCosts activityCost;
private ForwardTransportTime transportTime;
private ForwardTransportCost transportCost;
private RouteStates routeStates;
private boolean activityStatesSet = false;
public void setStates(RouteStates actStates){
this.routeStates = actStates;
activityStatesSet = true;
}
public ActivityState state(TourActivity act){
return routeStates.getState(act);
}
public UpdateTourStatesForwardInTime(ForwardTransportTime transportTime, ForwardTransportCost transportCost, VehicleRoutingActivityCosts activityCost) {
super();
this.transportTime = transportTime;
this.transportCost = transportCost;
this.activityCost = activityCost;
}
/**
*
*
*/
public boolean updateRoute(VehicleRoute vehicleRoute) {
vehicleRoute.getVehicleRouteCostCalculator().reset();
Vehicle vehicle = vehicleRoute.getVehicle();
Driver driver = vehicleRoute.getDriver();
TourActivity prevAct = vehicleRoute.getStart();
double startAtPrevAct = vehicleRoute.getStart().getEndTime();
double totalOperationCost = 0.0;
int totalLoadPicked = 0;
int currentLoadState = 0;
for(TourActivity currentAct : vehicleRoute.getTourActivities().getActivities()){
totalLoadPicked += getPickedLoad(currentAct);
currentLoadState += getCapDemand(currentAct);
double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
double operationStartTime = Math.max(currentAct.getTheoreticalEarliestOperationStartTime(), arrivalTimeAtCurrAct);
double operationEndTime = operationStartTime + currentAct.getOperationTime();
currentAct.setArrTime(arrivalTimeAtCurrAct);
currentAct.setEndTime(operationEndTime);
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
double actCost = activityCost.getActivityCost(currentAct, arrivalTimeAtCurrAct, driver, vehicle);
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
totalOperationCost += transportCost;
totalOperationCost += actCost;
if(activityStatesSet){
ActivityState currentState = state(currentAct);
currentState.setEarliestOperationStart(operationStartTime);
currentState.setCurrentLoad(currentLoadState);
currentState.setCurrentCost(totalOperationCost);
}
prevAct = currentAct;
startAtPrevAct = operationEndTime;
}
End currentAct = vehicleRoute.getEnd();
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
currentAct.setArrTime(arrivalTimeAtCurrAct);
currentAct.setEndTime(arrivalTimeAtCurrAct);
totalOperationCost += transportCost;
routeStates.getRouteState(vehicleRoute).setCosts(totalOperationCost);
routeStates.getRouteState(vehicleRoute).setLoad(totalLoadPicked);
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver());
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().finish();
return true;
}
private int getCapDemand(TourActivity currentAct) {
return currentAct.getCapacityDemand();
}
private double getPickedLoad(TourActivity currentAct) {
if(currentAct instanceof ServiceActivity){
return currentAct.getCapacityDemand();
}
// else if(currentAct instanceof Pickup){
// return currentAct.getCapacityDemand();
// }
return 0.0;
}
}

View file

@ -24,6 +24,6 @@ import basics.route.VehicleRoute;
interface VehicleRouteUpdater { interface VehicleRouteUpdater {
public boolean updateRoute(VehicleRoute vehicleRoute); public void iterate(VehicleRoute vehicleRoute);
} }

View file

@ -57,6 +57,7 @@ import basics.VehicleRoutingProblem.FleetSize;
import basics.VehicleRoutingProblemSolution; import basics.VehicleRoutingProblemSolution;
import basics.algo.AlgorithmStartsListener; import basics.algo.AlgorithmStartsListener;
import basics.algo.InsertionListener; import basics.algo.InsertionListener;
import basics.algo.IterationStartsListener;
import basics.algo.IterationWithoutImprovementBreaker; import basics.algo.IterationWithoutImprovementBreaker;
import basics.algo.PrematureAlgorithmBreaker; import basics.algo.PrematureAlgorithmBreaker;
import basics.algo.SearchStrategy; import basics.algo.SearchStrategy;
@ -447,9 +448,21 @@ public class VehicleRoutingAlgorithms {
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier())); algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier()));
RouteStates routeStates = new RouteStates(); final StatesContainerImpl routeStates = new StatesContainerImpl();
routeStates.initialiseStateOfJobs(vrp.getJobs().values()); IterationStartsListener resetStates = new IterationStartsListener() {
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, routeStates));
@Override
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
routeStates.clear();
}
};
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, resetStates));
// insertionListeners.add(new UdateCostsAtRouteLevel(routeStates,vrp.getTransportCosts(),vrp.getActivityCosts()));
// RouteStates routeStates = new RouteStates();
// routeStates.initialiseStateOfJobs(vrp.getJobs().values());
// algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, routeStates));
TypedMap definedClasses = new TypedMap(); TypedMap definedClasses = new TypedMap();
@ -557,7 +570,7 @@ public class VehicleRoutingAlgorithms {
metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners); metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners);
} }
private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, RouteStates activityStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) { private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StatesContainerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
List<HierarchicalConfiguration> modConfigs = config.configurationsAt("construction.insertion"); List<HierarchicalConfiguration> modConfigs = config.configurationsAt("construction.insertion");
if(modConfigs == null) return null; if(modConfigs == null) return null;
if(modConfigs.isEmpty()) return null; if(modConfigs.isEmpty()) return null;
@ -572,7 +585,7 @@ public class VehicleRoutingAlgorithms {
InsertionStrategy insertionStrategy = definedClasses.get(insertionStrategyKey); InsertionStrategy insertionStrategy = definedClasses.get(insertionStrategyKey);
if(insertionStrategy == null){ if(insertionStrategy == null){
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>(); List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
insertionStrategy = createInsertionStrategy(modConfig, vrp, vehicleFleetManager, activityStates, prioListeners, executorService, nuOfThreads); insertionStrategy = createInsertionStrategy(modConfig, vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads);
algorithmListeners.addAll(prioListeners); algorithmListeners.addAll(prioListeners);
definedClasses.put(insertionStrategyKey,insertionStrategy); definedClasses.put(insertionStrategyKey,insertionStrategy);
} }
@ -654,7 +667,7 @@ public class VehicleRoutingAlgorithms {
} }
private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager,
final RouteStates activityStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) { final StatesContainerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
String moduleName = moduleConfig.getString("[@name]"); String moduleName = moduleConfig.getString("[@name]");
if(moduleName == null) throw new IllegalStateException("module(-name) is missing."); if(moduleName == null) throw new IllegalStateException("module(-name) is missing.");
String moduleId = moduleConfig.getString("[@id]"); String moduleId = moduleConfig.getString("[@id]");
@ -675,7 +688,7 @@ public class VehicleRoutingAlgorithms {
final RuinStrategy ruin; final RuinStrategy ruin;
ModKey ruinKey = makeKey(ruin_name,ruin_id); ModKey ruinKey = makeKey(ruin_name,ruin_id);
if(ruin_name.equals("randomRuin")){ if(ruin_name.equals("randomRuin")){
ruin = getRandomRuin(vrp, activityStates, definedClasses, ruinKey, shareToRuin); ruin = getRandomRuin(vrp, routeStates, definedClasses, ruinKey, shareToRuin);
} }
else if(ruin_name.equals("radialRuin")){ else if(ruin_name.equals("radialRuin")){
String ruin_distance = moduleConfig.getString("ruin.distance"); String ruin_distance = moduleConfig.getString("ruin.distance");
@ -688,7 +701,7 @@ public class VehicleRoutingAlgorithms {
else throw new IllegalStateException("does not know ruin.distance " + ruin_distance + ". either ommit ruin.distance then the " else throw new IllegalStateException("does not know ruin.distance " + ruin_distance + ". either ommit ruin.distance then the "
+ "default is used or use 'euclidean'"); + "default is used or use 'euclidean'");
} }
ruin = getRadialRuin(vrp, activityStates, definedClasses, ruinKey, shareToRuin, jobDistance); ruin = getRadialRuin(vrp, routeStates, definedClasses, ruinKey, shareToRuin, jobDistance);
} }
else throw new IllegalStateException("ruin[@name] " + ruin_name + " is not known. Use either randomRuin or radialRuin."); else throw new IllegalStateException("ruin[@name] " + ruin_name + " is not known. Use either randomRuin or radialRuin.");
@ -703,7 +716,7 @@ public class VehicleRoutingAlgorithms {
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion"); List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1"); if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>(); List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, activityStates, prioListeners, executorService, nuOfThreads); insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads);
algorithmListeners.addAll(prioListeners); algorithmListeners.addAll(prioListeners);
} }
final InsertionStrategy final_insertion = insertion; final InsertionStrategy final_insertion = insertion;
@ -758,23 +771,7 @@ public class VehicleRoutingAlgorithms {
RuinStrategy ruin = definedClasses.get(stratKey); RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){ if(ruin == null){
ruin = new RuinRadial(vrp, 0.3, new JobDistanceAvgCosts(vrp.getTransportCosts())); ruin = new RuinRadial(vrp, 0.3, new JobDistanceAvgCosts(vrp.getTransportCosts()));
ruin.addListener(new RuinListener() { ruin.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
TourStateUpdater updater = new TourStateUpdater(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts());
@Override
public void ruinStarts(Collection<VehicleRoute> routes) {}
@Override
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : routes){
updater.updateRoute(route);
}
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {}
});
definedClasses.put(stratKey, ruin); definedClasses.put(stratKey, ruin);
} }
@ -789,7 +786,7 @@ public class VehicleRoutingAlgorithms {
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion"); List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1"); if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>(); List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, activityStates, prioListeners, executorService, nuOfThreads); insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads);
algorithmListeners.addAll(prioListeners); algorithmListeners.addAll(prioListeners);
} }
Gendreau gendreau = new Gendreau(vrp, ruin, insertion); Gendreau gendreau = new Gendreau(vrp, ruin, insertion);
@ -808,62 +805,30 @@ public class VehicleRoutingAlgorithms {
"\n\tgendreauPostOpt"); "\n\tgendreauPostOpt");
} }
private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final RouteStates activityStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) { private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StatesContainerImpl routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) {
RuinStrategyKey stratKey = new RuinStrategyKey(modKey); RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
RuinStrategy ruin = definedClasses.get(stratKey); RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){ if(ruin == null){
ruin = new RuinRadial(vrp, shareToRuin, jobDistance); ruin = new RuinRadial(vrp, shareToRuin, jobDistance);
ruin.addListener(new RuinListener() { ruin.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
TourStateUpdater updater = new TourStateUpdater(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts());
@Override
public void ruinStarts(Collection<VehicleRoute> routes) {}
@Override
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : routes){
updater.updateRoute(route);
}
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {}
});
definedClasses.put(stratKey, ruin); definedClasses.put(stratKey, ruin);
} }
return ruin; return ruin;
} }
private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final RouteStates activityStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) { private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final StatesContainerImpl routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) {
RuinStrategyKey stratKey = new RuinStrategyKey(modKey); RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
RuinStrategy ruin = definedClasses.get(stratKey); RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){ if(ruin == null){
ruin = new RuinRandom(vrp, shareToRuin); ruin = new RuinRandom(vrp, shareToRuin);
ruin.addListener(new RuinListener() { ruin.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
TourStateUpdater updater = new TourStateUpdater(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts());
@Override
public void ruinStarts(Collection<VehicleRoute> routes) {}
@Override
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : routes){
updater.updateRoute(route);
}
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {}
});
definedClasses.put(stratKey, ruin); definedClasses.put(stratKey, ruin);
} }
return ruin; return ruin;
} }
private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, RouteStates activityStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads) { private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StatesContainerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads) {
InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, activityStates, algorithmListeners, executorService, nuOfThreads); InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads);
return insertion; return insertion;
} }

View file

@ -30,5 +30,5 @@ import basics.route.VehicleRoute;
public interface JobInsertedListener extends InsertionListener{ public interface JobInsertedListener extends InsertionListener{
public void informJobInserted(Job job2insert, VehicleRoute inRoute); public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime);
} }

View file

@ -61,6 +61,7 @@ public final class End implements TourActivity {
this.locationId = locationId; this.locationId = locationId;
theoretical_earliestOperationStartTime = theoreticalStart; theoretical_earliestOperationStartTime = theoreticalStart;
theoretical_latestOperationStartTime = theoreticalEnd; theoretical_latestOperationStartTime = theoreticalEnd;
endTime = theoreticalEnd;
} }
public End(End end) { public End(End end) {

View file

@ -36,7 +36,6 @@ import algorithms.selectors.SelectRandomlyTest;
GendreauPostOptTest.class, GendreauPostOptTest.class,
TestAlgorithmReader.class, TestAlgorithmReader.class,
// TestAux.class, // TestAux.class,
TestCalculatesActivityInsertion.class,
TestCalculatesServiceInsertion.class, TestCalculatesServiceInsertion.class,
TestCalculatesServiceInsertionOnRouteLevel.class, TestCalculatesServiceInsertionOnRouteLevel.class,
TestSchrimpf.class, TestSchrimpf.class,

View file

@ -41,12 +41,12 @@ import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts; import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver; import basics.route.Driver;
import basics.route.DriverImpl; import basics.route.DriverImpl;
import basics.route.ServiceActivity;
import basics.route.TimeWindow; import basics.route.TimeWindow;
import basics.route.TourActivities; import basics.route.TourActivities;
import basics.route.Vehicle; import basics.route.Vehicle;
import basics.route.VehicleImpl; import basics.route.VehicleImpl;
import basics.route.VehicleRoute; import basics.route.VehicleRoute;
import basics.route.VehicleType;
import basics.route.VehicleTypeImpl; import basics.route.VehicleTypeImpl;
public class GendreauPostOptTest { public class GendreauPostOptTest {
@ -71,16 +71,12 @@ public class GendreauPostOptTest {
Service job3; Service job3;
private RouteStates states; private StatesContainerImpl states;
private List<Vehicle> vehicles; private List<Vehicle> vehicles;
private TourStateUpdater updater;
private VehicleFleetManagerImpl fleetManager; private VehicleFleetManagerImpl fleetManager;
private RouteAlgorithmImpl routeAlgorithm;
private JobInsertionCalculator insertionCalc; private JobInsertionCalculator insertionCalc;
@Before @Before
@ -151,7 +147,7 @@ public class GendreauPostOptTest {
// Collection<Vehicle> vehicles = Arrays.asList(lightVehicle1,lightVehicle2, heavyVehicle); // Collection<Vehicle> vehicles = Arrays.asList(lightVehicle1,lightVehicle2, heavyVehicle);
fleetManager = new VehicleFleetManagerImpl(vehicles); fleetManager = new VehicleFleetManagerImpl(vehicles);
states = new RouteStates(); states = new StatesContainerImpl();
activityCosts = new ExampleActivityCostFunction(); activityCosts = new ExampleActivityCostFunction();
@ -162,23 +158,7 @@ public class GendreauPostOptTest {
insertionCalc = new CalculatesVehTypeDepServiceInsertion(fleetManager, withFixCost); insertionCalc = new CalculatesVehTypeDepServiceInsertion(fleetManager, withFixCost);
updater = new TourStateUpdater(states, cost, activityCosts); // updater = new TourStateUpdater(states, cost, activityCosts);
//
//
// routeAlgorithm = RouteAlgorithmImpl.newInstance(insertionCalc, updater);
// routeAlgorithm.setActivityStates(states);
// if(fleetManager != null){
// routeAlgorithm.getListeners().add(new RouteAlgorithm.VehicleSwitchedListener() {
//
// @Override
// public void vehicleSwitched(Vehicle oldVehicle, Vehicle newVehicle) {
// fleetManager.unlock(oldVehicle);
// fleetManager.lock(newVehicle);
// }
// });
// }
} }
@ -188,18 +168,19 @@ public class GendreauPostOptTest {
jobs.add(job1); jobs.add(job1);
jobs.add(job2); jobs.add(job2);
states.initialiseStateOfJobs(jobs);
vrp = VehicleRoutingProblem.Builder.newInstance().addAllJobs(jobs).addAllVehicles(vehicles).setRoutingCost(cost).build(); vrp = VehicleRoutingProblem.Builder.newInstance().addAllJobs(jobs).addAllVehicles(vehicles).setRoutingCost(cost).build();
TourActivities tour = new TourActivities(); TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(job1, true)); tour.addActivity(ServiceActivity.newInstance(job1));
tour.addActivity(states.getActivity(job2, true)); tour.addActivity(ServiceActivity.newInstance(job2));
VehicleRoute route = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),heavyVehicle); VehicleRoute route = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),heavyVehicle);
updater.updateRoute(route);
fleetManager.lock(heavyVehicle); fleetManager.lock(heavyVehicle);
UpdateStates stateUpdater = new UpdateStates(states, vrp.getTransportCosts(), vrp.getActivityCosts());
stateUpdater.update(route);
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>(); Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
routes.add(route); routes.add(route);
// routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle())); // routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle()));
@ -209,7 +190,6 @@ public class GendreauPostOptTest {
assertEquals(110.0, sol.getCost(), 0.5); assertEquals(110.0, sol.getCost(), 0.5);
UpdateRoute stateUpdater = new UpdateRoute(states, vrp.getTransportCosts(), vrp.getActivityCosts());
RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts())); RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()));
radialRuin.addListener(stateUpdater); radialRuin.addListener(stateUpdater);
@ -234,17 +214,17 @@ public class GendreauPostOptTest {
jobs.add(job2); jobs.add(job2);
jobs.add(job3); jobs.add(job3);
states.initialiseStateOfJobs(jobs);
vrp = VehicleRoutingProblem.Builder.newInstance().addAllJobs(jobs).addAllVehicles(vehicles).setRoutingCost(cost).build(); vrp = VehicleRoutingProblem.Builder.newInstance().addAllJobs(jobs).addAllVehicles(vehicles).setRoutingCost(cost).build();
TourActivities tour = new TourActivities(); TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(job1, true)); tour.addActivity(ServiceActivity.newInstance(job1));
tour.addActivity(states.getActivity(job2, true)); tour.addActivity(ServiceActivity.newInstance(job2));
tour.addActivity(states.getActivity(job3, true)); tour.addActivity(ServiceActivity.newInstance(job3));
VehicleRoute route = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),heavyVehicle); VehicleRoute route = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),heavyVehicle);
updater.updateRoute(route);
UpdateStates stateUpdater = new UpdateStates(states, vrp.getTransportCosts(), vrp.getActivityCosts());
stateUpdater.update(route);
fleetManager.lock(heavyVehicle); fleetManager.lock(heavyVehicle);
@ -255,8 +235,6 @@ public class GendreauPostOptTest {
assertEquals(110.0, sol.getCost(), 0.5); assertEquals(110.0, sol.getCost(), 0.5);
UpdateRoute stateUpdater = new UpdateRoute(states, vrp.getTransportCosts(), vrp.getActivityCosts());
RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts())); RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()));
InsertionStrategy insertionStrategy = new BestInsertion(insertionCalc); InsertionStrategy insertionStrategy = new BestInsertion(insertionCalc);
insertionStrategy.addListener(stateUpdater); insertionStrategy.addListener(stateUpdater);
@ -273,18 +251,6 @@ public class GendreauPostOptTest {
assertEquals(80.0,newSolution.getCost(),0.5); assertEquals(80.0,newSolution.getCost(),0.5);
} }
private Vehicle getNoVehicle() {
return new VehicleImpl.NoVehicle();
}
private Driver getDriver() {
return DriverImpl.noDriver();
}
private TourActivities getEmptyTour() {
return new TourActivities();
}
private Service getService(String to, double serviceTime) { private Service getService(String to, double serviceTime) {
Service s = Service.Builder.newInstance(to, 0).setLocationId(to).setServiceTime(serviceTime).setTimeWindow(TimeWindow.newInstance(0.0, 20.0)).build(); Service s = Service.Builder.newInstance(to, 0).setLocationId(to).setServiceTime(serviceTime).setTimeWindow(TimeWindow.newInstance(0.0, 20.0)).build();

View file

@ -1,286 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import algorithms.RouteStates.ActivityState;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
public class TestCalculatesActivityInsertion {
VehicleRoutingTransportCosts costs;
Vehicle newVehicle;
private RouteStates states;
private CalculatesActivityInsertionWithHardTimeWindows insertionCalculator;
@Before
public void setup(){
costs = mock(VehicleRoutingTransportCosts.class);
newVehicle = mock(Vehicle.class);
when(costs.getTransportCost("depot", "1", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("depot", "2", 0.0, null, null)).thenReturn(20.0);
when(costs.getTransportCost("depot", "3", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("1", "2", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("1", "3", 0.0, null, null)).thenReturn(20.0);
when(costs.getTransportCost("2", "3", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("1", "depot", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("2", "depot", 0.0, null, null)).thenReturn(20.0);
when(costs.getTransportCost("3", "depot", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("2", "1", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("3", "1", 0.0, null, null)).thenReturn(20.0);
when(costs.getTransportCost("3", "2", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("depot", "1", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("depot", "2", 0.0, null, newVehicle)).thenReturn(40.0);
when(costs.getTransportCost("depot", "3", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("1", "2", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("1", "3", 0.0, null, newVehicle)).thenReturn(40.0);
when(costs.getTransportCost("2", "3", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("1", "depot", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("2", "depot", 0.0, null, newVehicle)).thenReturn(40.0);
when(costs.getTransportCost("3", "depot", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("2", "1", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("3", "1", 0.0, null, newVehicle)).thenReturn(40.0);
when(costs.getTransportCost("3", "2", 0.0, null, newVehicle)).thenReturn(20.0);
states = new RouteStates();
insertionCalculator = new CalculatesActivityInsertionWithHardTimeWindows(states,costs,activityCosts());
}
private ExampleActivityCostFunction activityCosts() {
return new ExampleActivityCostFunction();
}
public TourActivity getActivityMock(String id, double earliestOperationStart, double currCost){
TourActivity act = mock(TourActivity.class);
when(act.getLocationId()).thenReturn(id);
states.getActivityStates().put(act, new ActivityState(act));
states.getState(act).setEarliestOperationStart(earliestOperationStart);
states.getState(act).setCurrentCost(currCost);
// when(act.getEarliestOperationStartTime()).thenReturn(earliestOperationStart);
// when(act.getCurrentCost()).thenReturn(currCost);
return act;
}
@Test
public void whenInsertingANewJob_itCalculatesMarginalCostChanges(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity prevAct = getActivityMock("1", 0.0, 10.0);
TourActivity nextAct = getActivityMock("3", 0.0, 30.0);
TourActivity act2insert = getActivityMock("2", 0.0, 0.0);
TourActivity end = getActivityMock("depot", 0.0, 40.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(prevAct);
vehicleRoute.getTourActivities().addActivity(nextAct);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,prevAct,nextAct,end);
when(tour.getActivities()).thenReturn(activities);
// when(states.getRouteState(vehicleRoute).getCosts()).thenReturn(40.0);
double c = insertionCalculator.calculate(vehicleRoute, prevAct, nextAct, act2insert, null, null);
assertEquals(0.0,c,0.2);
}
@Test
public void whenInsertingANewJob_itCalculatesMarginalCostChanges2(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity act1 = getActivityMock("1", 0.0, 10.0);
TourActivity act3 = getActivityMock("3", 0.0, 0.0);
TourActivity act2 = getActivityMock("2", 0.0, 20.0);
TourActivity end = getActivityMock("depot", 0.0, 40.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(act1);
vehicleRoute.getTourActivities().addActivity(act2);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,act1,act2,end);
when(tour.getActivities()).thenReturn(activities);
double c = insertionCalculator.calculate(vehicleRoute, act1, act2, act3, null, null);
assertEquals(20.0,c,0.2);
}
@Test
public void whenInsertingANewJob_itCalculatesMarginalCostChanges3(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity act1 = getActivityMock("1", 0.0, 10.0);
TourActivity act3 = getActivityMock("3", 0.0, 0.0);
TourActivity act2 = getActivityMock("2", 0.0, 0.0);
TourActivity end = getActivityMock("depot", 0.0, 20.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(act1);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,act1,end);
when(tour.getActivities()).thenReturn(activities);
double c = insertionCalculator.calculate(vehicleRoute, start, act1, act3, null, null);
assertEquals(20.0,c,0.2);
}
@Test
public void whenInsertingANewJobWithANewVehicle_itCalculatesLocalMarginalCostChanges(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity act1 = getActivityMock("1", 0.0, 10.0);
TourActivity act3 = getActivityMock("3", 0.0, 0.0);
TourActivity act2 = getActivityMock("2", 0.0, 20.0);
TourActivity end = getActivityMock("depot", 0.0, 40.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(act1);
vehicleRoute.getTourActivities().addActivity(act2);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,act1,act2,end);
when(tour.getActivities()).thenReturn(activities);
double c = insertionCalculator.calculate(vehicleRoute, act1, act2, act3, null, newVehicle);
assertEquals(50.0,c,0.2);
}
@Test
public void whenInsertingANewJobWithANewVehicle_itCalculatesLocalMarginalCostChangesAndAfterInsertionCostChanges(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity act1 = getActivityMock("1", 0.0, 10.0);
TourActivity act3 = getActivityMock("3", 0.0, 0.0);
TourActivity act2 = getActivityMock("2", 0.0, 20.0);
TourActivity end = getActivityMock("depot", 0.0, 40.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(act1);
vehicleRoute.getTourActivities().addActivity(act2);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,act1,act2,end);
when(tour.getActivities()).thenReturn(activities);
double c = insertionCalculator.calculate(vehicleRoute, act1, act2, act3, null, newVehicle);
assertEquals(50.0,c,0.2);
}
//already on route-level
// @Test
// public void whenInsertingANewJobWithANewVehicle_itCalculatesTotalMarginalCostChanges(){
// Tour tour = mock(Tour.class);
// TourActivity start = getActivityMock("depot", 0.0, 0.0);
// TourActivity act1 = getActivityMock("1", 0.0, 10.0);
// TourActivity act3 = getActivityMock("3", 0.0, 0.0);
// TourActivity act2 = getActivityMock("2", 0.0, 20.0);
// TourActivity end = getActivityMock("depot", 0.0, 40.0);
//
// List<TourActivity> activities = Arrays.asList(start,act1,act2,end);
// when(tour.getActivities()).thenReturn(activities);
//
// double c = insertionCalculator.calculate(tour, act1, act2, act3, null, newVehicle);
// assertEquals(80.0,c,0.2);
// }
@Test
public void whenInsertingANewJobWithANewVehicle_itCalculatesTotalMarginalCostChanges2(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity act1 = getActivityMock("1", 0.0, 10.0);
TourActivity act3 = getActivityMock("3", 0.0, 0.0);
TourActivity act2 = getActivityMock("2", 0.0, 20.0);
TourActivity end = getActivityMock("depot", 0.0, 40.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(act1);
vehicleRoute.getTourActivities().addActivity(act2);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,act1,act2,end);
when(tour.getActivities()).thenReturn(activities);
double c = insertionCalculator.calculate(vehicleRoute, act2, end, act3, null, newVehicle);
assertEquals(20.0,c,0.2);
}
@Test
public void whenInsertingANewJobWithANewVehicle_itCalculatesTotalMarginalCostChanges3(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity act1 = getActivityMock("1", 0.0, 10.0);
TourActivity act3 = getActivityMock("3", 0.0, 0.0);
TourActivity act2 = getActivityMock("2", 0.0, 20.0);
TourActivity end = getActivityMock("depot", 0.0, 40.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(act1);
vehicleRoute.getTourActivities().addActivity(act2);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,act1,act2,end);
when(tour.getActivities()).thenReturn(activities);
double c = insertionCalculator.calculate(vehicleRoute, start, act1, act3, null, newVehicle);
assertEquals(50.0,c,0.2);
}
}

View file

@ -36,6 +36,7 @@ import basics.Job;
import basics.Service; import basics.Service;
import basics.costs.VehicleRoutingTransportCosts; import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DriverImpl; import basics.route.DriverImpl;
import basics.route.ServiceActivity;
import basics.route.TimeWindow; import basics.route.TimeWindow;
import basics.route.TourActivities; import basics.route.TourActivities;
import basics.route.TourActivity; import basics.route.TourActivity;
@ -61,12 +62,12 @@ public class TestCalculatesServiceInsertion {
private Service third; private Service third;
private RouteStates states; private StatesContainerImpl states;
private TourStateUpdater tourStateUpdater;
private NoDriver driver; private NoDriver driver;
private UpdateStates stateUpdater;
@Before @Before
public void setup(){ public void setup(){
Logger.getRootLogger().setLevel(Level.DEBUG); Logger.getRootLogger().setLevel(Level.DEBUG);
@ -151,17 +152,14 @@ public class TestCalculatesServiceInsertion {
jobs.add(second); jobs.add(second);
jobs.add(third); jobs.add(third);
states = new RouteStates(); states = new StatesContainerImpl();
states.initialiseStateOfJobs(jobs);
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction(); ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
serviceInsertion = new CalculatesServiceInsertion(costs, activityCosts); serviceInsertion = new CalculatesServiceInsertion(costs, activityCosts);
serviceInsertion.setActivityStates(states); serviceInsertion.setActivityStates(states);
tourStateUpdater = new TourStateUpdater(states, costs, activityCosts); stateUpdater = new UpdateStates(states, costs, activityCosts);
} }
@ -176,7 +174,7 @@ public class TestCalculatesServiceInsertion {
TourActivities tour = new TourActivities(); TourActivities tour = new TourActivities();
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route); stateUpdater.update(route);
InsertionData iData = serviceInsertion.calculate(route, first, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); InsertionData iData = serviceInsertion.calculate(route, first, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(20.0, iData.getInsertionCost(), 0.2); assertEquals(20.0, iData.getInsertionCost(), 0.2);
@ -186,10 +184,10 @@ public class TestCalculatesServiceInsertion {
@Test @Test
public void whenInsertingTheSecondJobInAnNonEmptyTourWithVehicle_itCalculatesMarginalCostChanges(){ public void whenInsertingTheSecondJobInAnNonEmptyTourWithVehicle_itCalculatesMarginalCostChanges(){
TourActivities tour = new TourActivities(); TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first, true)); tour.addActivity(ServiceActivity.newInstance(first));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route); stateUpdater.update(route);
InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(20.0, iData.getInsertionCost(), 0.2); assertEquals(20.0, iData.getInsertionCost(), 0.2);
@ -199,12 +197,12 @@ public class TestCalculatesServiceInsertion {
@Test @Test
public void whenInsertingThirdJobWithVehicle_itCalculatesMarginalCostChanges(){ public void whenInsertingThirdJobWithVehicle_itCalculatesMarginalCostChanges(){
TourActivities tour = new TourActivities(); TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first,true)); tour.addActivity(ServiceActivity.newInstance(first));
tour.addActivity(states.getActivity(second,true)); tour.addActivity(ServiceActivity.newInstance(second));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route); stateUpdater.update(route);
InsertionData iData = serviceInsertion.calculate(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); InsertionData iData = serviceInsertion.calculate(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(0.0, iData.getInsertionCost(), 0.2); assertEquals(0.0, iData.getInsertionCost(), 0.2);
@ -214,12 +212,12 @@ public class TestCalculatesServiceInsertion {
@Test @Test
public void whenInsertingThirdJobWithNewVehicle_itCalculatesMarginalCostChanges(){ public void whenInsertingThirdJobWithNewVehicle_itCalculatesMarginalCostChanges(){
TourActivities tour = new TourActivities(); TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first,true)); tour.addActivity(ServiceActivity.newInstance(first));
tour.addActivity(states.getActivity(second,true)); tour.addActivity(ServiceActivity.newInstance(second));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route); stateUpdater.update(route);
InsertionData iData = serviceInsertion.calculate(route, third, newVehicle, newVehicle.getEarliestDeparture(), null, Double.MAX_VALUE); InsertionData iData = serviceInsertion.calculate(route, third, newVehicle, newVehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(20.0, iData.getInsertionCost(), 0.2); assertEquals(20.0, iData.getInsertionCost(), 0.2);
@ -229,11 +227,11 @@ public class TestCalculatesServiceInsertion {
@Test @Test
public void whenInsertingASecondJobWithAVehicle_itCalculatesLocalMarginalCostChanges(){ public void whenInsertingASecondJobWithAVehicle_itCalculatesLocalMarginalCostChanges(){
TourActivities tour = new TourActivities(); TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first,true)); tour.addActivity(ServiceActivity.newInstance(first));
tour.addActivity(states.getActivity(third,true)); tour.addActivity(ServiceActivity.newInstance(third));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route); stateUpdater.update(route);
InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(0.0, iData.getInsertionCost(), 0.2); assertEquals(0.0, iData.getInsertionCost(), 0.2);
@ -243,13 +241,13 @@ public class TestCalculatesServiceInsertion {
@Test @Test
public void whenInsertingASecondJobWithANewVehicle_itCalculatesLocalMarginalCostChanges(){ public void whenInsertingASecondJobWithANewVehicle_itCalculatesLocalMarginalCostChanges(){
TourActivities tour = new TourActivities(); TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first,true)); tour.addActivity(ServiceActivity.newInstance(first));
tour.addActivity(states.getActivity(third,true)); tour.addActivity(ServiceActivity.newInstance(third));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
// route.addActivity(states.getActivity(first,true)); // route.addActivity(states.getActivity(first,true));
// route.addActivity(states.getActivity(third,true)); // route.addActivity(states.getActivity(third,true));
tourStateUpdater.updateRoute(route); stateUpdater.update(route);
InsertionData iData = serviceInsertion.calculate(route, second, newVehicle, newVehicle.getEarliestDeparture(), null, Double.MAX_VALUE); InsertionData iData = serviceInsertion.calculate(route, second, newVehicle, newVehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(20.0, iData.getInsertionCost(), 0.2); assertEquals(20.0, iData.getInsertionCost(), 0.2);

View file

@ -64,9 +64,7 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
private Service third; private Service third;
private RouteStates states; private StatesContainerImpl states;
private TourStateUpdater tourStateUpdater;
private NoDriver driver; private NoDriver driver;
@ -167,7 +165,7 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
TourActivities tour = new TourActivities(); TourActivities tour = new TourActivities();
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route); tourStateUpdater.iterate(route);
InsertionData iData = serviceInsertion.calculate(route, first, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); InsertionData iData = serviceInsertion.calculate(route, first, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(20.0, iData.getInsertionCost(), 0.2); assertEquals(20.0, iData.getInsertionCost(), 0.2);
@ -208,7 +206,7 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route); tourStateUpdater.iterate(route);
InsertionData iData = serviceInsertion.calculate(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); InsertionData iData = serviceInsertion.calculate(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(0.0, iData.getInsertionCost(), 0.2); assertEquals(0.0, iData.getInsertionCost(), 0.2);
@ -223,7 +221,7 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route); tourStateUpdater.iterate(route);
InsertionData iData = serviceInsertion.calculate(route, third, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); InsertionData iData = serviceInsertion.calculate(route, third, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(40.0, iData.getInsertionCost(), 0.2); assertEquals(40.0, iData.getInsertionCost(), 0.2);
@ -237,7 +235,7 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
tour.addActivity(states.getActivity(third,true)); tour.addActivity(states.getActivity(third,true));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route); tourStateUpdater.iterate(route);
InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(0.0, iData.getInsertionCost(), 0.2); assertEquals(0.0, iData.getInsertionCost(), 0.2);
@ -251,7 +249,7 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
tour.addActivity(states.getActivity(third,true)); tour.addActivity(states.getActivity(third,true));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route); tourStateUpdater.iterate(route);
InsertionData iData = serviceInsertion.calculate(route, second, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); InsertionData iData = serviceInsertion.calculate(route, second, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(40.0, iData.getInsertionCost(), 0.2); assertEquals(40.0, iData.getInsertionCost(), 0.2);

View file

@ -0,0 +1,196 @@
package algorithms;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Collection;
import org.junit.Before;
import org.junit.Test;
import util.Coordinate;
import util.ManhattanDistanceCalculator;
import basics.Job;
import basics.Service;
import basics.costs.DefaultVehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver;
import basics.route.DriverImpl;
import basics.route.ServiceActivity;
import basics.route.TimeWindow;
import basics.route.TourActivities;
import basics.route.Vehicle;
import basics.route.VehicleImpl;
import basics.route.VehicleRoute;
import basics.route.VehicleTypeImpl;
public class TestIterateRouteForwardInTime {
TourActivities tour;
Driver driver;
Vehicle vehicle;
TourActivities anotherTour;
RouteStates states;
private VehicleRoute vehicleRoute;
private VehicleRoutingTransportCosts cost;
ServiceActivity firstAct;
ServiceActivity secondAct;
@Before
public void setUp(){
cost = new VehicleRoutingTransportCosts() {
@Override
public double getBackwardTransportTime(String fromId, String toId,
double arrivalTime, Driver driver, Vehicle vehicle) {
return getTransportCost(fromId, toId, arrivalTime, driver, vehicle);
}
@Override
public double getBackwardTransportCost(String fromId, String toId,
double arrivalTime, Driver driver, Vehicle vehicle) {
return getTransportCost(fromId, toId, arrivalTime, driver, vehicle);
}
@Override
public double getTransportCost(String fromId, String toId, double departureTime, Driver driver, Vehicle vehicle) {
String[] fromTokens = fromId.split(",");
String[] toTokens = toId.split(",");
double fromX = Double.parseDouble(fromTokens[0]);
double fromY = Double.parseDouble(fromTokens[1]);
double toX = Double.parseDouble(toTokens[0]);
double toY = Double.parseDouble(toTokens[1]);
return ManhattanDistanceCalculator.calculateDistance(new Coordinate(fromX, fromY), new Coordinate(toX, toY));
}
@Override
public double getTransportTime(String fromId, String toId, double departureTime, Driver driver, Vehicle vehicle) {
return getTransportCost(fromId, toId, departureTime, driver, vehicle);
}
};
Service firstService = Service.Builder.newInstance("1", 5).setLocationId("10,0").setTimeWindow(TimeWindow.newInstance(0, 20)).build();
Service secondService = Service.Builder.newInstance("2", 5).setLocationId("0,10").setTimeWindow(TimeWindow.newInstance(0, 50)).build();
Collection<Job> services = new ArrayList<Job>();
services.add(firstService);
services.add(secondService);
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("test", 0).build();
vehicle = VehicleImpl.Builder.newInstance("testvehicle").setType(type).setLocationId("0,0")
.setEarliestStart(0.0).setLatestArrival(50.0).build();
tour = new TourActivities();
firstAct = ServiceActivity.newInstance(firstService);
tour.addActivity(firstAct);
secondAct = ServiceActivity.newInstance(secondService);
tour.addActivity(secondAct);
vehicleRoute = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),vehicle);
}
@Test
public void whenIteratingWithoutUpdate_itShouldUpdateNothing() {
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
forwardInTime.iterate(vehicleRoute);
assertEquals(0.0,firstAct.getArrTime(),0.1);
assertEquals(0.0,firstAct.getEndTime(),0.1);
assertEquals(0.0,secondAct.getArrTime(),0.1);
assertEquals(0.0,secondAct.getEndTime(),0.1);
}
@Test
public void whenIteratingWithActivityTimeUpdater_itShouldUpdateActivityTimes() {
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
forwardInTime.addListener(new UpdateActivityTimes());
forwardInTime.iterate(vehicleRoute);
assertEquals(10.0,firstAct.getArrTime(),0.1);
assertEquals(10.0,firstAct.getEndTime(),0.1);
assertEquals(30.0,secondAct.getArrTime(),0.1);
assertEquals(30.0,secondAct.getEndTime(),0.1);
}
@Test
public void whenIteratingWithLoadUpdateAtActLocations_itShouldUpdateLoad() {
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
StatesContainerImpl states = new StatesContainerImpl();
forwardInTime.addListener(new UpdateLoadAtAllLevels(states));
forwardInTime.iterate(vehicleRoute);
assertEquals(5.0, states.getActivityStates(firstAct).getState(StateTypes.LOAD).toDouble(), 0.01);
assertEquals(10.0, states.getActivityStates(secondAct).getState(StateTypes.LOAD).toDouble(), 0.01);
}
@Test
public void testStatesOfAct0(){
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
forwardInTime.iterate(vehicleRoute);
assertEquals(0.0, vehicleRoute.getStart().getEndTime(),0.05);
assertEquals(vehicleRoute.getVehicle().getLocationId(), vehicleRoute.getStart().getLocationId());
assertEquals(vehicleRoute.getVehicle().getEarliestDeparture(), vehicleRoute.getStart().getTheoreticalEarliestOperationStartTime(),0.05);
assertEquals(vehicleRoute.getVehicle().getLatestArrival(), vehicleRoute.getStart().getTheoreticalLatestOperationStartTime(),0.05);
}
@Test
public void testStatesOfAct1(){
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
StatesContainerImpl states = new StatesContainerImpl();
forwardInTime.addListener(new UpdateLoadAtAllLevels(states));
forwardInTime.addListener(new UpdateEarliestStartTimeWindowAtActLocations(states));
forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, states));
forwardInTime.iterate(vehicleRoute);
assertEquals(10.0, states.getActivityStates(firstAct).getState(StateTypes.COSTS).toDouble(),0.05);
assertEquals(5.0, states.getActivityStates(firstAct).getState(StateTypes.LOAD).toDouble(),0.05);
assertEquals(10.0, states.getActivityStates(firstAct).getState(StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05);
// assertEquals(20.0, states.getState(tour.getActivities().get(0)).getLatestOperationStart(),0.05);
}
@Test
public void testStatesOfAct2(){
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
StatesContainerImpl states = new StatesContainerImpl();
forwardInTime.addListener(new UpdateLoadAtAllLevels(states));
forwardInTime.addListener(new UpdateEarliestStartTimeWindowAtActLocations(states));
forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, states));
forwardInTime.iterate(vehicleRoute);
assertEquals(30.0, states.getActivityStates(secondAct).getState(StateTypes.COSTS).toDouble(),0.05);
assertEquals(10.0, states.getActivityStates(secondAct).getState(StateTypes.LOAD).toDouble(),0.05);
assertEquals(30.0, states.getActivityStates(secondAct).getState(StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05);
// assertEquals(40.0, states.getState(tour.getActivities().get(1)).getLatestOperationStart(),0.05);
}
@Test
public void testStatesOfAct3(){
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
StatesContainerImpl states = new StatesContainerImpl();
forwardInTime.addListener(new UpdateActivityTimes());
forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, states));
forwardInTime.iterate(vehicleRoute);
assertEquals(40.0, states.getRouteStates(vehicleRoute).getState(StateTypes.COSTS).toDouble(), 0.05);
assertEquals(40.0, vehicleRoute.getEnd().getEndTime(),0.05);
assertEquals(50.0, vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime(),0.05);
}
}

View file

@ -119,14 +119,14 @@ public class TestTourStateUpdaterWithService {
@Test @Test
public void testCalculatedCost() { public void testCalculatedCost() {
tdTourStatusProcessor.updateRoute(vehicleRoute); tdTourStatusProcessor.iterate(vehicleRoute);
assertEquals(40.0, states.getRouteState(vehicleRoute).getCosts(), 0.05); assertEquals(40.0, states.getRouteState(vehicleRoute).getCosts(), 0.05);
assertEquals(10, states.getRouteState(vehicleRoute).getLoad()); assertEquals(10, states.getRouteState(vehicleRoute).getLoad());
} }
@Test @Test
public void testStatesOfAct0(){ public void testStatesOfAct0(){
tdTourStatusProcessor.updateRoute(vehicleRoute); tdTourStatusProcessor.iterate(vehicleRoute);
assertEquals(0.0, vehicleRoute.getStart().getEndTime(),0.05); assertEquals(0.0, vehicleRoute.getStart().getEndTime(),0.05);
assertEquals(vehicleRoute.getVehicle().getLocationId(), vehicleRoute.getStart().getLocationId()); assertEquals(vehicleRoute.getVehicle().getLocationId(), vehicleRoute.getStart().getLocationId());
assertEquals(vehicleRoute.getVehicle().getEarliestDeparture(), vehicleRoute.getStart().getTheoreticalEarliestOperationStartTime(),0.05); assertEquals(vehicleRoute.getVehicle().getEarliestDeparture(), vehicleRoute.getStart().getTheoreticalEarliestOperationStartTime(),0.05);
@ -136,7 +136,7 @@ public class TestTourStateUpdaterWithService {
@Test @Test
public void testStatesOfAct1(){ public void testStatesOfAct1(){
tdTourStatusProcessor.updateRoute(vehicleRoute); tdTourStatusProcessor.iterate(vehicleRoute);
assertEquals(10.0, states.getState(tour.getActivities().get(0)).getCurrentCost(),0.05); assertEquals(10.0, states.getState(tour.getActivities().get(0)).getCurrentCost(),0.05);
assertEquals(5.0, states.getState(tour.getActivities().get(0)).getCurrentLoad(),0.05); assertEquals(5.0, states.getState(tour.getActivities().get(0)).getCurrentLoad(),0.05);
assertEquals(10.0, states.getState(tour.getActivities().get(0)).getEarliestOperationStart(),0.05); assertEquals(10.0, states.getState(tour.getActivities().get(0)).getEarliestOperationStart(),0.05);
@ -145,7 +145,7 @@ public class TestTourStateUpdaterWithService {
@Test @Test
public void testStatesOfAct2(){ public void testStatesOfAct2(){
tdTourStatusProcessor.updateRoute(vehicleRoute); tdTourStatusProcessor.iterate(vehicleRoute);
assertEquals(30.0, states.getState(tour.getActivities().get(1)).getCurrentCost(),0.05); assertEquals(30.0, states.getState(tour.getActivities().get(1)).getCurrentCost(),0.05);
assertEquals(10.0, states.getState(tour.getActivities().get(1)).getCurrentLoad(),0.05); assertEquals(10.0, states.getState(tour.getActivities().get(1)).getCurrentLoad(),0.05);
assertEquals(30.0, states.getState(tour.getActivities().get(1)).getEarliestOperationStart(),0.05); assertEquals(30.0, states.getState(tour.getActivities().get(1)).getEarliestOperationStart(),0.05);
@ -154,7 +154,7 @@ public class TestTourStateUpdaterWithService {
@Test @Test
public void testStatesOfAct3(){ public void testStatesOfAct3(){
tdTourStatusProcessor.updateRoute(vehicleRoute); tdTourStatusProcessor.iterate(vehicleRoute);
assertEquals(40.0, states.getRouteState(vehicleRoute).getCosts(), 0.05); assertEquals(40.0, states.getRouteState(vehicleRoute).getCosts(), 0.05);
assertEquals(40.0, vehicleRoute.getEnd().getEndTime(),0.05); assertEquals(40.0, vehicleRoute.getEnd().getEndTime(),0.05);
assertEquals(50.0, vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime(),0.05); assertEquals(50.0, vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime(),0.05);

View file

@ -25,7 +25,9 @@
<iterations>10000</iterations> <iterations>10000</iterations>
<construction> <construction>
<insertion name="bestInsertion"/> <insertion name="bestInsertion">
<level forwardLooking="0" memory="1">route</level>
</insertion>
</construction> </construction>
<strategy> <strategy>