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

separate waiting time feature from variable start times

This commit is contained in:
oblonski 2015-08-03 22:31:55 +02:00
parent 70d6ae1797
commit c8eb1dd7b4
14 changed files with 148 additions and 1002 deletions

View file

@ -23,7 +23,6 @@ import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.Start;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import jsprit.core.problem.vehicle.Vehicle;
@ -45,12 +44,10 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
private VehicleRoutingActivityCosts activityCosts;
private double activityCostsWeight = 0.75;
private double activityCostsWeight = 1.;
private double solutionCompletenessRatio = 1.;
private double variableStartTimeFactor = 1.;
private RouteAndActivityStateGetter stateManager;
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, RouteAndActivityStateGetter stateManager) {
@ -60,10 +57,6 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
this.stateManager = stateManager;
}
public void setVariableStartTimeFactor(double variableStartTimeFactor) {
this.variableStartTimeFactor = variableStartTimeFactor;
}
@Override
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
@ -74,17 +67,6 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double slack_time_new = 0;
double slack_time_prev = 0;
if(isStart(prevAct) && hasVariableDeparture(iFacts.getNewVehicle())) act_costs_newAct = 0;
else if(hasVariableDeparture(iFacts.getNewVehicle())){
Double slack_time_prev_ = stateManager.getActivityState(prevAct,iFacts.getNewVehicle(),InternalStates.TIME_SLACK,Double.class);
if(slack_time_prev_ == null) slack_time_prev = 0.;
else slack_time_prev = slack_time_prev_;
act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime + slack_time_prev, iFacts.getNewDriver(), iFacts.getNewVehicle());
slack_time_new = Math.min(newAct.getTheoreticalLatestOperationStartTime() - newAct.getTheoreticalEarliestOperationStartTime(), Math.max(newAct_arrTime + slack_time_prev - newAct.getTheoreticalEarliestOperationStartTime(), 0));
}
if(isEnd(nextAct) && !toDepot(iFacts.getNewVehicle())) return tp_costs_prevAct_newAct;
double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocation(), nextAct.getLocation(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
@ -93,10 +75,6 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
double endTime_nextAct_new = CalculationUtils.getActivityEndTime(nextAct_arrTime, nextAct);
double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
if(hasVariableDeparture(iFacts.getNewVehicle())){
act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime + slack_time_new, iFacts.getNewDriver(), iFacts.getNewVehicle());
}
double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + solutionCompletenessRatio * activityCostsWeight * (act_costs_newAct + act_costs_nextAct);
double oldCosts = 0.;
@ -109,28 +87,13 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
double arrTime_nextAct = depTimeAtPrevAct + routingCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
double endTime_nextAct_old = CalculationUtils.getActivityEndTime(arrTime_nextAct,nextAct);
double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
if(isStart(prevAct) && hasVariableDeparture(iFacts.getRoute().getVehicle())) {
actCost_nextAct = 0;
}
else if(hasVariableDeparture(iFacts.getRoute().getVehicle())){
actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct + slack_time_prev, iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
Double earliestWithoutWaiting = stateManager.getActivityState(nextAct,iFacts.getRoute().getVehicle(),InternalStates.EARLIEST_WITHOUT_WAITING,Double.class);
if(earliestWithoutWaiting != null){
double potentialArrivalTimeAtNewAct = earliestWithoutWaiting - routingCosts.getBackwardTransportTime(nextAct.getLocation(), newAct.getLocation(), earliestWithoutWaiting, iFacts.getRoute().getDriver(),iFacts.getRoute().getVehicle()) - newAct.getOperationTime();
if(potentialArrivalTimeAtNewAct > newAct.getTheoreticalLatestOperationStartTime()){
double delta = potentialArrivalTimeAtNewAct - newAct.getTheoreticalLatestOperationStartTime();
totalCosts += solutionCompletenessRatio * activityCostsWeight * delta * iFacts.getNewVehicle().getType().getVehicleCostParams().perWaitingTimeUnit;
}
}
}
else {
double endTimeDelay_nextAct = Math.max(0, endTime_nextAct_new - endTime_nextAct_old);
Double futureWaiting = stateManager.getActivityState(nextAct, iFacts.getRoute().getVehicle(), InternalStates.FUTURE_WAITING, Double.class);
if (futureWaiting == null) futureWaiting = 0.;
double waitingTime_savings_timeUnit = Math.min(futureWaiting, endTimeDelay_nextAct);
double waitingTime_savings = waitingTime_savings_timeUnit * iFacts.getRoute().getVehicle().getType().getVehicleCostParams().perWaitingTimeUnit;
oldCosts += solutionCompletenessRatio * activityCostsWeight * waitingTime_savings;
}
double endTimeDelay_nextAct = Math.max(0, endTime_nextAct_new - endTime_nextAct_old);
Double futureWaiting = stateManager.getActivityState(nextAct, iFacts.getRoute().getVehicle(), InternalStates.FUTURE_WAITING, Double.class);
if (futureWaiting == null) futureWaiting = 0.;
double waitingTime_savings_timeUnit = Math.min(futureWaiting, endTimeDelay_nextAct);
double waitingTime_savings = waitingTime_savings_timeUnit * iFacts.getRoute().getVehicle().getType().getVehicleCostParams().perWaitingTimeUnit;
oldCosts += solutionCompletenessRatio * activityCostsWeight * waitingTime_savings;
oldCosts += tp_costs_prevAct_nextAct + solutionCompletenessRatio * activityCostsWeight * actCost_nextAct;
}
return totalCosts - oldCosts;
@ -144,20 +107,7 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
return nextAct instanceof End;
}
private boolean hasVariableDeparture(Vehicle newVehicle) {
return newVehicle.hasVariableDepartureTime();
}
private boolean isStart(TourActivity prevAct) {
return prevAct instanceof Start;
}
public void setActivityCostWeight(double weight){
this.activityCostsWeight = weight;
}
public void setSolutionCompletenessRatio(double solutionCompletenessRatio) {
// this.solutionCompletenessRatio = 1.;
this.solutionCompletenessRatio = solutionCompletenessRatio;
}
}

