mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
variable departure times and waiting time opt
This commit is contained in:
parent
1604a637a5
commit
552729d7ee
10 changed files with 403 additions and 14 deletions
|
|
@ -0,0 +1,40 @@
|
|||
package jsprit.core.algorithm.recreate;
|
||||
|
||||
import jsprit.core.algorithm.recreate.listener.InsertionStartsListener;
|
||||
import jsprit.core.algorithm.recreate.listener.JobInsertedListener;
|
||||
import jsprit.core.problem.VehicleRoutingProblem;
|
||||
import jsprit.core.problem.job.Job;
|
||||
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 22/07/15.
|
||||
*/
|
||||
public class ConfigureLocalActivityInsertionCalculator implements InsertionStartsListener, JobInsertedListener {
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
private LocalActivityInsertionCostsCalculator localActivityInsertionCostsCalculator;
|
||||
|
||||
private int nuOfJobsToRecreate;
|
||||
|
||||
public ConfigureLocalActivityInsertionCalculator(VehicleRoutingProblem vrp, LocalActivityInsertionCostsCalculator localActivityInsertionCostsCalculator) {
|
||||
this.vrp = vrp;
|
||||
this.localActivityInsertionCostsCalculator = localActivityInsertionCostsCalculator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||
this.nuOfJobsToRecreate = unassignedJobs.size();
|
||||
double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)vrp.getJobs().values().size()));
|
||||
localActivityInsertionCostsCalculator.setSolutionCompletenessRatio(completenessRatio);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||
nuOfJobsToRecreate--;
|
||||
double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)vrp.getJobs().values().size()));
|
||||
localActivityInsertionCostsCalculator.setSolutionCompletenessRatio(completenessRatio);
|
||||
}
|
||||
}
|
||||
|
|
@ -259,8 +259,10 @@ public class JobInsertionCostsCalculatorBuilder {
|
|||
if(constraintManager == null) throw new IllegalStateException("constraint-manager is null");
|
||||
|
||||
ActivityInsertionCostsCalculator actInsertionCalc;
|
||||
ConfigureLocalActivityInsertionCalculator configLocal = null;
|
||||
if(activityInsertionCostCalculator == null && addDefaultCostCalc){
|
||||
actInsertionCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||
configLocal = new ConfigureLocalActivityInsertionCalculator(vrp, (LocalActivityInsertionCostsCalculator) actInsertionCalc);
|
||||
}
|
||||
else if(activityInsertionCostCalculator == null && !addDefaultCostCalc){
|
||||
actInsertionCalc = new ActivityInsertionCostsCalculator(){
|
||||
|
|
@ -296,7 +298,11 @@ public class JobInsertionCostsCalculatorBuilder {
|
|||
switcher.put(Pickup.class, serviceInsertion);
|
||||
switcher.put(Delivery.class, serviceInsertion);
|
||||
|
||||
return new CalculatorPlusListeners(switcher);
|
||||
CalculatorPlusListeners calculatorPlusListeners = new CalculatorPlusListeners(switcher);
|
||||
if(configLocal != null){
|
||||
calculatorPlusListeners.insertionListener.add(configLocal);
|
||||
}
|
||||
return calculatorPlusListeners;
|
||||
}
|
||||
|
||||
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCostsCalculator baseCalculator, RouteAndActivityStateGetter activityStates2, double weightOfFixedCosts){
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ 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.util.CalculationUtils;
|
||||
|
||||
|
|
@ -40,8 +41,11 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
|
|||
private VehicleRoutingTransportCosts routingCosts;
|
||||
|
||||
private VehicleRoutingActivityCosts activityCosts;
|
||||
|
||||
|
||||
|
||||
private double activityCostsWeight = 1.;
|
||||
|
||||
private double solutionCompletenessRatio = 1.;
|
||||
|
||||
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts) {
|
||||
super();
|
||||
this.routingCosts = routingCosts;
|
||||
|
|
@ -56,7 +60,12 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
|
|||
double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct;
|
||||
double newAct_endTime = CalculationUtils.getActivityEndTime(newAct_arrTime, newAct);
|
||||
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
|
||||
if(prevAct instanceof Start) {
|
||||
if(iFacts.getNewVehicle().hasVariableDepartureTime()){
|
||||
act_costs_newAct = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//open routes
|
||||
if(nextAct instanceof End){
|
||||
if(!iFacts.getNewVehicle().isReturnToDepot()){
|
||||
|
|
@ -68,22 +77,30 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
|
|||
double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocation(), nextAct.getLocation(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct;
|
||||
double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct;
|
||||
|
||||
double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + solutionCompletenessRatio * activityCostsWeight * (act_costs_newAct + act_costs_nextAct);
|
||||
|
||||
double oldCosts;
|
||||
if(iFacts.getRoute().isEmpty()){
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct;
|
||||
oldCosts = tp_costs_prevAct_nextAct + solutionCompletenessRatio * activityCostsWeight * actCost_nextAct;
|
||||
}
|
||||
else{
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocation(), nextAct.getLocation(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||
double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), 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;
|
||||
oldCosts = tp_costs_prevAct_nextAct + solutionCompletenessRatio * activityCostsWeight * actCost_nextAct;
|
||||
}
|
||||
return totalCosts - oldCosts;
|
||||
}
|
||||
|
||||
public void setActivityCostWeight(double weight){
|
||||
this.activityCostsWeight = weight;
|
||||
}
|
||||
|
||||
public void setSolutionCompletenessRatio(double solutionCompletenessRatio) {
|
||||
this.solutionCompletenessRatio = solutionCompletenessRatio;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
/*******************************************************************************
|
||||
* 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;
|
||||
|
||||
public class UpdateDepartureTime implements StateUpdater, RouteVisitor{
|
||||
|
||||
private VehicleRoutingTransportCosts routingCosts;
|
||||
|
||||
public UpdateDepartureTime(VehicleRoutingTransportCosts routingCosts) {
|
||||
this.routingCosts = routingCosts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(VehicleRoute route) {
|
||||
if(route.getVehicle() != null){
|
||||
if(route.getVehicle().hasVariableDepartureTime()) {
|
||||
if (!route.isEmpty()) {
|
||||
TourActivity first = route.getActivities().get(0);
|
||||
double earliestStart = first.getTheoreticalEarliestOperationStartTime();
|
||||
double backwardTravelTime = routingCosts.getBackwardTransportTime(first.getLocation(), route.getStart().getLocation(),
|
||||
earliestStart, route.getDriver(), route.getVehicle());
|
||||
double newDepartureTime = Math.max(route.getStart().getEndTime(), earliestStart - backwardTravelTime);
|
||||
route.setVehicleAndDepartureTime(route.getVehicle(), newDepartureTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -72,4 +72,6 @@ public interface Vehicle extends HasId, HasIndex {
|
|||
public abstract VehicleTypeKey getVehicleTypeIdentifier();
|
||||
|
||||
public abstract Skills getSkills();
|
||||
|
||||
public boolean hasVariableDepartureTime();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,12 @@ public class VehicleImpl extends AbstractVehicle{
|
|||
public Skills getSkills() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasVariableDepartureTime() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder that builds the vehicle.
|
||||
|
|
@ -125,7 +130,9 @@ public class VehicleImpl extends AbstractVehicle{
|
|||
|
||||
private Location endLocation;
|
||||
|
||||
private Builder(String id) {
|
||||
private boolean hasVariableDepartureTime = false;
|
||||
|
||||
private Builder(String id) {
|
||||
super();
|
||||
this.id = id;
|
||||
}
|
||||
|
|
@ -142,6 +149,11 @@ public class VehicleImpl extends AbstractVehicle{
|
|||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setHasVariableDepartureTime(boolean hasVariableDepartureTime){
|
||||
this.hasVariableDepartureTime = hasVariableDepartureTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the flag whether the vehicle must return to depot or not.
|
||||
|
|
@ -274,6 +286,8 @@ public class VehicleImpl extends AbstractVehicle{
|
|||
|
||||
private final Location startLocation;
|
||||
|
||||
private final boolean hasVariableDepartureTime;
|
||||
|
||||
private VehicleImpl(Builder builder){
|
||||
id = builder.id;
|
||||
type = builder.type;
|
||||
|
|
@ -283,6 +297,7 @@ 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));
|
||||
}
|
||||
|
||||
|
|
@ -341,7 +356,12 @@ public class VehicleImpl extends AbstractVehicle{
|
|||
return skills;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@Override
|
||||
public boolean hasVariableDepartureTime() {
|
||||
return hasVariableDepartureTime;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue