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

multiple tws

This commit is contained in:
oblonski 2015-07-08 18:54:22 +02:00
parent ed95f90fc5
commit ebeae6f693
17 changed files with 384 additions and 30 deletions

View file

@ -0,0 +1,14 @@
package jsprit.core.algorithm.state;
import jsprit.core.problem.solution.route.activity.TourActivity;
/**
* Created by schroeder on 08/07/15.
*/
public class ActivityStartAsSoonAsArrived implements ActivityStartStrategy {
@Override
public double getActivityStartTime(TourActivity activity, double arrivalTime) {
return arrivalTime;
}
}

View file

@ -0,0 +1,12 @@
package jsprit.core.algorithm.state;
import jsprit.core.problem.solution.route.activity.TourActivity;
/**
* Created by schroeder on 08/07/15.
*/
public interface ActivityStartStrategy {
public double getActivityStartTime(TourActivity activity, double arrivalTime);
}

View file

@ -0,0 +1,31 @@
package jsprit.core.algorithm.state;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.problem.solution.route.activity.TourActivity;
/**
* Created by schroeder on 08/07/15.
*/
public class ActivityStartsAsSoonAsNextTimeWindowOpens implements ActivityStartStrategy {
@Override
public double getActivityStartTime(TourActivity activity, double arrivalTime) {
boolean next = false;
for(TimeWindow tw : activity.getTimeWindows()){
if(next){
return Math.max(tw.getStart(),arrivalTime);
}
if(tw.getStart() <= arrivalTime && tw.getEnd() >= arrivalTime){
return arrivalTime;
}
else if(tw.getEnd() < arrivalTime){
next = true;
}
else if(tw.getStart() > arrivalTime){
return tw.getStart();
}
}
return arrivalTime;
}
}

View file

@ -0,0 +1,15 @@
package jsprit.core.algorithm.state;
import jsprit.core.problem.solution.route.activity.TourActivity;
/**
* Created by schroeder on 08/07/15.
*/
public class ActivityStartsAsSoonAsTimeWindowOpens implements ActivityStartStrategy {
@Override
public double getActivityStartTime(TourActivity activity, double arrivalTime) {
return Math.max(activity.getTheoreticalEarliestOperationStartTime(),arrivalTime);
}
}

View file

