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:
parent
70d6ae1797
commit
c8eb1dd7b4
14 changed files with 148 additions and 1002 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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() {}
|
||||
|
||||
}
|
||||
|
|
@ -73,5 +73,4 @@ public interface Vehicle extends HasId, HasIndex {
|
|||
|
||||
public abstract Skills getSkills();
|
||||
|
||||
public boolean hasVariableDepartureTime();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue