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

add shipment based activities, modify inserter and implement

insertionAlgo for shipments
This commit is contained in:
oblonski 2013-10-21 07:53:09 +02:00
parent c31e61a797
commit 2835d15dd3
12 changed files with 570 additions and 51 deletions

View file

@ -19,19 +19,91 @@ package algorithms;
import algorithms.InsertionData.NoInsertionFound;
import basics.Job;
import basics.Service;
import basics.Shipment;
import basics.route.DefaultShipmentActivityFactory;
import basics.route.DefaultTourActivityFactory;
import basics.route.TourActivity;
import basics.route.TourActivityFactory;
import basics.route.TourShipmentActivityFactory;
import basics.route.VehicleRoute;
class Inserter {
interface JobInsertionHandler {
void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route);
void setNextHandler(JobInsertionHandler handler);
}
class JobExceptionHandler implements JobInsertionHandler{
@Override
public void handleJobInsertion(Job job, InsertionData iData,VehicleRoute route) {
throw new IllegalStateException("job insertion is not supported. Do not know job type.");
}
@Override
public void setNextHandler(JobInsertionHandler handler) {
// TODO Auto-generated method stub
}
}
class ServiceInsertionHandler implements JobInsertionHandler{
private TourActivityFactory activityFactory = new DefaultTourActivityFactory();
private JobInsertionHandler delegator = new JobExceptionHandler();
@Override
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
if(job instanceof Service){
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), this.activityFactory.createActivity((Service)job));
route.setDepartureTime(iData.getVehicleDepartureTime());
}
else delegator.handleJobInsertion(job, iData, route);
}
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
this.delegator = jobInsertionHandler;
}
}
class ShipmentInsertionHandler implements JobInsertionHandler {
private TourShipmentActivityFactory activityFactory = new DefaultShipmentActivityFactory();
private JobInsertionHandler delegator = new JobExceptionHandler();
@Override
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
if(job instanceof Shipment){
TourActivity pickupShipment = this.activityFactory.createPickup((Shipment)job);
TourActivity deliverShipment = this.activityFactory.createDelivery((Shipment)job);
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), deliverShipment);
route.getTourActivities().addActivity(iData.getPickupInsertionIndex(), pickupShipment);
route.setDepartureTime(iData.getVehicleDepartureTime());
}
else delegator.handleJobInsertion(job, iData, route);
}
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
this.delegator = jobInsertionHandler;
}
}
private InsertionListeners insertionListeners;
private TourActivityFactory activityFactory;
private JobInsertionHandler jobInsertionHandler;
public Inserter(InsertionListeners insertionListeners) {
this.insertionListeners = insertionListeners;
activityFactory = new DefaultTourActivityFactory();
new DefaultTourActivityFactory();
jobInsertionHandler = new ServiceInsertionHandler();
jobInsertionHandler.setNextHandler(new ShipmentInsertionHandler());
}
public void insertJob(Job job, InsertionData insertionData, VehicleRoute vehicleRoute){
@ -43,14 +115,7 @@ class Inserter {
insertionListeners.informVehicleSwitched(vehicleRoute, vehicleRoute.getVehicle(), insertionData.getSelectedVehicle());
vehicleRoute.setVehicle(insertionData.getSelectedVehicle(), insertionData.getVehicleDepartureTime());
}
// if(vehicleRoute.getDepartureTime() != vehicleRoute.g)
if(job instanceof Service) {
vehicleRoute.getTourActivities().addActivity(insertionData.getDeliveryInsertionIndex(), activityFactory.createActivity((Service)job));
vehicleRoute.setDepartureTime(insertionData.getVehicleDepartureTime());
}
else throw new IllegalStateException("neither service nor shipment. this is not supported.");
jobInsertionHandler.handleJobInsertion(job, insertionData, vehicleRoute);
insertionListeners.informJobInserted(job, vehicleRoute, insertionData.getInsertionCost(), insertionData.getAdditionalTime());
// updateTour(vehicleRoute);
}
}

View file