@ -19,8 +19,11 @@ package jsprit.core.algorithm.state;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts; import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.ReverseActivityVisitor; import jsprit.core.problem.solution.route.activity.ReverseActivityVisitor;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.problem.solution.route.activity.TourActivity; import jsprit.core.problem.solution.route.activity.TourActivity;
import java.util.Collection;
/** /**
* Updates and memorizes latest operation start times at activities. * Updates and memorizes latest operation start times at activities.
* *
@ -55,14 +58,31 @@ class UpdatePracticalTimeWindows implements ReverseActivityVisitor, StateUpdater
@Override @Override
public void visit(TourActivity activity) { public void visit(TourActivity activity) {
double potentialLatestArrivalTimeAtCurrAct = latestArrTimeAtPrevAct - transportCosts.getBackwardTransportTime(activity.getLocation(), prevAct.getLocation(), latestArrTimeAtPrevAct, route.getDriver(),route.getVehicle()) - activity.getOperationTime(); double potentialLatestArrivalTimeAtCurrAct = latestArrTimeAtPrevAct - transportCosts.getBackwardTransportTime(activity.getLocation(), prevAct.getLocation(), latestArrTimeAtPrevAct, route.getDriver(),route.getVehicle()) - activity.getOperationTime();
double latestArrivalTime = Math.min(activity.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct); Collection<TimeWindow> timeWindows = activity.getTimeWindows();
double latestArrivalTime = getLatestArrivalTime(timeWindows,potentialLatestArrivalTimeAtCurrAct);
states.putInternalTypedActivityState(activity, InternalStates.LATEST_OPERATION_START_TIME, latestArrivalTime); states.putInternalTypedActivityState(activity, InternalStates.LATEST_OPERATION_START_TIME, latestArrivalTime);
latestArrTimeAtPrevAct = latestArrivalTime; latestArrTimeAtPrevAct = latestArrivalTime;
prevAct = activity; prevAct = activity;
} }
private double getLatestArrivalTime(Collection<TimeWindow> timeWindows, double potentialLatestArrivalTimeAtCurrAct) {
TimeWindow last = null;
for(TimeWindow tw : timeWindows){
if(tw.getStart() <= potentialLatestArrivalTimeAtCurrAct && tw.getEnd() >= potentialLatestArrivalTimeAtCurrAct){
return potentialLatestArrivalTimeAtCurrAct;
}
else if(tw.getStart() > potentialLatestArrivalTimeAtCurrAct){
if(last == null){
return potentialLatestArrivalTimeAtCurrAct;
}
else return last.getEnd();
}
last = tw;
}
return last.getEnd();
}
@Override @Override
public void finish() {} public void finish() {}
} }

View file

@ -21,6 +21,7 @@ import jsprit.core.problem.Location;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts; import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.ReverseActivityVisitor; import jsprit.core.problem.solution.route.activity.ReverseActivityVisitor;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.problem.solution.route.activity.TourActivity; import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.Vehicle; import jsprit.core.problem.vehicle.Vehicle;
@ -85,7 +86,7 @@ public class UpdateVehicleDependentPracticalTimeWindows implements ReverseActivi
Location prevLocation = location_of_prevAct[vehicle.getVehicleTypeIdentifier().getIndex()]; Location prevLocation = location_of_prevAct[vehicle.getVehicleTypeIdentifier().getIndex()];
double potentialLatestArrivalTimeAtCurrAct = latestArrTimeAtPrevAct - transportCosts.getBackwardTransportTime(activity.getLocation(), prevLocation, double potentialLatestArrivalTimeAtCurrAct = latestArrTimeAtPrevAct - transportCosts.getBackwardTransportTime(activity.getLocation(), prevLocation,
latestArrTimeAtPrevAct, route.getDriver(), vehicle) - activity.getOperationTime(); latestArrTimeAtPrevAct, route.getDriver(), vehicle) - activity.getOperationTime();
double latestArrivalTime = Math.min(activity.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct); double latestArrivalTime = getLatestArrivalTime(activity.getTimeWindows(),potentialLatestArrivalTimeAtCurrAct);
stateManager.putInternalTypedActivityState(activity, vehicle, InternalStates.LATEST_OPERATION_START_TIME, latestArrivalTime); stateManager.putInternalTypedActivityState(activity, vehicle, InternalStates.LATEST_OPERATION_START_TIME, latestArrivalTime);
latest_arrTimes_at_prevAct[vehicle.getVehicleTypeIdentifier().getIndex()] = latestArrivalTime; latest_arrTimes_at_prevAct[vehicle.getVehicleTypeIdentifier().getIndex()] = latestArrivalTime;
location_of_prevAct[vehicle.getVehicleTypeIdentifier().getIndex()] = activity.getLocation(); location_of_prevAct[vehicle.getVehicleTypeIdentifier().getIndex()] = activity.getLocation();
@ -95,5 +96,22 @@ public class UpdateVehicleDependentPracticalTimeWindows implements ReverseActivi
@Override @Override
public void finish() {} public void finish() {}
private double getLatestArrivalTime(Collection<TimeWindow> timeWindows, double potentialLatestArrivalTimeAtCurrAct) {
TimeWindow last = null;
for(TimeWindow tw : timeWindows){
if(tw.getStart() <= potentialLatestArrivalTimeAtCurrAct && tw.getEnd() >= potentialLatestArrivalTimeAtCurrAct){
return potentialLatestArrivalTimeAtCurrAct;
}
else if(tw.getStart() > potentialLatestArrivalTimeAtCurrAct){
if(last == null){
return potentialLatestArrivalTimeAtCurrAct;
}
else return last.getEnd();
}
last = tw;
}
return last.getEnd();
}
} }

View file

@ -45,11 +45,21 @@ public class VehicleDependentTimeWindowConstraints implements HardActivityConstr
this.routingCosts = routingCosts; this.routingCosts = routingCosts;
} }
public double getLatestOperationStartTime(TourActivity act){
return act.getTimeWindows().get(act.getTimeWindows().size()-1).getEnd();
}
public double getEarliestOperationStartTime(TourActivity act){
return act.getTimeWindows().get(0).getStart();
}
@Override @Override
public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
double latestVehicleArrival = iFacts.getNewVehicle().getLatestArrival(); double latestVehicleArrival = iFacts.getNewVehicle().getLatestArrival();
Double latestArrTimeAtNextAct; Double latestArrTimeAtNextAct;
Location nextActLocation; Location nextActLocation;
double nextAct_theoreticalLatestOperationStartTime = getLatestOperationStartTime(nextAct);
if(nextAct instanceof End) { if(nextAct instanceof End) {
latestArrTimeAtNextAct = latestVehicleArrival; latestArrTimeAtNextAct = latestVehicleArrival;
nextActLocation = iFacts.getNewVehicle().getEndLocation(); nextActLocation = iFacts.getNewVehicle().getEndLocation();
@ -63,7 +73,7 @@ public class VehicleDependentTimeWindowConstraints implements HardActivityConstr
// if(latestArrTimeAtNextAct == null) //try to get latest_operation_start_time of currVehicle // if(latestArrTimeAtNextAct == null) //try to get latest_operation_start_time of currVehicle
// latestArrTimeAtNextAct = states.getActivityState(nextAct, iFacts.getRoute().getVehicle(), StateFactory.LATEST_OPERATION_START_TIME ,Double.class); // latestArrTimeAtNextAct = states.getActivityState(nextAct, iFacts.getRoute().getVehicle(), StateFactory.LATEST_OPERATION_START_TIME ,Double.class);
if(latestArrTimeAtNextAct == null) {//otherwise set it to theoretical_latest_operation_startTime if(latestArrTimeAtNextAct == null) {//otherwise set it to theoretical_latest_operation_startTime
latestArrTimeAtNextAct = nextAct.getTheoreticalLatestOperationStartTime(); latestArrTimeAtNextAct = nextAct_theoreticalLatestOperationStartTime;
// throw new IllegalStateException("this is strange and should not be"); // throw new IllegalStateException("this is strange and should not be");
//ToDo here, there should be another solution //ToDo here, there should be another solution
} }
@ -77,9 +87,15 @@ public class VehicleDependentTimeWindowConstraints implements HardActivityConstr
* |--- vehicle's operation time ---| * |--- vehicle's operation time ---|
* |--- prevAct or newAct or nextAct ---| * |--- prevAct or newAct or nextAct ---|
*/ */
if(latestVehicleArrival < prevAct.getTheoreticalEarliestOperationStartTime() || double prevAct_theoreticalEarliestOperationStartTime = getEarliestOperationStartTime(prevAct);
latestVehicleArrival < newAct.getTheoreticalEarliestOperationStartTime() || double newAct_theoreticalEarliestOperationStartTime = getEarliestOperationStartTime(newAct);
latestVehicleArrival < nextAct.getTheoreticalEarliestOperationStartTime()){ // newAct.getTheoreticalEarliestOperationStartTime();
double nextAct_theoreticalEarliestOperationStartTime = getEarliestOperationStartTime(nextAct);
// nextAct.getTheoreticalEarliestOperationStartTime();
if(latestVehicleArrival < prevAct_theoreticalEarliestOperationStartTime ||
latestVehicleArrival < newAct_theoreticalEarliestOperationStartTime ||
latestVehicleArrival < nextAct_theoreticalEarliestOperationStartTime){
return ConstraintsStatus.NOT_FULFILLED_BREAK; return ConstraintsStatus.NOT_FULFILLED_BREAK;
} }
/* /*
@ -89,7 +105,10 @@ public class VehicleDependentTimeWindowConstraints implements HardActivityConstr
* |--- prevAct ---| * |--- prevAct ---|
* |--- newAct ---| * |--- newAct ---|
*/ */
if(newAct.getTheoreticalLatestOperationStartTime() < prevAct.getTheoreticalEarliestOperationStartTime()){ double newAct_theoreticalLatestOperationStartTime = getLatestOperationStartTime(newAct);
// newAct.getTheoreticalLatestOperationStartTime();
if(newAct_theoreticalLatestOperationStartTime < prevAct_theoreticalEarliestOperationStartTime){
return ConstraintsStatus.NOT_FULFILLED_BREAK; return ConstraintsStatus.NOT_FULFILLED_BREAK;
} }
@ -107,14 +126,14 @@ public class VehicleDependentTimeWindowConstraints implements HardActivityConstr
* |--- newAct ---| * |--- newAct ---|
* |--- nextAct ---| * |--- nextAct ---|
*/ */
if(newAct.getTheoreticalEarliestOperationStartTime() > nextAct.getTheoreticalLatestOperationStartTime()){ if(newAct_theoreticalEarliestOperationStartTime > nextAct_theoreticalLatestOperationStartTime){
return ConstraintsStatus.NOT_FULFILLED; return ConstraintsStatus.NOT_FULFILLED;
} }
// log.info("check insertion of " + newAct + " between " + prevAct + " and " + nextAct + ". prevActDepTime=" + prevActDepTime); // log.info("check insertion of " + newAct + " between " + prevAct + " and " + nextAct + ". prevActDepTime=" + prevActDepTime);
double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocation(), newAct.getLocation(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocation(), newAct.getLocation(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double endTimeAtNewAct = CalculationUtils.getActivityEndTime(arrTimeAtNewAct, newAct); double endTimeAtNewAct = CalculationUtils.getActivityEndTime(arrTimeAtNewAct, newAct);
double latestArrTimeAtNewAct = double latestArrTimeAtNewAct =
Math.min(newAct.getTheoreticalLatestOperationStartTime(), Math.min(newAct_theoreticalLatestOperationStartTime,
latestArrTimeAtNextAct - latestArrTimeAtNextAct -
routingCosts.getBackwardTransportTime(newAct.getLocation(),nextActLocation,latestArrTimeAtNextAct,iFacts.getNewDriver(),iFacts.getNewVehicle()) routingCosts.getBackwardTransportTime(newAct.getLocation(),nextActLocation,latestArrTimeAtNextAct,iFacts.getNewDriver(),iFacts.getNewVehicle())
- newAct.getOperationTime() - newAct.getOperationTime()

View file

@ -21,6 +21,9 @@ import jsprit.core.problem.Capacity;
import jsprit.core.problem.Location; import jsprit.core.problem.Location;
import jsprit.core.problem.job.Delivery; import jsprit.core.problem.job.Delivery;
import java.util.ArrayList;
import java.util.List;
public final class DeliverService extends AbstractActivity implements DeliveryActivity{ public final class DeliverService extends AbstractActivity implements DeliveryActivity{
private Delivery delivery; private Delivery delivery;
@ -35,10 +38,13 @@ public final class DeliverService extends AbstractActivity implements DeliveryAc
private double theoreticalLatest; private double theoreticalLatest;
private List<TimeWindow> timeWindows;
public DeliverService(Delivery delivery) { public DeliverService(Delivery delivery) {
super(); super();
this.delivery = delivery; this.delivery = delivery;
capacity = Capacity.invert(delivery.getSize()); capacity = Capacity.invert(delivery.getSize());
timeWindows = new ArrayList<TimeWindow>(delivery.getTimeWindows(0.));
} }
private DeliverService(DeliverService deliveryActivity){ private DeliverService(DeliverService deliveryActivity){
@ -49,6 +55,7 @@ public final class DeliverService extends AbstractActivity implements DeliveryAc
this.theoreticalLatest = deliveryActivity.getTheoreticalLatestOperationStartTime(); this.theoreticalLatest = deliveryActivity.getTheoreticalLatestOperationStartTime();
capacity = deliveryActivity.getSize(); capacity = deliveryActivity.getSize();
setIndex(deliveryActivity.getIndex()); setIndex(deliveryActivity.getIndex());
timeWindows = new ArrayList<TimeWindow>(delivery.getTimeWindows(0.));
} }
@Override @Override
@ -61,6 +68,11 @@ public final class DeliverService extends AbstractActivity implements DeliveryAc
theoreticalLatest = latest; theoreticalLatest = latest;
} }
@Override
public List<TimeWindow> getTimeWindows() {
return timeWindows;
}
@Override @Override
public String getName() { public String getName() {
return delivery.getType(); return delivery.getType();

View file

@ -22,6 +22,8 @@ import jsprit.core.problem.Location;
import jsprit.core.problem.job.Job; import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Shipment; import jsprit.core.problem.job.Shipment;
import java.util.List;
public final class DeliverShipment extends AbstractActivity implements DeliveryActivity{ public final class DeliverShipment extends AbstractActivity implements DeliveryActivity{
private Shipment shipment; private Shipment shipment;
@ -62,6 +64,12 @@ public final class DeliverShipment extends AbstractActivity implements DeliveryA
} }
@Override
public List<TimeWindow> getTimeWindows() {
// return shipment.getDeliveryTimeWindow();
return null;
}
@Override @Override
public String getName() { public String getName() {
return "deliverShipment"; return "deliverShipment";

View file

@ -21,6 +21,9 @@ import jsprit.core.problem.Capacity;
import jsprit.core.problem.Location; import jsprit.core.problem.Location;
import jsprit.core.util.Coordinate; import jsprit.core.util.Coordinate;
import java.util.Arrays;
import java.util.List;
public final class End extends AbstractActivity implements TourActivity { public final class End extends AbstractActivity implements TourActivity {
@Deprecated @Deprecated
@ -68,6 +71,11 @@ public final class End extends AbstractActivity implements TourActivity {
theoretical_latestOperationStartTime = theoreticalLatestOperationStartTime; theoretical_latestOperationStartTime = theoreticalLatestOperationStartTime;
} }
@Override
public List<TimeWindow> getTimeWindows() {
return Arrays.asList(TimeWindow.newInstance(theoretical_earliestOperationStartTime,theoretical_latestOperationStartTime));
}
public End(Location location, double theoreticalStart, double theoreticalEnd) { public End(Location location, double theoreticalStart, double theoreticalEnd) {
super(); super();
this.location = location; this.location = location;

View file

@ -22,6 +22,9 @@ import jsprit.core.problem.Location;
import jsprit.core.problem.job.Pickup; import jsprit.core.problem.job.Pickup;
import jsprit.core.problem.job.Service; import jsprit.core.problem.job.Service;
import java.util.ArrayList;
import java.util.List;
public final class PickupService extends AbstractActivity implements PickupActivity{ public final class PickupService extends AbstractActivity implements PickupActivity{
private Service pickup; private Service pickup;
@ -34,9 +37,12 @@ public final class PickupService extends AbstractActivity implements PickupActiv
private double theoreticalLatest; private double theoreticalLatest;
private List<TimeWindow> timeWindows;
public PickupService(Pickup pickup) { public PickupService(Pickup pickup) {
super(); super();
this.pickup = pickup; this.pickup = pickup;
timeWindows = new ArrayList<TimeWindow>(pickup.getTimeWindows(0.));
} }
public PickupService(Service service){ public PickupService(Service service){
@ -50,6 +56,7 @@ public final class PickupService extends AbstractActivity implements PickupActiv
this.theoreticalEarliest = pickupActivity.getTheoreticalEarliestOperationStartTime(); this.theoreticalEarliest = pickupActivity.getTheoreticalEarliestOperationStartTime();
this.theoreticalLatest = pickupActivity.getTheoreticalLatestOperationStartTime(); this.theoreticalLatest = pickupActivity.getTheoreticalLatestOperationStartTime();
setIndex(pickupActivity.getIndex()); setIndex(pickupActivity.getIndex());
timeWindows = new ArrayList<TimeWindow>(pickup.getTimeWindows(0.));
} }
@Override @Override
@ -62,6 +69,11 @@ public final class PickupService extends AbstractActivity implements PickupActiv
this.theoreticalLatest = latest; this.theoreticalLatest = latest;
} }
@Override
public List<TimeWindow> getTimeWindows() {
return timeWindows;
}
@Override @Override
public String getName() { public String getName() {
return pickup.getType(); return pickup.getType();

View file

@ -22,6 +22,8 @@ import jsprit.core.problem.Location;
import jsprit.core.problem.job.Job; import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Shipment; import jsprit.core.problem.job.Shipment;
import java.util.List;
public final class PickupShipment extends AbstractActivity implements PickupActivity{ public final class PickupShipment extends AbstractActivity implements PickupActivity{
private Shipment shipment; private Shipment shipment;
@ -58,6 +60,11 @@ public final class PickupShipment extends AbstractActivity implements PickupActi
} }
@Override
public List<TimeWindow> getTimeWindows() {
return null;
}
@Override @Override
public String getName() { public String getName() {
return "pickupShipment"; return "pickupShipment";

View file

@ -22,6 +22,9 @@ import jsprit.core.problem.Location;
import jsprit.core.problem.job.Service; import jsprit.core.problem.job.Service;
import jsprit.core.problem.solution.route.activity.TourActivity.JobActivity; import jsprit.core.problem.solution.route.activity.TourActivity.JobActivity;
import java.util.ArrayList;
import java.util.List;
public class ServiceActivity extends AbstractActivity implements JobActivity{ public class ServiceActivity extends AbstractActivity implements JobActivity{
@Deprecated @Deprecated
@ -73,9 +76,12 @@ public class ServiceActivity extends AbstractActivity implements JobActivity{
private final Service service; private final Service service;
private List<TimeWindow> timeWindows;
protected ServiceActivity(Service service) { protected ServiceActivity(Service service) {
counter++; counter++;
this.service = service; this.service = service;
timeWindows = new ArrayList<TimeWindow>(service.getTimeWindows(0.));
} }
protected ServiceActivity(ServiceActivity serviceActivity) { protected ServiceActivity(ServiceActivity serviceActivity) {
@ -84,6 +90,7 @@ public class ServiceActivity extends AbstractActivity implements JobActivity{
this.arrTime = serviceActivity.getArrTime(); this.arrTime = serviceActivity.getArrTime();
this.endTime = serviceActivity.getEndTime(); this.endTime = serviceActivity.getEndTime();
setIndex(serviceActivity.getIndex()); setIndex(serviceActivity.getIndex());
timeWindows = new ArrayList<TimeWindow>(serviceActivity.getTimeWindows());
} }
@ -166,6 +173,11 @@ public class ServiceActivity extends AbstractActivity implements JobActivity{
theoreticalLatest = latest; theoreticalLatest = latest;
} }
@Override
public List<TimeWindow> getTimeWindows() {
return timeWindows;
}
@Override @Override
public String getName() { public String getName() {
return service.getType(); return service.getType();

View file

@ -20,6 +20,9 @@ import jsprit.core.problem.AbstractActivity;
import jsprit.core.problem.Capacity; import jsprit.core.problem.Capacity;
import jsprit.core.problem.Location; import jsprit.core.problem.Location;
import java.util.Arrays;
import java.util.List;
public final class Start extends AbstractActivity implements TourActivity { public final class Start extends AbstractActivity implements TourActivity {
public final static String ACTIVITY_NAME = "start"; public final static String ACTIVITY_NAME = "start";
@ -103,6 +106,11 @@ public final class Start extends AbstractActivity implements TourActivity {
this.theoretical_latestOperationStartTime=time; this.theoretical_latestOperationStartTime=time;
} }
@Override
public List<TimeWindow> getTimeWindows() {
return Arrays.asList(TimeWindow.newInstance(theoretical_earliestOperationStartTime,theoretical_latestOperationStartTime));
}
@Deprecated @Deprecated
@Override @Override
public String getLocationId() { public String getLocationId() {

View file

@ -21,6 +21,8 @@ import jsprit.core.problem.HasIndex;
import jsprit.core.problem.Location; import jsprit.core.problem.Location;
import jsprit.core.problem.job.Job; import jsprit.core.problem.job.Job;
import java.util.List;
/** /**
* Basic interface for tour-activities. * Basic interface for tour-activities.
* *
@ -35,6 +37,8 @@ public interface TourActivity extends HasIndex {
public void setTheoreticalLatestOperationStartTime(double latest); public void setTheoreticalLatestOperationStartTime(double latest);
public List<TimeWindow> getTimeWindows();
/** /**
* Basic interface of job-activies. * Basic interface of job-activies.
* *

View file

@ -16,6 +16,9 @@
******************************************************************************/ ******************************************************************************/
package jsprit.core.util; package jsprit.core.util;
import jsprit.core.algorithm.state.ActivityStartAsSoonAsArrived;
import jsprit.core.algorithm.state.ActivityStartStrategy;
import jsprit.core.algorithm.state.ActivityStartsAsSoonAsTimeWindowOpens;
import jsprit.core.problem.cost.ForwardTransportTime; import jsprit.core.problem.cost.ForwardTransportTime;
import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.ActivityVisitor; import jsprit.core.problem.solution.route.activity.ActivityVisitor;
@ -43,17 +46,27 @@ public class ActivityTimeTracker implements ActivityVisitor{
private double actEndTime; private double actEndTime;
private ActivityPolicy activityPolicy = ActivityPolicy.AS_SOON_AS_TIME_WINDOW_OPENS; private ActivityStartStrategy startStrategy;
public ActivityTimeTracker(ForwardTransportTime transportTime) { public ActivityTimeTracker(ForwardTransportTime transportTime) {
super(); super();
this.transportTime = transportTime; this.transportTime = transportTime;
this.startStrategy = new ActivityStartsAsSoonAsTimeWindowOpens();
} }
public ActivityTimeTracker(ForwardTransportTime transportTime, ActivityPolicy activityPolicy) { public ActivityTimeTracker(ForwardTransportTime transportTime, ActivityPolicy activityPolicy) {
super(); super();
this.transportTime = transportTime; this.transportTime = transportTime;
this.activityPolicy = activityPolicy; if(activityPolicy.equals(ActivityPolicy.AS_SOON_AS_ARRIVED)){
this.startStrategy = new ActivityStartsAsSoonAsTimeWindowOpens();
}
else this.startStrategy = new ActivityStartAsSoonAsArrived();
}
public ActivityTimeTracker(ForwardTransportTime transportTime, ActivityStartStrategy startStrategy) {
super();
this.transportTime = transportTime;
this.startStrategy = startStrategy;
} }
public double getActArrTime(){ public double getActArrTime(){
@ -78,35 +91,19 @@ public class ActivityTimeTracker implements ActivityVisitor{
if(!beginFirst) throw new IllegalStateException("never called begin. this however is essential here"); if(!beginFirst) throw new IllegalStateException("never called begin. this however is essential here");
double transportTime = this.transportTime.getTransportTime(prevAct.getLocation(), activity.getLocation(), startAtPrevAct, route.getDriver(), route.getVehicle()); double transportTime = this.transportTime.getTransportTime(prevAct.getLocation(), activity.getLocation(), startAtPrevAct, route.getDriver(), route.getVehicle());
double arrivalTimeAtCurrAct = startAtPrevAct + transportTime; double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
actArrTime = arrivalTimeAtCurrAct; actArrTime = arrivalTimeAtCurrAct;
double operationStartTime; double operationEndTime = startStrategy.getActivityStartTime(activity,arrivalTimeAtCurrAct) + activity.getOperationTime();
if(activityPolicy.equals(ActivityPolicy.AS_SOON_AS_TIME_WINDOW_OPENS)){
operationStartTime = Math.max(activity.getTheoreticalEarliestOperationStartTime(), arrivalTimeAtCurrAct);
}
else if(activityPolicy.equals(ActivityPolicy.AS_SOON_AS_ARRIVED)){
operationStartTime = actArrTime;
}
else operationStartTime = actArrTime;
double operationEndTime = operationStartTime + activity.getOperationTime();
actEndTime = operationEndTime; actEndTime = operationEndTime;
prevAct = activity; prevAct = activity;
startAtPrevAct = operationEndTime; startAtPrevAct = operationEndTime;
} }
@Override @Override
public void finish() { public void finish() {
double transportTime = this.transportTime.getTransportTime(prevAct.getLocation(), route.getEnd().getLocation(), startAtPrevAct, route.getDriver(), route.getVehicle()); double transportTime = this.transportTime.getTransportTime(prevAct.getLocation(), route.getEnd().getLocation(), startAtPrevAct, route.getDriver(), route.getVehicle());
double arrivalTimeAtCurrAct = startAtPrevAct + transportTime; double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
actArrTime = arrivalTimeAtCurrAct; actArrTime = arrivalTimeAtCurrAct;
actEndTime = arrivalTimeAtCurrAct; actEndTime = arrivalTimeAtCurrAct;
beginFirst = false; beginFirst = false;
} }

View file

@ -0,0 +1,157 @@
package jsprit.core.algorithm.state;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import junit.framework.Assert;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collection;
/**
* Created by schroeder on 08/07/15.
*/
public class GetLatestArrivalTimeTest {
@Test
public void whenSingleTW_itShouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(0,10);
Assert.assertEquals(10.,getLatestArrivalTime(Arrays.asList(tw),20));
}
@Test
public void whenSingleTW2_itShouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(0,10);
Assert.assertEquals(8.,getLatestArrivalTime(Arrays.asList(tw),8));
}
@Test
public void whenSingleTW3_itShouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
Assert.assertEquals(1.,getLatestArrivalTime(Arrays.asList(tw),1));
}
@Test
public void whenMultipleTW_itShouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
TimeWindow tw2 = TimeWindow.newInstance(20,30);
Assert.assertEquals(30.,getLatestArrivalTime(Arrays.asList(tw,tw2),40));
}
@Test
public void whenMultipleTW2_itShouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
TimeWindow tw2 = TimeWindow.newInstance(20,30);
Assert.assertEquals(25.,getLatestArrivalTime(Arrays.asList(tw,tw2),25));
}
@Test
public void whenMultipleTW3_itShouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
TimeWindow tw2 = TimeWindow.newInstance(20,30);
Assert.assertEquals(10.,getLatestArrivalTime(Arrays.asList(tw,tw2),19));
}
@Test
public void whenMultipleTW4_itShouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
TimeWindow tw2 = TimeWindow.newInstance(20,30);
Assert.assertEquals(8.,getLatestArrivalTime(Arrays.asList(tw,tw2),8));
}
@Test
public void whenMultipleTW5_itShouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
TimeWindow tw2 = TimeWindow.newInstance(20,30);
Assert.assertEquals(1.,getLatestArrivalTime(Arrays.asList(tw,tw2),1));
}
@Test
public void whenSingleTW_ActivityStartTime_shouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
Assert.assertEquals(2.,getActivityStartTime(Arrays.asList(tw),1));
}
@Test
public void whenSingleTW2_ActivityStartTime_shouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
Assert.assertEquals(3.,getActivityStartTime(Arrays.asList(tw),3));
}
@Test
public void whenSingleTW3_ActivityStartTime_shouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
Assert.assertEquals(11.,getActivityStartTime(Arrays.asList(tw),11));
}
@Test
public void whenMultipleTW1_ActivityStartTime_shouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
TimeWindow tw2 = TimeWindow.newInstance(20,30);
Assert.assertEquals(2.,getActivityStartTime(Arrays.asList(tw,tw2),1));
}
@Test
public void whenMultipleTW2_ActivityStartTime_shouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
TimeWindow tw2 = TimeWindow.newInstance(20,30);
Assert.assertEquals(3.,getActivityStartTime(Arrays.asList(tw,tw2),3));
}
@Test
public void whenMultipleTW3_ActivityStartTime_shouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
TimeWindow tw2 = TimeWindow.newInstance(20,30);
Assert.assertEquals(20.,getActivityStartTime(Arrays.asList(tw,tw2),11));
}
@Test
public void whenMultipleTW4_ActivityStartTime_shouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
TimeWindow tw2 = TimeWindow.newInstance(20,30);
Assert.assertEquals(21.,getActivityStartTime(Arrays.asList(tw,tw2),21));
}
@Test
public void whenMultipleTW5_ActivityStartTime_shouldReturnCorrectTime(){
TimeWindow tw = TimeWindow.newInstance(2,10);
TimeWindow tw2 = TimeWindow.newInstance(20,30);
Assert.assertEquals(31.,getActivityStartTime(Arrays.asList(tw,tw2),31));
}
private double getLatestArrivalTime(Collection<TimeWindow> timeWindows, double potentialLatestArrivalTimeAtCurrAct) {
TimeWindow last = null;
for(TimeWindow tw : timeWindows){
if(tw.getStart() <= potentialLatestArrivalTimeAtCurrAct && tw.getEnd() >= potentialLatestArrivalTimeAtCurrAct){
return potentialLatestArrivalTimeAtCurrAct;
}
else if(tw.getStart() > potentialLatestArrivalTimeAtCurrAct){
if(last == null){
return potentialLatestArrivalTimeAtCurrAct;
}
else return last.getEnd();
}
last = tw;
}
return last.getEnd();
}
private double getActivityStartTime(Collection<TimeWindow> timeWindows, double arrivalTime) {
boolean next = false;
for(TimeWindow tw : timeWindows){
if(next){
return Math.max(tw.getStart(),arrivalTime);
}
if(tw.getStart() <= arrivalTime && tw.getEnd() >= arrivalTime){
return arrivalTime;
}
else if(tw.getEnd() < arrivalTime){
next = true;
}
else if(tw.getStart() > arrivalTime){
return tw.getStart();
}
}
return arrivalTime;
}
}