View file

@ -1,109 +0,0 @@
/*******************************************************************************
* Copyright (C) 2014 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.algorithm.state;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.solution.route.RouteVisitor;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.TourActivity;
import java.util.Iterator;
/**
* Updates and memorizes latest operation start times at activities.
*
* @author schroeder
*
*/
public class UpdateDepartureTime implements RouteVisitor, StateUpdater{
private VehicleRoute route;
private VehicleRoutingTransportCosts transportCosts;
private double arrTimeAtPrevActWithoutWaiting;
private TourActivity prevAct;
private boolean hasEarliest = false;
private boolean hasVariableDepartureTime;
private StateManager stateManager;
public UpdateDepartureTime(VehicleRoutingTransportCosts tpCosts, StateManager stateManager) {
super();
this.transportCosts = tpCosts;
this.stateManager = stateManager;
}
public void begin(VehicleRoute route) {
this.route = route;
hasEarliest = false;
prevAct = route.getEnd();
hasVariableDepartureTime = route.getVehicle().hasVariableDepartureTime();
}
public void visit(TourActivity activity) {
if(!hasVariableDepartureTime) return;
if(hasEarliest){
double potentialArrivalTimeAtCurrAct = arrTimeAtPrevActWithoutWaiting - transportCosts.getBackwardTransportTime(activity.getLocation(), prevAct.getLocation(), arrTimeAtPrevActWithoutWaiting, route.getDriver(),route.getVehicle()) - activity.getOperationTime();
if(potentialArrivalTimeAtCurrAct < activity.getTheoreticalEarliestOperationStartTime()){
arrTimeAtPrevActWithoutWaiting = activity.getTheoreticalEarliestOperationStartTime();
}
else if(potentialArrivalTimeAtCurrAct >= activity.getTheoreticalEarliestOperationStartTime() && potentialArrivalTimeAtCurrAct <= activity.getTheoreticalLatestOperationStartTime()){
arrTimeAtPrevActWithoutWaiting = potentialArrivalTimeAtCurrAct;
}
else {
arrTimeAtPrevActWithoutWaiting = activity.getTheoreticalLatestOperationStartTime();
}
stateManager.putInternalTypedActivityState(activity,route.getVehicle(),InternalStates.EARLIEST_WITHOUT_WAITING,arrTimeAtPrevActWithoutWaiting);
}
else{
if(activity.getTheoreticalEarliestOperationStartTime() > 0){
hasEarliest = true;
arrTimeAtPrevActWithoutWaiting = activity.getTheoreticalEarliestOperationStartTime();
stateManager.putInternalTypedActivityState(activity,route.getVehicle(),InternalStates.EARLIEST_WITHOUT_WAITING,arrTimeAtPrevActWithoutWaiting);
}
}
prevAct = activity;
}
public void finish() {
if(!hasVariableDepartureTime) return;
if(hasEarliest){
double dep = arrTimeAtPrevActWithoutWaiting - transportCosts.getBackwardTransportTime(route.getStart().getLocation(), prevAct.getLocation(), arrTimeAtPrevActWithoutWaiting, route.getDriver(),route.getVehicle());
double newDepartureTime = Math.max(route.getVehicle().getEarliestDeparture(), dep);
route.setVehicleAndDepartureTime(route.getVehicle(),newDepartureTime);
}
else route.setVehicleAndDepartureTime(route.getVehicle(),route.getVehicle().getEarliestDeparture());
}
@Override
public void visit(VehicleRoute route) {
begin(route);
Iterator<TourActivity> revIterator = route.getTourActivities().reverseActivityIterator();
while(revIterator.hasNext()){
visit(revIterator.next());
}
finish();
}
}

