mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
relax API
This commit is contained in:
parent
a51abf6302
commit
289b7a0f77
70 changed files with 1674 additions and 1226 deletions
|
|
@ -3,7 +3,7 @@ package algorithms;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
interface ActivityVisitor {
|
public interface ActivityVisitor {
|
||||||
|
|
||||||
public void begin(VehicleRoute route);
|
public void begin(VehicleRoute route);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,28 @@ import basics.route.VehicleRoute;
|
||||||
|
|
||||||
final class BestInsertion implements InsertionStrategy{
|
final class BestInsertion implements InsertionStrategy{
|
||||||
|
|
||||||
|
class Insertion {
|
||||||
|
|
||||||
|
private final VehicleRoute route;
|
||||||
|
|
||||||
|
private final InsertionData insertionData;
|
||||||
|
|
||||||
|
public Insertion(VehicleRoute vehicleRoute, InsertionData insertionData) {
|
||||||
|
super();
|
||||||
|
this.route = vehicleRoute;
|
||||||
|
this.insertionData = insertionData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VehicleRoute getRoute() {
|
||||||
|
return route;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InsertionData getInsertionData() {
|
||||||
|
return insertionData;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static Logger logger = Logger.getLogger(BestInsertion.class);
|
private static Logger logger = Logger.getLogger(BestInsertion.class);
|
||||||
|
|
||||||
private Random random = RandomNumberGeneration.getRandom();
|
private Random random = RandomNumberGeneration.getRandom();
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
|
import algorithms.constraints.ConstraintManager;
|
||||||
|
import algorithms.constraints.HardActivityLevelConstraint;
|
||||||
|
import algorithms.constraints.HardRouteLevelConstraint;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import algorithms.HardConstraints.HardActivityLevelConstraint;
|
import basics.VehicleRoutingProblem.FleetSize;
|
||||||
import algorithms.HardConstraints.HardRouteLevelConstraint;
|
|
||||||
|
|
||||||
public class BestInsertionBuilder implements InsertionStrategyBuilder{
|
public class BestInsertionBuilder implements InsertionStrategyBuilder{
|
||||||
|
|
||||||
|
|
@ -10,25 +12,58 @@ public class BestInsertionBuilder implements InsertionStrategyBuilder{
|
||||||
|
|
||||||
private StateManager stateManager;
|
private StateManager stateManager;
|
||||||
|
|
||||||
|
private boolean local = true;
|
||||||
|
|
||||||
|
private ConstraintManager constraintManager;
|
||||||
|
|
||||||
|
private VehicleFleetManager fleetManager;
|
||||||
|
|
||||||
public BestInsertionBuilder(VehicleRoutingProblem vrp, StateManager stateManager) {
|
public BestInsertionBuilder(VehicleRoutingProblem vrp, StateManager stateManager) {
|
||||||
super();
|
super();
|
||||||
this.vrp = vrp;
|
this.vrp = vrp;
|
||||||
this.stateManager = stateManager;
|
this.stateManager = stateManager;
|
||||||
|
this.constraintManager = new ConstraintManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addConstraint(HardActivityLevelConstraint hardActvitiyLevelConstraint){};
|
public void addConstraint(HardActivityLevelConstraint hardActvitiyLevelConstraint){
|
||||||
|
constraintManager.addConstraint(hardActvitiyLevelConstraint);
|
||||||
|
};
|
||||||
|
|
||||||
public void addConstraint(HardRouteLevelConstraint hardRouteLevelConstraint){};
|
public void addConstraint(HardRouteLevelConstraint hardRouteLevelConstraint){
|
||||||
|
constraintManager.addConstraint(hardRouteLevelConstraint);
|
||||||
|
};
|
||||||
|
|
||||||
public void setRouteLevel(int forwardLooking, int memory){};
|
//public void setRouteLevel(int forwardLooking, int memory){};
|
||||||
|
|
||||||
public void setLocalLevel(){};
|
public void setLocalLevel(){
|
||||||
|
local = true;
|
||||||
|
};
|
||||||
|
|
||||||
public void setActivityInsertionCostCalculator(ActivityInsertionCostCalculator costCalc){};
|
public void setFleetManager(VehicleFleetManager fleetManager){
|
||||||
|
this.fleetManager = fleetManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
//public void setActivityInsertionCostCalculator(ActivityInsertionCostCalculator costCalc){};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InsertionStrategy build() {
|
public InsertionStrategy build() {
|
||||||
return null;
|
CalculatorBuilder calcBuilder = new CalculatorBuilder(null, null);
|
||||||
|
if(local){
|
||||||
|
calcBuilder.setLocalLevel();
|
||||||
|
}
|
||||||
|
calcBuilder.setConstraintManager(constraintManager);
|
||||||
|
calcBuilder.setStates(stateManager);
|
||||||
|
calcBuilder.setVehicleRoutingProblem(vrp);
|
||||||
|
calcBuilder.setVehicleFleetManager(fleetManager);
|
||||||
|
JobInsertionCalculator jobInsertions = calcBuilder.build();
|
||||||
|
return new BestInsertion(jobInsertions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private VehicleFleetManager createFleetManager(VehicleRoutingProblem vrp) {
|
||||||
|
if(vrp.getFleetSize().equals(FleetSize.INFINITE)){
|
||||||
|
return new InfiniteVehicles(vrp.getVehicles());
|
||||||
|
}
|
||||||
|
else return new VehicleFleetManagerImpl(vrp.getVehicles());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,9 +47,9 @@ import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
final class CreateInitialSolution implements InitialSolutionFactory {
|
public final class BestInsertionInitialSolutionFactory implements InitialSolutionFactory {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(CreateInitialSolution.class);
|
private static final Logger logger = Logger.getLogger(BestInsertionInitialSolutionFactory.class);
|
||||||
|
|
||||||
private final InsertionStrategy insertion;
|
private final InsertionStrategy insertion;
|
||||||
|
|
||||||
|
|
@ -59,13 +59,13 @@ final class CreateInitialSolution implements InitialSolutionFactory {
|
||||||
this.generateAsMuchAsRoutesAsVehiclesExist = generateAsMuchAsRoutesAsVehiclesExist;
|
this.generateAsMuchAsRoutesAsVehiclesExist = generateAsMuchAsRoutesAsVehiclesExist;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CreateInitialSolution(InsertionStrategy insertionStrategy) {
|
public BestInsertionInitialSolutionFactory(InsertionStrategy insertionStrategy) {
|
||||||
super();
|
super();
|
||||||
this.insertion = insertionStrategy;
|
this.insertion = insertionStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VehicleRoutingProblemSolution createInitialSolution(final VehicleRoutingProblem vrp) {
|
public VehicleRoutingProblemSolution createSolution(final VehicleRoutingProblem vrp) {
|
||||||
logger.info("create initial solution.");
|
logger.info("create initial solution.");
|
||||||
List<VehicleRoute> vehicleRoutes = new ArrayList<VehicleRoute>();
|
List<VehicleRoute> vehicleRoutes = new ArrayList<VehicleRoute>();
|
||||||
if(generateAsMuchAsRoutesAsVehiclesExist){
|
if(generateAsMuchAsRoutesAsVehiclesExist){
|
||||||
|
|
@ -15,18 +15,17 @@ package algorithms;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import util.Neighborhood;
|
import util.Neighborhood;
|
||||||
import algorithms.HardConstraints.HardRouteLevelConstraint;
|
|
||||||
import algorithms.ActivityInsertionCostCalculator.Marginals;
|
import algorithms.ActivityInsertionCostCalculator.Marginals;
|
||||||
|
import algorithms.constraints.HardRouteLevelConstraint;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
|
import basics.route.DefaultTourActivityFactory;
|
||||||
import basics.route.Driver;
|
import basics.route.Driver;
|
||||||
import basics.route.End;
|
import basics.route.End;
|
||||||
import basics.route.ServiceActivity;
|
|
||||||
import basics.route.Start;
|
import basics.route.Start;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
import basics.route.TourActivityFactory;
|
import basics.route.TourActivityFactory;
|
||||||
import basics.route.DefaultTourActivityFactory;
|
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
import basics.route.VehicleImpl.NoVehicle;
|
import basics.route.VehicleImpl.NoVehicle;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
@ -117,7 +116,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
||||||
}
|
}
|
||||||
|
|
||||||
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle);
|
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle);
|
||||||
double nextActEndTime = CalcUtils.getActivityEndTime(nextActArrTime, nextAct);
|
double nextActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
|
||||||
|
|
||||||
prevActStartTime = nextActEndTime;
|
prevActStartTime = nextActEndTime;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,6 @@ package algorithms;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import algorithms.InsertionData.NoInsertionFound;
|
import algorithms.InsertionData.NoInsertionFound;
|
||||||
import algorithms.StateManager.State;
|
|
||||||
import algorithms.StateManager.States;
|
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.route.Driver;
|
import basics.route.Driver;
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ import java.util.Collection;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import algorithms.InsertionData.NoInsertionFound;
|
import algorithms.InsertionData.NoInsertionFound;
|
||||||
import algorithms.VehicleFleetManager.TypeKey;
|
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.route.Driver;
|
import basics.route.Driver;
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ package algorithms;
|
||||||
|
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
|
|
||||||
class CalcUtils {
|
public class CalculationUtils {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -32,7 +32,7 @@ class CalcUtils {
|
||||||
* @param act
|
* @param act
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static double getActivityEndTime(double actArrTime, TourActivity act){
|
public static double getActivityEndTime(double actArrTime, TourActivity act){
|
||||||
return Math.max(actArrTime, act.getTheoreticalEarliestOperationStartTime()) + act.getOperationTime();
|
return Math.max(actArrTime, act.getTheoreticalEarliestOperationStartTime()) + act.getOperationTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -23,7 +23,7 @@ package algorithms;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import algorithms.HardConstraints.ConstraintManager;
|
import algorithms.constraints.ConstraintManager;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.algo.InsertionListener;
|
import basics.algo.InsertionListener;
|
||||||
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package algorithms;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import basics.route.Vehicle;
|
||||||
|
|
||||||
|
public class FiniteFleetManagerFactory implements VehicleFleetManagerFactory{
|
||||||
|
|
||||||
|
private Collection<Vehicle> vehicles;
|
||||||
|
|
||||||
|
public FiniteFleetManagerFactory(Collection<Vehicle> vehicles) {
|
||||||
|
super();
|
||||||
|
this.vehicles = vehicles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VehicleFleetManager createFleetManager() {
|
||||||
|
return new VehicleFleetManagerImpl(vehicles);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,311 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* Copyright (C) 2013 Stefan Schroeder
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* Contributors:
|
|
||||||
* Stefan Schroeder - initial API and implementation
|
|
||||||
******************************************************************************/
|
|
||||||
package algorithms;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import basics.Delivery;
|
|
||||||
import basics.Pickup;
|
|
||||||
import basics.Service;
|
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
|
||||||
import basics.route.DeliveryActivity;
|
|
||||||
import basics.route.PickupActivity;
|
|
||||||
import basics.route.ServiceActivity;
|
|
||||||
import basics.route.Start;
|
|
||||||
import basics.route.TourActivity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* collection of hard constrainters bot at activity and at route level.
|
|
||||||
*
|
|
||||||
* <p>HardPickupAndDeliveryLoadConstraint requires LOAD_AT_DEPOT and LOAD (i.e. load at end) at route-level
|
|
||||||
*
|
|
||||||
* <p>HardTimeWindowConstraint requires LATEST_OPERATION_START_TIME
|
|
||||||
*
|
|
||||||
* <p>HardPickupAndDeliveryConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level
|
|
||||||
*
|
|
||||||
* <p>HardPickupAndDeliveryBackhaulConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level
|
|
||||||
*
|
|
||||||
* @author stefan
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class HardConstraints {
|
|
||||||
|
|
||||||
interface HardRouteLevelConstraint {
|
|
||||||
|
|
||||||
public boolean fulfilled(InsertionContext insertionContext);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
interface HardActivityLevelConstraint {
|
|
||||||
|
|
||||||
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class HardRouteLevelConstraintManager implements HardRouteLevelConstraint {
|
|
||||||
|
|
||||||
private Collection<HardRouteLevelConstraint> hardConstraints = new ArrayList<HardRouteLevelConstraint>();
|
|
||||||
|
|
||||||
public void addConstraint(HardRouteLevelConstraint constraint){
|
|
||||||
hardConstraints.add(constraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean fulfilled(InsertionContext insertionContext) {
|
|
||||||
for(HardRouteLevelConstraint constraint : hardConstraints){
|
|
||||||
if(!constraint.fulfilled(insertionContext)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ConstraintManager implements HardActivityLevelConstraint, HardRouteLevelConstraint{
|
|
||||||
|
|
||||||
private HardActivityLevelConstraintManager actLevelConstraintManager = new HardActivityLevelConstraintManager();
|
|
||||||
|
|
||||||
private HardRouteLevelConstraintManager routeLevelConstraintManager = new HardRouteLevelConstraintManager();
|
|
||||||
|
|
||||||
public void addConstraint(HardActivityLevelConstraint actLevelConstraint){
|
|
||||||
actLevelConstraintManager.addConstraint(actLevelConstraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addConstraint(HardRouteLevelConstraint routeLevelConstraint){
|
|
||||||
routeLevelConstraintManager.addConstraint(routeLevelConstraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean fulfilled(InsertionContext insertionContext) {
|
|
||||||
return routeLevelConstraintManager.fulfilled(insertionContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
|
|
||||||
return actLevelConstraintManager.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class HardActivityLevelConstraintManager implements HardActivityLevelConstraint {
|
|
||||||
|
|
||||||
private Collection<HardActivityLevelConstraint> hardConstraints = new ArrayList<HardActivityLevelConstraint>();
|
|
||||||
|
|
||||||
public void addConstraint(HardActivityLevelConstraint constraint){
|
|
||||||
hardConstraints.add(constraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class HardLoadConstraint implements HardRouteLevelConstraint{
|
|
||||||
|
|
||||||
private StateManager states;
|
|
||||||
|
|
||||||
public HardLoadConstraint(StateManager states) {
|
|
||||||
super();
|
|
||||||
this.states = states;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean fulfilled(InsertionContext insertionContext) {
|
|
||||||
int currentLoad = (int) states.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble();
|
|
||||||
Service service = (Service) insertionContext.getJob();
|
|
||||||
if(currentLoad + service.getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* lsjdfjsdlfjsa
|
|
||||||
*
|
|
||||||
* @author stefan
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static class HardPickupAndDeliveryLoadConstraint implements HardRouteLevelConstraint {
|
|
||||||
|
|
||||||
private StateManager stateManager;
|
|
||||||
|
|
||||||
public HardPickupAndDeliveryLoadConstraint(StateManager stateManager) {
|
|
||||||
super();
|
|
||||||
this.stateManager = stateManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean fulfilled(InsertionContext insertionContext) {
|
|
||||||
if(insertionContext.getJob() instanceof Delivery){
|
|
||||||
int loadAtDepot = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
|
|
||||||
if(loadAtDepot + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(insertionContext.getJob() instanceof Pickup || insertionContext.getJob() instanceof Service){
|
|
||||||
int loadAtEnd = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble();
|
|
||||||
if(loadAtEnd + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ljsljslfjs
|
|
||||||
* @author stefan
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static class HardTimeWindowActivityLevelConstraint implements HardActivityLevelConstraint {
|
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(HardTimeWindowActivityLevelConstraint.class);
|
|
||||||
|
|
||||||
private StateManager states;
|
|
||||||
|
|
||||||
private VehicleRoutingTransportCosts routingCosts;
|
|
||||||
|
|
||||||
public HardTimeWindowActivityLevelConstraint(StateManager states, VehicleRoutingTransportCosts routingCosts) {
|
|
||||||
super();
|
|
||||||
this.states = states;
|
|
||||||
this.routingCosts = routingCosts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
|
||||||
double latestArrTimeAtNewAct = states.getActivityState(newAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble();
|
|
||||||
if(arrTimeAtNewAct > latestArrTimeAtNewAct){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// log.info(newAct + " arrTime=" + arrTimeAtNewAct);
|
|
||||||
double endTimeAtNewAct = CalcUtils.getActivityEndTime(arrTimeAtNewAct, newAct);
|
|
||||||
double arrTimeAtNextAct = endTimeAtNewAct + routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), endTimeAtNewAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
|
||||||
double latestArrTimeAtNextAct = states.getActivityState(nextAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble();
|
|
||||||
if(arrTimeAtNextAct > latestArrTimeAtNextAct){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// log.info(nextAct + " arrTime=" + arrTimeAtNextAct);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class HardPickupAndDeliveryActivityLevelConstraint implements HardActivityLevelConstraint {
|
|
||||||
|
|
||||||
private StateManager stateManager;
|
|
||||||
|
|
||||||
public HardPickupAndDeliveryActivityLevelConstraint(StateManager stateManager) {
|
|
||||||
super();
|
|
||||||
this.stateManager = stateManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
|
|
||||||
int loadAtPrevAct;
|
|
||||||
int futurePicks;
|
|
||||||
int pastDeliveries;
|
|
||||||
if(prevAct instanceof Start){
|
|
||||||
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
|
|
||||||
futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble();
|
|
||||||
pastDeliveries = 0;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateTypes.LOAD).toDouble();
|
|
||||||
futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble();
|
|
||||||
pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble();
|
|
||||||
}
|
|
||||||
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
|
|
||||||
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(newAct instanceof DeliveryActivity){
|
|
||||||
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class HardPickupAndDeliveryBackhaulActivityLevelConstraint implements HardActivityLevelConstraint {
|
|
||||||
|
|
||||||
private StateManager stateManager;
|
|
||||||
|
|
||||||
public HardPickupAndDeliveryBackhaulActivityLevelConstraint(StateManager stateManager) {
|
|
||||||
super();
|
|
||||||
this.stateManager = stateManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@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; }
|
|
||||||
int loadAtPrevAct;
|
|
||||||
int futurePicks;
|
|
||||||
int pastDeliveries;
|
|
||||||
if(prevAct instanceof Start){
|
|
||||||
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
|
|
||||||
futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble();
|
|
||||||
pastDeliveries = 0;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateTypes.LOAD).toDouble();
|
|
||||||
futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble();
|
|
||||||
pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble();
|
|
||||||
}
|
|
||||||
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
|
|
||||||
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(newAct instanceof DeliveryActivity){
|
|
||||||
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package algorithms;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import basics.route.Vehicle;
|
||||||
|
|
||||||
|
public class InfiniteFleetManagerFactory implements VehicleFleetManagerFactory{
|
||||||
|
|
||||||
|
private Collection<Vehicle> vehicles;
|
||||||
|
|
||||||
|
public InfiniteFleetManagerFactory(Collection<Vehicle> vehicles) {
|
||||||
|
super();
|
||||||
|
this.vehicles = vehicles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VehicleFleetManager createFleetManager() {
|
||||||
|
return new InfiniteVehicles(vehicles);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -45,9 +45,9 @@ class InfiniteVehicles implements VehicleFleetManager{
|
||||||
|
|
||||||
private static Logger logger = Logger.getLogger(InfiniteVehicles.class);
|
private static Logger logger = Logger.getLogger(InfiniteVehicles.class);
|
||||||
|
|
||||||
private Map<TypeKey,Vehicle> types = new HashMap<TypeKey, Vehicle>();
|
private Map<VehicleTypeKey,Vehicle> types = new HashMap<VehicleTypeKey, Vehicle>();
|
||||||
|
|
||||||
private List<TypeKey> sortedTypes = new ArrayList<VehicleFleetManager.TypeKey>();
|
private List<VehicleTypeKey> sortedTypes = new ArrayList<VehicleTypeKey>();
|
||||||
|
|
||||||
public InfiniteVehicles(Collection<Vehicle> vehicles){
|
public InfiniteVehicles(Collection<Vehicle> vehicles){
|
||||||
extractTypes(vehicles);
|
extractTypes(vehicles);
|
||||||
|
|
@ -61,7 +61,7 @@ class InfiniteVehicles implements VehicleFleetManager{
|
||||||
|
|
||||||
private void extractTypes(Collection<Vehicle> vehicles) {
|
private void extractTypes(Collection<Vehicle> vehicles) {
|
||||||
for(Vehicle v : vehicles){
|
for(Vehicle v : vehicles){
|
||||||
TypeKey typeKey = new TypeKey(v.getType().getTypeId(),v.getLocationId());
|
VehicleTypeKey typeKey = new VehicleTypeKey(v.getType().getTypeId(),v.getLocationId());
|
||||||
types.put(typeKey,v);
|
types.put(typeKey,v);
|
||||||
sortedTypes.add(typeKey);
|
sortedTypes.add(typeKey);
|
||||||
|
|
||||||
|
|
@ -99,8 +99,8 @@ class InfiniteVehicles implements VehicleFleetManager{
|
||||||
@Override
|
@Override
|
||||||
public Collection<Vehicle> getAvailableVehicles(String withoutThisType, String locationId) {
|
public Collection<Vehicle> getAvailableVehicles(String withoutThisType, String locationId) {
|
||||||
Collection<Vehicle> vehicles = new ArrayList<Vehicle>();
|
Collection<Vehicle> vehicles = new ArrayList<Vehicle>();
|
||||||
TypeKey thisKey = new TypeKey(withoutThisType,locationId);
|
VehicleTypeKey thisKey = new VehicleTypeKey(withoutThisType,locationId);
|
||||||
for(TypeKey key : types.keySet()){
|
for(VehicleTypeKey key : types.keySet()){
|
||||||
if(!key.equals(thisKey)){
|
if(!key.equals(thisKey)){
|
||||||
vehicles.add(types.get(key));
|
vehicles.add(types.get(key));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ import basics.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface InitialSolutionFactory {
|
public interface InitialSolutionFactory {
|
||||||
|
|
||||||
public VehicleRoutingProblemSolution createInitialSolution(VehicleRoutingProblem vrp);
|
public VehicleRoutingProblemSolution createSolution(VehicleRoutingProblem vrp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import basics.route.Driver;
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
class InsertionContext {
|
public class InsertionContext {
|
||||||
|
|
||||||
private VehicleRoute route;
|
private VehicleRoute route;
|
||||||
private Job job;
|
private Job job;
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,7 @@ import java.util.concurrent.ExecutorService;
|
||||||
import org.apache.commons.configuration.HierarchicalConfiguration;
|
import org.apache.commons.configuration.HierarchicalConfiguration;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import algorithms.HardConstraints.ConstraintManager;
|
import algorithms.constraints.ConstraintManager;
|
||||||
import algorithms.StateUpdates.UpdateStates;
|
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.algo.InsertionListener;
|
import basics.algo.InsertionListener;
|
||||||
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
||||||
|
|
@ -39,8 +38,7 @@ class InsertionFactory {
|
||||||
|
|
||||||
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
|
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
|
||||||
VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){
|
VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){
|
||||||
boolean concurrentInsertion = false;
|
|
||||||
if(executorService != null) concurrentInsertion = true;
|
|
||||||
if(config.containsKey("[@name]")){
|
if(config.containsKey("[@name]")){
|
||||||
String insertionName = config.getString("[@name]");
|
String insertionName = config.getString("[@name]");
|
||||||
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
|
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
|
||||||
|
|
@ -100,20 +98,7 @@ class InsertionFactory {
|
||||||
if(insertionName.equals("bestInsertion")){
|
if(insertionName.equals("bestInsertion")){
|
||||||
insertionStrategy = new BestInsertion(jic);
|
insertionStrategy = new BestInsertion(jic);
|
||||||
}
|
}
|
||||||
// else if(insertionName.equals("regretInsertion")){
|
|
||||||
// insertionStrategy = RegretInsertion.newInstance(routeAlgorithm);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager));
|
|
||||||
// insertionStrategy.addListener(new ResetAndIniFleetManager(vehicleFleetManager));
|
|
||||||
// insertionStrategy.addListener(new VehicleSwitched(vehicleFleetManager));
|
|
||||||
|
|
||||||
// insertionStrategy.addListener(new UpdateLoadAtRouteLevel(routeStates));
|
|
||||||
|
|
||||||
// insertionStrategy.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
|
|
||||||
for(InsertionListener l : insertionListeners) insertionStrategy.addListener(l);
|
for(InsertionListener l : insertionListeners) insertionStrategy.addListener(l);
|
||||||
// insertionStrategy.addListener(new FindCheaperVehicle(
|
|
||||||
// new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator)));
|
|
||||||
|
|
||||||
algorithmListeners.addAll(algoListeners);
|
algorithmListeners.addAll(algoListeners);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,32 +29,6 @@ import basics.route.VehicleRoute;
|
||||||
|
|
||||||
public interface InsertionStrategy {
|
public interface InsertionStrategy {
|
||||||
|
|
||||||
class Insertion {
|
|
||||||
|
|
||||||
private final VehicleRoute route;
|
|
||||||
|
|
||||||
private final InsertionData insertionData;
|
|
||||||
|
|
||||||
public Insertion(VehicleRoute vehicleRoute, InsertionData insertionData) {
|
|
||||||
super();
|
|
||||||
this.route = vehicleRoute;
|
|
||||||
this.insertionData = insertionData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public VehicleRoute getRoute() {
|
|
||||||
return route;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InsertionData getInsertionData() {
|
|
||||||
return insertionData;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns the unassigned jobs to service-providers
|
* Assigns the unassigned jobs to service-providers
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
import algorithms.HardConstraints.HardActivityLevelConstraint;
|
import algorithms.constraints.HardActivityLevelConstraint;
|
||||||
import basics.costs.VehicleRoutingActivityCosts;
|
import basics.costs.VehicleRoutingActivityCosts;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
|
|
@ -50,7 +50,7 @@ class MarginalsCalculusTriangleInequality implements ActivityInsertionCostCalcul
|
||||||
|
|
||||||
double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct;
|
double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct;
|
||||||
|
|
||||||
double newAct_endTime = CalcUtils.getActivityEndTime(newAct_arrTime, newAct);
|
double newAct_endTime = CalculationUtils.getActivityEndTime(newAct_arrTime, newAct);
|
||||||
|
|
||||||
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,13 @@ import basics.algo.InsertionEndsListener;
|
||||||
import basics.algo.InsertionStartsListener;
|
import basics.algo.InsertionStartsListener;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
class RemoveEmptyVehicles implements InsertionEndsListener{
|
public class RemoveEmptyVehicles implements InsertionEndsListener{
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(RemoveEmptyVehicles.class);
|
private static Logger log = Logger.getLogger(RemoveEmptyVehicles.class);
|
||||||
|
|
||||||
private VehicleFleetManager fleetManager;
|
private VehicleFleetManager fleetManager;
|
||||||
|
|
||||||
RemoveEmptyVehicles(VehicleFleetManager fleetManager) {
|
public RemoveEmptyVehicles(VehicleFleetManager fleetManager) {
|
||||||
super();
|
super();
|
||||||
this.fleetManager = fleetManager;
|
this.fleetManager = fleetManager;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package algorithms;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
interface ReverseActivityVisitor {
|
public interface ReverseActivityVisitor {
|
||||||
|
|
||||||
public void begin(VehicleRoute route);
|
public void begin(VehicleRoute route);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import java.util.Iterator;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
class ReverseRouteActivityVisitor implements RouteVisitor{
|
public class ReverseRouteActivityVisitor implements RouteVisitor{
|
||||||
|
|
||||||
private Collection<ReverseActivityVisitor> visitors = new ArrayList<ReverseActivityVisitor>();
|
private Collection<ReverseActivityVisitor> visitors = new ArrayList<ReverseActivityVisitor>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import java.util.Collection;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
class RouteActivityVisitor implements RouteVisitor{
|
public class RouteActivityVisitor implements RouteVisitor{
|
||||||
|
|
||||||
private Collection<ActivityVisitor> visitors = new ArrayList<ActivityVisitor>();
|
private Collection<ActivityVisitor> visitors = new ArrayList<ActivityVisitor>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package algorithms;
|
||||||
|
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
interface RouteVisitor {
|
public interface RouteVisitor {
|
||||||
|
|
||||||
public void visit(VehicleRoute route);
|
public void visit(VehicleRoute route);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import util.StopWatch;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.algo.RuinListener;
|
import basics.algo.RuinListener;
|
||||||
|
import basics.algo.RuinListeners;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import util.RandomNumberGeneration;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.algo.RuinListener;
|
import basics.algo.RuinListener;
|
||||||
|
import basics.algo.RuinListeners;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,42 +29,6 @@ public interface StateManager {
|
||||||
double toDouble();
|
double toDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
class StateImpl implements State{
|
|
||||||
double state;
|
|
||||||
|
|
||||||
public StateImpl(double state) {
|
|
||||||
super();
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double toDouble() {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public void setState(double val){
|
|
||||||
// state=val;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
interface States {
|
|
||||||
|
|
||||||
// void putState(String key, State state);
|
|
||||||
|
|
||||||
State getState(String key);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Map<VehicleRoute, States> getRouteStates();
|
|
||||||
|
|
||||||
// void put(VehicleRoute route, States states);
|
|
||||||
|
|
||||||
// Map<TourActivity, States> getActivityStates();
|
|
||||||
|
|
||||||
// void put(TourActivity act, States states);
|
|
||||||
|
|
||||||
State getActivityState(TourActivity act, String stateType);
|
State getActivityState(TourActivity act, String stateType);
|
||||||
|
|
||||||
State getRouteState(VehicleRoute route, String stateType);
|
State getRouteState(VehicleRoute route, String stateType);
|
||||||
|
|
|
||||||
|
|
@ -25,21 +25,45 @@ import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import algorithms.StateManager.State;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import basics.VehicleRoutingProblemSolution;
|
||||||
import basics.algo.InsertionEndsListener;
|
import basics.algo.InsertionEndsListener;
|
||||||
import basics.algo.InsertionListener;
|
import basics.algo.InsertionListener;
|
||||||
|
import basics.algo.InsertionListeners;
|
||||||
import basics.algo.InsertionStartsListener;
|
import basics.algo.InsertionStartsListener;
|
||||||
import basics.algo.IterationStartsListener;
|
import basics.algo.IterationStartsListener;
|
||||||
import basics.algo.JobInsertedListener;
|
import basics.algo.JobInsertedListener;
|
||||||
import basics.algo.RuinListener;
|
import basics.algo.RuinListener;
|
||||||
|
import basics.algo.RuinListeners;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
public class StateManagerImpl implements StateManager, IterationStartsListener, RuinListener, InsertionStartsListener, JobInsertedListener, InsertionEndsListener {
|
public class StateManagerImpl implements StateManager, IterationStartsListener, RuinListener, InsertionStartsListener, JobInsertedListener, InsertionEndsListener {
|
||||||
|
|
||||||
static class StatesImpl implements States{
|
private interface States {
|
||||||
|
|
||||||
|
State getState(String key);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StateImpl implements State{
|
||||||
|
double state;
|
||||||
|
|
||||||
|
public StateImpl(double state) {
|
||||||
|
super();
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double toDouble() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StatesImpl implements States{
|
||||||
|
|
||||||
private Map<String,State> states = new HashMap<String, State>();
|
private Map<String,State> states = new HashMap<String, State>();
|
||||||
|
|
||||||
|
|
@ -54,9 +78,9 @@ public class StateManagerImpl implements StateManager, IterationStartsListener,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<VehicleRoute,States> vehicleRouteStates = new HashMap<VehicleRoute, StateManager.States>();
|
private Map<VehicleRoute,States> vehicleRouteStates = new HashMap<VehicleRoute, States>();
|
||||||
|
|
||||||
private Map<TourActivity,States> activityStates = new HashMap<TourActivity, StateManager.States>();
|
private Map<TourActivity,States> activityStates = new HashMap<TourActivity, States>();
|
||||||
|
|
||||||
private RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor();
|
private RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor();
|
||||||
|
|
||||||
|
|
@ -64,6 +88,27 @@ public class StateManagerImpl implements StateManager, IterationStartsListener,
|
||||||
|
|
||||||
private Collection<RouteVisitor> routeVisitors = new ArrayList<RouteVisitor>();
|
private Collection<RouteVisitor> routeVisitors = new ArrayList<RouteVisitor>();
|
||||||
|
|
||||||
|
private RuinListeners ruinListeners = new RuinListeners();
|
||||||
|
|
||||||
|
private InsertionListeners insertionListeners = new InsertionListeners();
|
||||||
|
|
||||||
|
public void addListener(RuinListener ruinListener){
|
||||||
|
ruinListeners.addListener(ruinListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(RuinListener ruinListener){
|
||||||
|
ruinListeners.removeListener(ruinListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListener(InsertionListener insertionListener){
|
||||||
|
insertionListeners.addListener(insertionListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(InsertionListener insertionListener){
|
||||||
|
insertionListeners.removeListener(insertionListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void clear(){
|
public void clear(){
|
||||||
vehicleRouteStates.clear();
|
vehicleRouteStates.clear();
|
||||||
activityStates.clear();
|
activityStates.clear();
|
||||||
|
|
@ -133,6 +178,7 @@ public class StateManagerImpl implements StateManager, IterationStartsListener,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||||
|
insertionListeners.jobInserted(job2insert, inRoute, additionalCosts, additionalTime);
|
||||||
for(RouteVisitor v : routeVisitors){ v.visit(inRoute); }
|
for(RouteVisitor v : routeVisitors){ v.visit(inRoute); }
|
||||||
routeActivityVisitor.visit(inRoute);
|
routeActivityVisitor.visit(inRoute);
|
||||||
revRouteActivityVisitor.visit(inRoute);
|
revRouteActivityVisitor.visit(inRoute);
|
||||||
|
|
@ -140,6 +186,7 @@ public class StateManagerImpl implements StateManager, IterationStartsListener,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes,Collection<Job> unassignedJobs) {
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes,Collection<Job> unassignedJobs) {
|
||||||
|
insertionListeners.insertionStarts(vehicleRoutes, unassignedJobs);
|
||||||
for(VehicleRoute route : vehicleRoutes){
|
for(VehicleRoute route : vehicleRoutes){
|
||||||
for(RouteVisitor v : routeVisitors){ v.visit(route); }
|
for(RouteVisitor v : routeVisitors){ v.visit(route); }
|
||||||
routeActivityVisitor.visit(route);
|
routeActivityVisitor.visit(route);
|
||||||
|
|
@ -147,10 +194,24 @@ public class StateManagerImpl implements StateManager, IterationStartsListener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an activityVisitor.
|
||||||
|
* <p>This visitor visits all activities in a route subsequently in two cases. First, if insertionStart (after ruinStrategies have removed activities from routes)
|
||||||
|
* and, second, if a job has been inserted and thus if a route has changed.
|
||||||
|
*
|
||||||
|
* @param activityVistor
|
||||||
|
*/
|
||||||
public void addActivityVisitor(ActivityVisitor activityVistor){
|
public void addActivityVisitor(ActivityVisitor activityVistor){
|
||||||
routeActivityVisitor.addActivityVisitor(activityVistor);
|
routeActivityVisitor.addActivityVisitor(activityVistor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an reverseActivityVisitor.
|
||||||
|
* <p>This reverseVisitor visits all activities in a route subsequently (starting from the end of the route) in two cases. First, if insertionStart (after ruinStrategies have removed activities from routes)
|
||||||
|
* and, second, if a job has been inserted and thus if a route has changed.
|
||||||
|
*
|
||||||
|
* @param reverseActivityVistor
|
||||||
|
*/
|
||||||
public void addActivityVisitor(ReverseActivityVisitor activityVistor){
|
public void addActivityVisitor(ReverseActivityVisitor activityVistor){
|
||||||
revRouteActivityVisitor.addActivityVisitor(activityVistor);
|
revRouteActivityVisitor.addActivityVisitor(activityVistor);
|
||||||
}
|
}
|
||||||
|
|
@ -166,25 +227,21 @@ public class StateManagerImpl implements StateManager, IterationStartsListener,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void ruinStarts(Collection<VehicleRoute> routes) {
|
public void ruinStarts(Collection<VehicleRoute> routes) {
|
||||||
// TODO Auto-generated method stub
|
ruinListeners.ruinStarts(routes);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||||
// TODO Auto-generated method stub
|
ruinListeners.ruinEnds(routes, unassignedJobs);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removed(Job job, VehicleRoute fromRoute) {
|
public void removed(Job job, VehicleRoute fromRoute) {
|
||||||
// TODO Auto-generated method stub
|
ruinListeners.removed(job, fromRoute);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
|
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
|
||||||
// TODO Auto-generated method stub
|
insertionListeners.insertionEnds(vehicleRoutes);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,20 +20,20 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
class StateTypes {
|
public class StateTypes {
|
||||||
final static String LOAD = "load";
|
public final static String LOAD = "load";
|
||||||
|
|
||||||
final static String LOAD_AT_DEPOT = "loadAtDepot";
|
public final static String LOAD_AT_DEPOT = "loadAtDepot";
|
||||||
|
|
||||||
final static String DURATION = "duration";
|
public final static String DURATION = "duration";
|
||||||
|
|
||||||
final static String LATEST_OPERATION_START_TIME = "latestOST";
|
public final static String LATEST_OPERATION_START_TIME = "latestOST";
|
||||||
|
|
||||||
final static String EARLIEST_OPERATION_START_TIME = "earliestOST";
|
public final static String EARLIEST_OPERATION_START_TIME = "earliestOST";
|
||||||
|
|
||||||
static final String COSTS = "costs";
|
public static final String COSTS = "costs";
|
||||||
|
|
||||||
final static String FUTURE_PICKS = "futurePicks";
|
public final static String FUTURE_PICKS = "futurePicks";
|
||||||
|
|
||||||
final static String PAST_DELIVERIES = "pastDeliveries";
|
public final static String PAST_DELIVERIES = "pastDeliveries";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,636 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* Copyright (C) 2013 Stefan Schroeder
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* Contributors:
|
|
||||||
* Stefan Schroeder - initial API and implementation
|
|
||||||
******************************************************************************/
|
|
||||||
package algorithms;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import algorithms.BackwardInTimeListeners.BackwardInTimeListener;
|
|
||||||
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
|
|
||||||
import algorithms.StateManager.StateImpl;
|
|
||||||
import basics.Delivery;
|
|
||||||
import basics.Job;
|
|
||||||
import basics.Pickup;
|
|
||||||
import basics.Service;
|
|
||||||
import basics.VehicleRoutingProblem;
|
|
||||||
import basics.VehicleRoutingProblemSolution;
|
|
||||||
import basics.algo.InsertionEndsListener;
|
|
||||||
import basics.algo.InsertionStartsListener;
|
|
||||||
import basics.algo.IterationEndsListener;
|
|
||||||
import basics.algo.IterationStartsListener;
|
|
||||||
import basics.algo.JobInsertedListener;
|
|
||||||
import basics.algo.RuinListener;
|
|
||||||
import basics.algo.VehicleRoutingAlgorithmListener;
|
|
||||||
import basics.costs.ForwardTransportCost;
|
|
||||||
import basics.costs.ForwardTransportTime;
|
|
||||||
import basics.costs.VehicleRoutingActivityCosts;
|
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
|
||||||
import basics.route.DeliveryActivity;
|
|
||||||
import basics.route.Driver;
|
|
||||||
import basics.route.End;
|
|
||||||
import basics.route.PickupActivity;
|
|
||||||
import basics.route.ServiceActivity;
|
|
||||||
import basics.route.Start;
|
|
||||||
import basics.route.TourActivity;
|
|
||||||
import basics.route.Vehicle;
|
|
||||||
import basics.route.VehicleRoute;
|
|
||||||
|
|
||||||
class StateUpdates {
|
|
||||||
|
|
||||||
static class UpdateCostsAtRouteLevel implements JobInsertedListener, InsertionStartsListener, InsertionEndsListener{
|
|
||||||
|
|
||||||
private StateManagerImpl states;
|
|
||||||
|
|
||||||
private VehicleRoutingTransportCosts tpCosts;
|
|
||||||
|
|
||||||
private VehicleRoutingActivityCosts actCosts;
|
|
||||||
|
|
||||||
public UpdateCostsAtRouteLevel(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts, VehicleRoutingActivityCosts actCosts) {
|
|
||||||
super();
|
|
||||||
this.states = states;
|
|
||||||
this.tpCosts = tpCosts;
|
|
||||||
this.actCosts = actCosts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
|
||||||
// inRoute.getVehicleRouteCostCalculator().addTransportCost(additionalCosts);
|
|
||||||
double oldCosts = states.getRouteState(inRoute, StateTypes.COSTS).toDouble();
|
|
||||||
oldCosts += additionalCosts;
|
|
||||||
states.putRouteState(inRoute, StateTypes.COSTS, new StateImpl(oldCosts));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
|
||||||
RouteActivityVisitor forwardInTime = new RouteActivityVisitor();
|
|
||||||
forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
|
|
||||||
for(VehicleRoute route : vehicleRoutes){
|
|
||||||
forwardInTime.visit(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
|
|
||||||
|
|
||||||
// IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts);
|
|
||||||
// forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
|
|
||||||
for(VehicleRoute route : vehicleRoutes){
|
|
||||||
if(route.isEmpty()) continue;
|
|
||||||
route.getVehicleRouteCostCalculator().reset();
|
|
||||||
route.getVehicleRouteCostCalculator().addOtherCost(states.getRouteState(route, StateTypes.COSTS).toDouble());
|
|
||||||
route.getVehicleRouteCostCalculator().price(route.getVehicle());
|
|
||||||
// forwardInTime.iterate(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class UpdateActivityTimes implements ActivityVisitor{
|
|
||||||
|
|
||||||
private Logger log = Logger.getLogger(UpdateActivityTimes.class);
|
|
||||||
|
|
||||||
private ActivityTimeTracker timeTracker;
|
|
||||||
|
|
||||||
private VehicleRoute route;
|
|
||||||
|
|
||||||
public UpdateActivityTimes(ForwardTransportTime transportTime) {
|
|
||||||
super();
|
|
||||||
timeTracker = new ActivityTimeTracker(transportTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void begin(VehicleRoute route) {
|
|
||||||
timeTracker.begin(route);
|
|
||||||
this.route = route;
|
|
||||||
route.getStart().setEndTime(timeTracker.getActEndTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(TourActivity activity) {
|
|
||||||
timeTracker.visit(activity);
|
|
||||||
activity.setArrTime(timeTracker.getActArrTime());
|
|
||||||
activity.setEndTime(timeTracker.getActEndTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() {
|
|
||||||
timeTracker.finish();
|
|
||||||
route.getEnd().setArrTime(timeTracker.getActArrTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class UpdateCostsAtAllLevels implements ActivityVisitor{
|
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(UpdateCostsAtAllLevels.class);
|
|
||||||
|
|
||||||
private VehicleRoutingActivityCosts activityCost;
|
|
||||||
|
|
||||||
private ForwardTransportCost transportCost;
|
|
||||||
|
|
||||||
private StateManagerImpl states;
|
|
||||||
|
|
||||||
private double totalOperationCost = 0.0;
|
|
||||||
|
|
||||||
private VehicleRoute vehicleRoute = null;
|
|
||||||
|
|
||||||
private TourActivity prevAct = null;
|
|
||||||
|
|
||||||
private double startTimeAtPrevAct = 0.0;
|
|
||||||
|
|
||||||
private ActivityTimeTracker timeTracker;
|
|
||||||
|
|
||||||
public UpdateCostsAtAllLevels(VehicleRoutingActivityCosts activityCost, VehicleRoutingTransportCosts transportCost, StateManagerImpl states) {
|
|
||||||
super();
|
|
||||||
this.activityCost = activityCost;
|
|
||||||
this.transportCost = transportCost;
|
|
||||||
this.states = states;
|
|
||||||
timeTracker = new ActivityTimeTracker(transportCost);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void begin(VehicleRoute route) {
|
|
||||||
vehicleRoute = route;
|
|
||||||
vehicleRoute.getVehicleRouteCostCalculator().reset();
|
|
||||||
timeTracker.begin(route);
|
|
||||||
prevAct = route.getStart();
|
|
||||||
startTimeAtPrevAct = timeTracker.getActEndTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(TourActivity act) {
|
|
||||||
timeTracker.visit(act);
|
|
||||||
|
|
||||||
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), act.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
|
|
||||||
double actCost = activityCost.getActivityCost(act, timeTracker.getActArrTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle());
|
|
||||||
|
|
||||||
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
|
|
||||||
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
|
|
||||||
|
|
||||||
totalOperationCost += transportCost;
|
|
||||||
totalOperationCost += actCost;
|
|
||||||
|
|
||||||
states.putActivityState(act, StateTypes.COSTS, new StateImpl(totalOperationCost));
|
|
||||||
|
|
||||||
prevAct = act;
|
|
||||||
startTimeAtPrevAct = timeTracker.getActEndTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() {
|
|
||||||
timeTracker.finish();
|
|
||||||
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), vehicleRoute.getEnd().getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
|
|
||||||
double actCost = activityCost.getActivityCost(vehicleRoute.getEnd(), timeTracker.getActEndTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle());
|
|
||||||
|
|
||||||
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
|
|
||||||
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
|
|
||||||
|
|
||||||
totalOperationCost += transportCost;
|
|
||||||
totalOperationCost += actCost;
|
|
||||||
|
|
||||||
states.putRouteState(vehicleRoute, StateTypes.COSTS, new StateImpl(totalOperationCost));
|
|
||||||
|
|
||||||
//this is rather strange and likely to change
|
|
||||||
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver());
|
|
||||||
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle());
|
|
||||||
vehicleRoute.getVehicleRouteCostCalculator().finish();
|
|
||||||
|
|
||||||
startTimeAtPrevAct = 0.0;
|
|
||||||
prevAct = null;
|
|
||||||
vehicleRoute = null;
|
|
||||||
totalOperationCost = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class UpdateEarliestStartTimeWindowAtActLocations implements ActivityVisitor{
|
|
||||||
|
|
||||||
private StateManagerImpl states;
|
|
||||||
|
|
||||||
private ActivityTimeTracker timeTracker;
|
|
||||||
|
|
||||||
public UpdateEarliestStartTimeWindowAtActLocations(StateManagerImpl states, VehicleRoutingTransportCosts transportCosts) {
|
|
||||||
super();
|
|
||||||
this.states = states;
|
|
||||||
timeTracker = new ActivityTimeTracker(transportCosts);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void begin(VehicleRoute route) {
|
|
||||||
timeTracker.begin(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(TourActivity activity) {
|
|
||||||
timeTracker.visit(activity);
|
|
||||||
states.putActivityState(activity, StateTypes.EARLIEST_OPERATION_START_TIME, new StateImpl(Math.max(timeTracker.getActArrTime(), activity.getTheoreticalEarliestOperationStartTime())));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() {}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class UpdateLatestOperationStartTimeAtActLocations implements ReverseActivityVisitor{
|
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(UpdateLatestOperationStartTimeAtActLocations.class);
|
|
||||||
|
|
||||||
private StateManagerImpl states;
|
|
||||||
|
|
||||||
private VehicleRoute route;
|
|
||||||
|
|
||||||
private VehicleRoutingTransportCosts transportCosts;
|
|
||||||
|
|
||||||
private double latestArrTimeAtPrevAct;
|
|
||||||
|
|
||||||
private TourActivity prevAct;
|
|
||||||
|
|
||||||
public UpdateLatestOperationStartTimeAtActLocations(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts) {
|
|
||||||
super();
|
|
||||||
this.states = states;
|
|
||||||
this.transportCosts = tpCosts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void begin(VehicleRoute route) {
|
|
||||||
this.route = route;
|
|
||||||
latestArrTimeAtPrevAct = route.getEnd().getTheoreticalLatestOperationStartTime();
|
|
||||||
prevAct = route.getEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(TourActivity activity) {
|
|
||||||
double potentialLatestArrivalTimeAtCurrAct = latestArrTimeAtPrevAct - transportCosts.getBackwardTransportTime(activity.getLocationId(), prevAct.getLocationId(), latestArrTimeAtPrevAct, route.getDriver(),route.getVehicle()) - activity.getOperationTime();
|
|
||||||
double latestArrivalTime = Math.min(activity.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct);
|
|
||||||
|
|
||||||
states.putActivityState(activity, StateTypes.LATEST_OPERATION_START_TIME, new StateImpl(latestArrivalTime));
|
|
||||||
|
|
||||||
latestArrTimeAtPrevAct = latestArrivalTime;
|
|
||||||
prevAct = activity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class UpdateLoadAtAllLevels implements ActivityVisitor{
|
|
||||||
|
|
||||||
private double load = 0.0;
|
|
||||||
|
|
||||||
private StateManagerImpl states;
|
|
||||||
|
|
||||||
private VehicleRoute vehicleRoute;
|
|
||||||
|
|
||||||
public UpdateLoadAtAllLevels(StateManagerImpl states) {
|
|
||||||
super();
|
|
||||||
this.states = states;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void begin(VehicleRoute route) {
|
|
||||||
vehicleRoute = route;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(TourActivity activity) {
|
|
||||||
load += (double)activity.getCapacityDemand();
|
|
||||||
states.putActivityState(activity, StateTypes.LOAD, new StateImpl(load));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() {
|
|
||||||
states.putRouteState(vehicleRoute, StateTypes.LOAD, new StateImpl(load));
|
|
||||||
load=0;
|
|
||||||
vehicleRoute = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class UpdateLoadAtRouteLevel implements JobInsertedListener, InsertionStartsListener{
|
|
||||||
|
|
||||||
private StateManagerImpl states;
|
|
||||||
|
|
||||||
public UpdateLoadAtRouteLevel(StateManagerImpl states) {
|
|
||||||
super();
|
|
||||||
this.states = states;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
|
||||||
if(!(job2insert instanceof Service)){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
double oldLoad = states.getRouteState(inRoute, StateTypes.LOAD).toDouble();
|
|
||||||
states.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(oldLoad + job2insert.getCapacityDemand()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
|
||||||
for(VehicleRoute route : vehicleRoutes){
|
|
||||||
int load = 0;
|
|
||||||
for(Job j : route.getTourActivities().getJobs()){
|
|
||||||
load += j.getCapacityDemand();
|
|
||||||
}
|
|
||||||
states.putRouteState(route, StateTypes.LOAD, new StateImpl(load));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class UpdateStates implements JobInsertedListener, RuinListener{
|
|
||||||
|
|
||||||
private RouteActivityVisitor routeActivityVisitor;
|
|
||||||
|
|
||||||
private ReverseRouteActivityVisitor revRouteActivityVisitor;
|
|
||||||
|
|
||||||
public UpdateStates(StateManagerImpl states, VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts) {
|
|
||||||
routeActivityVisitor = new RouteActivityVisitor();
|
|
||||||
routeActivityVisitor.addActivityVisitor(new UpdateActivityTimes(routingCosts));
|
|
||||||
routeActivityVisitor.addActivityVisitor(new UpdateCostsAtAllLevels(activityCosts, routingCosts, states));
|
|
||||||
routeActivityVisitor.addActivityVisitor(new UpdateLoadAtAllLevels(states));
|
|
||||||
|
|
||||||
revRouteActivityVisitor = new ReverseRouteActivityVisitor();
|
|
||||||
revRouteActivityVisitor.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(states, routingCosts));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(VehicleRoute route){
|
|
||||||
routeActivityVisitor.visit(route);
|
|
||||||
revRouteActivityVisitor.visit(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
|
||||||
routeActivityVisitor.visit(inRoute);
|
|
||||||
revRouteActivityVisitor.visit(inRoute);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void ruinStarts(Collection<VehicleRoute> routes) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void ruinEnds(Collection<VehicleRoute> routes,Collection<Job> unassignedJobs) {
|
|
||||||
for(VehicleRoute route : routes) {
|
|
||||||
routeActivityVisitor.visit(route);
|
|
||||||
revRouteActivityVisitor.visit(route);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removed(Job job, VehicleRoute fromRoute) {}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class UpdateFuturePickupsAtActivityLevel implements ReverseActivityVisitor {
|
|
||||||
private StateManagerImpl stateManager;
|
|
||||||
private int futurePicks = 0;
|
|
||||||
private VehicleRoute route;
|
|
||||||
|
|
||||||
public UpdateFuturePickupsAtActivityLevel(StateManagerImpl stateManager) {
|
|
||||||
super();
|
|
||||||
this.stateManager = stateManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void begin(VehicleRoute route) {
|
|
||||||
this.route = route;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(TourActivity act) {
|
|
||||||
stateManager.putActivityState(act, StateTypes.FUTURE_PICKS, new StateImpl(futurePicks));
|
|
||||||
if(act instanceof PickupActivity || act instanceof ServiceActivity){
|
|
||||||
futurePicks += act.getCapacityDemand();
|
|
||||||
}
|
|
||||||
assert futurePicks <= route.getVehicle().getCapacity() : "sum of pickups must not be > vehicleCap";
|
|
||||||
assert futurePicks >= 0 : "sum of pickups must not < 0";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() {
|
|
||||||
futurePicks = 0;
|
|
||||||
route = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class UpdateOccuredDeliveriesAtActivityLevel implements ActivityVisitor {
|
|
||||||
private StateManagerImpl stateManager;
|
|
||||||
private int deliveries = 0;
|
|
||||||
private VehicleRoute route;
|
|
||||||
|
|
||||||
public UpdateOccuredDeliveriesAtActivityLevel(StateManagerImpl stateManager) {
|
|
||||||
super();
|
|
||||||
this.stateManager = stateManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void begin(VehicleRoute route) {
|
|
||||||
this.route = route;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(TourActivity act) {
|
|
||||||
if(act instanceof DeliveryActivity){
|
|
||||||
deliveries += Math.abs(act.getCapacityDemand());
|
|
||||||
}
|
|
||||||
stateManager.putActivityState(act, StateTypes.PAST_DELIVERIES, new StateImpl(deliveries));
|
|
||||||
assert deliveries >= 0 : "deliveries < 0";
|
|
||||||
assert deliveries <= route.getVehicle().getCapacity() : "deliveries > vehicleCap";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() {
|
|
||||||
deliveries = 0;
|
|
||||||
route = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates load at activity level. Note that this assumed that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT.
|
|
||||||
* If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot.
|
|
||||||
*
|
|
||||||
* @author stefan
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static class UpdateLoadAtActivityLevel implements ActivityVisitor {
|
|
||||||
private StateManagerImpl stateManager;
|
|
||||||
private int currentLoad = 0;
|
|
||||||
private VehicleRoute route;
|
|
||||||
|
|
||||||
public UpdateLoadAtActivityLevel(StateManagerImpl stateManager) {
|
|
||||||
super();
|
|
||||||
this.stateManager = stateManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void begin(VehicleRoute route) {
|
|
||||||
currentLoad = (int) stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT).toDouble();
|
|
||||||
this.route = route;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(TourActivity act) {
|
|
||||||
currentLoad += act.getCapacityDemand();
|
|
||||||
stateManager.putActivityState(act, StateTypes.LOAD, new StateImpl(currentLoad));
|
|
||||||
assert currentLoad <= route.getVehicle().getCapacity() : "currentLoad at activity must not be > vehicleCapacity";
|
|
||||||
assert currentLoad >= 0 : "currentLoad at act must not be < 0";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() {
|
|
||||||
currentLoad = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ResetStateManager implements IterationStartsListener {
|
|
||||||
|
|
||||||
private StateManagerImpl stateManager;
|
|
||||||
|
|
||||||
public ResetStateManager(StateManagerImpl stateManager) {
|
|
||||||
super();
|
|
||||||
this.stateManager = stateManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
|
||||||
stateManager.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static interface InsertionStarts {
|
|
||||||
|
|
||||||
void insertionStarts(VehicleRoute route);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts implements InsertionStarts {
|
|
||||||
|
|
||||||
private StateManagerImpl stateManager;
|
|
||||||
|
|
||||||
public UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(StateManagerImpl stateManager) {
|
|
||||||
super();
|
|
||||||
this.stateManager = stateManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void insertionStarts(VehicleRoute route) {
|
|
||||||
int loadAtDepot = 0;
|
|
||||||
int loadAtEnd = 0;
|
|
||||||
for(Job j : route.getTourActivities().getJobs()){
|
|
||||||
if(j instanceof Delivery){
|
|
||||||
loadAtDepot += j.getCapacityDemand();
|
|
||||||
}
|
|
||||||
else if(j instanceof Pickup || j instanceof Service){
|
|
||||||
loadAtEnd += j.getCapacityDemand();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stateManager.putRouteState(route, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot));
|
|
||||||
stateManager.putRouteState(route, StateTypes.LOAD, new StateImpl(loadAtEnd));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted implements JobInsertedListener {
|
|
||||||
|
|
||||||
private StateManagerImpl stateManager;
|
|
||||||
|
|
||||||
public UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(StateManagerImpl stateManager) {
|
|
||||||
super();
|
|
||||||
this.stateManager = stateManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
|
||||||
if(job2insert instanceof Delivery){
|
|
||||||
int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD_AT_DEPOT).toDouble();
|
|
||||||
// log.info("loadAtDepot="+loadAtDepot);
|
|
||||||
stateManager.putRouteState(inRoute, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot + job2insert.getCapacityDemand()));
|
|
||||||
}
|
|
||||||
else if(job2insert instanceof Pickup || job2insert instanceof Service){
|
|
||||||
int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD).toDouble();
|
|
||||||
// log.info("loadAtEnd="+loadAtEnd);
|
|
||||||
stateManager.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(loadAtEnd + job2insert.getCapacityDemand()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static class UpdateRouteStatesOnceTheRouteHasBeenChanged implements InsertionStartsListener, JobInsertedListener {
|
|
||||||
|
|
||||||
private RouteActivityVisitor forwardInTimeIterator;
|
|
||||||
|
|
||||||
private ReverseRouteActivityVisitor backwardInTimeIterator;
|
|
||||||
|
|
||||||
private Collection<InsertionStarts> insertionStartsListeners;
|
|
||||||
|
|
||||||
private Collection<JobInsertedListener> jobInsertionListeners;
|
|
||||||
|
|
||||||
public UpdateRouteStatesOnceTheRouteHasBeenChanged(VehicleRoutingTransportCosts routingCosts) {
|
|
||||||
forwardInTimeIterator = new RouteActivityVisitor();
|
|
||||||
backwardInTimeIterator = new ReverseRouteActivityVisitor();
|
|
||||||
insertionStartsListeners = new ArrayList<InsertionStarts>();
|
|
||||||
jobInsertionListeners = new ArrayList<JobInsertedListener>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void addVisitor(ActivityVisitor vis){
|
|
||||||
forwardInTimeIterator.addActivityVisitor(vis);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addVisitor(ReverseActivityVisitor revVis){
|
|
||||||
backwardInTimeIterator.addActivityVisitor(revVis);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addInsertionStartsListener(InsertionStarts insertionStartListener){
|
|
||||||
insertionStartsListeners.add(insertionStartListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addJobInsertedListener(JobInsertedListener jobInsertedListener){
|
|
||||||
jobInsertionListeners.add(jobInsertedListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
|
||||||
for(JobInsertedListener l : jobInsertionListeners){ l.informJobInserted(job2insert, inRoute, additionalCosts, additionalTime); }
|
|
||||||
forwardInTimeIterator.visit(inRoute);
|
|
||||||
backwardInTimeIterator.visit(inRoute);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
|
||||||
for(VehicleRoute route : vehicleRoutes){
|
|
||||||
for(InsertionStarts insertionsStartsHandler : insertionStartsListeners){
|
|
||||||
insertionsStartsHandler.insertionStarts(route);
|
|
||||||
}
|
|
||||||
forwardInTimeIterator.visit(route);
|
|
||||||
backwardInTimeIterator.visit(route);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -24,65 +24,18 @@ import java.util.Collection;
|
||||||
|
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
|
|
||||||
interface VehicleFleetManager {
|
public interface VehicleFleetManager {
|
||||||
|
|
||||||
static class TypeKey {
|
public abstract void lock(Vehicle vehicle);
|
||||||
|
|
||||||
public final String type;
|
public abstract void unlock(Vehicle vehicle);
|
||||||
public final String locationId;
|
|
||||||
|
|
||||||
public TypeKey(String typeId, String locationId) {
|
public abstract boolean isLocked(Vehicle vehicle);
|
||||||
super();
|
|
||||||
this.type = typeId;
|
|
||||||
this.locationId = locationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public abstract void unlockAll();
|
||||||
public int hashCode() {
|
|
||||||
final int prime = 31;
|
|
||||||
int result = 1;
|
|
||||||
result = prime * result
|
|
||||||
+ ((locationId == null) ? 0 : locationId.hashCode());
|
|
||||||
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public abstract Collection<Vehicle> getAvailableVehicles();
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null)
|
|
||||||
return false;
|
|
||||||
if (getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
TypeKey other = (TypeKey) obj;
|
|
||||||
if (locationId == null) {
|
|
||||||
if (other.locationId != null)
|
|
||||||
return false;
|
|
||||||
} else if (!locationId.equals(other.locationId))
|
|
||||||
return false;
|
|
||||||
if (type == null) {
|
|
||||||
if (other.type != null)
|
|
||||||
return false;
|
|
||||||
} else if (!type.equals(other.type))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public Collection<Vehicle> getAvailableVehicles(String withoutThisType, String locationId);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract void lock(Vehicle vehicle);
|
|
||||||
|
|
||||||
abstract void unlock(Vehicle vehicle);
|
|
||||||
|
|
||||||
abstract boolean isLocked(Vehicle vehicle);
|
|
||||||
|
|
||||||
abstract void unlockAll();
|
|
||||||
|
|
||||||
abstract Collection<Vehicle> getAvailableVehicles();
|
|
||||||
|
|
||||||
Collection<Vehicle> getAvailableVehicles(String withoutThisType, String locationId);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package algorithms;
|
||||||
|
|
||||||
|
public interface VehicleFleetManagerFactory {
|
||||||
|
|
||||||
|
public VehicleFleetManager createFleetManager();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -58,11 +58,11 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
|
||||||
|
|
||||||
static class TypeContainer {
|
static class TypeContainer {
|
||||||
|
|
||||||
private TypeKey type;
|
private VehicleTypeKey type;
|
||||||
|
|
||||||
private ArrayList<Vehicle> vehicleList;
|
private ArrayList<Vehicle> vehicleList;
|
||||||
|
|
||||||
public TypeContainer(TypeKey type) {
|
public TypeContainer(VehicleTypeKey type) {
|
||||||
super();
|
super();
|
||||||
this.type = type;
|
this.type = type;
|
||||||
vehicleList = new ArrayList<Vehicle>();
|
vehicleList = new ArrayList<Vehicle>();
|
||||||
|
|
@ -96,9 +96,9 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
|
||||||
|
|
||||||
private Set<Vehicle> lockedVehicles;
|
private Set<Vehicle> lockedVehicles;
|
||||||
|
|
||||||
private Map<TypeKey,TypeContainer> typeMapOfAvailableVehicles;
|
private Map<VehicleTypeKey,TypeContainer> typeMapOfAvailableVehicles;
|
||||||
|
|
||||||
private Map<TypeKey,Vehicle> penaltyVehicles = new HashMap<VehicleFleetManager.TypeKey, Vehicle>();
|
private Map<VehicleTypeKey,Vehicle> penaltyVehicles = new HashMap<VehicleTypeKey, Vehicle>();
|
||||||
|
|
||||||
// private Map<TypeKey,TypeContainer> typeMapOfAvailablePenaltyVehicles;
|
// private Map<TypeKey,TypeContainer> typeMapOfAvailablePenaltyVehicles;
|
||||||
|
|
||||||
|
|
@ -126,8 +126,8 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void makeMap() {
|
private void makeMap() {
|
||||||
typeMapOfAvailableVehicles = new HashMap<TypeKey, TypeContainer>();
|
typeMapOfAvailableVehicles = new HashMap<VehicleTypeKey, TypeContainer>();
|
||||||
penaltyVehicles = new HashMap<VehicleFleetManager.TypeKey, Vehicle>();
|
penaltyVehicles = new HashMap<VehicleTypeKey, Vehicle>();
|
||||||
for(Vehicle v : vehicles){
|
for(Vehicle v : vehicles){
|
||||||
addVehicle(v);
|
addVehicle(v);
|
||||||
}
|
}
|
||||||
|
|
@ -139,11 +139,11 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
|
||||||
}
|
}
|
||||||
String typeId = v.getType().getTypeId();
|
String typeId = v.getType().getTypeId();
|
||||||
if(v.getType() instanceof PenaltyVehicleType){
|
if(v.getType() instanceof PenaltyVehicleType){
|
||||||
TypeKey typeKey = new TypeKey(typeId,v.getLocationId());
|
VehicleTypeKey typeKey = new VehicleTypeKey(typeId,v.getLocationId());
|
||||||
penaltyVehicles.put(typeKey, v);
|
penaltyVehicles.put(typeKey, v);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
TypeKey typeKey = new TypeKey(v.getType().getTypeId(),v.getLocationId());
|
VehicleTypeKey typeKey = new VehicleTypeKey(v.getType().getTypeId(),v.getLocationId());
|
||||||
if(!typeMapOfAvailableVehicles.containsKey(typeKey)){
|
if(!typeMapOfAvailableVehicles.containsKey(typeKey)){
|
||||||
typeMapOfAvailableVehicles.put(typeKey, new TypeContainer(typeKey));
|
typeMapOfAvailableVehicles.put(typeKey, new TypeContainer(typeKey));
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +154,7 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
|
||||||
private void removeVehicle(Vehicle v){
|
private void removeVehicle(Vehicle v){
|
||||||
//it might be better to introduce a class PenaltyVehicle
|
//it might be better to introduce a class PenaltyVehicle
|
||||||
if(!(v.getType() instanceof PenaltyVehicleType)){
|
if(!(v.getType() instanceof PenaltyVehicleType)){
|
||||||
TypeKey key = new TypeKey(v.getType().getTypeId(),v.getLocationId());
|
VehicleTypeKey key = new VehicleTypeKey(v.getType().getTypeId(),v.getLocationId());
|
||||||
if(typeMapOfAvailableVehicles.containsKey(key)){
|
if(typeMapOfAvailableVehicles.containsKey(key)){
|
||||||
typeMapOfAvailableVehicles.get(key).remove(v);
|
typeMapOfAvailableVehicles.get(key).remove(v);
|
||||||
}
|
}
|
||||||
|
|
@ -171,7 +171,7 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
|
||||||
@Override
|
@Override
|
||||||
public Collection<Vehicle> getAvailableVehicles() {
|
public Collection<Vehicle> getAvailableVehicles() {
|
||||||
List<Vehicle> vehicles = new ArrayList<Vehicle>();
|
List<Vehicle> vehicles = new ArrayList<Vehicle>();
|
||||||
for(TypeKey key : typeMapOfAvailableVehicles.keySet()){
|
for(VehicleTypeKey key : typeMapOfAvailableVehicles.keySet()){
|
||||||
if(!typeMapOfAvailableVehicles.get(key).isEmpty()){
|
if(!typeMapOfAvailableVehicles.get(key).isEmpty()){
|
||||||
vehicles.add(typeMapOfAvailableVehicles.get(key).getVehicle());
|
vehicles.add(typeMapOfAvailableVehicles.get(key).getVehicle());
|
||||||
}
|
}
|
||||||
|
|
@ -197,8 +197,8 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
|
||||||
@Override
|
@Override
|
||||||
public Collection<Vehicle> getAvailableVehicles(String withoutThisType, String withThisLocationId) {
|
public Collection<Vehicle> getAvailableVehicles(String withoutThisType, String withThisLocationId) {
|
||||||
List<Vehicle> vehicles = new ArrayList<Vehicle>();
|
List<Vehicle> vehicles = new ArrayList<Vehicle>();
|
||||||
TypeKey thisKey = new TypeKey(withoutThisType,withThisLocationId);
|
VehicleTypeKey thisKey = new VehicleTypeKey(withoutThisType,withThisLocationId);
|
||||||
for(TypeKey key : typeMapOfAvailableVehicles.keySet()){
|
for(VehicleTypeKey key : typeMapOfAvailableVehicles.keySet()){
|
||||||
if(key.equals(thisKey)) continue;
|
if(key.equals(thisKey)) continue;
|
||||||
if(!typeMapOfAvailableVehicles.get(key).isEmpty()){
|
if(!typeMapOfAvailableVehicles.get(key).isEmpty()){
|
||||||
vehicles.add(typeMapOfAvailableVehicles.get(key).getVehicle());
|
vehicles.add(typeMapOfAvailableVehicles.get(key).getVehicle());
|
||||||
|
|
|
||||||
|
|
@ -35,13 +35,6 @@ import org.apache.commons.configuration.HierarchicalConfiguration;
|
||||||
import org.apache.commons.configuration.XMLConfiguration;
|
import org.apache.commons.configuration.XMLConfiguration;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import algorithms.HardConstraints.ConstraintManager;
|
|
||||||
import algorithms.HardConstraints.HardTimeWindowActivityLevelConstraint;
|
|
||||||
import algorithms.StateUpdates.UpdateActivityTimes;
|
|
||||||
import algorithms.StateUpdates.UpdateCostsAtAllLevels;
|
|
||||||
import algorithms.StateUpdates.UpdateEarliestStartTimeWindowAtActLocations;
|
|
||||||
import algorithms.StateUpdates.UpdateLatestOperationStartTimeAtActLocations;
|
|
||||||
import algorithms.StateUpdates.UpdateStates;
|
|
||||||
import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractKey;
|
import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractKey;
|
||||||
import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
|
import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
|
||||||
import algorithms.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey;
|
import algorithms.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey;
|
||||||
|
|
@ -52,9 +45,22 @@ import algorithms.acceptors.AcceptNewIfBetterThanWorst;
|
||||||
import algorithms.acceptors.AcceptNewRemoveFirst;
|
import algorithms.acceptors.AcceptNewRemoveFirst;
|
||||||
import algorithms.acceptors.SchrimpfAcceptance;
|
import algorithms.acceptors.SchrimpfAcceptance;
|
||||||
import algorithms.acceptors.SolutionAcceptor;
|
import algorithms.acceptors.SolutionAcceptor;
|
||||||
|
import algorithms.constraints.ConstraintManager;
|
||||||
|
import algorithms.constraints.HardPickupAndDeliveryActivityLevelConstraint;
|
||||||
|
import algorithms.constraints.HardPickupAndDeliveryBackhaulActivityLevelConstraint;
|
||||||
|
import algorithms.constraints.HardPickupAndDeliveryLoadConstraint;
|
||||||
|
import algorithms.constraints.HardTimeWindowActivityLevelConstraint;
|
||||||
import algorithms.selectors.SelectBest;
|
import algorithms.selectors.SelectBest;
|
||||||
import algorithms.selectors.SelectRandomly;
|
import algorithms.selectors.SelectRandomly;
|
||||||
import algorithms.selectors.SolutionSelector;
|
import algorithms.selectors.SolutionSelector;
|
||||||
|
import algorithms.states.InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts;
|
||||||
|
import algorithms.states.UpdateActivityTimes;
|
||||||
|
import algorithms.states.UpdateCostsAtAllLevels;
|
||||||
|
import algorithms.states.UpdateFuturePickupsAtActivityLevel;
|
||||||
|
import algorithms.states.UpdateLatestOperationStartTimeAtActLocations;
|
||||||
|
import algorithms.states.UpdateLoadAtActivityLevel;
|
||||||
|
import algorithms.states.UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted;
|
||||||
|
import algorithms.states.UpdateOccuredDeliveriesAtActivityLevel;
|
||||||
import basics.VehicleRoutingAlgorithm;
|
import basics.VehicleRoutingAlgorithm;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblem.Constraint;
|
import basics.VehicleRoutingProblem.Constraint;
|
||||||
|
|
@ -451,16 +457,16 @@ public class VehicleRoutingAlgorithms {
|
||||||
*/
|
*/
|
||||||
//constraint manager
|
//constraint manager
|
||||||
ConstraintManager constraintManager = new ConstraintManager();
|
ConstraintManager constraintManager = new ConstraintManager();
|
||||||
constraintManager.addConstraint(new HardConstraints.HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts()));
|
constraintManager.addConstraint(new HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts()));
|
||||||
|
|
||||||
if(vrp.getProblemConstraints().contains(Constraint.DELIVERIES_FIRST)){
|
if(vrp.getProblemConstraints().contains(Constraint.DELIVERIES_FIRST)){
|
||||||
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager));
|
constraintManager.addConstraint(new HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryActivityLevelConstraint(stateManager));
|
constraintManager.addConstraint(new HardPickupAndDeliveryActivityLevelConstraint(stateManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryLoadConstraint(stateManager));
|
constraintManager.addConstraint(new HardPickupAndDeliveryLoadConstraint(stateManager));
|
||||||
|
|
||||||
//construct initial solution creator
|
//construct initial solution creator
|
||||||
AlgorithmStartsListener createInitialSolution = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,constraintManager);
|
AlgorithmStartsListener createInitialSolution = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,constraintManager);
|
||||||
|
|
@ -498,23 +504,38 @@ public class VehicleRoutingAlgorithms {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//reset stateManager
|
//reset stateManager
|
||||||
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new StateUpdates.ResetStateManager(stateManager)));
|
// algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new StateUpdates.ResetStateManager(stateManager)));
|
||||||
//update states
|
//update states
|
||||||
// metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateStates(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts()));
|
// metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateStates(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts()));
|
||||||
StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged routeChangedListener = new StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged(vrp.getTransportCosts());
|
// UpdateRouteStatesOnceTheRouteHasBeenChanged routeChangedListener = new StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged(vrp.getTransportCosts());
|
||||||
|
//
|
||||||
|
// routeChangedListener.addInsertionStartsListener(new InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts.UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager));
|
||||||
|
// routeChangedListener.addJobInsertedListener(new UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager));
|
||||||
|
//
|
||||||
|
// routeChangedListener.addVisitor(new StateUpdates.UpdateActivityTimes(vrp.getTransportCosts()));
|
||||||
|
// routeChangedListener.addVisitor(new StateUpdates.UpdateLoadAtActivityLevel(stateManager));
|
||||||
|
// routeChangedListener.addVisitor(new StateUpdates.UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
|
||||||
|
//
|
||||||
|
// routeChangedListener.addVisitor(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager));
|
||||||
|
// routeChangedListener.addVisitor(new StateUpdates.UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
|
||||||
|
// routeChangedListener.addVisitor(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager));
|
||||||
|
|
||||||
routeChangedListener.addInsertionStartsListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager));
|
stateManager.addListener(new InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager));
|
||||||
routeChangedListener.addJobInsertedListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager));
|
stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager));
|
||||||
|
|
||||||
routeChangedListener.addVisitor(new StateUpdates.UpdateActivityTimes(vrp.getTransportCosts()));
|
stateManager.addActivityVisitor(new UpdateActivityTimes(vrp.getTransportCosts()));
|
||||||
routeChangedListener.addVisitor(new StateUpdates.UpdateLoadAtActivityLevel(stateManager));
|
stateManager.addActivityVisitor(new UpdateLoadAtActivityLevel(stateManager));
|
||||||
routeChangedListener.addVisitor(new StateUpdates.UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
|
|
||||||
|
|
||||||
routeChangedListener.addVisitor(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager));
|
stateManager.addActivityVisitor(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
|
||||||
routeChangedListener.addVisitor(new StateUpdates.UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
|
|
||||||
routeChangedListener.addVisitor(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager));
|
stateManager.addActivityVisitor(new UpdateOccuredDeliveriesAtActivityLevel(stateManager));
|
||||||
|
stateManager.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
|
||||||
|
stateManager.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager));
|
||||||
|
|
||||||
|
|
||||||
|
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(stateManager);
|
||||||
|
metaAlgorithm.getAlgorithmListeners().addListener(stateManager);
|
||||||
|
|
||||||
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(routeChangedListener);
|
|
||||||
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(vehicleFleetManager));
|
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(vehicleFleetManager));
|
||||||
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new ResetAndIniFleetManager(vehicleFleetManager));
|
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new ResetAndIniFleetManager(vehicleFleetManager));
|
||||||
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new VehicleSwitched(vehicleFleetManager));
|
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new VehicleSwitched(vehicleFleetManager));
|
||||||
|
|
@ -637,9 +658,9 @@ public class VehicleRoutingAlgorithms {
|
||||||
@Override
|
@Override
|
||||||
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||||
|
|
||||||
CreateInitialSolution createInitialSolution = new CreateInitialSolution(finalInsertionStrategy);
|
BestInsertionInitialSolutionFactory createInitialSolution = new BestInsertionInitialSolutionFactory(finalInsertionStrategy);
|
||||||
createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false);
|
createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false);
|
||||||
VehicleRoutingProblemSolution vrpSol = createInitialSolution.createInitialSolution(vrp);
|
VehicleRoutingProblemSolution vrpSol = createInitialSolution.createSolution(vrp);
|
||||||
solutions.add(vrpSol);
|
solutions.add(vrpSol);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -836,4 +857,6 @@ public class VehicleRoutingAlgorithms {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
48
jsprit-core/src/main/java/algorithms/VehicleTypeKey.java
Normal file
48
jsprit-core/src/main/java/algorithms/VehicleTypeKey.java
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
package algorithms;
|
||||||
|
|
||||||
|
class VehicleTypeKey {
|
||||||
|
|
||||||
|
public final String type;
|
||||||
|
public final String locationId;
|
||||||
|
|
||||||
|
VehicleTypeKey(String typeId, String locationId) {
|
||||||
|
super();
|
||||||
|
this.type = typeId;
|
||||||
|
this.locationId = locationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result
|
||||||
|
+ ((locationId == null) ? 0 : locationId.hashCode());
|
||||||
|
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
VehicleTypeKey other = (VehicleTypeKey) obj;
|
||||||
|
if (locationId == null) {
|
||||||
|
if (other.locationId != null)
|
||||||
|
return false;
|
||||||
|
} else if (!locationId.equals(other.locationId))
|
||||||
|
return false;
|
||||||
|
if (type == null) {
|
||||||
|
if (other.type != null)
|
||||||
|
return false;
|
||||||
|
} else if (!type.equals(other.type))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package algorithms.constraints;
|
||||||
|
|
||||||
|
import algorithms.InsertionContext;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
|
||||||
|
public class ConstraintManager implements HardActivityLevelConstraint, HardRouteLevelConstraint{
|
||||||
|
|
||||||
|
private HardActivityLevelConstraintManager actLevelConstraintManager = new HardActivityLevelConstraintManager();
|
||||||
|
|
||||||
|
private HardRouteLevelConstraintManager routeLevelConstraintManager = new HardRouteLevelConstraintManager();
|
||||||
|
|
||||||
|
public void addConstraint(HardActivityLevelConstraint actLevelConstraint){
|
||||||
|
actLevelConstraintManager.addConstraint(actLevelConstraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConstraint(HardRouteLevelConstraint routeLevelConstraint){
|
||||||
|
routeLevelConstraintManager.addConstraint(routeLevelConstraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean fulfilled(InsertionContext insertionContext) {
|
||||||
|
return routeLevelConstraintManager.fulfilled(insertionContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
|
||||||
|
return actLevelConstraintManager.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package algorithms.constraints;
|
||||||
|
|
||||||
|
import algorithms.InsertionContext;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
|
||||||
|
public interface HardActivityLevelConstraint {
|
||||||
|
|
||||||
|
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package algorithms.constraints;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import algorithms.InsertionContext;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
|
||||||
|
class HardActivityLevelConstraintManager implements HardActivityLevelConstraint {
|
||||||
|
|
||||||
|
private Collection<HardActivityLevelConstraint> hardConstraints = new ArrayList<HardActivityLevelConstraint>();
|
||||||
|
|
||||||
|
public void addConstraint(HardActivityLevelConstraint constraint){
|
||||||
|
hardConstraints.add(constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2013 Stefan Schroeder
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Stefan Schroeder - initial API and implementation
|
||||||
|
******************************************************************************/
|
||||||
|
package algorithms.constraints;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* collection of hard constrainters bot at activity and at route level.
|
||||||
|
*
|
||||||
|
* <p>HardPickupAndDeliveryLoadConstraint requires LOAD_AT_DEPOT and LOAD (i.e. load at end) at route-level
|
||||||
|
*
|
||||||
|
* <p>HardTimeWindowConstraint requires LATEST_OPERATION_START_TIME
|
||||||
|
*
|
||||||
|
* <p>HardPickupAndDeliveryConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level
|
||||||
|
*
|
||||||
|
* <p>HardPickupAndDeliveryBackhaulConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level
|
||||||
|
*
|
||||||
|
* @author stefan
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class HardConstraints {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package algorithms.constraints;
|
||||||
|
|
||||||
|
import algorithms.InsertionContext;
|
||||||
|
import algorithms.StateManager;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.Service;
|
||||||
|
|
||||||
|
public class HardLoadConstraint implements HardRouteLevelConstraint{
|
||||||
|
|
||||||
|
private StateManager states;
|
||||||
|
|
||||||
|
public HardLoadConstraint(StateManager states) {
|
||||||
|
super();
|
||||||
|
this.states = states;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean fulfilled(InsertionContext insertionContext) {
|
||||||
|
int currentLoad = (int) states.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble();
|
||||||
|
Service service = (Service) insertionContext.getJob();
|
||||||
|
if(currentLoad + service.getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package algorithms.constraints;
|
||||||
|
|
||||||
|
import algorithms.InsertionContext;
|
||||||
|
import algorithms.StateManager;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.route.DeliveryActivity;
|
||||||
|
import basics.route.PickupActivity;
|
||||||
|
import basics.route.ServiceActivity;
|
||||||
|
import basics.route.Start;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
|
||||||
|
public class HardPickupAndDeliveryActivityLevelConstraint implements HardActivityLevelConstraint {
|
||||||
|
|
||||||
|
private StateManager stateManager;
|
||||||
|
|
||||||
|
public HardPickupAndDeliveryActivityLevelConstraint(StateManager stateManager) {
|
||||||
|
super();
|
||||||
|
this.stateManager = stateManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
|
||||||
|
int loadAtPrevAct;
|
||||||
|
int futurePicks;
|
||||||
|
int pastDeliveries;
|
||||||
|
if(prevAct instanceof Start){
|
||||||
|
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
|
||||||
|
futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble();
|
||||||
|
pastDeliveries = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateTypes.LOAD).toDouble();
|
||||||
|
futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble();
|
||||||
|
pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble();
|
||||||
|
}
|
||||||
|
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
|
||||||
|
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(newAct instanceof DeliveryActivity){
|
||||||
|
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
package algorithms.constraints;
|
||||||
|
|
||||||
|
import algorithms.InsertionContext;
|
||||||
|
import algorithms.StateManager;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.route.DeliveryActivity;
|
||||||
|
import basics.route.PickupActivity;
|
||||||
|
import basics.route.ServiceActivity;
|
||||||
|
import basics.route.Start;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
|
||||||
|
public class HardPickupAndDeliveryBackhaulActivityLevelConstraint implements HardActivityLevelConstraint {
|
||||||
|
|
||||||
|
private StateManager stateManager;
|
||||||
|
|
||||||
|
public HardPickupAndDeliveryBackhaulActivityLevelConstraint(StateManager stateManager) {
|
||||||
|
super();
|
||||||
|
this.stateManager = stateManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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; }
|
||||||
|
int loadAtPrevAct;
|
||||||
|
int futurePicks;
|
||||||
|
int pastDeliveries;
|
||||||
|
if(prevAct instanceof Start){
|
||||||
|
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
|
||||||
|
futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble();
|
||||||
|
pastDeliveries = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateTypes.LOAD).toDouble();
|
||||||
|
futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble();
|
||||||
|
pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble();
|
||||||
|
}
|
||||||
|
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
|
||||||
|
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(newAct instanceof DeliveryActivity){
|
||||||
|
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package algorithms.constraints;
|
||||||
|
|
||||||
|
import algorithms.InsertionContext;
|
||||||
|
import algorithms.StateManager;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.Delivery;
|
||||||
|
import basics.Pickup;
|
||||||
|
import basics.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lsjdfjsdlfjsa
|
||||||
|
*
|
||||||
|
* @author stefan
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class HardPickupAndDeliveryLoadConstraint implements HardRouteLevelConstraint {
|
||||||
|
|
||||||
|
private StateManager stateManager;
|
||||||
|
|
||||||
|
public HardPickupAndDeliveryLoadConstraint(StateManager stateManager) {
|
||||||
|
super();
|
||||||
|
this.stateManager = stateManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean fulfilled(InsertionContext insertionContext) {
|
||||||
|
if(insertionContext.getJob() instanceof Delivery){
|
||||||
|
int loadAtDepot = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
|
||||||
|
if(loadAtDepot + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(insertionContext.getJob() instanceof Pickup || insertionContext.getJob() instanceof Service){
|
||||||
|
int loadAtEnd = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble();
|
||||||
|
if(loadAtEnd + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package algorithms.constraints;
|
||||||
|
|
||||||
|
import algorithms.InsertionContext;
|
||||||
|
|
||||||
|
public interface HardRouteLevelConstraint {
|
||||||
|
|
||||||
|
public boolean fulfilled(InsertionContext insertionContext);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package algorithms.constraints;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import algorithms.InsertionContext;
|
||||||
|
|
||||||
|
class HardRouteLevelConstraintManager implements HardRouteLevelConstraint {
|
||||||
|
|
||||||
|
private Collection<HardRouteLevelConstraint> hardConstraints = new ArrayList<HardRouteLevelConstraint>();
|
||||||
|
|
||||||
|
public void addConstraint(HardRouteLevelConstraint constraint){
|
||||||
|
hardConstraints.add(constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean fulfilled(InsertionContext insertionContext) {
|
||||||
|
for(HardRouteLevelConstraint constraint : hardConstraints){
|
||||||
|
if(!constraint.fulfilled(insertionContext)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package algorithms.constraints;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import algorithms.CalculationUtils;
|
||||||
|
import algorithms.InsertionContext;
|
||||||
|
import algorithms.StateManager;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ljsljslfjs
|
||||||
|
* @author stefan
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class HardTimeWindowActivityLevelConstraint implements HardActivityLevelConstraint {
|
||||||
|
|
||||||
|
private static Logger log = Logger.getLogger(HardTimeWindowActivityLevelConstraint.class);
|
||||||
|
|
||||||
|
private StateManager states;
|
||||||
|
|
||||||
|
private VehicleRoutingTransportCosts routingCosts;
|
||||||
|
|
||||||
|
public HardTimeWindowActivityLevelConstraint(StateManager states, VehicleRoutingTransportCosts routingCosts) {
|
||||||
|
super();
|
||||||
|
this.states = states;
|
||||||
|
this.routingCosts = routingCosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||||
|
double latestArrTimeAtNewAct = states.getActivityState(newAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble();
|
||||||
|
if(arrTimeAtNewAct > latestArrTimeAtNewAct){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 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, StateTypes.LATEST_OPERATION_START_TIME).toDouble();
|
||||||
|
if(arrTimeAtNextAct > latestArrTimeAtNextAct){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// log.info(nextAct + " arrTime=" + arrTimeAtNextAct);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package algorithms;
|
package algorithms.states;
|
||||||
|
|
||||||
|
import algorithms.ActivityVisitor;
|
||||||
import basics.costs.ForwardTransportTime;
|
import basics.costs.ForwardTransportTime;
|
||||||
import basics.route.Driver;
|
import basics.route.Driver;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import algorithms.StateManagerImpl;
|
||||||
|
import algorithms.StateManagerImpl.StateImpl;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.Delivery;
|
||||||
|
import basics.Job;
|
||||||
|
import basics.Pickup;
|
||||||
|
import basics.Service;
|
||||||
|
import basics.algo.InsertionStartsListener;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the load of each route/vehicle at start- and end-location before insertion starts.
|
||||||
|
*
|
||||||
|
* <p>StateTypes.LOAD_AT_DEPOT and StateTypes.LOAD are modified for each route
|
||||||
|
* <p>These states can be retrieved by <br>
|
||||||
|
* stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT) for LOAD_AT_DEPOT and <br>
|
||||||
|
* stateManager.getRouteState(route, StateTypes.LOAD) for LOAD (i.e. load at end)
|
||||||
|
*
|
||||||
|
* @param stateManager
|
||||||
|
*/
|
||||||
|
public class InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts implements InsertionStartsListener {
|
||||||
|
|
||||||
|
private StateManagerImpl stateManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the load of each route/vehicle at start- and end-location before insertion starts.
|
||||||
|
*
|
||||||
|
* <p>StateTypes.LOAD_AT_DEPOT and StateTypes.LOAD are modified for each route
|
||||||
|
* <p>These states can be retrieved by <br>
|
||||||
|
* stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT) for LOAD_AT_DEPOT and <br>
|
||||||
|
* stateManager.getRouteState(route, StateTypes.LOAD) for LOAD (i.e. load at end)
|
||||||
|
*
|
||||||
|
* @param stateManager
|
||||||
|
*/
|
||||||
|
public InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts(StateManagerImpl stateManager) {
|
||||||
|
super();
|
||||||
|
this.stateManager = stateManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
void insertionStarts(VehicleRoute route) {
|
||||||
|
int loadAtDepot = 0;
|
||||||
|
int loadAtEnd = 0;
|
||||||
|
for(Job j : route.getTourActivities().getJobs()){
|
||||||
|
if(j instanceof Delivery){
|
||||||
|
loadAtDepot += j.getCapacityDemand();
|
||||||
|
}
|
||||||
|
else if(j instanceof Pickup || j instanceof Service){
|
||||||
|
loadAtEnd += j.getCapacityDemand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stateManager.putRouteState(route, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot));
|
||||||
|
stateManager.putRouteState(route, StateTypes.LOAD, new StateImpl(loadAtEnd));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
|
for(VehicleRoute route : vehicleRoutes){ insertionStarts(route); }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
162
jsprit-core/src/main/java/algorithms/states/StateUpdates.java
Normal file
162
jsprit-core/src/main/java/algorithms/states/StateUpdates.java
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2013 Stefan Schroeder
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Stefan Schroeder - initial API and implementation
|
||||||
|
******************************************************************************/
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
|
||||||
|
import algorithms.ActivityVisitor;
|
||||||
|
import algorithms.ReverseActivityVisitor;
|
||||||
|
import algorithms.ReverseRouteActivityVisitor;
|
||||||
|
import algorithms.RouteActivityVisitor;
|
||||||
|
import algorithms.StateManagerImpl;
|
||||||
|
import basics.Job;
|
||||||
|
import basics.VehicleRoutingProblem;
|
||||||
|
import basics.VehicleRoutingProblemSolution;
|
||||||
|
import basics.algo.InsertionStartsListener;
|
||||||
|
import basics.algo.IterationStartsListener;
|
||||||
|
import basics.algo.JobInsertedListener;
|
||||||
|
import basics.algo.RuinListener;
|
||||||
|
import basics.costs.VehicleRoutingActivityCosts;
|
||||||
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
public class StateUpdates {
|
||||||
|
|
||||||
|
public static class UpdateStates implements JobInsertedListener, RuinListener{
|
||||||
|
|
||||||
|
private RouteActivityVisitor routeActivityVisitor;
|
||||||
|
|
||||||
|
private ReverseRouteActivityVisitor revRouteActivityVisitor;
|
||||||
|
|
||||||
|
public UpdateStates(StateManagerImpl states, VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts) {
|
||||||
|
routeActivityVisitor = new RouteActivityVisitor();
|
||||||
|
routeActivityVisitor.addActivityVisitor(new UpdateActivityTimes(routingCosts));
|
||||||
|
routeActivityVisitor.addActivityVisitor(new UpdateCostsAtAllLevels(activityCosts, routingCosts, states));
|
||||||
|
routeActivityVisitor.addActivityVisitor(new UpdateLoadAtAllLevels(states));
|
||||||
|
|
||||||
|
revRouteActivityVisitor = new ReverseRouteActivityVisitor();
|
||||||
|
revRouteActivityVisitor.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(states, routingCosts));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(VehicleRoute route){
|
||||||
|
routeActivityVisitor.visit(route);
|
||||||
|
revRouteActivityVisitor.visit(route);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||||
|
routeActivityVisitor.visit(inRoute);
|
||||||
|
revRouteActivityVisitor.visit(inRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ruinStarts(Collection<VehicleRoute> routes) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ruinEnds(Collection<VehicleRoute> routes,Collection<Job> unassignedJobs) {
|
||||||
|
for(VehicleRoute route : routes) {
|
||||||
|
routeActivityVisitor.visit(route);
|
||||||
|
revRouteActivityVisitor.visit(route);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removed(Job job, VehicleRoute fromRoute) {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ResetStateManager implements IterationStartsListener {
|
||||||
|
|
||||||
|
private StateManagerImpl stateManager;
|
||||||
|
|
||||||
|
public ResetStateManager(StateManagerImpl stateManager) {
|
||||||
|
super();
|
||||||
|
this.stateManager = stateManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||||
|
stateManager.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static interface InsertionStarts {
|
||||||
|
|
||||||
|
void insertionStarts(VehicleRoute route);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class UpdateRouteStatesOnceTheRouteHasBeenChanged implements InsertionStartsListener, JobInsertedListener {
|
||||||
|
|
||||||
|
private RouteActivityVisitor forwardInTimeIterator;
|
||||||
|
|
||||||
|
private ReverseRouteActivityVisitor backwardInTimeIterator;
|
||||||
|
|
||||||
|
private Collection<InsertionStarts> insertionStartsListeners;
|
||||||
|
|
||||||
|
private Collection<JobInsertedListener> jobInsertionListeners;
|
||||||
|
|
||||||
|
public UpdateRouteStatesOnceTheRouteHasBeenChanged(VehicleRoutingTransportCosts routingCosts) {
|
||||||
|
forwardInTimeIterator = new RouteActivityVisitor();
|
||||||
|
backwardInTimeIterator = new ReverseRouteActivityVisitor();
|
||||||
|
insertionStartsListeners = new ArrayList<InsertionStarts>();
|
||||||
|
jobInsertionListeners = new ArrayList<JobInsertedListener>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addVisitor(ActivityVisitor vis){
|
||||||
|
forwardInTimeIterator.addActivityVisitor(vis);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addVisitor(ReverseActivityVisitor revVis){
|
||||||
|
backwardInTimeIterator.addActivityVisitor(revVis);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addInsertionStartsListener(InsertionStarts insertionStartListener){
|
||||||
|
insertionStartsListeners.add(insertionStartListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addJobInsertedListener(JobInsertedListener jobInsertedListener){
|
||||||
|
jobInsertionListeners.add(jobInsertedListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||||
|
for(JobInsertedListener l : jobInsertionListeners){ l.informJobInserted(job2insert, inRoute, additionalCosts, additionalTime); }
|
||||||
|
forwardInTimeIterator.visit(inRoute);
|
||||||
|
backwardInTimeIterator.visit(inRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
|
for(VehicleRoute route : vehicleRoutes){
|
||||||
|
for(InsertionStarts insertionsStartsHandler : insertionStartsListeners){
|
||||||
|
insertionsStartsHandler.insertionStarts(route);
|
||||||
|
}
|
||||||
|
forwardInTimeIterator.visit(route);
|
||||||
|
backwardInTimeIterator.visit(route);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import algorithms.ActivityVisitor;
|
||||||
|
import basics.costs.ForwardTransportTime;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 UpdateActivityTimes implements ActivityVisitor{
|
||||||
|
|
||||||
|
private Logger log = Logger.getLogger(UpdateActivityTimes.class);
|
||||||
|
|
||||||
|
private ActivityTimeTracker timeTracker;
|
||||||
|
|
||||||
|
private VehicleRoute route;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates arrival and end times of activities.
|
||||||
|
*
|
||||||
|
* <p>Note that this modifies arrTime and endTime of each activity in a route.
|
||||||
|
*
|
||||||
|
* <p>ArrTimes and EndTimes can be retrieved by <br>
|
||||||
|
* <code>activity.getArrTime()</code> and
|
||||||
|
* <code>activity.getEndTime()</code>
|
||||||
|
*
|
||||||
|
* @author stefan
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public UpdateActivityTimes(ForwardTransportTime transportTime) {
|
||||||
|
super();
|
||||||
|
timeTracker = new ActivityTimeTracker(transportTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void begin(VehicleRoute route) {
|
||||||
|
timeTracker.begin(route);
|
||||||
|
this.route = route;
|
||||||
|
route.getStart().setEndTime(timeTracker.getActEndTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TourActivity activity) {
|
||||||
|
timeTracker.visit(activity);
|
||||||
|
activity.setArrTime(timeTracker.getActArrTime());
|
||||||
|
activity.setEndTime(timeTracker.getActEndTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {
|
||||||
|
timeTracker.finish();
|
||||||
|
route.getEnd().setArrTime(timeTracker.getActArrTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import algorithms.ActivityVisitor;
|
||||||
|
import algorithms.StateManagerImpl;
|
||||||
|
import algorithms.StateManagerImpl.StateImpl;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.costs.ForwardTransportCost;
|
||||||
|
import basics.costs.VehicleRoutingActivityCosts;
|
||||||
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates total costs (i.e. transport and activity costs) at route and activity level.
|
||||||
|
*
|
||||||
|
* <p>Thus it modifies <code>stateManager.getRouteState(route, StateTypes.COSTS)</code> and <br>
|
||||||
|
* <code>stateManager.getActivityState(activity, StateTypes.COSTS)</code>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param activityCost
|
||||||
|
* @param transportCost
|
||||||
|
* @param states
|
||||||
|
*/
|
||||||
|
public class UpdateCostsAtAllLevels implements ActivityVisitor{
|
||||||
|
|
||||||
|
private static Logger log = Logger.getLogger(UpdateCostsAtAllLevels.class);
|
||||||
|
|
||||||
|
private VehicleRoutingActivityCosts activityCost;
|
||||||
|
|
||||||
|
private ForwardTransportCost transportCost;
|
||||||
|
|
||||||
|
private StateManagerImpl states;
|
||||||
|
|
||||||
|
private double totalOperationCost = 0.0;
|
||||||
|
|
||||||
|
private VehicleRoute vehicleRoute = null;
|
||||||
|
|
||||||
|
private TourActivity prevAct = null;
|
||||||
|
|
||||||
|
private double startTimeAtPrevAct = 0.0;
|
||||||
|
|
||||||
|
private ActivityTimeTracker timeTracker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates total costs (i.e. transport and activity costs) at route and activity level.
|
||||||
|
*
|
||||||
|
* <p>Thus it modifies <code>stateManager.getRouteState(route, StateTypes.COSTS)</code> and <br>
|
||||||
|
* <code>stateManager.getActivityState(activity, StateTypes.COSTS)</code>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param activityCost
|
||||||
|
* @param transportCost
|
||||||
|
* @param states
|
||||||
|
*/
|
||||||
|
public UpdateCostsAtAllLevels(VehicleRoutingActivityCosts activityCost, VehicleRoutingTransportCosts transportCost, StateManagerImpl states) {
|
||||||
|
super();
|
||||||
|
this.activityCost = activityCost;
|
||||||
|
this.transportCost = transportCost;
|
||||||
|
this.states = states;
|
||||||
|
timeTracker = new ActivityTimeTracker(transportCost);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void begin(VehicleRoute route) {
|
||||||
|
vehicleRoute = route;
|
||||||
|
vehicleRoute.getVehicleRouteCostCalculator().reset();
|
||||||
|
timeTracker.begin(route);
|
||||||
|
prevAct = route.getStart();
|
||||||
|
startTimeAtPrevAct = timeTracker.getActEndTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TourActivity act) {
|
||||||
|
timeTracker.visit(act);
|
||||||
|
|
||||||
|
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), act.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
|
||||||
|
double actCost = activityCost.getActivityCost(act, timeTracker.getActArrTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle());
|
||||||
|
|
||||||
|
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
|
||||||
|
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
|
||||||
|
|
||||||
|
totalOperationCost += transportCost;
|
||||||
|
totalOperationCost += actCost;
|
||||||
|
|
||||||
|
states.putActivityState(act, StateTypes.COSTS, new StateImpl(totalOperationCost));
|
||||||
|
|
||||||
|
prevAct = act;
|
||||||
|
startTimeAtPrevAct = timeTracker.getActEndTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {
|
||||||
|
timeTracker.finish();
|
||||||
|
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), vehicleRoute.getEnd().getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
|
||||||
|
double actCost = activityCost.getActivityCost(vehicleRoute.getEnd(), timeTracker.getActEndTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle());
|
||||||
|
|
||||||
|
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
|
||||||
|
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
|
||||||
|
|
||||||
|
totalOperationCost += transportCost;
|
||||||
|
totalOperationCost += actCost;
|
||||||
|
|
||||||
|
states.putRouteState(vehicleRoute, StateTypes.COSTS, new StateImpl(totalOperationCost));
|
||||||
|
|
||||||
|
//this is rather strange and likely to change
|
||||||
|
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver());
|
||||||
|
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle());
|
||||||
|
vehicleRoute.getVehicleRouteCostCalculator().finish();
|
||||||
|
|
||||||
|
startTimeAtPrevAct = 0.0;
|
||||||
|
prevAct = null;
|
||||||
|
vehicleRoute = null;
|
||||||
|
totalOperationCost = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import algorithms.RouteActivityVisitor;
|
||||||
|
import algorithms.StateManagerImpl;
|
||||||
|
import algorithms.StateManagerImpl.StateImpl;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.Job;
|
||||||
|
import basics.algo.InsertionEndsListener;
|
||||||
|
import basics.algo.InsertionStartsListener;
|
||||||
|
import basics.algo.JobInsertedListener;
|
||||||
|
import basics.costs.VehicleRoutingActivityCosts;
|
||||||
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
public class UpdateCostsAtRouteLevel implements JobInsertedListener, InsertionStartsListener, InsertionEndsListener{
|
||||||
|
|
||||||
|
private StateManagerImpl states;
|
||||||
|
|
||||||
|
private VehicleRoutingTransportCosts tpCosts;
|
||||||
|
|
||||||
|
private VehicleRoutingActivityCosts actCosts;
|
||||||
|
|
||||||
|
public UpdateCostsAtRouteLevel(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts, VehicleRoutingActivityCosts actCosts) {
|
||||||
|
super();
|
||||||
|
this.states = states;
|
||||||
|
this.tpCosts = tpCosts;
|
||||||
|
this.actCosts = actCosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||||
|
// inRoute.getVehicleRouteCostCalculator().addTransportCost(additionalCosts);
|
||||||
|
double oldCosts = states.getRouteState(inRoute, StateTypes.COSTS).toDouble();
|
||||||
|
oldCosts += additionalCosts;
|
||||||
|
states.putRouteState(inRoute, StateTypes.COSTS, new StateImpl(oldCosts));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
|
RouteActivityVisitor forwardInTime = new RouteActivityVisitor();
|
||||||
|
forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
|
||||||
|
for(VehicleRoute route : vehicleRoutes){
|
||||||
|
forwardInTime.visit(route);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
|
||||||
|
|
||||||
|
// IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts);
|
||||||
|
// forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
|
||||||
|
for(VehicleRoute route : vehicleRoutes){
|
||||||
|
if(route.isEmpty()) continue;
|
||||||
|
route.getVehicleRouteCostCalculator().reset();
|
||||||
|
route.getVehicleRouteCostCalculator().addOtherCost(states.getRouteState(route, StateTypes.COSTS).toDouble());
|
||||||
|
route.getVehicleRouteCostCalculator().price(route.getVehicle());
|
||||||
|
// forwardInTime.iterate(route);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import algorithms.ActivityVisitor;
|
||||||
|
import algorithms.StateManagerImpl;
|
||||||
|
import algorithms.StateManagerImpl.StateImpl;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
public class UpdateEarliestStartTimeWindowAtActLocations implements ActivityVisitor{
|
||||||
|
|
||||||
|
private StateManagerImpl states;
|
||||||
|
|
||||||
|
private ActivityTimeTracker timeTracker;
|
||||||
|
|
||||||
|
public UpdateEarliestStartTimeWindowAtActLocations(StateManagerImpl states, VehicleRoutingTransportCosts transportCosts) {
|
||||||
|
super();
|
||||||
|
this.states = states;
|
||||||
|
timeTracker = new ActivityTimeTracker(transportCosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void begin(VehicleRoute route) {
|
||||||
|
timeTracker.begin(route);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TourActivity activity) {
|
||||||
|
timeTracker.visit(activity);
|
||||||
|
states.putActivityState(activity, StateTypes.EARLIEST_OPERATION_START_TIME, new StateImpl(Math.max(timeTracker.getActArrTime(), activity.getTheoreticalEarliestOperationStartTime())));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import algorithms.ReverseActivityVisitor;
|
||||||
|
import algorithms.StateManagerImpl;
|
||||||
|
import algorithms.StateManagerImpl.StateImpl;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.route.PickupActivity;
|
||||||
|
import basics.route.ServiceActivity;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
public class UpdateFuturePickupsAtActivityLevel implements ReverseActivityVisitor {
|
||||||
|
private StateManagerImpl stateManager;
|
||||||
|
private int futurePicks = 0;
|
||||||
|
private VehicleRoute route;
|
||||||
|
|
||||||
|
public UpdateFuturePickupsAtActivityLevel(StateManagerImpl stateManager) {
|
||||||
|
super();
|
||||||
|
this.stateManager = stateManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void begin(VehicleRoute route) {
|
||||||
|
this.route = route;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TourActivity act) {
|
||||||
|
stateManager.putActivityState(act, StateTypes.FUTURE_PICKS, new StateImpl(futurePicks));
|
||||||
|
if(act instanceof PickupActivity || act instanceof ServiceActivity){
|
||||||
|
futurePicks += act.getCapacityDemand();
|
||||||
|
}
|
||||||
|
assert futurePicks <= route.getVehicle().getCapacity() : "sum of pickups must not be > vehicleCap";
|
||||||
|
assert futurePicks >= 0 : "sum of pickups must not < 0";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {
|
||||||
|
futurePicks = 0;
|
||||||
|
route = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import algorithms.ReverseActivityVisitor;
|
||||||
|
import algorithms.StateManagerImpl;
|
||||||
|
import algorithms.StateManagerImpl.StateImpl;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
public class UpdateLatestOperationStartTimeAtActLocations implements ReverseActivityVisitor{
|
||||||
|
|
||||||
|
private static Logger log = Logger.getLogger(UpdateLatestOperationStartTimeAtActLocations.class);
|
||||||
|
|
||||||
|
private StateManagerImpl states;
|
||||||
|
|
||||||
|
private VehicleRoute route;
|
||||||
|
|
||||||
|
private VehicleRoutingTransportCosts transportCosts;
|
||||||
|
|
||||||
|
private double latestArrTimeAtPrevAct;
|
||||||
|
|
||||||
|
private TourActivity prevAct;
|
||||||
|
|
||||||
|
public UpdateLatestOperationStartTimeAtActLocations(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts) {
|
||||||
|
super();
|
||||||
|
this.states = states;
|
||||||
|
this.transportCosts = tpCosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void begin(VehicleRoute route) {
|
||||||
|
this.route = route;
|
||||||
|
latestArrTimeAtPrevAct = route.getEnd().getTheoreticalLatestOperationStartTime();
|
||||||
|
prevAct = route.getEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TourActivity activity) {
|
||||||
|
double potentialLatestArrivalTimeAtCurrAct = latestArrTimeAtPrevAct - transportCosts.getBackwardTransportTime(activity.getLocationId(), prevAct.getLocationId(), latestArrTimeAtPrevAct, route.getDriver(),route.getVehicle()) - activity.getOperationTime();
|
||||||
|
double latestArrivalTime = Math.min(activity.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct);
|
||||||
|
|
||||||
|
states.putActivityState(activity, StateTypes.LATEST_OPERATION_START_TIME, new StateImpl(latestArrivalTime));
|
||||||
|
|
||||||
|
latestArrTimeAtPrevAct = latestArrivalTime;
|
||||||
|
prevAct = activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import algorithms.ActivityVisitor;
|
||||||
|
import algorithms.StateManagerImpl;
|
||||||
|
import algorithms.StateManagerImpl.StateImpl;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates load at activity level.
|
||||||
|
*
|
||||||
|
* <p>Note that this assumes that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT.
|
||||||
|
* If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot.
|
||||||
|
*
|
||||||
|
* <p>Thus it DEPENDS on StateTypes.LOAD_AT_DEPOT
|
||||||
|
*
|
||||||
|
* @author stefan
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class UpdateLoadAtActivityLevel implements ActivityVisitor {
|
||||||
|
private StateManagerImpl stateManager;
|
||||||
|
private int currentLoad = 0;
|
||||||
|
private VehicleRoute route;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates load at activity level.
|
||||||
|
*
|
||||||
|
* <p>Note that this assumes that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT.
|
||||||
|
* If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot.
|
||||||
|
*
|
||||||
|
* <p>Thus it DEPENDS on StateTypes.LOAD_AT_DEPOT
|
||||||
|
*
|
||||||
|
* <p>If you want to update StateTypes.LOAD_AT_DEPOT see {@link InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts}, {@link UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted}
|
||||||
|
*
|
||||||
|
* <p>The loads can be retrieved by <br>
|
||||||
|
* <code>stateManager.getActivityState(activity,StateTypes.LOAD);</code>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @see {@link InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts}, {@link UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted}
|
||||||
|
* @author stefan
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public UpdateLoadAtActivityLevel(StateManagerImpl stateManager) {
|
||||||
|
super();
|
||||||
|
this.stateManager = stateManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void begin(VehicleRoute route) {
|
||||||
|
currentLoad = (int) stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT).toDouble();
|
||||||
|
this.route = route;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TourActivity act) {
|
||||||
|
currentLoad += act.getCapacityDemand();
|
||||||
|
stateManager.putActivityState(act, StateTypes.LOAD, new StateImpl(currentLoad));
|
||||||
|
assert currentLoad <= route.getVehicle().getCapacity() : "currentLoad at activity must not be > vehicleCapacity";
|
||||||
|
assert currentLoad >= 0 : "currentLoad at act must not be < 0";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {
|
||||||
|
currentLoad = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import algorithms.ActivityVisitor;
|
||||||
|
import algorithms.StateManagerImpl;
|
||||||
|
import algorithms.StateManagerImpl.StateImpl;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
public class UpdateLoadAtAllLevels implements ActivityVisitor{
|
||||||
|
|
||||||
|
private double load = 0.0;
|
||||||
|
|
||||||
|
private StateManagerImpl states;
|
||||||
|
|
||||||
|
private VehicleRoute vehicleRoute;
|
||||||
|
|
||||||
|
public UpdateLoadAtAllLevels(StateManagerImpl states) {
|
||||||
|
super();
|
||||||
|
this.states = states;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void begin(VehicleRoute route) {
|
||||||
|
vehicleRoute = route;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TourActivity activity) {
|
||||||
|
load += (double)activity.getCapacityDemand();
|
||||||
|
states.putActivityState(activity, StateTypes.LOAD, new StateImpl(load));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {
|
||||||
|
states.putRouteState(vehicleRoute, StateTypes.LOAD, new StateImpl(load));
|
||||||
|
load=0;
|
||||||
|
vehicleRoute = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import algorithms.StateManagerImpl;
|
||||||
|
import algorithms.StateManagerImpl.StateImpl;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.Job;
|
||||||
|
import basics.Service;
|
||||||
|
import basics.algo.InsertionStartsListener;
|
||||||
|
import basics.algo.JobInsertedListener;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates load at route level, i.e. modifies StateTypes.LOAD for each route.
|
||||||
|
*
|
||||||
|
* @author stefan
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class UpdateLoadAtRouteLevel implements JobInsertedListener, InsertionStartsListener{
|
||||||
|
|
||||||
|
private StateManagerImpl states;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates load at route level, i.e. modifies StateTypes.LOAD for each route.
|
||||||
|
*
|
||||||
|
* @author stefan
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public UpdateLoadAtRouteLevel(StateManagerImpl states) {
|
||||||
|
super();
|
||||||
|
this.states = states;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||||
|
if(!(job2insert instanceof Service)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
double oldLoad = states.getRouteState(inRoute, StateTypes.LOAD).toDouble();
|
||||||
|
states.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(oldLoad + job2insert.getCapacityDemand()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
|
for(VehicleRoute route : vehicleRoutes){
|
||||||
|
int load = 0;
|
||||||
|
for(Job j : route.getTourActivities().getJobs()){
|
||||||
|
load += j.getCapacityDemand();
|
||||||
|
}
|
||||||
|
states.putRouteState(route, StateTypes.LOAD, new StateImpl(load));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import algorithms.StateManagerImpl;
|
||||||
|
import algorithms.StateManagerImpl.StateImpl;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.Delivery;
|
||||||
|
import basics.Job;
|
||||||
|
import basics.Pickup;
|
||||||
|
import basics.Service;
|
||||||
|
import basics.algo.JobInsertedListener;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates loads at start and end of a route if a job has been inserted in that route.
|
||||||
|
*
|
||||||
|
* <p>These states can be retrieved by <br>
|
||||||
|
* stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT) for LOAD_AT_DEPOT and <br>
|
||||||
|
* stateManager.getRouteState(route, StateTypes.LOAD) for LOAD (i.e. load at end)
|
||||||
|
*
|
||||||
|
* @param stateManager
|
||||||
|
*/
|
||||||
|
public class UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted implements JobInsertedListener {
|
||||||
|
|
||||||
|
private StateManagerImpl stateManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates loads at start and end of a route if a job has been inserted in that route.
|
||||||
|
*
|
||||||
|
* <p>These states can be retrieved by <br>
|
||||||
|
* stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT) for LOAD_AT_DEPOT and <br>
|
||||||
|
* stateManager.getRouteState(route, StateTypes.LOAD) for LOAD (i.e. load at end)
|
||||||
|
*
|
||||||
|
* @param stateManager
|
||||||
|
*/
|
||||||
|
public UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(StateManagerImpl stateManager) {
|
||||||
|
super();
|
||||||
|
this.stateManager = stateManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||||
|
if(job2insert instanceof Delivery){
|
||||||
|
int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD_AT_DEPOT).toDouble();
|
||||||
|
// log.info("loadAtDepot="+loadAtDepot);
|
||||||
|
stateManager.putRouteState(inRoute, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot + job2insert.getCapacityDemand()));
|
||||||
|
}
|
||||||
|
else if(job2insert instanceof Pickup || job2insert instanceof Service){
|
||||||
|
int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD).toDouble();
|
||||||
|
// log.info("loadAtEnd="+loadAtEnd);
|
||||||
|
stateManager.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(loadAtEnd + job2insert.getCapacityDemand()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package algorithms.states;
|
||||||
|
|
||||||
|
import algorithms.ActivityVisitor;
|
||||||
|
import algorithms.StateManagerImpl;
|
||||||
|
import algorithms.StateManagerImpl.StateImpl;
|
||||||
|
import algorithms.StateTypes;
|
||||||
|
import basics.route.DeliveryActivity;
|
||||||
|
import basics.route.TourActivity;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
public class UpdateOccuredDeliveriesAtActivityLevel implements ActivityVisitor {
|
||||||
|
private StateManagerImpl stateManager;
|
||||||
|
private int deliveries = 0;
|
||||||
|
private VehicleRoute route;
|
||||||
|
|
||||||
|
public UpdateOccuredDeliveriesAtActivityLevel(StateManagerImpl stateManager) {
|
||||||
|
super();
|
||||||
|
this.stateManager = stateManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void begin(VehicleRoute route) {
|
||||||
|
this.route = route;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TourActivity act) {
|
||||||
|
if(act instanceof DeliveryActivity){
|
||||||
|
deliveries += Math.abs(act.getCapacityDemand());
|
||||||
|
}
|
||||||
|
stateManager.putActivityState(act, StateTypes.PAST_DELIVERIES, new StateImpl(deliveries));
|
||||||
|
assert deliveries >= 0 : "deliveries < 0";
|
||||||
|
assert deliveries <= route.getVehicle().getCapacity() : "deliveries > vehicleCap";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {
|
||||||
|
deliveries = 0;
|
||||||
|
route = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package basics.algo;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import basics.Job;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
public class InsertionListeners {
|
||||||
|
|
||||||
|
private Collection<InsertionStartsListener> startListeners = new ArrayList<InsertionStartsListener>();
|
||||||
|
|
||||||
|
private Collection<JobInsertedListener> jobInsertedListeners = new ArrayList<JobInsertedListener>();
|
||||||
|
|
||||||
|
private Collection<InsertionEndsListener> endListeners = new ArrayList<InsertionEndsListener>();
|
||||||
|
|
||||||
|
public void addListener(InsertionListener insertionListener){
|
||||||
|
if(insertionListener instanceof InsertionStartsListener) startListeners.add((InsertionStartsListener) insertionListener);
|
||||||
|
else if(insertionListener instanceof JobInsertedListener) jobInsertedListeners.add((JobInsertedListener) insertionListener);
|
||||||
|
else if(insertionListener instanceof InsertionEndsListener) endListeners.add((InsertionEndsListener) insertionListener);
|
||||||
|
else throw new IllegalStateException("cannot add this type of insertionListener");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeListener(InsertionListener insertionListener){
|
||||||
|
if(insertionListener instanceof InsertionStartsListener) startListeners.remove((InsertionStartsListener) insertionListener);
|
||||||
|
else if(insertionListener instanceof JobInsertedListener) jobInsertedListeners.remove((JobInsertedListener) insertionListener);
|
||||||
|
else if(insertionListener instanceof InsertionEndsListener) endListeners.remove((InsertionEndsListener) insertionListener);
|
||||||
|
else throw new IllegalStateException("cannot remove this type of insertionListener");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs){
|
||||||
|
for(InsertionStartsListener l : startListeners) l.informInsertionStarts(vehicleRoutes, unassignedJobs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime){
|
||||||
|
for(JobInsertedListener l : jobInsertedListeners) l.informJobInserted(job2insert, inRoute, additionalCosts, additionalTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertionEnds(Collection<VehicleRoute> vehicleRoutes){
|
||||||
|
for(InsertionEndsListener l : endListeners){ l.informInsertionEnds(vehicleRoutes); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,4 +29,5 @@ import basics.route.VehicleRoute;
|
||||||
public interface InsertionStartsListener extends InsertionListener {
|
public interface InsertionStartsListener extends InsertionListener {
|
||||||
|
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,41 +18,40 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Stefan Schroeder - initial API and implementation
|
* Stefan Schroeder - initial API and implementation
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package algorithms;
|
package basics.algo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.algo.RuinListener;
|
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
class RuinListeners {
|
public class RuinListeners {
|
||||||
|
|
||||||
private Collection<RuinListener> ruinListeners = new ArrayList<RuinListener>();
|
private Collection<RuinListener> ruinListeners = new ArrayList<RuinListener>();
|
||||||
|
|
||||||
void ruinStarts(Collection<VehicleRoute> routes){
|
public void ruinStarts(Collection<VehicleRoute> routes){
|
||||||
for(RuinListener l : ruinListeners) l.ruinStarts(routes);
|
for(RuinListener l : ruinListeners) l.ruinStarts(routes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs){
|
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs){
|
||||||
for(RuinListener l : ruinListeners) l.ruinEnds(routes, unassignedJobs);
|
for(RuinListener l : ruinListeners) l.ruinEnds(routes, unassignedJobs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removed(Job job, VehicleRoute fromRoute){
|
public void removed(Job job, VehicleRoute fromRoute){
|
||||||
for(RuinListener l : ruinListeners) l.removed(job, fromRoute);
|
for(RuinListener l : ruinListeners) l.removed(job, fromRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addListener(RuinListener ruinListener){
|
public void addListener(RuinListener ruinListener){
|
||||||
ruinListeners.add(ruinListener);
|
ruinListeners.add(ruinListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeListener(RuinListener ruinListener){
|
public void removeListener(RuinListener ruinListener){
|
||||||
ruinListeners.remove(ruinListener);
|
ruinListeners.remove(ruinListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<RuinListener> getListeners(){
|
public Collection<RuinListener> getListeners(){
|
||||||
return Collections.unmodifiableCollection(ruinListeners);
|
return Collections.unmodifiableCollection(ruinListeners);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -26,6 +26,7 @@ import basics.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
public class Solutions {
|
public class Solutions {
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public static VehicleRoutingProblemSolution getBest(Collection<VehicleRoutingProblemSolution> solutions){
|
public static VehicleRoutingProblemSolution getBest(Collection<VehicleRoutingProblemSolution> solutions){
|
||||||
VehicleRoutingProblemSolution best = null;
|
VehicleRoutingProblemSolution best = null;
|
||||||
for(VehicleRoutingProblemSolution s : solutions){
|
for(VehicleRoutingProblemSolution s : solutions){
|
||||||
|
|
@ -35,4 +36,14 @@ public class Solutions {
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static VehicleRoutingProblemSolution bestOf(Collection<VehicleRoutingProblemSolution> solutions){
|
||||||
|
VehicleRoutingProblemSolution best = null;
|
||||||
|
for(VehicleRoutingProblemSolution s : solutions){
|
||||||
|
if(best == null) best = s;
|
||||||
|
else if(s.getCost() < best.getCost()) best = s;
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,12 @@ import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import util.Solutions;
|
import util.Solutions;
|
||||||
import algorithms.HardConstraints.HardActivityLevelConstraint;
|
|
||||||
import algorithms.StateUpdates.UpdateCostsAtRouteLevel;
|
|
||||||
import algorithms.StateUpdates.UpdateLoadAtRouteLevel;
|
|
||||||
import algorithms.acceptors.AcceptNewIfBetterThanWorst;
|
import algorithms.acceptors.AcceptNewIfBetterThanWorst;
|
||||||
|
import algorithms.constraints.HardActivityLevelConstraint;
|
||||||
|
import algorithms.constraints.HardLoadConstraint;
|
||||||
import algorithms.selectors.SelectBest;
|
import algorithms.selectors.SelectBest;
|
||||||
|
import algorithms.states.UpdateCostsAtRouteLevel;
|
||||||
|
import algorithms.states.UpdateLoadAtRouteLevel;
|
||||||
import basics.VehicleRoutingAlgorithm;
|
import basics.VehicleRoutingAlgorithm;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import basics.VehicleRoutingProblemSolution;
|
||||||
|
|
@ -63,7 +64,7 @@ public class BuildCVRPAlgoFromScratchTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ActivityInsertionCostCalculator marginalCalculus = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), hardActLevelConstraint);
|
ActivityInsertionCostCalculator marginalCalculus = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), hardActLevelConstraint);
|
||||||
CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardLoadConstraint(stateManager));
|
CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardLoadConstraint(stateManager));
|
||||||
|
|
||||||
VehicleFleetManager fleetManager = new InfiniteVehicles(vrp.getVehicles());
|
VehicleFleetManager fleetManager = new InfiniteVehicles(vrp.getVehicles());
|
||||||
JobInsertionCalculator finalServiceInsertion = new CalculatesVehTypeDepServiceInsertion(fleetManager, serviceInsertion);
|
JobInsertionCalculator finalServiceInsertion = new CalculatesVehTypeDepServiceInsertion(fleetManager, serviceInsertion);
|
||||||
|
|
@ -101,7 +102,7 @@ public class BuildCVRPAlgoFromScratchTest {
|
||||||
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateCostsAtRouteLevel(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts()));
|
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateCostsAtRouteLevel(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts()));
|
||||||
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateLoadAtRouteLevel(stateManager));
|
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateLoadAtRouteLevel(stateManager));
|
||||||
|
|
||||||
VehicleRoutingProblemSolution iniSolution = new CreateInitialSolution(bestInsertion).createInitialSolution(vrp);
|
VehicleRoutingProblemSolution iniSolution = new BestInsertionInitialSolutionFactory(bestInsertion).createSolution(vrp);
|
||||||
// System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size());
|
// System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size());
|
||||||
vra.addInitialSolution(iniSolution);
|
vra.addInitialSolution(iniSolution);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,17 +26,20 @@ import org.apache.log4j.Logger;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import util.Solutions;
|
import algorithms.StateManagerImpl.StateImpl;
|
||||||
import algorithms.BackwardInTimeListeners.BackwardInTimeListener;
|
|
||||||
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
|
|
||||||
import algorithms.HardConstraints.HardActivityLevelConstraintManager;
|
|
||||||
import algorithms.StateManager.StateImpl;
|
|
||||||
import algorithms.StateUpdates.UpdateActivityTimes;
|
|
||||||
import algorithms.StateUpdates.UpdateCostsAtAllLevels;
|
|
||||||
import algorithms.StateUpdates.UpdateEarliestStartTimeWindowAtActLocations;
|
|
||||||
import algorithms.StateUpdates.UpdateLatestOperationStartTimeAtActLocations;
|
|
||||||
import algorithms.acceptors.AcceptNewIfBetterThanWorst;
|
import algorithms.acceptors.AcceptNewIfBetterThanWorst;
|
||||||
|
import algorithms.constraints.ConstraintManager;
|
||||||
|
import algorithms.constraints.HardPickupAndDeliveryActivityLevelConstraint;
|
||||||
|
import algorithms.constraints.HardPickupAndDeliveryLoadConstraint;
|
||||||
|
import algorithms.constraints.HardTimeWindowActivityLevelConstraint;
|
||||||
import algorithms.selectors.SelectBest;
|
import algorithms.selectors.SelectBest;
|
||||||
|
import algorithms.states.UpdateActivityTimes;
|
||||||
|
import algorithms.states.UpdateCostsAtAllLevels;
|
||||||
|
import algorithms.states.UpdateEarliestStartTimeWindowAtActLocations;
|
||||||
|
import algorithms.states.UpdateFuturePickupsAtActivityLevel;
|
||||||
|
import algorithms.states.UpdateLatestOperationStartTimeAtActLocations;
|
||||||
|
import algorithms.states.UpdateLoadAtActivityLevel;
|
||||||
|
import algorithms.states.UpdateOccuredDeliveriesAtActivityLevel;
|
||||||
import basics.Delivery;
|
import basics.Delivery;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Pickup;
|
import basics.Pickup;
|
||||||
|
|
@ -44,17 +47,10 @@ import basics.VehicleRoutingAlgorithm;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import basics.VehicleRoutingProblemSolution;
|
||||||
import basics.algo.InsertionStartsListener;
|
import basics.algo.InsertionStartsListener;
|
||||||
import basics.algo.IterationStartsListener;
|
|
||||||
import basics.algo.JobInsertedListener;
|
import basics.algo.JobInsertedListener;
|
||||||
import basics.algo.SearchStrategy;
|
import basics.algo.SearchStrategy;
|
||||||
import basics.algo.SearchStrategyManager;
|
import basics.algo.SearchStrategyManager;
|
||||||
import basics.io.VrpXMLReader;
|
import basics.io.VrpXMLReader;
|
||||||
import basics.io.VrpXMLWriter;
|
|
||||||
import basics.route.DeliveryActivity;
|
|
||||||
import basics.route.End;
|
|
||||||
import basics.route.PickupActivity;
|
|
||||||
import basics.route.Start;
|
|
||||||
import basics.route.TourActivity;
|
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
public class BuildPDVRPAlgoFromScratchTest {
|
public class BuildPDVRPAlgoFromScratchTest {
|
||||||
|
|
@ -74,13 +70,13 @@ public class BuildPDVRPAlgoFromScratchTest {
|
||||||
|
|
||||||
final StateManagerImpl stateManager = new StateManagerImpl();
|
final StateManagerImpl stateManager = new StateManagerImpl();
|
||||||
|
|
||||||
HardActivityLevelConstraintManager actLevelConstraintAccumulator = new HardActivityLevelConstraintManager();
|
ConstraintManager actLevelConstraintAccumulator = new ConstraintManager();
|
||||||
actLevelConstraintAccumulator.addConstraint(new HardConstraints.HardPickupAndDeliveryActivityLevelConstraint(stateManager));
|
actLevelConstraintAccumulator.addConstraint(new HardPickupAndDeliveryActivityLevelConstraint(stateManager));
|
||||||
actLevelConstraintAccumulator.addConstraint(new HardConstraints.HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts()));
|
actLevelConstraintAccumulator.addConstraint(new HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts()));
|
||||||
|
|
||||||
ActivityInsertionCostCalculator marginalCalculus = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), actLevelConstraintAccumulator);
|
ActivityInsertionCostCalculator marginalCalculus = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), actLevelConstraintAccumulator);
|
||||||
|
|
||||||
CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardPickupAndDeliveryLoadConstraint(stateManager));
|
CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardPickupAndDeliveryLoadConstraint(stateManager));
|
||||||
// CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardLoadConstraint(stateManager));
|
// CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardLoadConstraint(stateManager));
|
||||||
|
|
||||||
VehicleFleetManager fleetManager = new InfiniteVehicles(vrp.getVehicles());
|
VehicleFleetManager fleetManager = new InfiniteVehicles(vrp.getVehicles());
|
||||||
|
|
@ -105,7 +101,7 @@ public class BuildPDVRPAlgoFromScratchTest {
|
||||||
|
|
||||||
vra = new VehicleRoutingAlgorithm(vrp, strategyManager);
|
vra = new VehicleRoutingAlgorithm(vrp, strategyManager);
|
||||||
|
|
||||||
vra.getAlgorithmListeners().addListener(new StateUpdates.ResetStateManager(stateManager));
|
vra.getAlgorithmListeners().addListener(stateManager);
|
||||||
|
|
||||||
final RouteActivityVisitor iterateForward = new RouteActivityVisitor();
|
final RouteActivityVisitor iterateForward = new RouteActivityVisitor();
|
||||||
|
|
||||||
|
|
@ -113,12 +109,12 @@ public class BuildPDVRPAlgoFromScratchTest {
|
||||||
iterateForward.addActivityVisitor(new UpdateEarliestStartTimeWindowAtActLocations(stateManager, vrp.getTransportCosts()));
|
iterateForward.addActivityVisitor(new UpdateEarliestStartTimeWindowAtActLocations(stateManager, vrp.getTransportCosts()));
|
||||||
iterateForward.addActivityVisitor(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
|
iterateForward.addActivityVisitor(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
|
||||||
|
|
||||||
iterateForward.addActivityVisitor(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager));
|
iterateForward.addActivityVisitor(new UpdateOccuredDeliveriesAtActivityLevel(stateManager));
|
||||||
iterateForward.addActivityVisitor(new StateUpdates.UpdateLoadAtActivityLevel(stateManager));
|
iterateForward.addActivityVisitor(new UpdateLoadAtActivityLevel(stateManager));
|
||||||
|
|
||||||
final ReverseRouteActivityVisitor iterateBackward = new ReverseRouteActivityVisitor();
|
final ReverseRouteActivityVisitor iterateBackward = new ReverseRouteActivityVisitor();
|
||||||
iterateBackward.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
|
iterateBackward.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
|
||||||
iterateBackward.addActivityVisitor(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager));
|
iterateBackward.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager));
|
||||||
|
|
||||||
|
|
||||||
InsertionStartsListener loadVehicleInDepot = new InsertionStartsListener() {
|
InsertionStartsListener loadVehicleInDepot = new InsertionStartsListener() {
|
||||||
|
|
@ -171,7 +167,7 @@ public class BuildPDVRPAlgoFromScratchTest {
|
||||||
bestInsertion.addListener(loadVehicleInDepot);
|
bestInsertion.addListener(loadVehicleInDepot);
|
||||||
bestInsertion.addListener(updateLoadAfterJobHasBeenInserted);
|
bestInsertion.addListener(updateLoadAfterJobHasBeenInserted);
|
||||||
|
|
||||||
VehicleRoutingProblemSolution iniSolution = new CreateInitialSolution(bestInsertion).createInitialSolution(vrp);
|
VehicleRoutingProblemSolution iniSolution = new BestInsertionInitialSolutionFactory(bestInsertion).createSolution(vrp);
|
||||||
// System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size());
|
// System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size());
|
||||||
vra.addInitialSolution(iniSolution);
|
vra.addInitialSolution(iniSolution);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,9 @@ import org.junit.Test;
|
||||||
import util.Coordinate;
|
import util.Coordinate;
|
||||||
import util.ManhattanDistanceCalculator;
|
import util.ManhattanDistanceCalculator;
|
||||||
import util.RouteUtils;
|
import util.RouteUtils;
|
||||||
import algorithms.StateUpdates.UpdateStates;
|
import algorithms.constraints.HardLoadConstraint;
|
||||||
|
import algorithms.constraints.HardTimeWindowActivityLevelConstraint;
|
||||||
|
import algorithms.states.StateUpdates.UpdateStates;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
|
|
@ -152,7 +154,7 @@ public class GendreauPostOptTest {
|
||||||
|
|
||||||
activityCosts = new ExampleActivityCostFunction();
|
activityCosts = new ExampleActivityCostFunction();
|
||||||
|
|
||||||
CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(cost, new MarginalsCalculusTriangleInequality(cost, activityCosts, new HardConstraints.HardTimeWindowActivityLevelConstraint(states, cost)), new HardConstraints.HardLoadConstraint(states));
|
CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(cost, new MarginalsCalculusTriangleInequality(cost, activityCosts, new HardTimeWindowActivityLevelConstraint(states, cost)), new HardLoadConstraint(states));
|
||||||
|
|
||||||
CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(standardServiceInsertion, states);
|
CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(standardServiceInsertion, states);
|
||||||
withFixCost.setWeightOfFixCost(1.2);
|
withFixCost.setWeightOfFixCost(1.2);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,9 @@ import org.apache.log4j.Logger;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import algorithms.StateUpdates.UpdateStates;
|
import algorithms.constraints.HardLoadConstraint;
|
||||||
|
import algorithms.constraints.HardTimeWindowActivityLevelConstraint;
|
||||||
|
import algorithms.states.StateUpdates.UpdateStates;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
|
|
@ -157,7 +159,7 @@ public class TestCalculatesServiceInsertion {
|
||||||
|
|
||||||
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
|
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
|
||||||
|
|
||||||
serviceInsertion = new CalculatesServiceInsertion(costs, new MarginalsCalculusTriangleInequality(costs, activityCosts, new HardConstraints.HardTimeWindowActivityLevelConstraint(states, costs)), new HardConstraints.HardLoadConstraint(states));
|
serviceInsertion = new CalculatesServiceInsertion(costs, new MarginalsCalculusTriangleInequality(costs, activityCosts, new HardTimeWindowActivityLevelConstraint(states, costs)), new HardLoadConstraint(states));
|
||||||
|
|
||||||
stateUpdater = new UpdateStates(states, costs, activityCosts);
|
stateUpdater = new UpdateStates(states, costs, activityCosts);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import util.Coordinate;
|
import util.Coordinate;
|
||||||
import util.ManhattanDistanceCalculator;
|
import util.ManhattanDistanceCalculator;
|
||||||
import algorithms.StateUpdates.UpdateStates;
|
import algorithms.states.StateUpdates.UpdateStates;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,10 @@ import org.junit.Test;
|
||||||
|
|
||||||
import util.Coordinate;
|
import util.Coordinate;
|
||||||
import util.ManhattanDistanceCalculator;
|
import util.ManhattanDistanceCalculator;
|
||||||
import algorithms.StateUpdates.UpdateActivityTimes;
|
import algorithms.states.UpdateActivityTimes;
|
||||||
import algorithms.StateUpdates.UpdateCostsAtAllLevels;
|
import algorithms.states.UpdateCostsAtAllLevels;
|
||||||
import algorithms.StateUpdates.UpdateEarliestStartTimeWindowAtActLocations;
|
import algorithms.states.UpdateEarliestStartTimeWindowAtActLocations;
|
||||||
import algorithms.StateUpdates.UpdateLoadAtAllLevels;
|
import algorithms.states.UpdateLoadAtAllLevels;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.costs.DefaultVehicleRoutingActivityCosts;
|
import basics.costs.DefaultVehicleRoutingActivityCosts;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import util.Coordinate;
|
import util.Coordinate;
|
||||||
import util.ManhattanDistanceCalculator;
|
import util.ManhattanDistanceCalculator;
|
||||||
import algorithms.StateUpdates.UpdateStates;
|
import algorithms.states.StateUpdates.UpdateStates;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue