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

modify/extend HardActivityLevelConstraint

This commit is contained in:
Stefan Schroeder 2013-10-23 14:06:37 +02:00
parent f37e599973
commit fb78d60a36
9 changed files with 90 additions and 63 deletions

View file

@ -22,7 +22,7 @@ class ConstraintManager implements HardActivityLevelConstraint, HardRouteLevelCo
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
return actLevelConstraintManager.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
}

View file

@ -4,6 +4,12 @@ import basics.route.TourActivity;
public interface HardActivityLevelConstraint {
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime);
static enum ConstraintsStatus {
NOT_FULFILLED_BREAK, NOT_FULFILLED, FULFILLED;
}
public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime);
}

View file

@ -14,13 +14,14 @@ class HardActivityLevelConstraintManager implements HardActivityLevelConstraint
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
for(HardActivityLevelConstraint constraint : hardConstraints){
if(!constraint.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime)){
return false;
ConstraintsStatus status = constraint.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK) || status.equals(ConstraintsStatus.NOT_FULFILLED)){
return status;
}
}
return true;
return ConstraintsStatus.FULFILLED;
}
}

View file

@ -16,7 +16,7 @@ class HardPickupAndDeliveryActivityLevelConstraint implements HardActivityLevelC
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
int loadAtPrevAct;
int futurePicks;
int pastDeliveries;
@ -32,16 +32,16 @@ class HardPickupAndDeliveryActivityLevelConstraint implements HardActivityLevelC
}
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
return false;
return ConstraintsStatus.NOT_FULFILLED;
}
}
if(newAct instanceof DeliveryActivity){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
return false;
return ConstraintsStatus.NOT_FULFILLED;
}
}
return true;
return ConstraintsStatus.FULFILLED;
}
}

View file

@ -16,11 +16,11 @@ class HardPickupAndDeliveryBackhaulActivityLevelConstraint implements HardActivi
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(newAct instanceof PickupActivity && nextAct instanceof DeliveryActivity){ return false; }
if(newAct instanceof ServiceActivity && nextAct instanceof DeliveryActivity){ return false; }
if(newAct instanceof DeliveryActivity && prevAct instanceof PickupActivity){ return false; }
if(newAct instanceof DeliveryActivity && prevAct instanceof ServiceActivity){ return false; }
public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(newAct instanceof PickupActivity && nextAct instanceof DeliveryActivity){ return ConstraintsStatus.NOT_FULFILLED; }
if(newAct instanceof ServiceActivity && nextAct instanceof DeliveryActivity){ return ConstraintsStatus.NOT_FULFILLED; }
if(newAct instanceof DeliveryActivity && prevAct instanceof PickupActivity){ return ConstraintsStatus.NOT_FULFILLED; }
if(newAct instanceof DeliveryActivity && prevAct instanceof ServiceActivity){ return ConstraintsStatus.NOT_FULFILLED; }
int loadAtPrevAct;
int futurePicks;
int pastDeliveries;
@ -36,16 +36,16 @@ class HardPickupAndDeliveryBackhaulActivityLevelConstraint implements HardActivi
}
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
return false;
return ConstraintsStatus.NOT_FULFILLED;
}
}
if(newAct instanceof DeliveryActivity){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
return false;
return ConstraintsStatus.NOT_FULFILLED;
}
}
return true;
return ConstraintsStatus.FULFILLED;
}
}

View file