View file

@ -1,81 +0,0 @@
/*******************************************************************************
* Copyright (C) 2014 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.algorithm.state;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.ActivityVisitor;
import jsprit.core.problem.solution.route.activity.TourActivity;
/**
* Updates arrival and end times of activities.
*
* <p>Note that this modifies arrTime and endTime of each activity in a route.
*
* @author stefan
*
*/
public class UpdateTimeSlack implements ActivityVisitor, StateUpdater{
private VehicleRoute route;
private StateManager stateManager;
private VehicleRoutingTransportCosts costs;
private double prevTimeSlack;
private double prevActDeparture;
private TourActivity prevAct;
public UpdateTimeSlack(StateManager stateManager, VehicleRoutingTransportCosts costs) {
this.stateManager = stateManager;
this.costs = costs;
}
@Override
public void begin(VehicleRoute route) {
if(route.isEmpty()) return;
this.route = route;
prevActDeparture = route.getVehicle().getEarliestDeparture();
TourActivity first = route.getActivities().get(0);
double latestArr = stateManager.getActivityState(first,route.getVehicle(),InternalStates.LATEST_OPERATION_START_TIME,Double.class);
double latest = latestArr - costs.getBackwardTransportCost(first.getLocation(),route.getStart().getLocation(),latestArr,route.getDriver(),route.getVehicle());
prevTimeSlack = latest - prevActDeparture;
prevAct = route.getStart();
}
@Override
public void visit(TourActivity activity) {
double actArrTime = prevActDeparture + costs.getTransportTime(prevAct.getLocation(),activity.getLocation(),prevActDeparture,route.getDriver(),route.getVehicle());
double actEarliestStart = Math.max(actArrTime,activity.getTheoreticalEarliestOperationStartTime());
double actLatestStart = stateManager.getActivityState(activity,route.getVehicle(),InternalStates.LATEST_OPERATION_START_TIME,Double.class);
double latest_minus_earliest = actLatestStart - actEarliestStart;
double time_slack_ = Math.max(actArrTime + prevTimeSlack - activity.getTheoreticalEarliestOperationStartTime(),0);
double time_slack = Math.min(latest_minus_earliest,time_slack_);
stateManager.putInternalTypedActivityState(activity,route.getVehicle(), InternalStates.TIME_SLACK, time_slack);
prevTimeSlack = time_slack;
prevAct = activity;
prevActDeparture = actEarliestStart + activity.getOperationTime();
}
@Override
public void finish() {}
}

View file

@ -73,5 +73,4 @@ public interface Vehicle extends HasId, HasIndex {
public abstract Skills getSkills();
public boolean hasVariableDepartureTime();
}

View file

@ -92,10 +92,7 @@ public class VehicleImpl extends AbstractVehicle{
return null;
}
@Override
public boolean hasVariableDepartureTime() {
return false;
}
}
/**
@ -130,7 +127,6 @@ public class VehicleImpl extends AbstractVehicle{
private Location endLocation;
private boolean hasVariableDepartureTime = false;
private Builder(String id) {
super();
@ -150,11 +146,7 @@ public class VehicleImpl extends AbstractVehicle{
return this;
}
public Builder setHasVariableDepartureTime(boolean hasVariableDepartureTime){
this.hasVariableDepartureTime = hasVariableDepartureTime;
return this;
}
/**
* Sets the flag whether the vehicle must return to depot or not.
*
@ -286,8 +278,6 @@ public class VehicleImpl extends AbstractVehicle{
private final Location startLocation;
private final boolean hasVariableDepartureTime;
private VehicleImpl(Builder builder){
id = builder.id;
type = builder.type;
@ -297,7 +287,6 @@ public class VehicleImpl extends AbstractVehicle{
skills = builder.skills;
endLocation = builder.endLocation;
startLocation = builder.startLocation;
hasVariableDepartureTime = builder.hasVariableDepartureTime;
setVehicleIdentifier(new VehicleTypeKey(type.getTypeId(),startLocation.getId(),endLocation.getId(),earliestDeparture,latestArrival,skills, returnToDepot));
}
@ -356,10 +345,6 @@ public class VehicleImpl extends AbstractVehicle{
return skills;
}
@Override
public boolean hasVariableDepartureTime() {
return hasVariableDepartureTime;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()