@ -30,6 +30,7 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
private HardActivityLevelConstraint hardConstraint;
private VehicleRoutingTransportCosts routingCosts;
private VehicleRoutingActivityCosts activityCosts;
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint) {
@ -66,12 +67,16 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
double oldCosts;
double oldTime;
if(iFacts.getRoute().isEmpty()){
oldCosts = 0.0;
oldTime = 0.0;
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct;
oldTime = (nextAct.getArrTime() - depTimeAtPrevAct);
}
else{
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getNewDriver(), iFacts.getNewVehicle());
double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct;

View file

@ -145,7 +145,7 @@ final class ShipmentInsertionCalculator implements JobInsertionCalculator{
if(totalActivityInsertionCosts < bestCost){
bestCost = totalActivityInsertionCosts;
pickupInsertionIndex = i;
deliveryInsertionIndex = activities.size() - 1;
deliveryInsertionIndex = activities.size();
}
}
//update prevAct and endTime
@ -166,43 +166,11 @@ final class ShipmentInsertionCalculator implements JobInsertionCalculator{
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
if(totalActivityInsertionCosts < bestCost){
bestCost = totalActivityInsertionCosts;
pickupInsertionIndex = activities.size() - 1;
deliveryInsertionIndex = activities.size() - 1;
pickupInsertionIndex = activities.size();
deliveryInsertionIndex = activities.size();
}
}
}
// for(TourActivity nextAct : activities){
// if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
// ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActEndTime);
// if(mc != null){
// if(mc.getAdditionalCosts() < bestCost){
// bestCost = mc.getAdditionalCosts();
// bestMarginals = mc;
// insertionIndex = actIndex;
// }
// }
// }
// double nextActArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActEndTime, newDriver, newVehicle);
// double nextActEndTime = CalcUtils.getActivityEndTime(nextActArrTime, nextAct);
//
// prevActEndTime = nextActEndTime;
//
// prevAct = nextAct;
// actIndex++;
// }
// End nextAct = end;
// if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
// ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActEndTime);
// if(mc != null) {
// if(mc.getAdditionalCosts() < bestCost){
// bestCost = mc.getAdditionalCosts();
// bestMarginals = mc;
// insertionIndex = actIndex;
// }
// }
// }
if(pickupInsertionIndex == InsertionData.NO_INDEX) {
return InsertionData.noInsertionFound();
}
@ -211,7 +179,7 @@ final class ShipmentInsertionCalculator implements JobInsertionCalculator{
return insertionData;
}
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double departureTimeAtPrevAct) {
private ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double departureTimeAtPrevAct) {
return activityInsertionCostsCalculator.calculate(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
}

View file

@ -236,14 +236,25 @@ public class VehicleRoutingProblem {
if(job instanceof Service) {
addService((Service) job);
}
else if(job instanceof Shipment){
addShipment((Shipment)job);
}
else{
if(jobs.containsKey(job.getId())){ logger.warn("job " + job + " already in job list. overrides existing job."); }
jobs.put(job.getId(),job);
// if(jobs.containsKey(job.getId())){ logger.warn("job " + job + " already in job list. overrides existing job."); }
// coordinates.put(job.getLocationId(), job.getCoord());
// jobs.put(job.getId(),job);
}
return this;
}
private void addShipment(Shipment job) {
if(jobs.containsKey(job.getId())){ logger.warn("job " + job + " already in job list. overrides existing job."); }
coordinates.put(job.getPickupLocation(), job.getPickupCoord());
coordinates.put(job.getDeliveryLocation(), job.getDeliveryCoord());
jobs.put(job.getId(),job);
}
/**
* Adds a vehicle.
*

View file

@ -80,4 +80,8 @@ public final class DeliverShipment implements DeliveryActivity{
return new DeliverShipment(this);
}
@Override
public String toString() {
return "[act="+getName()+"][loc="+getLocationId()+"]";
}
}

View file

@ -79,5 +79,10 @@ public final class PickupShipment implements PickupActivity{
public TourActivity duplicate() {
return new PickupShipment(this);
}
@Override
public String toString() {
return "[act="+getName()+"][loc="+getLocationId()+"]";
}
}

View file

@ -152,6 +152,7 @@ public class TourActivities {
public void addActivity(int insertionIndex, TourActivity act) {
assert insertionIndex >= 0 : "insertionIndex == 0, this cannot be";
if(tourActivities.contains(act)) throw new IllegalStateException("act " + act + " already in tour. cannot add act twice.");
/*
* if 1 --> between start and act(0) --> act(0)
* if 2 && 2 <= acts.size --> between act(0) and act(1) --> act(1)
@ -164,6 +165,12 @@ public class TourActivities {
addJob(act);
}
/**
* adds activity.
*
* @throw {@link IllegalStateException} if same activity is added twice.
* @param act
*/
public void addActivity(TourActivity act){
if(tourActivities.contains(act)) throw new IllegalStateException("act " + act + " already in tour. cannot add act twice.");
tourActivities.add(act);

View file

@ -187,6 +187,11 @@ public class VehicleRoute {
public End getEnd() {
return end;
}
@Override
public String toString() {
return "[start="+start+"][end=" + end + "][departureTime=" + start.getEndTime() + "][vehicle=" + vehicle + "][driver=" + driver + "][nuOfActs="+tourActivities.getActivities().size()+"]";
}
@Deprecated
public void setVehicleRouteCostCalculator(VehicleRouteCostCalculator costAccumulator){