@ -25,21 +25,27 @@ import basics.route.TourActivity;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
// log.info("check insertion of " + newAct + " between " + prevAct + " and " + nextAct + ". prevActDepTime=" + prevActDepTime);
public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(newAct.getTheoreticalLatestOperationStartTime() < prevAct.getTheoreticalEarliestOperationStartTime()){
return ConstraintsStatus.NOT_FULFILLED_BREAK;
}
if(newAct.getTheoreticalEarliestOperationStartTime() > nextAct.getTheoreticalLatestOperationStartTime()){
return ConstraintsStatus.NOT_FULFILLED;
}
// log.info("check insertion of " + newAct + " between " + prevAct + " and " + nextAct + ". prevActDepTime=" + prevActDepTime);
double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double latestArrTimeAtNewAct = states.getActivityState(newAct, StateFactory.LATEST_OPERATION_START_TIME).toDouble();
if(arrTimeAtNewAct > latestArrTimeAtNewAct){
return false;
return ConstraintsStatus.NOT_FULFILLED;
}
// log.info(newAct + " arrTime=" + arrTimeAtNewAct);
double endTimeAtNewAct = CalculationUtils.getActivityEndTime(arrTimeAtNewAct, newAct);
double arrTimeAtNextAct = endTimeAtNewAct + routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), endTimeAtNewAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double latestArrTimeAtNextAct = states.getActivityState(nextAct, StateFactory.LATEST_OPERATION_START_TIME).toDouble();
if(arrTimeAtNextAct > latestArrTimeAtNextAct){
return false;
return ConstraintsStatus.NOT_FULFILLED;
}
// log.info(nextAct + " arrTime=" + arrTimeAtNextAct);
return true;
return ConstraintsStatus.FULFILLED;
}
}

View file

@ -20,6 +20,7 @@ import org.apache.log4j.Logger;
import util.Neighborhood;
import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import algorithms.HardActivityLevelConstraint.ConstraintsStatus;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
@ -102,16 +103,16 @@ final class ServiceInsertionCalculator implements JobInsertionCalculator{
Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
start.setEndTime(newVehicleDepartureTime);
End end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival());
TourActivity prevAct = start;
double prevActStartTime = newVehicleDepartureTime;
int actIndex = 0;
boolean loopBroken = false;
for(TourActivity nextAct : currentRoute.getTourActivities().getActivities()){
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
if(hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime)){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
if(status.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc.getAdditionalCosts() < bestCost){
bestCost = mc.getAdditionalCosts();
@ -119,23 +120,27 @@ final class ServiceInsertionCalculator implements JobInsertionCalculator{
insertionIndex = actIndex;
}
}
else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
loopBroken = true;
}
}
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle);
double nextActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
prevActStartTime = nextActEndTime;
prevAct = nextAct;
actIndex++;
}
End nextAct = end;
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
if(hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime)){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc.getAdditionalCosts() < bestCost){
bestCost = mc.getAdditionalCosts();
bestMarginals = mc;
insertionIndex = actIndex;
if(!loopBroken){
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
if(status.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc.getAdditionalCosts() < bestCost){
bestCost = mc.getAdditionalCosts();
bestMarginals = mc;
insertionIndex = actIndex;
}
}
}
}

View file

@ -27,6 +27,7 @@ import org.apache.log4j.Logger;
import util.Neighborhood;
import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import algorithms.HardActivityLevelConstraint.ConstraintsStatus;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingActivityCosts;
@ -167,6 +168,7 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCalcul
double sumOf_prevCosts_newVehicle = 0.0;
double prevActDepTime_newVehicle = start.getEndTime();
boolean loopBroken = false;
/**
* inserting serviceAct2Insert in route r={0,1,...,i-1,i,j,j+1,...,n(r),n(r)+1}
* i=prevAct
@ -175,7 +177,8 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCalcul
*/
for(TourActivity nextAct : tour.getActivities()){
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
if(hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle)){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
if(status.equals(ConstraintsStatus.FULFILLED)){
/**
* builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking}
*/
@ -193,7 +196,10 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCalcul
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
}
}
else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
loopBroken = true;
break;
}
}
/**
@ -223,21 +229,24 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCalcul
actIndex++;
}
End nextAct = end;
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
if(hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle)){
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
if(actInsertionCosts != null){
/**
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
*/
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts();
if(!loopBroken){
End nextAct = end;
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
if(status.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
if(actInsertionCosts != null){
/**
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
*/
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts();
/**
* memorize it in insertion-queue
*/
if(insertion_cost_approximation < best_known_insertion_costs){
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
/**
* memorize it in insertion-queue
*/
if(insertion_cost_approximation < best_known_insertion_costs){
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
}
}
}
}

View file

@ -53,8 +53,8 @@ public class BuildCVRPAlgoFromScratchTest {
HardActivityLevelConstraint hardActLevelConstraint = new HardActivityLevelConstraint() {
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
return true;
public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
return ConstraintsStatus.FULFILLED;
}
};