1
0
Fork 0
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:
oblonski 2015-07-22 22:53:45 +02:00
parent 1604a637a5
commit 552729d7ee
10 changed files with 403 additions and 14 deletions

View file

@ -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);
}
}

View file

@ -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){

View file

@ -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;
}
}

View file

@ -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);
}
}
}
}
}

View file

@ -72,4 +72,6 @@ public interface Vehicle extends HasId, HasIndex {
public abstract VehicleTypeKey getVehicleTypeIdentifier();
public abstract Skills getSkills();
public boolean hasVariableDepartureTime();
}

View file

@ -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