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

Merge remote-tracking branch 'choose_remote_name/relaxAPI' into

PickupAndDelivery

Conflicts:
	jsprit-core/src/main/java/algorithms/CalculatorBuilder.java
	jsprit-core/src/main/java/algorithms/HardConstraints.java
	jsprit-core/src/main/java/algorithms/ServiceInsertionCalculator.java
	jsprit-core/src/main/java/basics/route/TourActivities.java
	jsprit-core/src/test/java/algorithms/BuildCVRPAlgoFromScratchTest.java
	jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java
	jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java
	jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java
This commit is contained in:
oblonski 2013-11-07 08:26:46 +01:00
commit d63abea764
122 changed files with 3454 additions and 3171 deletions

View file

@ -22,9 +22,9 @@ package algorithms;
import basics.route.TourActivity;
interface ActivityInsertionCostsCalculator {
public interface ActivityInsertionCostsCalculator {
class ActivityInsertionCosts {
public class ActivityInsertionCosts {
private double additionalCosts;
private double additionalTime;
@ -50,6 +50,6 @@ interface ActivityInsertionCostsCalculator {
}
ActivityInsertionCosts calculate(InsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct);
public ActivityInsertionCosts getCosts(InsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct);
}

View file

@ -52,7 +52,7 @@ class AvgJobDistance implements JobDistance {
* <p>If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
*/
@Override
public double calculateDistance(Job i, Job j) {
public double getDistance(Job i, Job j) {
if (i.equals(j)) return 0.0;
if (i instanceof Service && j instanceof Service) {

View file

@ -42,6 +42,28 @@ import basics.route.VehicleRoute;
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 Random random = RandomNumberGeneration.getRandom();
@ -56,7 +78,7 @@ final class BestInsertion implements InsertionStrategy{
private Inserter inserter;
private JobInsertionCalculator bestInsertionCostCalculator;
private JobInsertionCostsCalculator bestInsertionCostCalculator;
private boolean minVehiclesFirst = false;
@ -64,7 +86,7 @@ final class BestInsertion implements InsertionStrategy{
this.random = random;
}
public BestInsertion(JobInsertionCalculator jobInsertionCalculator) {
public BestInsertion(JobInsertionCostsCalculator jobInsertionCalculator) {
super();
this.insertionsListeners = new InsertionListeners();
inserter = new Inserter(insertionsListeners);
@ -86,7 +108,7 @@ final class BestInsertion implements InsertionStrategy{
Insertion bestInsertion = null;
double bestInsertionCost = Double.MAX_VALUE;
for(VehicleRoute vehicleRoute : vehicleRoutes){
InsertionData iData = bestInsertionCostCalculator.calculate(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if(iData instanceof NoInsertionFound) {
continue;
}
@ -97,7 +119,7 @@ final class BestInsertion implements InsertionStrategy{
}
if(!minVehiclesFirst){
VehicleRoute newRoute = VehicleRoute.emptyRoute();
InsertionData newIData = bestInsertionCostCalculator.calculate(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if(newIData.getInsertionCost() < bestInsertionCost){
bestInsertion = new Insertion(newRoute,newIData);
bestInsertionCost = newIData.getInsertionCost();
@ -106,7 +128,7 @@ final class BestInsertion implements InsertionStrategy{
}
if(bestInsertion == null){
VehicleRoute newRoute = VehicleRoute.emptyRoute();
InsertionData bestI = bestInsertionCostCalculator.calculate(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
InsertionData bestI = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
if(bestI instanceof InsertionData.NoInsertionFound){
throw new IllegalStateException(getErrorMsg(unassignedJob));
}

View file

@ -0,0 +1,129 @@
package algorithms;
import java.util.ArrayList;
import java.util.List;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblem.Constraint;
import basics.algo.InsertionListener;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import basics.route.VehicleFleetManager;
public class BestInsertionBuilder implements InsertionStrategyBuilder{
private VehicleRoutingProblem vrp;
private StateManager stateManager;
private boolean local = true;
private ConstraintManager constraintManager;
private VehicleFleetManager fleetManager;
private double weightOfFixedCosts;
private boolean considerFixedCosts = false;
private ActivityInsertionCostsCalculator actInsertionCostsCalculator = null;
private int forwaredLooking;
private int memory;
public BestInsertionBuilder(VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManager stateManager) {
super();
this.vrp = vrp;
this.stateManager = stateManager;
this.constraintManager = new ConstraintManager();
this.fleetManager = vehicleFleetManager;
addCoreStateUpdaters();
}
private void addCoreStateUpdaters(){
stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager));
stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager));
stateManager.addActivityVisitor(new UpdateMaxLoad(stateManager));
stateManager.addActivityVisitor(new UpdateActivityTimes(vrp.getTransportCosts()));
stateManager.addActivityVisitor(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
}
public BestInsertionBuilder addHardLoadConstraints(){
constraintManager.addConstraint(new HardPickupAndDeliveryLoadRouteLevelConstraint(stateManager));
if(vrp.getProblemConstraints().contains(Constraint.DELIVERIES_FIRST)){
constraintManager.addConstraint(new HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager));
}
else{
constraintManager.addConstraint(new HardPickupAndDeliveryActivityLevelConstraint(stateManager));
}
stateManager.addActivityVisitor(new UpdateOccuredDeliveriesAtActivityLevel(stateManager));
stateManager.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager));
return this;
}
public BestInsertionBuilder addHardTimeWindowConstraint(){
constraintManager.addConstraint(new HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts()));
// stateManager.addActivityVisitor(new UpdateEarliestStartTimeWindowAtActLocations(stateManager, vrp.getTransportCosts()));
stateManager.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
return this;
}
public BestInsertionBuilder addConstraint(HardActivityLevelConstraint hardActvitiyLevelConstraint){
constraintManager.addConstraint(hardActvitiyLevelConstraint);
return this;
};
public BestInsertionBuilder addConstraint(HardRouteLevelConstraint hardRouteLevelConstraint){
constraintManager.addConstraint(hardRouteLevelConstraint);
return this;
};
public void setRouteLevel(int forwardLooking, int memory){
local = false;
this.forwaredLooking = forwardLooking;
this.memory = memory;
};
public BestInsertionBuilder setLocalLevel(){
local = true;
return this;
};
public BestInsertionBuilder considerFixedCosts(double weightOfFixedCosts){
this.weightOfFixedCosts = weightOfFixedCosts;
this.considerFixedCosts = true;
return this;
}
public void setActivityInsertionCostCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator){
this.actInsertionCostsCalculator = activityInsertionCostsCalculator;
};
@Override
public InsertionStrategy build() {
List<InsertionListener> iListeners = new ArrayList<InsertionListener>();
List<PrioritizedVRAListener> algorithmListeners = new ArrayList<PrioritizedVRAListener>();
CalculatorBuilder calcBuilder = new CalculatorBuilder(iListeners, algorithmListeners);
if(local){
calcBuilder.setLocalLevel();
}
else {
calcBuilder.setRouteLevel(forwaredLooking, memory);
}
calcBuilder.setConstraintManager(constraintManager);
calcBuilder.setStates(stateManager);
calcBuilder.setVehicleRoutingProblem(vrp);
calcBuilder.setVehicleFleetManager(fleetManager);
calcBuilder.setActivityInsertionCostsCalculator(actInsertionCostsCalculator);
if(considerFixedCosts) {
calcBuilder.considerFixedCosts(weightOfFixedCosts);
}
JobInsertionCostsCalculator jobInsertions = calcBuilder.build();
BestInsertion bestInsertion = new BestInsertion(jobInsertions);
for(InsertionListener l : iListeners) bestInsertion.addListener(l);
return bestInsertion;
}
}

View file

@ -0,0 +1,19 @@
package algorithms;
import basics.VehicleRoutingProblem;
public class BestInsertionStrategyFactory implements InsertionStrategyFactory{
private JobInsertionCostsCalculator jobInsertionCalculator;
public BestInsertionStrategyFactory(JobInsertionCostsCalculator jobInsertionCalculator) {
super();
this.jobInsertionCalculator = jobInsertionCalculator;
}
@Override
public InsertionStrategy createStrategy(VehicleRoutingProblem vrp) {
return new BestInsertion(jobInsertionCalculator);
}
}

View file

@ -27,11 +27,11 @@ import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalculator{
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsCalculator{
private static Logger log = Logger.getLogger(CalculatesServiceInsertionWithTimeScheduling.class);
private JobInsertionCalculator jic;
private JobInsertionCostsCalculator jic;
private Random random = new Random();
@ -39,7 +39,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul
private double timeSlice = 900.0;
public CalculatesServiceInsertionWithTimeScheduling(JobInsertionCalculator jic, double timeSlice, int neighbors) {
public CalculatesServiceInsertionWithTimeScheduling(JobInsertionCostsCalculator jic, double timeSlice, int neighbors) {
super();
this.jic = jic;
this.timeSlice = timeSlice;
@ -53,7 +53,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul
}
@Override
public InsertionData calculate(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
List<Double> vehicleDepartureTimes = new ArrayList<Double>();
double currentStart;
if(currentRoute.getStart() == null){
@ -74,7 +74,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul
InsertionData bestIData = null;
for(Double departureTime : vehicleDepartureTimes){
InsertionData iData = jic.calculate(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore);
InsertionData iData = jic.getInsertionData(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore);
if(bestIData == null) bestIData = iData;
else if(iData.getInsertionCost() < bestIData.getInsertionCost()){
iData.setVehicleDepartureTime(departureTime);

View file

@ -0,0 +1,38 @@
/*******************************************************************************
* 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 basics.route.TourActivity;
class CalculationUtils {
/**
* Calculates actEndTime assuming that activity can at earliest start at act.getTheoreticalEarliestOperationStartTime().
*
* @param actArrTime
* @param act
* @return
*/
public static double getActivityEndTime(double actArrTime, TourActivity act){
return Math.max(actArrTime, act.getTheoreticalEarliestOperationStartTime()) + act.getOperationTime();
}
}

View file

@ -19,10 +19,10 @@ package algorithms;
import java.util.ArrayList;
import java.util.List;
import algorithms.HardConstraints.ConstraintManager;
import basics.VehicleRoutingProblem;
import basics.algo.InsertionListener;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import basics.route.VehicleFleetManager;
@ -30,16 +30,16 @@ class CalculatorBuilder {
private static class CalculatorPlusListeners {
private JobInsertionCalculator calculator;
private JobInsertionCostsCalculator calculator;
public JobInsertionCalculator getCalculator() {
public JobInsertionCostsCalculator getCalculator() {
return calculator;
}
private List<PrioritizedVRAListener> algorithmListener = new ArrayList<PrioritizedVRAListener>();
private List<InsertionListener> insertionListener = new ArrayList<InsertionListener>();
public CalculatorPlusListeners(JobInsertionCalculator calculator) {
public CalculatorPlusListeners(JobInsertionCostsCalculator calculator) {
super();
this.calculator = calculator;
}
@ -59,7 +59,7 @@ class CalculatorBuilder {
private VehicleRoutingProblem vrp;
private StateManager states;
private StateGetter states;
private boolean local = true;
@ -80,6 +80,8 @@ class CalculatorBuilder {
private int neighbors;
private ConstraintManager constraintManager;
private ActivityInsertionCostsCalculator activityInsertionCostCalculator = null;
/**
* Constructs the builder.
@ -102,7 +104,7 @@ class CalculatorBuilder {
*
* @return
*/
public CalculatorBuilder setStates(StateManager states){
public CalculatorBuilder setStates(StateGetter states){
this.states = states;
return this;
}
@ -137,6 +139,10 @@ class CalculatorBuilder {
public void setLocalLevel(){
local = true;
}
public void setActivityInsertionCostsCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator){
this.activityInsertionCostCalculator = activityInsertionCostsCalculator;
}
/**
* Sets a flag to build a calculator that evaluates job insertion on route-level.
@ -173,11 +179,11 @@ class CalculatorBuilder {
* @return jobInsertionCalculator.
* @throws IllegalStateException if vrp == null or activityStates == null or fleetManager == null.
*/
public JobInsertionCalculator build(){
public JobInsertionCostsCalculator build(){
if(vrp == null) throw new IllegalStateException("vehicle-routing-problem is null, but it must be set (this.setVehicleRoutingProblem(vrp))");
if(states == null) throw new IllegalStateException("states is null, but is must be set (this.setStates(states))");
if(fleetManager == null) throw new IllegalStateException("fleetManager is null, but it must be set (this.setVehicleFleetManager(fleetManager))");
JobInsertionCalculator baseCalculator = null;
JobInsertionCostsCalculator baseCalculator = null;
CalculatorPlusListeners standardLocal = null;
if(local){
standardLocal = createStandardLocal(vrp, states);
@ -212,40 +218,58 @@ class CalculatorBuilder {
}
}
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateManager statesManager){
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateGetter statesManager){
if(constraintManager == null) throw new IllegalStateException("constraint-manager is null");
ActivityInsertionCostsCalculator defaultCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager);
JobInsertionCalculator standardServiceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), defaultCalc, constraintManager);
//<<<<<<< HEAD
// ActivityInsertionCostsCalculator defaultCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager);
// JobInsertionCalculator standardServiceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), defaultCalc, constraintManager);
//
//=======
ActivityInsertionCostsCalculator actInsertionCalc;
if(activityInsertionCostCalculator == null){
actInsertionCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts());
}
else{
actInsertionCalc = activityInsertionCostCalculator;
}
JobInsertionCostsCalculator standardServiceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
//>>>>>>> refs/remotes/choose_remote_name/relaxAPI
((ServiceInsertionCalculator) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion);
return calcPlusListeners;
}
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCalculator baseCalculator, StateManager activityStates2, double weightOfFixedCosts){
final CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(baseCalculator, activityStates2);
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCostsCalculator baseCalculator, StateGetter activityStates2, double weightOfFixedCosts){
final JobInsertionConsideringFixCostsCalculator withFixCost = new JobInsertionConsideringFixCostsCalculator(baseCalculator, activityStates2);
withFixCost.setWeightOfFixCost(weightOfFixedCosts);
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost);
calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost));
return calcPlusListeners;
}
private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, StateManager activityStates2, int forwardLooking, int solutionMemory){
private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, StateGetter activityStates2, int forwardLooking, int solutionMemory){
int after = forwardLooking;
ActivityInsertionCostsCalculator routeLevelCostEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager, activityStates2);
JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager, routeLevelCostEstimator);
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNuOfActsForwardLooking(after);
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setMemorySize(solutionMemory);
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood());
((CalculatesServiceInsertionOnRouteLevel) jobInsertionCalculator).setStates(activityStates2);
ActivityInsertionCostsCalculator routeLevelCostEstimator;
if(activityInsertionCostCalculator == null){
routeLevelCostEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), activityStates2);
}
else{
routeLevelCostEstimator = activityInsertionCostCalculator;
}
JobInsertionCostsCalculator jobInsertionCalculator = new ServiceInsertionOnRouteLevelCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), routeLevelCostEstimator, constraintManager, constraintManager);
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setNuOfActsForwardLooking(after);
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setMemorySize(solutionMemory);
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood());
((ServiceInsertionOnRouteLevelCalculator) jobInsertionCalculator).setStates(activityStates2);
CalculatorPlusListeners calcPlusListener = new CalculatorPlusListeners(jobInsertionCalculator);
return calcPlusListener;
}
private JobInsertionCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCalculator baseCalc, StateManager activityStates2){
return new CalculatesVehTypeDepServiceInsertion(fleetManager, baseCalc);
private JobInsertionCostsCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCostsCalculator baseCalc, StateGetter activityStates2){
return new VehicleTypeDependentJobInsertionCalculator(fleetManager, baseCalc);
}
public void setConstraintManager(ConstraintManager constraintManager) {

View file

@ -37,11 +37,11 @@ final class ConfigureFixCostCalculator implements InsertionStartsListener, JobIn
VehicleRoutingProblem vrp;
CalculatesServiceInsertionConsideringFixCost calcConsideringFix;
JobInsertionConsideringFixCostsCalculator calcConsideringFix;
private int nuOfJobsToRecreate;
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, CalculatesServiceInsertionConsideringFixCost calcConsideringFix) {
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, JobInsertionConsideringFixCostsCalculator calcConsideringFix) {
super();
this.vrp = vrp;
this.calcConsideringFix = calcConsideringFix;

View file

@ -0,0 +1,29 @@
package algorithms;
import basics.route.TourActivity;
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 ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
return actLevelConstraintManager.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
}
}

View file

@ -27,7 +27,7 @@ class EuclideanServiceDistance implements JobDistance {
}
@Override
public double calculateDistance(Job i, Job j) {
public double getDistance(Job i, Job j) {
double avgCost = 0.0;
if (i instanceof Service && j instanceof Service) {
if (i.equals(j)) {

View file

@ -24,6 +24,7 @@ import org.apache.log4j.Logger;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleFleetManager;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
@ -41,13 +42,13 @@ final class FindCheaperVehicleAlgo {
private double weightFixCosts = 1.0;
private StateManager states;
private StateGetter states;
public void setWeightFixCosts(double weightFixCosts) {
this.weightFixCosts = weightFixCosts;
}
public void setStates(StateManager states) {
public void setStates(StateGetter states) {
this.states = states;
}
@ -79,11 +80,11 @@ final class FindCheaperVehicleAlgo {
if(vehicle.getType().getTypeId().equals(vehicleRoute.getVehicle().getType().getTypeId())){
continue;
}
if(states.getRouteState(vehicleRoute,StateTypes.LOAD).toDouble() <= vehicle.getCapacity()){
if(states.getRouteState(vehicleRoute,StateFactory.LOAD).toDouble() <= vehicle.getCapacity()){
double fixCostSaving = vehicleRoute.getVehicle().getType().getVehicleCostParams().fix - vehicle.getType().getVehicleCostParams().fix;
double departureTime = vehicleRoute.getStart().getEndTime();
double newCost = auxilliaryCostCalculator.costOfPath(path, departureTime, vehicleRoute.getDriver(), vehicle);
double varCostSaving = states.getRouteState(vehicleRoute, StateTypes.COSTS).toDouble() - newCost;
double varCostSaving = states.getRouteState(vehicleRoute, StateFactory.COSTS).toDouble() - newCost;
double totalCostSaving = varCostSaving + weightFixCosts*fixCostSaving;
if(totalCostSaving > bestSaving){
bestSaving = totalCostSaving;

View file

@ -28,14 +28,15 @@ import java.util.Set;
import org.apache.log4j.Logger;
import util.RandomNumberGeneration;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.InsertionListener;
import basics.algo.RuinListener;
import basics.algo.SearchStrategyModule;
import basics.algo.SearchStrategyModuleListener;
import basics.route.TourActivity;
import basics.route.VehicleFleetManager;
import basics.route.TourActivity.JobActivity;
import basics.route.VehicleRoute;

View file

@ -0,0 +1,15 @@
package algorithms;
import basics.route.TourActivity;
public interface HardActivityLevelConstraint {
static enum ConstraintsStatus {
NOT_FULFILLED_BREAK, NOT_FULFILLED, FULFILLED;
}
public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime);
}

View file

@ -0,0 +1,27 @@
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
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 ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
for(HardActivityLevelConstraint constraint : hardConstraints){
ConstraintsStatus status = constraint.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK) || status.equals(ConstraintsStatus.NOT_FULFILLED)){
return status;
}
}
return ConstraintsStatus.FULFILLED;
}
}

View file

@ -1,382 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package 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.DeliverService;
import basics.route.DeliverShipment;
import basics.route.DeliveryActivity;
import basics.route.PickupActivity;
import basics.route.PickupService;
import basics.route.PickupShipment;
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;
private boolean backhaul = false;
public HardPickupAndDeliveryActivityLevelConstraint(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
public HardPickupAndDeliveryActivityLevelConstraint(StateManager stateManager, boolean backhaul) {
super();
this.stateManager = stateManager;
this.backhaul = backhaul;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(!(newAct instanceof PickupService) && !(newAct instanceof DeliverService)){
return true;
}
if(backhaul){
if(newAct instanceof PickupService && nextAct instanceof DeliverService){ return false; }
if(newAct instanceof DeliverService && prevAct instanceof PickupService){ 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 PickupService){
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
if(newAct instanceof DeliverService){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
return true;
}
}
static class HardPickupAndDeliveryShipmentActivityLevelConstraint implements HardActivityLevelConstraint {
private StateManager stateManager;
private boolean backhaul = false;
public HardPickupAndDeliveryShipmentActivityLevelConstraint(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
public HardPickupAndDeliveryShipmentActivityLevelConstraint(StateManager stateManager, boolean backhaul) {
super();
this.stateManager = stateManager;
this.backhaul = backhaul;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(!(newAct instanceof PickupShipment) && !(newAct instanceof DeliverShipment)){
return true;
}
if(backhaul){
// if(newAct instanceof PickupShipment && nextAct instanceof DeliverShipment){ return false; }
if(newAct instanceof DeliverShipment && prevAct instanceof PickupShipment){ 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 PickupShipment){
if(loadAtPrevAct + newAct.getCapacityDemand() > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
if(newAct instanceof DeliverShipment){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) > 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 PickupService && nextAct instanceof DeliverService){ return false; }
// if(newAct instanceof ServiceActivity && nextAct instanceof DeliveryActivity){ return false; }
if(newAct instanceof DeliverService && prevAct instanceof PickupService){ 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;
}
}
}

View file

@ -0,0 +1,23 @@
package algorithms;
import basics.Service;
class HardLoadConstraint implements HardRouteLevelConstraint{
private StateGetter states;
public HardLoadConstraint(StateGetter states) {
super();
this.states = states;
}
@Override
public boolean fulfilled(InsertionContext insertionContext) {
int currentLoad = (int) states.getRouteState(insertionContext.getRoute(), StateFactory.LOAD).toDouble();
Service service = (Service) insertionContext.getJob();
if(currentLoad + service.getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
return false;
}
return true;
}
}

View file

@ -0,0 +1,47 @@
package algorithms;
import basics.route.DeliveryActivity;
import basics.route.PickupActivity;
import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.TourActivity;
class HardPickupAndDeliveryActivityLevelConstraint implements HardActivityLevelConstraint {
private StateGetter stateManager;
public HardPickupAndDeliveryActivityLevelConstraint(StateGetter stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public ConstraintsStatus 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(), StateFactory.LOAD_AT_BEGINNING).toDouble();
futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_END).toDouble();
pastDeliveries = 0;
}
else{
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateFactory.LOAD).toDouble();
futurePicks = (int) stateManager.getActivityState(prevAct, StateFactory.FUTURE_PICKS).toDouble();
pastDeliveries = (int) stateManager.getActivityState(prevAct, StateFactory.PAST_DELIVERIES).toDouble();
}
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
return ConstraintsStatus.NOT_FULFILLED;
}
}
if(newAct instanceof DeliveryActivity){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
return ConstraintsStatus.NOT_FULFILLED;
}
}
return ConstraintsStatus.FULFILLED;
}
}

View file

@ -0,0 +1,51 @@
package algorithms;
import basics.route.DeliveryActivity;
import basics.route.PickupActivity;
import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.TourActivity;
class HardPickupAndDeliveryBackhaulActivityLevelConstraint implements HardActivityLevelConstraint {
private StateGetter stateManager;
public HardPickupAndDeliveryBackhaulActivityLevelConstraint(StateGetter stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(newAct instanceof PickupActivity && nextAct instanceof DeliveryActivity){ return ConstraintsStatus.NOT_FULFILLED; }
if(newAct instanceof ServiceActivity && nextAct instanceof DeliveryActivity){ return ConstraintsStatus.NOT_FULFILLED; }
if(newAct instanceof DeliveryActivity && prevAct instanceof PickupActivity){ return ConstraintsStatus.NOT_FULFILLED; }
if(newAct instanceof DeliveryActivity && prevAct instanceof ServiceActivity){ return ConstraintsStatus.NOT_FULFILLED; }
int loadAtPrevAct;
int futurePicks;
int pastDeliveries;
if(prevAct instanceof Start){
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_BEGINNING).toDouble();
futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_END).toDouble();
pastDeliveries = 0;
}
else{
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateFactory.LOAD).toDouble();
futurePicks = (int) stateManager.getActivityState(prevAct, StateFactory.FUTURE_PICKS).toDouble();
pastDeliveries = (int) stateManager.getActivityState(prevAct, StateFactory.PAST_DELIVERIES).toDouble();
}
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
return ConstraintsStatus.NOT_FULFILLED;
}
}
if(newAct instanceof DeliveryActivity){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
return ConstraintsStatus.NOT_FULFILLED;
}
}
return ConstraintsStatus.FULFILLED;
}
}

View file

@ -0,0 +1,39 @@
package algorithms;
import basics.Delivery;
import basics.Pickup;
import basics.Service;
/**
* lsjdfjsdlfjsa
*
* @author stefan
*
*/
class HardPickupAndDeliveryLoadRouteLevelConstraint implements HardRouteLevelConstraint {
private StateGetter stateManager;
public HardPickupAndDeliveryLoadRouteLevelConstraint(StateGetter stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public boolean fulfilled(InsertionContext insertionContext) {
if(insertionContext.getJob() instanceof Delivery){
int loadAtDepot = (int) stateManager.getRouteState(insertionContext.getRoute(), StateFactory.LOAD_AT_BEGINNING).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(), StateFactory.LOAD_AT_END).toDouble();
if(loadAtEnd + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
return false;
}
}
return true;
}
}

View file

@ -0,0 +1,8 @@
package algorithms;
public interface HardRouteLevelConstraint {
public boolean fulfilled(InsertionContext insertionContext);
}

View file

@ -0,0 +1,25 @@
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
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;
}
}

View file

@ -0,0 +1,51 @@
package algorithms;
import org.apache.log4j.Logger;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.TourActivity;
/**
* ljsljslfjs
* @author stefan
*
*/
class HardTimeWindowActivityLevelConstraint implements HardActivityLevelConstraint {
private static Logger log = Logger.getLogger(HardTimeWindowActivityLevelConstraint.class);
private StateGetter states;
private VehicleRoutingTransportCosts routingCosts;
public HardTimeWindowActivityLevelConstraint(StateGetter states, VehicleRoutingTransportCosts routingCosts) {
super();
this.states = states;
this.routingCosts = routingCosts;
}
@Override
public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(newAct.getTheoreticalLatestOperationStartTime() < prevAct.getTheoreticalEarliestOperationStartTime()){
return ConstraintsStatus.NOT_FULFILLED_BREAK;
}
if(newAct.getTheoreticalEarliestOperationStartTime() > nextAct.getTheoreticalLatestOperationStartTime()){
return ConstraintsStatus.NOT_FULFILLED;
}
// 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, StateFactory.LATEST_OPERATION_START_TIME).toDouble();
if(arrTimeAtNewAct > latestArrTimeAtNewAct){
return ConstraintsStatus.NOT_FULFILLED;
}
// 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, StateFactory.LATEST_OPERATION_START_TIME).toDouble();
if(arrTimeAtNextAct > latestArrTimeAtNextAct){
return ConstraintsStatus.NOT_FULFILLED;
}
return ConstraintsStatus.FULFILLED;
}
}

View file

@ -21,8 +21,8 @@ import basics.VehicleRoutingProblemSolution;
interface InitialSolutionFactory {
public interface InitialSolutionFactory {
public VehicleRoutingProblemSolution createInitialSolution(VehicleRoutingProblem vrp);
public VehicleRoutingProblemSolution createSolution(VehicleRoutingProblem vrp);
}

View file

@ -21,7 +21,7 @@ import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
class InsertionContext {
public class InsertionContext {
private VehicleRoute route;
private Job job;

View file

@ -19,9 +19,14 @@ package algorithms;
import basics.route.Driver;
import basics.route.Vehicle;
class InsertionData {
/**
* Data object that collects insertion information. It collects insertionCosts, insertionIndeces, vehicle and driver to be employed
* and departureTime of vehicle at vehicle's start location (e.g. depot).
*
* @author stefan
*
*/
public class InsertionData {
static class NoInsertionFound extends InsertionData{
@ -33,7 +38,15 @@ class InsertionData {
private static InsertionData noInsertion = new NoInsertionFound();
public static InsertionData noInsertionFound(){
/**
* Returns an instance of InsertionData that represents an EmptyInsertionData (which might indicate
* that no insertion has been found). It is internally instantiated as follows:<br>
* <code>new InsertionData(Double.MAX_VALUE, NO_INDEX, NO_INDEX, null, null);</code><br>
* where NO_INDEX=-1.
*
* @return
*/
public static InsertionData createEmptyInsertionData(){
return noInsertion;
}
@ -80,22 +93,47 @@ class InsertionData {
return "[iCost="+insertionCost+"][iIndex="+deliveryInsertionIndex+"][depTime="+departureTime+"][vehicle="+selectedVehicle+"][driver="+selectedDriver+"]";
}
/**
* Returns insertionIndex of deliveryActivity. If no insertionPosition is found, it returns NO_INDEX (=-1).
*
* @return
*/
public int getDeliveryInsertionIndex(){
return deliveryInsertionIndex;
}
/**
* Returns insertionIndex of pickkupActivity. If no insertionPosition is found, it returns NO_INDEX (=-1).
*
* @return
*/
public int getPickupInsertionIndex(){
return pickupInsertionIndex;
}
/**
* Returns insertion costs (which might be the additional costs of inserting the corresponding job).
*
* @return
*/
public double getInsertionCost() {
return insertionCost;
}
/**
* Returns the vehicle to be employed.
*
* @return
*/
public Vehicle getSelectedVehicle() {
return selectedVehicle;
}
/**
* Returns the vehicle to be employed.
*
* @return
*/
public Driver getSelectedDriver(){
return selectedDriver;
}

View file

@ -23,19 +23,18 @@ import java.util.concurrent.ExecutorService;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.log4j.Logger;
import algorithms.HardConstraints.ConstraintManager;
import basics.VehicleRoutingProblem;
import basics.algo.InsertionListener;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import basics.route.VehicleFleetManager;
class InsertionFactory {
private static Logger log = Logger.getLogger(InsertionFactory.class);
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){
boolean concurrentInsertion = false;
if(executorService != null) concurrentInsertion = true;
VehicleFleetManager vehicleFleetManager, StateManager routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){
if(config.containsKey("[@name]")){
String insertionName = config.getString("[@name]");
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
@ -89,27 +88,14 @@ class InsertionFactory {
calcBuilder.experimentalTimeScheduler(Double.parseDouble(timeSliceString),Integer.parseInt(neighbors));
}
JobInsertionCalculator jic = calcBuilder.build();
JobInsertionCostsCalculator jic = calcBuilder.build();
if(insertionName.equals("bestInsertion")){
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);
// insertionStrategy.addListener(new FindCheaperVehicle(
// new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator)));
algorithmListeners.addAll(algoListeners);
return insertionStrategy;

View file

@ -1,18 +1,14 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
* Copyright (c) 2011 Stefan Schroeder.
* eMail: stefan.schroeder@kit.edu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
/* *********************************************************************** *
* project: org.matsim.*
@ -45,48 +41,34 @@ import basics.Job;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.SolutionCostCalculator;
import basics.route.DriverImpl;
import basics.route.TourActivities;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
final class CreateInitialSolution implements InitialSolutionFactory {
public final class InsertionInitialSolutionFactory implements InitialSolutionFactory {
private static final Logger logger = Logger.getLogger(CreateInitialSolution.class);
private static final Logger logger = Logger.getLogger(InsertionInitialSolutionFactory.class);
private final InsertionStrategy insertion;
private SolutionCostCalculator solutionCostCalculator;
private boolean generateAsMuchAsRoutesAsVehiclesExist = false;
public void setGenerateAsMuchAsRoutesAsVehiclesExist(boolean generateAsMuchAsRoutesAsVehiclesExist) {
this.generateAsMuchAsRoutesAsVehiclesExist = generateAsMuchAsRoutesAsVehiclesExist;
}
public CreateInitialSolution(InsertionStrategy insertionStrategy, SolutionCostCalculator solutionCostCalculator) {
private SolutionCostCalculator solutionCostsCalculator;
public InsertionInitialSolutionFactory(InsertionStrategy insertionStrategy, SolutionCostCalculator solutionCostCalculator) {
super();
this.insertion = insertionStrategy;
this.solutionCostCalculator = solutionCostCalculator;
this.solutionCostsCalculator = solutionCostCalculator;
}
@Override
public VehicleRoutingProblemSolution createInitialSolution(final VehicleRoutingProblem vrp) {
public VehicleRoutingProblemSolution createSolution(final VehicleRoutingProblem vrp) {
logger.info("create initial solution.");
List<VehicleRoute> vehicleRoutes = new ArrayList<VehicleRoute>();
if(generateAsMuchAsRoutesAsVehiclesExist){
for(Vehicle vehicle : vrp.getVehicles()){
vehicleRoutes.add(VehicleRoute.newInstance(TourActivities.emptyTour(), DriverImpl.noDriver(), vehicle));
}
}
insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp));
// double totalCost = getTotalCost(vehicleRoutes);
VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(vehicleRoutes, Double.MAX_VALUE);
double costs = solutionCostsCalculator.getCosts(solution);
solution.setCost(costs);
logger.info("creation done");
VehicleRoutingProblemSolution vehicleRoutingProblemSolution = new VehicleRoutingProblemSolution(vehicleRoutes, 0.0);
solutionCostCalculator.calculateCosts(vehicleRoutingProblemSolution);
return vehicleRoutingProblemSolution;
return solution;
}
private List<Job> getUnassignedJobs(VehicleRoutingProblem vrp) {

View file

@ -31,33 +31,7 @@ import basics.route.VehicleRoute;
*
*/
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;
}
}
public interface InsertionStrategy {
/**
* Assigns the unassigned jobs to service-providers

View file

@ -0,0 +1,7 @@
package algorithms;
public interface InsertionStrategyBuilder {
public InsertionStrategy build();
}

View file

@ -1,82 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.Iterator;
import org.apache.log4j.Logger;
import algorithms.BackwardInTimeListeners.BackwardInTimeListener;
import basics.costs.BackwardTransportTime;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
/**
*
* @author stefan schroeder
*
*/
class IterateRouteBackwardInTime implements VehicleRouteUpdater{
private static Logger log = Logger.getLogger(IterateRouteBackwardInTime.class);
private BackwardTransportTime transportTime;
private BackwardInTimeListeners listeners;
public IterateRouteBackwardInTime(BackwardTransportTime transportTime) {
super();
this.transportTime = transportTime;
listeners = new BackwardInTimeListeners();
}
/*
*
*/
public void iterate(VehicleRoute vehicleRoute) {
if(listeners.isEmpty()) return;
if(vehicleRoute.isEmpty()) return;
listeners.start(vehicleRoute, vehicleRoute.getEnd(), vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime());
Iterator<TourActivity> reverseActIter = vehicleRoute.getTourActivities().reverseActivityIterator();
TourActivity prevAct;
prevAct = vehicleRoute.getEnd();
double latestArrivalTimeAtPrevAct = prevAct.getTheoreticalLatestOperationStartTime();
while(reverseActIter.hasNext()){
TourActivity currAct = reverseActIter.next();
double latestDepTimeAtCurrAct = latestArrivalTimeAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), latestArrivalTimeAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle());
double potentialLatestArrivalTimeAtCurrAct = latestDepTimeAtCurrAct - currAct.getOperationTime();
double latestArrivalTime = Math.min(currAct.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct);
listeners.prevActivity(currAct, latestDepTimeAtCurrAct, latestArrivalTime);
prevAct = currAct;
latestArrivalTimeAtPrevAct = latestArrivalTime;
}
TourActivity currAct = vehicleRoute.getStart();
double latestDepTimeAtCurrAct = latestArrivalTimeAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), latestArrivalTimeAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle());
listeners.end(vehicleRoute.getStart(), latestDepTimeAtCurrAct);
}
public void addListener(BackwardInTimeListener l){ listeners.addListener(l); }
}

View file

@ -1,87 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import org.apache.log4j.Logger;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import basics.costs.ForwardTransportTime;
import basics.route.Driver;
import basics.route.End;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
/**
*
* @author sschroeder
*
*/
class IterateRouteForwardInTime implements VehicleRouteUpdater{
private static Logger log = Logger.getLogger(IterateRouteForwardInTime.class);
private ForwardTransportTime transportTime;
private ForwardInTimeListeners listeners;
public IterateRouteForwardInTime(ForwardTransportTime transportTime) {
super();
this.transportTime = transportTime;
listeners = new ForwardInTimeListeners();
}
/**
*
*
*/
public void iterate(VehicleRoute vehicleRoute) {
if(listeners.isEmpty()) return;
if(vehicleRoute.isEmpty()) return;
listeners.start(vehicleRoute, vehicleRoute.getStart(), vehicleRoute.getStart().getEndTime());
Vehicle vehicle = vehicleRoute.getVehicle();
Driver driver = vehicleRoute.getDriver();
TourActivity prevAct = vehicleRoute.getStart();
double startAtPrevAct = prevAct.getEndTime();
for(TourActivity currentAct : vehicleRoute.getTourActivities().getActivities()){
double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
double operationStartTime = Math.max(currentAct.getTheoreticalEarliestOperationStartTime(), arrivalTimeAtCurrAct);
double operationEndTime = operationStartTime + currentAct.getOperationTime();
listeners.nextActivity(currentAct,arrivalTimeAtCurrAct,operationEndTime);
prevAct = currentAct;
startAtPrevAct = operationEndTime;
}
End currentAct = vehicleRoute.getEnd();
double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
listeners.end(vehicleRoute.getEnd(), arrivalTimeAtCurrAct);
}
public void addListener(ForwardInTimeListener l){
listeners.addListener(l);
}
}

View file

@ -8,18 +8,18 @@ import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
public class JobCalculatorSwitcher implements JobInsertionCalculator{
public class JobCalculatorSwitcher implements JobInsertionCostsCalculator{
private Map<Class<? extends Job>,JobInsertionCalculator> calcMap = new HashMap<Class<? extends Job>, JobInsertionCalculator>();
private Map<Class<? extends Job>,JobInsertionCostsCalculator> calcMap = new HashMap<Class<? extends Job>, JobInsertionCostsCalculator>();
void put(Class<? extends Job> jobClass, JobInsertionCalculator jic){
void put(Class<? extends Job> jobClass, JobInsertionCostsCalculator jic){
calcMap.put(jobClass, jic);
}
public InsertionData calculate(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore){
JobInsertionCalculator jic = calcMap.get(jobToInsert.getClass());
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore){
JobInsertionCostsCalculator jic = calcMap.get(jobToInsert.getClass());
if(jic==null) throw new IllegalStateException("cannot find calculator for " + jobToInsert.getClass());
return jic.calculate(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownScore);
return jic.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownScore);
}
}

View file

@ -20,8 +20,8 @@ import basics.Job;
interface JobDistance {
public interface JobDistance {
public double calculateDistance(Job i, Job j);
public double getDistance(Job i, Job j);
}

View file

@ -49,7 +49,7 @@ class JobDistanceAvgCosts implements JobDistance {
* <p>If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
*/
@Override
public double calculateDistance(Job i, Job j) {
public double getDistance(Job i, Job j) {
double avgCost = 0.0;
if (i instanceof Service && j instanceof Service) {
if (i.equals(j)) {
@ -76,7 +76,7 @@ class JobDistanceAvgCosts implements JobDistance {
// now try the euclidean distance between these two services
}
EuclideanServiceDistance euclidean = new EuclideanServiceDistance();
distance = euclidean.calculateDistance(s_i, s_j);
distance = euclidean.getDistance(s_i, s_j);
return distance;
}

View file

@ -33,7 +33,7 @@ class JobDistanceBeeline implements JobDistance {
}
@Override
public double calculateDistance(Job i, Job j) {
public double getDistance(Job i, Job j) {
double avgCost = 0.0;
if (i instanceof Service && j instanceof Service) {
if (i.equals(j)) {

View file

@ -27,35 +27,35 @@ import basics.route.VehicleRoute;
final class CalculatesServiceInsertionConsideringFixCost implements JobInsertionCalculator{
final class JobInsertionConsideringFixCostsCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertionConsideringFixCost.class);
private static final Logger logger = Logger.getLogger(JobInsertionConsideringFixCostsCalculator.class);
private final JobInsertionCalculator standardServiceInsertion;
private final JobInsertionCostsCalculator standardServiceInsertion;
private double weight_deltaFixCost = 0.5;
private double solution_completeness_ratio = 0.5;
private StateManager states;
private StateGetter stateGetter;
public CalculatesServiceInsertionConsideringFixCost(final JobInsertionCalculator standardInsertionCalculator, StateManager activityStates2) {
public JobInsertionConsideringFixCostsCalculator(final JobInsertionCostsCalculator standardInsertionCalculator, StateGetter stateGetter) {
super();
this.standardServiceInsertion = standardInsertionCalculator;
this.states = activityStates2;
this.stateGetter = stateGetter;
logger.info("inialise " + this);
}
@Override
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) {
double relFixCost = getDeltaRelativeFixCost(currentRoute, newVehicle, jobToInsert);
double absFixCost = getDeltaAbsoluteFixCost(currentRoute, newVehicle, jobToInsert);
double deltaFixCost = (1-solution_completeness_ratio)*relFixCost + solution_completeness_ratio*absFixCost;
double fixcost_contribution = weight_deltaFixCost*solution_completeness_ratio*deltaFixCost;
if(fixcost_contribution > bestKnownPrice){
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
InsertionData iData = standardServiceInsertion.calculate(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice);
InsertionData iData = standardServiceInsertion.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice);
if(iData instanceof NoInsertionFound){
return iData;
}
@ -80,7 +80,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
}
private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
double load = getCurrentLoad(route) + job.getCapacityDemand();
double load = getCurrentMaxLoadInRoute(route) + job.getCapacityDemand();
double currentFix = 0.0;
if(route.getVehicle() != null){
if(!(route.getVehicle() instanceof NoVehicle)){
@ -94,7 +94,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
}
private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
int currentLoad = getCurrentLoad(route);
int currentLoad = getCurrentMaxLoadInRoute(route);
double load = currentLoad + job.getCapacityDemand();
double currentRelFix = 0.0;
if(route.getVehicle() != null){
@ -109,8 +109,8 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
return relativeFixCost;
}
private int getCurrentLoad(VehicleRoute route) {
return (int) states.getRouteState(route, StateTypes.LOAD).toDouble();
private int getCurrentMaxLoadInRoute(VehicleRoute route) {
return (int) stateGetter.getRouteState(route, StateFactory.MAXLOAD).toDouble();
}
}

View file

@ -22,8 +22,8 @@ import basics.route.Vehicle;
import basics.route.VehicleRoute;
interface JobInsertionCalculator {
public interface JobInsertionCostsCalculator {
public InsertionData calculate(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore);
public InsertionData getInsertionData(VehicleRoute currentRoute, Job newJob, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownCosts);
}

View file

@ -20,38 +20,42 @@
******************************************************************************/
package algorithms;
import algorithms.HardConstraints.HardActivityLevelConstraint;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.TourActivity;
/**
* Calculates activity insertion costs locally, i.e. by comparing the additional costs of insertion the new activity k between
* activity i (prevAct) and j (nextAct).
* Additional costs are then basically calculated as delta c = c_ik + c_kj - c_ij.
*
* <p>Note once time has an effect on costs this class requires activity endTimes.
*
* @author stefan
*
*/
class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCalculator{
private HardActivityLevelConstraint hardConstraint;
private VehicleRoutingTransportCosts routingCosts;
private VehicleRoutingActivityCosts activityCosts;
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint) {
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts) {
super();
this.routingCosts = routingCosts;
this.activityCosts = actCosts;
this.hardConstraint = hardActivityLevelConstraint;
}
@Override
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
if(!hardConstraint.fulfilled(iFacts, prevAct, newAct, nextAct, depTimeAtPrevAct)){
return null;
}
public ActivityInsertionCosts getCosts(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
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());

View file

@ -35,7 +35,7 @@ import basics.algo.VehicleRoutingAlgorithmFactory;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
public class NeighborhoodThresholdInitialiser implements AlgorithmStartsListener{
class NeighborhoodThresholdInitialiser implements AlgorithmStartsListener{
private static Logger log = Logger.getLogger(NeighborhoodThresholdInitialiser.class);

View file

@ -0,0 +1,22 @@
package algorithms;
import basics.VehicleRoutingProblem;
public class RadialRuinStrategyFactory implements RuinStrategyFactory{
private double fraction;
private JobDistance jobDistance;
public RadialRuinStrategyFactory(double fraction, JobDistance jobDistance) {
super();
this.fraction = fraction;
this.jobDistance = jobDistance;
}
@Override
public RuinStrategy createStrategy(VehicleRoutingProblem vrp) {
return new RuinRadial(vrp,fraction,jobDistance);
}
}

View file

@ -0,0 +1,19 @@
package algorithms;
import basics.VehicleRoutingProblem;
public class RandomRuinStrategyFactory implements RuinStrategyFactory{
private double fraction;
public RandomRuinStrategyFactory(double fraction) {
super();
this.fraction = fraction;
}
@Override
public RuinStrategy createStrategy(VehicleRoutingProblem vrp) {
return new RuinRandom(vrp, fraction);
}
}

View file

@ -23,6 +23,7 @@ import java.util.List;
import org.apache.log4j.Logger;
import basics.algo.InsertionEndsListener;
import basics.route.VehicleFleetManager;
import basics.route.VehicleRoute;
class RemoveEmptyVehicles implements InsertionEndsListener{
@ -31,7 +32,7 @@ class RemoveEmptyVehicles implements InsertionEndsListener{
private VehicleFleetManager fleetManager;
RemoveEmptyVehicles(VehicleFleetManager fleetManager) {
public RemoveEmptyVehicles(VehicleFleetManager fleetManager) {
super();
this.fleetManager = fleetManager;
}

View file

@ -23,6 +23,7 @@ import org.apache.log4j.Logger;
import basics.Job;
import basics.algo.InsertionStartsListener;
import basics.route.VehicleFleetManager;
import basics.route.VehicleRoute;
class ResetAndIniFleetManager implements InsertionStartsListener{

View file

@ -23,7 +23,6 @@ package algorithms;
import java.util.ArrayList;
import java.util.List;
import algorithms.HardConstraints.HardActivityLevelConstraint;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.End;
@ -33,30 +32,23 @@ import basics.route.VehicleRoute;
class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCostsCalculator{
private HardActivityLevelConstraint hardConstraint;
private VehicleRoutingActivityCosts activityCosts;
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
private StateManager stateManager;
private StateGetter stateManager;
private int nuOfActivities2LookForward = 0;
public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint, StateManager stateManager) {
public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, StateGetter stateManager) {
super();
this.activityCosts = actCosts;
this.hardConstraint = hardActivityLevelConstraint;
this.stateManager = stateManager;
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(routingCosts, activityCosts);
}
@Override
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
if(!hardConstraint.fulfilled(iFacts, prevAct, newAct, nextAct, depTimeAtPrevAct)){
return null;
}
public ActivityInsertionCosts getCosts(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
List<TourActivity> path = new ArrayList<TourActivity>();
path.add(prevAct); path.add(newAct); path.add(nextAct);
int actIndex;
@ -77,9 +69,9 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost
private double actCostsOld(VehicleRoute vehicleRoute, TourActivity act) {
if(act instanceof End){
return stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble();
return stateManager.getRouteState(vehicleRoute,StateFactory.COSTS).toDouble();
}
return stateManager.getActivityState(act,StateTypes.COSTS).toDouble();
return stateManager.getActivityState(act,StateFactory.COSTS).toDouble();
}
private List<TourActivity> getForwardLookingPath(VehicleRoute route, int actIndex) {

View file

@ -18,14 +18,14 @@ package algorithms;
import java.util.Collection;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.VehicleRoutingProblemSolution;
import basics.algo.InsertionListener;
import basics.algo.RuinListener;
import basics.algo.SearchStrategyModule;
import basics.algo.SearchStrategyModuleListener;
class RuinAndRecreateModule implements SearchStrategyModule{
public class RuinAndRecreateModule implements SearchStrategyModule{
private InsertionStrategy insertion;
@ -44,9 +44,8 @@ class RuinAndRecreateModule implements SearchStrategyModule{
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobs);
// double totalCost = RouteUtils.getTotalCost(vrpSolution.getRoutes());
// vrpSolution.setCost(totalCost);
return vrpSolution;
}
@Override

View file

@ -1,54 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.route.VehicleRoute;
class RuinListeners {
private Collection<RuinListener> ruinListeners = new ArrayList<RuinListener>();
void ruinStarts(Collection<VehicleRoute> routes){
for(RuinListener l : ruinListeners) l.ruinStarts(routes);
}
void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs){
for(RuinListener l : ruinListeners) l.ruinEnds(routes, unassignedJobs);
}
void removed(Job job, VehicleRoute fromRoute){
for(RuinListener l : ruinListeners) l.removed(job, fromRoute);
}
void addListener(RuinListener ruinListener){
ruinListeners.add(ruinListener);
}
void removeListener(RuinListener ruinListener){
ruinListeners.remove(ruinListener);
}
Collection<RuinListener> getListeners(){
return Collections.unmodifiableCollection(ruinListeners);
}
}

View file

@ -33,6 +33,8 @@ import util.RandomNumberGeneration;
import util.StopWatch;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.algo.RuinListener;
import basics.algo.RuinListeners;
import basics.route.VehicleRoute;
@ -120,7 +122,7 @@ final class RuinRadial implements RuinStrategy {
});
distanceNodeTree.put(i.getId(), treeSet);
for (Job j : vrp.getJobs().values()) {
double distance = jobDistance.calculateDistance(i, j);
double distance = jobDistance.getDistance(i, j);
ReferencedJob refNode = new ReferencedJob(j, distance);
treeSet.add(refNode);
nuOfDistancesStored++;

View file

@ -27,6 +27,8 @@ import org.apache.log4j.Logger;
import util.RandomNumberGeneration;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.algo.RuinListener;
import basics.algo.RuinListeners;
import basics.route.VehicleRoute;

View file

@ -19,6 +19,7 @@ package algorithms;
import java.util.Collection;
import basics.Job;
import basics.algo.RuinListener;
import basics.route.VehicleRoute;
@ -30,41 +31,8 @@ import basics.route.VehicleRoute;
*
*/
interface RuinStrategy {
public interface RuinStrategy {
/**
* Listener that listens to the ruin-process. It informs whoever is interested about start, end and about a removal of a job.
*
* @author schroeder
*
*/
public static interface RuinListener {
/**
* informs about ruin-start.
*
* @param routes
*/
public void ruinStarts(Collection<VehicleRoute> routes);
/**
* informs about ruin-end.
*
* @param routes
* @param unassignedJobs
*/
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs);
/**
* informs if a {@link Job} has been removed from a {@link VehicleRoute}.
*
* @param job
* @param fromRoute
*/
public void removed(Job job, VehicleRoute fromRoute);
}
/**
* Ruins a current solution, i.e. a collection of vehicle-routes and
* returns a collection of removed and thus unassigned jobs.

View file

@ -18,7 +18,7 @@ package algorithms;
import basics.VehicleRoutingProblem;
interface RuinStrategyFactory {
public interface RuinStrategyFactory {
public RuinStrategy createStrategy(VehicleRoutingProblem vrp);

View file

@ -20,7 +20,8 @@ import org.apache.log4j.Logger;
import util.Neighborhood;
import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import algorithms.HardConstraints.HardRouteLevelConstraint;
import algorithms.HardActivityLevelConstraint.ConstraintsStatus;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
@ -36,12 +37,14 @@ import basics.route.VehicleRoute;
final class ServiceInsertionCalculator implements JobInsertionCalculator{
final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(ServiceInsertionCalculator.class);
private HardRouteLevelConstraint hardRouteLevelConstraint;
private HardActivityLevelConstraint hardActivityLevelConstraint;
private Neighborhood neighborhood = new Neighborhood() {
@Override
@ -61,10 +64,12 @@ final class ServiceInsertionCalculator implements JobInsertionCalculator{
logger.info("initialise neighborhood " + neighborhood);
}
public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint) {
public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint, HardActivityLevelConstraint hardActivityLevelConstraint) {
super();
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
this.transportCosts = routingCosts;
activityFactory = new DefaultTourActivityFactory();
logger.info("initialise " + this);
@ -81,13 +86,13 @@ final class ServiceInsertionCalculator implements JobInsertionCalculator{
*
*/
@Override
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing.");
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing.");
InsertionContext insertionContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
double bestCost = bestKnownCosts;
@ -99,17 +104,40 @@ final class ServiceInsertionCalculator implements JobInsertionCalculator{
Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
start.setEndTime(newVehicleDepartureTime);
End end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival());
TourActivity prevAct = start;
double prevActStartTime = newVehicleDepartureTime;
int actIndex = 0;
boolean loopBroken = false;
for(TourActivity nextAct : currentRoute.getTourActivities().getActivities()){
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc != null){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
if(status.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc.getAdditionalCosts() < bestCost){
bestCost = mc.getAdditionalCosts();
bestMarginals = mc;
insertionIndex = actIndex;
}
}
else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
loopBroken = true;
break;
}
}
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle);
double nextActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
prevActStartTime = nextActEndTime;
prevAct = nextAct;
actIndex++;
}
End nextAct = end;
if(!loopBroken){
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
if(status.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc.getAdditionalCosts() < bestCost){
bestCost = mc.getAdditionalCosts();
bestMarginals = mc;
@ -117,28 +145,10 @@ final class ServiceInsertionCalculator implements JobInsertionCalculator{
}
}
}
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle);
double nextActEndTime = CalcUtils.getActivityEndTime(nextActArrTime, nextAct);
prevActStartTime = nextActEndTime;
prevAct = nextAct;
actIndex++;
}
End nextAct = end;
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc != null) {
if(mc.getAdditionalCosts() < bestCost){
bestCost = mc.getAdditionalCosts();
bestMarginals = mc;
insertionIndex = actIndex;
}
}
}
if(insertionIndex == InsertionData.NO_INDEX) {
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
@ -147,7 +157,6 @@ final class ServiceInsertionCalculator implements JobInsertionCalculator{
}
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double departureTimeAtPrevAct) {
return activityInsertionCostsCalculator.calculate(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
return activityInsertionCostsCalculator.getCosts(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
}
}

View file

@ -27,7 +27,7 @@ import org.apache.log4j.Logger;
import util.Neighborhood;
import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import algorithms.HardConstraints.HardRouteLevelConstraint;
import algorithms.HardActivityLevelConstraint.ConstraintsStatus;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingActivityCosts;
@ -45,9 +45,9 @@ import basics.route.VehicleRoute;
final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalculator{
final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertionOnRouteLevel.class);
private static final Logger logger = Logger.getLogger(ServiceInsertionOnRouteLevelCalculator.class);
private final VehicleRoutingTransportCosts transportCosts;
@ -57,10 +57,12 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
private TourActivityFactory tourActivityFactory = new DefaultTourActivityFactory();
private StateManager stateManager;
private StateGetter stateManager;
private HardRouteLevelConstraint hardRouteLevelConstraint;
private HardActivityLevelConstraint hardActivityLevelConstraint;
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
private int nuOfActsForwardLooking = 0;
@ -94,18 +96,19 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
logger.info("set [solutionMemory="+memorySize+"]");
}
public CalculatesServiceInsertionOnRouteLevel(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, HardRouteLevelConstraint hardRouteLevelConstraint, ActivityInsertionCostsCalculator activityInsertionCostsCalculator) {
public ServiceInsertionOnRouteLevelCalculator(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint, HardActivityLevelConstraint hardActivityLevelConstraint) {
super();
this.transportCosts = vehicleRoutingCosts;
this.activityCosts = costFunc;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(transportCosts, activityCosts);
logger.info("initialise " + this);
}
public void setStates(StateManager stateManager){
public void setStates(StateGetter stateManager){
this.stateManager = stateManager;
}
@ -128,13 +131,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
*
*/
@Override
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double best_known_insertion_costs) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double best_known_insertion_costs) {
if(jobToInsert == null) throw new IllegalStateException("job is null. cannot calculate the insertion of a null-job.");
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("no vehicle given. set para vehicle!");
InsertionContext insertionContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
/**
@ -150,6 +153,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
TourActivities tour = currentRoute.getTourActivities();
double best_insertion_costs = best_known_insertion_costs;
Service service = (Service)jobToInsert;
/**
* some inis
@ -164,6 +168,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
double sumOf_prevCosts_newVehicle = 0.0;
double prevActDepTime_newVehicle = start.getEndTime();
boolean loopBroken = false;
/**
* inserting serviceAct2Insert in route r={0,1,...,i-1,i,j,j+1,...,n(r),n(r)+1}
* i=prevAct
@ -172,12 +177,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
*/
for(TourActivity nextAct : tour.getActivities()){
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
/**
* builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking}
*/
InsertionContext iContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, prevActDepTime_newVehicle);
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(iContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
if(actInsertionCosts != null){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
if(status.equals(ConstraintsStatus.FULFILLED)){
/**
* builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking}
*/
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
/**
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
*/
@ -190,6 +196,10 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
}
}
else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
loopBroken = true;
break;
}
}
/**
@ -219,22 +229,25 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
actIndex++;
}
End nextAct = end;
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
if(!loopBroken){
End nextAct = end;
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
if(status.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
if(actInsertionCosts != null){
/**
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
*/
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts();
InsertionContext iContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, prevActDepTime_newVehicle);
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(iContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
if(actInsertionCosts != null){
/**
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
*/
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts();
/**
* memorize it in insertion-queue
*/
if(insertion_cost_approximation < best_known_insertion_costs){
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
/**
* memorize it in insertion-queue
*/
if(insertion_cost_approximation < best_known_insertion_costs){
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
}
}
}
}
}
@ -254,6 +267,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
}
}
else{
for(int i=0;i<memorySize;i++){
InsertionData data = bestInsertionsQueue.poll();
if(data == null){
@ -271,7 +285,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
/**
* compute cost-diff of tour with and without new activity --> insertion_costs
*/
double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - stateManager.getRouteState(currentRoute,StateTypes.COSTS).toDouble();
double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - stateManager.getRouteState(currentRoute,StateFactory.COSTS).toDouble();
/**
* if better than best known, make it the best known
@ -282,7 +296,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
}
}
}
if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.noInsertionFound();
if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.createEmptyInsertionData();
return new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver);
}
@ -316,9 +330,9 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
private double sumOf_prevCosts_oldVehicle(VehicleRoute vehicleRoute, TourActivity act) {
if(act instanceof End){
return stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble();
return stateManager.getRouteState(vehicleRoute,StateFactory.COSTS).toDouble();
}
return stateManager.getActivityState(act,StateTypes.COSTS).toDouble();
return stateManager.getActivityState(act,StateFactory.COSTS).toDouble();
}
/**

View file

@ -22,7 +22,7 @@ import org.apache.log4j.Logger;
import util.Neighborhood;
import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import algorithms.HardConstraints.HardRouteLevelConstraint;
import algorithms.HardActivityLevelConstraint.ConstraintsStatus;
import basics.Job;
import basics.Shipment;
import basics.costs.VehicleRoutingTransportCosts;
@ -38,12 +38,14 @@ import basics.route.VehicleRoute;
final class ShipmentInsertionCalculator implements JobInsertionCalculator{
final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(ShipmentInsertionCalculator.class);
private HardRouteLevelConstraint hardRouteLevelConstraint;
private HardActivityLevelConstraint hardActivityLevelConstraint;
private Neighborhood neighborhood = new Neighborhood() {
@Override
@ -63,10 +65,11 @@ final class ShipmentInsertionCalculator implements JobInsertionCalculator{
logger.info("initialise neighborhood " + neighborhood);
}
public ShipmentInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint) {
public ShipmentInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint, HardActivityLevelConstraint hardActivityLevelConstraint) {
super();
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
this.transportCosts = routingCosts;
activityFactory = new DefaultShipmentActivityFactory();
logger.info("initialise " + this);
@ -83,25 +86,24 @@ final class ShipmentInsertionCalculator implements JobInsertionCalculator{
*
*/
@Override
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing.");
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing.");
if(!(jobToInsert instanceof Shipment)) throw new IllegalStateException("jobToInsert should be of type Shipment!");
InsertionContext insertionContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
double bestCost = bestKnownCosts;
Shipment shipment = (Shipment)jobToInsert;
TourActivity pickupShipment = activityFactory.createPickup(shipment);
TourActivity deliveryShipment = activityFactory.createDelivery(shipment);
TourActivity deliverShipment = activityFactory.createDelivery(shipment);
int pickupInsertionIndex = InsertionData.NO_INDEX;
int deliveryInsertionIndex = InsertionData.NO_INDEX;
// int insertionIndex = 0;
Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
start.setEndTime(newVehicleDepartureTime);
@ -109,23 +111,32 @@ final class ShipmentInsertionCalculator implements JobInsertionCalculator{
TourActivity prevAct = start;
double prevActEndTime = newVehicleDepartureTime;
boolean pickupShipmentLoopBroken = false;
//pickupShipmentLoop
List<TourActivity> activities = currentRoute.getTourActivities().getActivities();
for(int i=0;i<activities.size();i++){
ActivityInsertionCosts pickupAIC = calculate(insertionContext,prevAct,pickupShipment,activities.get(i),prevActEndTime);
if(pickupAIC == null){
ConstraintsStatus pickupShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, pickupShipment, activities.get(i), prevActEndTime);
if(pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED)){
double nextActArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), activities.get(i).getLocationId(), prevActEndTime, newDriver, newVehicle);
prevActEndTime = CalcUtils.getActivityEndTime(nextActArrTime, activities.get(i));
prevActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, activities.get(i));
prevAct = activities.get(i);
continue;
}
else if(pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
pickupShipmentLoopBroken = true;
break;
}
ActivityInsertionCosts pickupAIC = calculate(insertionContext,prevAct,pickupShipment,activities.get(i),prevActEndTime);
TourActivity prevAct_deliveryLoop = pickupShipment;
double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), pickupShipment.getLocationId(), prevActEndTime, newDriver, newVehicle);
double shipmentPickupEndTime = CalcUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment);
double shipmentPickupEndTime = CalculationUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment);
double prevActEndTime_deliveryLoop = shipmentPickupEndTime;
boolean deliverShipmentLoopBroken = false;
//deliverShipmentLoop
for(int j=i;j<activities.size();j++){
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliveryShipment,activities.get(j),prevActEndTime_deliveryLoop);
if(deliveryAIC != null){
ConstraintsStatus deliverShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, activities.get(j), prevActEndTime_deliveryLoop);
if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,activities.get(j),prevActEndTime_deliveryLoop);
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
if(totalActivityInsertionCosts < bestCost){
bestCost = totalActivityInsertionCosts;
@ -133,36 +144,40 @@ final class ShipmentInsertionCalculator implements JobInsertionCalculator{
deliveryInsertionIndex = j;
}
}
else if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
deliverShipmentLoopBroken = true;
break;
}
//update prevAct and endTime
double nextActArrTime = prevActEndTime_deliveryLoop + transportCosts.getTransportTime(prevAct_deliveryLoop.getLocationId(), activities.get(j).getLocationId(), prevActEndTime_deliveryLoop, newDriver, newVehicle);
prevActEndTime_deliveryLoop = CalcUtils.getActivityEndTime(nextActArrTime, activities.get(j));
prevActEndTime_deliveryLoop = CalculationUtils.getActivityEndTime(nextActArrTime, activities.get(j));
prevAct_deliveryLoop = activities.get(j);
}
//endInsertion
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliveryShipment,end,prevActEndTime_deliveryLoop);
if(deliveryAIC != null){
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
if(totalActivityInsertionCosts < bestCost){
bestCost = totalActivityInsertionCosts;
pickupInsertionIndex = i;
deliveryInsertionIndex = activities.size();
if(!deliverShipmentLoopBroken){ //check insertion between lastAct and endOfTour
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,end,prevActEndTime_deliveryLoop);
if(deliveryAIC != null){
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
if(totalActivityInsertionCosts < bestCost){
bestCost = totalActivityInsertionCosts;
pickupInsertionIndex = i;
deliveryInsertionIndex = activities.size();
}
}
}
//update prevAct and endTime
double nextActArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), activities.get(i).getLocationId(), prevActEndTime, newDriver, newVehicle);
prevActEndTime = CalcUtils.getActivityEndTime(nextActArrTime, activities.get(i));
prevActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, activities.get(i));
prevAct = activities.get(i);
}
//endInsertion
ActivityInsertionCosts pickupAIC = calculate(insertionContext,prevAct,pickupShipment,end,prevActEndTime);
if(pickupAIC != null){ //evaluate delivery
TourActivity prevAct_deliveryLoop = pickupShipment;
double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), pickupShipment.getLocationId(), prevActEndTime, newDriver, newVehicle);
double shipmentPickupEndTime = CalcUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment);
double prevActEndTime_deliveryLoop = shipmentPickupEndTime;
if(!pickupShipmentLoopBroken){ //check insertion of pickupShipment and deliverShipment at just before tour ended
ActivityInsertionCosts pickupAIC = calculate(insertionContext,prevAct,pickupShipment,end,prevActEndTime);
if(pickupAIC != null){ //evaluate delivery
TourActivity prevAct_deliveryLoop = pickupShipment;
double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), pickupShipment.getLocationId(), prevActEndTime, newDriver, newVehicle);
double shipmentPickupEndTime = CalculationUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment);
double prevActEndTime_deliveryLoop = shipmentPickupEndTime;
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliveryShipment,end,prevActEndTime_deliveryLoop);
if(deliveryAIC != null){
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,end,prevActEndTime_deliveryLoop);
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
if(totalActivityInsertionCosts < bestCost){
bestCost = totalActivityInsertionCosts;
@ -172,7 +187,7 @@ final class ShipmentInsertionCalculator implements JobInsertionCalculator{
}
}
if(pickupInsertionIndex == InsertionData.NO_INDEX) {
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
InsertionData insertionData = new InsertionData(bestCost, pickupInsertionIndex, deliveryInsertionIndex, newVehicle, newDriver);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
@ -180,7 +195,7 @@ final class ShipmentInsertionCalculator implements JobInsertionCalculator{
}
private ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double departureTimeAtPrevAct) {
return activityInsertionCostsCalculator.calculate(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
return activityInsertionCostsCalculator.getCosts(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
}
}

View file

@ -0,0 +1,114 @@
/*******************************************************************************
* 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.Arrays;
import java.util.List;
import algorithms.StateGetter.State;
import algorithms.StateGetter.StateId;
import algorithms.StateManager.StateImpl;
public class StateFactory {
final static StateId MAXLOAD = new StateIdImpl("maxload");
final static StateId LOAD = new StateIdImpl("load");
final static StateId COSTS = new StateIdImpl("costs");
final static StateId LOAD_AT_BEGINNING = new StateIdImpl("loadAtBeginning");
final static StateId LOAD_AT_END = new StateIdImpl("loadAtEnd");
final static StateId DURATION = new StateIdImpl("duration");
final static StateId LATEST_OPERATION_START_TIME = new StateIdImpl("latestOST");
final static StateId EARLIEST_OPERATION_START_TIME = new StateIdImpl("earliestOST");
final static StateId FUTURE_PICKS = new StateIdImpl("futurePicks");
final static StateId PAST_DELIVERIES = new StateIdImpl("pastDeliveries");
final static List<String> reservedIds = Arrays.asList("maxload","load","costs","loadAtBeginning","loadAtEnd","duration","latestOST","earliestOST"
,"futurePicks","pastDeliveries");
public static StateId createId(String name){
if(reservedIds.contains(name)){ throwException(name); }
return new StateIdImpl(name);
}
public static State createState(double value){
return new StateImpl(value);
}
private static void throwException(String name) {
throw new IllegalStateException("state-id with name '" + name + "' cannot be created. it is already reserved internally.");
}
static class StateIdImpl implements StateId {
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
StateIdImpl other = (StateIdImpl) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
private String name;
public StateIdImpl(String name) {
super();
this.name = name;
}
public String toString(){
return name;
}
}
}

View file

@ -17,18 +17,22 @@
package algorithms;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class CalcUtils {
public interface StateGetter {
public interface StateId {
}
public interface State {
double toDouble();
}
/**
* Calculates actEndTime assuming that activity can at earliest start at act.getTheoreticalEarliestOperationStartTime().
*
* @param actArrTime
* @param act
* @return
*/
static double getActivityEndTime(double actArrTime, TourActivity act){
return Math.max(actArrTime, act.getTheoreticalEarliestOperationStartTime()) + act.getOperationTime();
}
State getActivityState(TourActivity act, StateId stateId);
State getRouteState(VehicleRoute route, StateId stateId);
}

View file

@ -16,16 +16,42 @@
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.InsertionEndsListener;
import basics.algo.InsertionListener;
import basics.algo.InsertionListeners;
import basics.algo.InsertionStartsListener;
import basics.algo.IterationStartsListener;
import basics.algo.JobInsertedListener;
import basics.algo.RuinListener;
import basics.algo.RuinListeners;
import basics.route.ActivityVisitor;
import basics.route.ReverseActivityVisitor;
import basics.route.ReverseRouteActivityVisitor;
import basics.route.RouteActivityVisitor;
import basics.route.RouteVisitor;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
interface StateManager {
public class StateManager implements StateGetter, IterationStartsListener, RuinListener, InsertionStartsListener, JobInsertedListener, InsertionEndsListener {
interface State {
double toDouble();
private interface States {
State getState(StateId key);
}
class StateImpl implements State{
static class StateImpl implements State{
double state;
public StateImpl(double state) {
@ -40,14 +66,225 @@ interface StateManager {
}
interface States {
State getState(String key);
}
State getActivityState(TourActivity act, String stateType);
State getRouteState(VehicleRoute route, String stateType);
private static class StatesImpl implements States{
private Map<StateId,State> states = new HashMap<StateId, State>();
public void putState(StateId key, State state) {
states.put(key, state);
}
@Override
public State getState(StateId key) {
return states.get(key);
}
}
private Map<VehicleRoute,States> vehicleRouteStates = new HashMap<VehicleRoute, States>();
private Map<TourActivity,States> activityStates = new HashMap<TourActivity, States>();
private RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor();
private ReverseRouteActivityVisitor revRouteActivityVisitor = new ReverseRouteActivityVisitor();
private Collection<RouteVisitor> routeVisitors = new ArrayList<RouteVisitor>();
private RuinListeners ruinListeners = new RuinListeners();
private InsertionListeners insertionListeners = new InsertionListeners();
private Collection<StateUpdater> updaters = new ArrayList<StateUpdater>();
private Map<StateId,State> defaultRouteStates = new HashMap<StateGetter.StateId, StateGetter.State>();
private Map<StateId,State> defaultActivityStates = new HashMap<StateId, State>();
public void addDefaultRouteState(StateId stateId, State defaultState){
defaultRouteStates.put(stateId, defaultState);
}
public void addDefaultActivityState(StateId stateId, State defaultState){
defaultActivityStates.put(stateId, defaultState);
}
public void clear(){
vehicleRouteStates.clear();
activityStates.clear();
}
@Override
public State getActivityState(TourActivity act, StateId stateId) {
if(!activityStates.containsKey(act)){
return getDefaultActState(stateId,act);
}
StatesImpl actStates = (StatesImpl) activityStates.get(act);
State state = actStates.getState(stateId);
if(state == null){
return getDefaultActState(stateId,act);
}
return state;
}
public void putActivityState(TourActivity act, StateId stateId, State state){
if(!activityStates.containsKey(act)){
activityStates.put(act, new StatesImpl());
}
StatesImpl actStates = (StatesImpl) activityStates.get(act);
actStates.putState(stateId, state);
}
public void putRouteState(VehicleRoute route, StateId stateId, State state){
if(!vehicleRouteStates.containsKey(route)){
vehicleRouteStates.put(route, new StatesImpl());
}
StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route);
routeStates.putState(stateId, state);
}
@Override
public State getRouteState(VehicleRoute route, StateId stateId) {
if(!vehicleRouteStates.containsKey(route)){
return getDefaultRouteState(stateId,route);
}
StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route);
State state = routeStates.getState(stateId);
if(state == null){
return getDefaultRouteState(stateId, route);
}
return state;
}
/**
* Adds state updater.
*
* <p>Note that a state update occurs if route and/or activity states change, i.e. if jobs are removed
* or inserted into a route. Thus here, it is assumed that a state updater is either of type InsertionListener,
* RuinListener, ActivityVisitor, ReverseActivityVisitor, RouteVisitor, ReverseRouteVisitor.
*
* <p>The following rule pertain for activity/route visitors:These visitors visits all activities/route 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 updater
*/
public void addStateUpdater(StateUpdater updater){
if(updater instanceof ActivityVisitor) addActivityVisitor((ActivityVisitor) updater);
if(updater instanceof ReverseActivityVisitor) addActivityVisitor((ReverseActivityVisitor)updater);
if(updater instanceof RouteVisitor) addRouteVisitor((RouteVisitor) updater);
if(updater instanceof InsertionListener) addListener((InsertionListener) updater);
if(updater instanceof RuinListener) addListener((RuinListener) updater);
updaters.add(updater);
}
Collection<StateUpdater> getStateUpdaters(){
return Collections.unmodifiableCollection(updaters);
}
/**
* 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
*/
void addActivityVisitor(ActivityVisitor 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
*/
void addActivityVisitor(ReverseActivityVisitor activityVistor){
revRouteActivityVisitor.addActivityVisitor(activityVistor);
}
void addRouteVisitor(RouteVisitor routeVisitor){
routeVisitors.add(routeVisitor);
}
void addListener(RuinListener ruinListener){
ruinListeners.addListener(ruinListener);
}
void removeListener(RuinListener ruinListener){
ruinListeners.removeListener(ruinListener);
}
void addListener(InsertionListener insertionListener){
insertionListeners.addListener(insertionListener);
}
void removeListener(InsertionListener insertionListener){
insertionListeners.removeListener(insertionListener);
}
private State getDefaultActState(StateId stateId, TourActivity act){
if(stateId.equals(StateFactory.LOAD)) return new StateImpl(0);
if(stateId.equals(StateFactory.COSTS)) return new StateImpl(0);
if(stateId.equals(StateFactory.DURATION)) return new StateImpl(0);
if(stateId.equals(StateFactory.EARLIEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalEarliestOperationStartTime());
if(stateId.equals(StateFactory.LATEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalLatestOperationStartTime());
if(stateId.equals(StateFactory.FUTURE_PICKS)) return new StateImpl(0);
if(stateId.equals(StateFactory.PAST_DELIVERIES)) return new StateImpl(0);
return null;
}
private State getDefaultRouteState(StateId stateId, VehicleRoute route){
if(stateId.equals(StateFactory.MAXLOAD)) return new StateImpl(0);
if(stateId.equals(StateFactory.LOAD)) return new StateImpl(0);
if(stateId.equals(StateFactory.LOAD_AT_END)) return new StateImpl(0);
if(stateId.equals(StateFactory.LOAD_AT_BEGINNING)) return new StateImpl(0);
if(stateId.equals(StateFactory.COSTS)) return new StateImpl(0);
if(stateId.equals(StateFactory.DURATION)) return new StateImpl(0);
return null;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
insertionListeners.jobInserted(job2insert, inRoute, additionalCosts, additionalTime);
for(RouteVisitor v : routeVisitors){ v.visit(inRoute); }
routeActivityVisitor.visit(inRoute);
revRouteActivityVisitor.visit(inRoute);
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes,Collection<Job> unassignedJobs) {
insertionListeners.insertionStarts(vehicleRoutes, unassignedJobs);
for(VehicleRoute route : vehicleRoutes){
for(RouteVisitor v : routeVisitors){ v.visit(route); }
routeActivityVisitor.visit(route);
revRouteActivityVisitor.visit(route);
}
}
@Override
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
clear();
}
@Override
public void ruinStarts(Collection<VehicleRoute> routes) {
ruinListeners.ruinStarts(routes);
}
@Override
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
ruinListeners.ruinEnds(routes, unassignedJobs);
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {
ruinListeners.removed(job, fromRoute);
}
@Override
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
insertionListeners.insertionEnds(vehicleRoutes);
}
}

View file

@ -1,151 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import basics.Job;
import basics.algo.InsertionStartsListener;
import basics.algo.JobInsertedListener;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class StateManagerImpl implements StateManager, InsertionStartsListener, JobInsertedListener {
static class StatesImpl implements States{
private Map<String,State> states = new HashMap<String, State>();
public void putState(String key, State state) {
states.put(key, state);
}
@Override
public State getState(String key) {
return states.get(key);
}
}
private Map<VehicleRoute,States> vehicleRouteStates = new HashMap<VehicleRoute, StateManager.States>();
private Map<TourActivity,States> activityStates = new HashMap<TourActivity, StateManager.States>();
private RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor();
private ReverseRouteActivityVisitor revRouteActivityVisitor = new ReverseRouteActivityVisitor();
private Collection<RouteVisitor> routeVisitors = new ArrayList<RouteVisitor>();
public void clear(){
vehicleRouteStates.clear();
activityStates.clear();
}
@Override
public State getActivityState(TourActivity act, String stateType) {
if(!activityStates.containsKey(act)){
return getDefaultActState(stateType,act);
}
StatesImpl actStates = (StatesImpl) activityStates.get(act);
State state = actStates.getState(stateType);
if(state == null){
return getDefaultActState(stateType,act);
}
return state;
}
public void putActivityState(TourActivity act, String stateType, State state){
if(!activityStates.containsKey(act)){
activityStates.put(act, new StatesImpl());
}
StatesImpl actStates = (StatesImpl) activityStates.get(act);
actStates.putState(stateType, state);
}
private State getDefaultActState(String stateType, TourActivity act){
if(stateType.equals(StateTypes.LOAD)) return new StateImpl(0);
if(stateType.equals(StateTypes.COSTS)) return new StateImpl(0);
if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0);
if(stateType.equals(StateTypes.EARLIEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalEarliestOperationStartTime());
if(stateType.equals(StateTypes.LATEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalLatestOperationStartTime());
if(stateType.equals(StateTypes.FUTURE_PICKS)) return new StateImpl(0);
if(stateType.equals(StateTypes.PAST_DELIVERIES)) return new StateImpl(0);
return null;
}
private State getDefaultRouteState(String stateType, VehicleRoute route){
if(stateType.equals(StateTypes.LOAD)) return new StateImpl(0);
if(stateType.equals(StateTypes.LOAD_AT_DEPOT)) return new StateImpl(0);
if(stateType.equals(StateTypes.COSTS)) return new StateImpl(0);
if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0);
return null;
}
@Override
public State getRouteState(VehicleRoute route, String stateType) {
if(!vehicleRouteStates.containsKey(route)){
return getDefaultRouteState(stateType,route);
}
StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route);
State state = routeStates.getState(stateType);
if(state == null){
return getDefaultRouteState(stateType, route);
}
return state;
}
public void putRouteState(VehicleRoute route, String stateType, State state){
if(!vehicleRouteStates.containsKey(route)){
vehicleRouteStates.put(route, new StatesImpl());
}
StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route);
routeStates.putState(stateType, state);
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
for(RouteVisitor v : routeVisitors){ v.visit(inRoute); }
routeActivityVisitor.visit(inRoute);
revRouteActivityVisitor.visit(inRoute);
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes,Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
for(RouteVisitor v : routeVisitors){ v.visit(route); }
routeActivityVisitor.visit(route);
revRouteActivityVisitor.visit(route);
}
}
public void addActivityVisitor(ActivityVisitor activityVistor){
routeActivityVisitor.addActivityVisitor(activityVistor);
}
public void addActivityVisitor(ReverseActivityVisitor activityVistor){
revRouteActivityVisitor.addActivityVisitor(activityVistor);
}
public void addRouteVisitor(RouteVisitor routeVisitor){
routeVisitors.add(routeVisitor);
}
}

View file

@ -0,0 +1,5 @@
package algorithms;
public interface StateUpdater {
}

View file

@ -1,633 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.log4j.Logger;
import algorithms.RuinStrategy.RuinListener;
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.IterationStartsListener;
import basics.algo.JobInsertedListener;
import basics.costs.ForwardTransportCost;
import basics.costs.ForwardTransportTime;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DeliveryActivity;
import basics.route.PickupActivity;
import basics.route.ServiceActivity;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import basics.route.VehicleType;
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;
// totalOperationCost += getFixCosts();
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;
}
private double getFixCosts() {
Vehicle vehicle = vehicleRoute.getVehicle();
if(vehicle == null) return 0.0;
VehicleType type = vehicle.getType();
if(type == null) return 0.0;
return type.getVehicleCostParams().fix;
}
}
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);
}
}
}
}

View file

@ -0,0 +1,24 @@
package algorithms;
import basics.VehicleRoutingProblem;
class StateUtils {
public static void addCoreStateUpdaters(VehicleRoutingProblem vrp, StateManager stateManager){
stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager));
stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager));
stateManager.addActivityVisitor(new UpdateActivityTimes(vrp.getTransportCosts()));
stateManager.addActivityVisitor(new UpdateLoadAtActivityLevel(stateManager));
stateManager.addActivityVisitor(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
stateManager.addActivityVisitor(new UpdateOccuredDeliveriesAtActivityLevel(stateManager));
stateManager.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
stateManager.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager));
}
}

View file

@ -0,0 +1,65 @@
package algorithms;
import org.apache.log4j.Logger;
import util.ActivityTimeTracker;
import basics.costs.ForwardTransportTime;
import basics.route.ActivityVisitor;
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
*
*/
class UpdateActivityTimes implements ActivityVisitor, StateUpdater{
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());
}
}

View file

@ -0,0 +1,126 @@
package algorithms;
import org.apache.log4j.Logger;
import util.ActivityTimeTracker;
import algorithms.StateManager.StateImpl;
import basics.costs.ForwardTransportCost;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.ActivityVisitor;
import basics.route.TourActivity;
import basics.route.Vehicle;
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
*/
class UpdateCostsAtAllLevels implements ActivityVisitor,StateUpdater{
private static Logger log = Logger.getLogger(UpdateCostsAtAllLevels.class);
private VehicleRoutingActivityCosts activityCost;
private ForwardTransportCost transportCost;
private StateManager 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, StateManager 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, StateFactory.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;
// totalOperationCost += getFixCosts(vehicleRoute.getVehicle());
states.putRouteState(vehicleRoute, StateFactory.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;
}
private double getFixCosts(Vehicle vehicle) {
if(vehicle == null) return 0.0;
if(vehicle.getType() == null) return 0.0;
return vehicle.getType().getVehicleCostParams().fix;
}
}

View file

@ -0,0 +1,63 @@
package algorithms;
import java.util.Collection;
import algorithms.StateManager.StateImpl;
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.RouteActivityVisitor;
import basics.route.VehicleRoute;
class UpdateCostsAtRouteLevel implements StateUpdater,JobInsertedListener, InsertionStartsListener, InsertionEndsListener{
private StateManager states;
private VehicleRoutingTransportCosts tpCosts;
private VehicleRoutingActivityCosts actCosts;
public UpdateCostsAtRouteLevel(StateManager 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, StateFactory.COSTS).toDouble();
oldCosts += additionalCosts;
states.putRouteState(inRoute, StateFactory.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, StateFactory.COSTS).toDouble());
route.getVehicleRouteCostCalculator().price(route.getVehicle());
// forwardInTime.iterate(route);
}
}
}

View file

@ -0,0 +1,37 @@
package algorithms;
import util.ActivityTimeTracker;
import algorithms.StateManager.StateImpl;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.ActivityVisitor;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class UpdateEarliestStartTimeWindowAtActLocations implements ActivityVisitor,StateUpdater{
private StateManager states;
private ActivityTimeTracker timeTracker;
public UpdateEarliestStartTimeWindowAtActLocations(StateManager 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, StateFactory.EARLIEST_OPERATION_START_TIME, new StateImpl(Math.max(timeTracker.getActArrTime(), activity.getTheoreticalEarliestOperationStartTime())));
}
@Override
public void finish() {}
}

View file

@ -0,0 +1,39 @@
package algorithms;
import basics.route.PickupActivity;
import basics.route.ReverseActivityVisitor;
import basics.route.ServiceActivity;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class UpdateFuturePickupsAtActivityLevel implements ReverseActivityVisitor, StateUpdater {
private StateManager stateManager;
private int futurePicks = 0;
private VehicleRoute route;
public UpdateFuturePickupsAtActivityLevel(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
this.route = route;
}
@Override
public void visit(TourActivity act) {
stateManager.putActivityState(act, StateFactory.FUTURE_PICKS, StateFactory.createState(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;
}
}

View file

@ -0,0 +1,51 @@
package algorithms;
import org.apache.log4j.Logger;
import algorithms.StateManager.StateImpl;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.ReverseActivityVisitor;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class UpdateLatestOperationStartTimeAtActLocations implements ReverseActivityVisitor, StateUpdater{
private static Logger log = Logger.getLogger(UpdateLatestOperationStartTimeAtActLocations.class);
private StateManager states;
private VehicleRoute route;
private VehicleRoutingTransportCosts transportCosts;
private double latestArrTimeAtPrevAct;
private TourActivity prevAct;
public UpdateLatestOperationStartTimeAtActLocations(StateManager 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, StateFactory.LATEST_OPERATION_START_TIME, new StateImpl(latestArrivalTime));
latestArrTimeAtPrevAct = latestArrivalTime;
prevAct = activity;
}
@Override
public void finish() {}
}

View file

@ -0,0 +1,67 @@
package algorithms;
import algorithms.StateManager.StateImpl;
import basics.route.ActivityVisitor;
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
*
*/
class UpdateLoadAtActivityLevel implements ActivityVisitor, StateUpdater {
private StateManager 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 UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts}, {@link UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted}
*
* <p>The loads can be retrieved by <br>
* <code>stateManager.getActivityState(activity,StateTypes.LOAD);</code>
*
*
*
* @see {@link UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts}, {@link UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted}
* @author stefan
*
*/
public UpdateLoadAtActivityLevel(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
currentLoad = (int) stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble();
this.route = route;
}
@Override
public void visit(TourActivity act) {
currentLoad += act.getCapacityDemand();
stateManager.putActivityState(act, StateFactory.LOAD, StateFactory.createState(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() {
// stateManager.putRouteState(route, StateFactory., state)
currentLoad = 0;
}
}

View file

@ -0,0 +1,39 @@
package algorithms;
import algorithms.StateManager.StateImpl;
import basics.route.ActivityVisitor;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class UpdateLoadAtAllLevels implements ActivityVisitor,StateUpdater{
private double load = 0.0;
private StateManager states;
private VehicleRoute vehicleRoute;
public UpdateLoadAtAllLevels(StateManager 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, StateFactory.LOAD, new StateImpl(load));
}
@Override
public void finish() {
states.putRouteState(vehicleRoute, StateFactory.LOAD, new StateImpl(load));
load=0;
vehicleRoute = null;
}
}

View file

@ -0,0 +1,54 @@
package algorithms;
import java.util.Collection;
import algorithms.StateManager.StateImpl;
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
*
*/
class UpdateLoadAtRouteLevel implements JobInsertedListener, InsertionStartsListener, StateUpdater{
private StateManager states;
/**
* Updates load at route level, i.e. modifies StateTypes.LOAD for each route.
*
* @author stefan
*
*/
public UpdateLoadAtRouteLevel(StateManager 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, StateFactory.LOAD).toDouble();
states.putRouteState(inRoute, StateFactory.LOAD, StateFactory.createState(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, StateFactory.LOAD, new StateImpl(load));
}
}
}

View file

@ -0,0 +1,62 @@
package algorithms;
import java.util.Collection;
import algorithms.StateManager.StateImpl;
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
*/
class UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts implements InsertionStartsListener {
private StateManager 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 UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(StateManager 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, StateFactory.LOAD_AT_BEGINNING, StateFactory.createState(loadAtDepot));
stateManager.putRouteState(route, StateFactory.LOAD_AT_END, StateFactory.createState(loadAtEnd));
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){ insertionStarts(route); }
}
}

View file

@ -0,0 +1,52 @@
package algorithms;
import algorithms.StateManager.StateImpl;
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
*/
class UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted implements JobInsertedListener, StateUpdater {
private StateManager 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(StateManager 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, StateFactory.LOAD_AT_BEGINNING).toDouble();
// log.info("loadAtDepot="+loadAtDepot);
stateManager.putRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING, StateFactory.createState(loadAtDepot + job2insert.getCapacityDemand()));
}
else if(job2insert instanceof Pickup || job2insert instanceof Service){
int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_END).toDouble();
// log.info("loadAtEnd="+loadAtEnd);
stateManager.putRouteState(inRoute, StateFactory.LOAD_AT_END, StateFactory.createState(loadAtEnd + job2insert.getCapacityDemand()));
}
}
}

View file

@ -0,0 +1,69 @@
package algorithms;
import basics.route.ActivityVisitor;
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
*
*/
class UpdateMaxLoad implements ActivityVisitor, StateUpdater {
private StateManager stateManager;
private int currentLoad = 0;
private VehicleRoute route;
private int maxLoad = 0;
/**
* 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 UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts}, {@link UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted}
*
* <p>The loads can be retrieved by <br>
* <code>stateManager.getActivityState(activity,StateTypes.LOAD);</code>
*
*
*
* @see {@link UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts}, {@link UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted}
* @author stefan
*
*/
public UpdateMaxLoad(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
currentLoad = (int) stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble();
maxLoad = currentLoad;
this.route = route;
}
@Override
public void visit(TourActivity act) {
currentLoad += act.getCapacityDemand();
maxLoad = Math.max(maxLoad, 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() {
stateManager.putRouteState(route, StateFactory.MAXLOAD, StateFactory.createState(maxLoad));
currentLoad = 0;
maxLoad = 0;
}
}

View file

@ -0,0 +1,39 @@
package algorithms;
import algorithms.StateManager.StateImpl;
import basics.route.ActivityVisitor;
import basics.route.DeliveryActivity;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class UpdateOccuredDeliveriesAtActivityLevel implements ActivityVisitor, StateUpdater {
private StateManager stateManager;
private int deliveries = 0;
private VehicleRoute route;
public UpdateOccuredDeliveriesAtActivityLevel(StateManager 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, StateFactory.PAST_DELIVERIES, StateFactory.createState(deliveries));
assert deliveries >= 0 : "deliveries < 0";
assert deliveries <= route.getVehicle().getCapacity() : "deliveries > vehicleCap";
}
@Override
public void finish() {
deliveries = 0;
route = null;
}
}

View file

@ -0,0 +1,31 @@
package algorithms;
import basics.VehicleRoutingProblemSolution;
import basics.algo.SolutionCostCalculator;
import basics.route.VehicleRoute;
public class VariablePlusFixedSolutionCostCalculatorFactory {
private StateManager stateManager;
public VariablePlusFixedSolutionCostCalculatorFactory(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
public SolutionCostCalculator createCalculator(){
return new SolutionCostCalculator() {
@Override
public double getCosts(VehicleRoutingProblemSolution solution) {
double c = 0.0;
for(VehicleRoute r : solution.getRoutes()){
c += stateManager.getRouteState(r, StateFactory.COSTS).toDouble();
c += r.getVehicle().getType().getVehicleCostParams().fix;
}
return c;
}
};
}
}

View file

@ -1,84 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.Collection;
import basics.route.Vehicle;
interface VehicleFleetManager {
static class TypeKey {
public final String type;
public final String locationId;
public TypeKey(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;
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;
}
}
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);
}

View file

@ -0,0 +1,44 @@
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.algo.SearchStrategyManager;
import basics.algo.VehicleRoutingAlgorithmListener;
import basics.route.VehicleFleetManager;
public class VehicleRoutingAlgorithmBuilder {
private VehicleRoutingProblem vrp;
private SearchStrategyManager searchStrategyManager;
private StateManager stateManager;
private Collection<VehicleRoutingAlgorithmListener> listeners = new ArrayList<VehicleRoutingAlgorithmListener>();
private VehicleFleetManager fleetManager;
public VehicleRoutingAlgorithmBuilder(VehicleRoutingProblem vrp, SearchStrategyManager searchStrategyManager, StateManager stateManager, VehicleFleetManager vehicleFleetManager) {
super();
this.vrp = vrp;
this.searchStrategyManager = searchStrategyManager;
this.stateManager = stateManager;
this.fleetManager = vehicleFleetManager;
}
public void addListener(VehicleRoutingAlgorithmListener listener){
listeners.add(listener);
}
public VehicleRoutingAlgorithm build(){
VehicleRoutingAlgorithm algorithm = new VehicleRoutingAlgorithm(vrp, searchStrategyManager);
algorithm.getAlgorithmListeners().addListener(stateManager);
algorithm.getSearchStrategyManager().addSearchStrategyModuleListener(stateManager);
algorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(fleetManager));
return algorithm;
}
}

View file

@ -31,7 +31,6 @@ import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.log4j.Logger;
import algorithms.HardConstraints.ConstraintManager;
import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey;
@ -65,7 +64,10 @@ import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
import basics.io.AlgorithmConfig;
import basics.io.AlgorithmConfigXmlReader;
import basics.route.FiniteFleetManagerFactory;
import basics.route.InfiniteFleetManagerFactory;
import basics.route.Vehicle;
import basics.route.VehicleFleetManager;
import basics.route.VehicleRoute;
@ -437,23 +439,23 @@ public class VehicleRoutingAlgorithms {
final VehicleFleetManager vehicleFleetManager = createFleetManager(vrp);
//create state-manager
final StateManagerImpl stateManager = new StateManagerImpl();
final StateManager stateManager = new StateManager();
/*
* define constraints
*/
//constraint manager
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)){
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager));
constraintManager.addConstraint(new HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager));
}
else{
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryActivityLevelConstraint(stateManager));
constraintManager.addConstraint(new HardPickupAndDeliveryActivityLevelConstraint(stateManager));
}
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryLoadConstraint(stateManager));
constraintManager.addConstraint(new HardPickupAndDeliveryLoadRouteLevelConstraint(stateManager));
//construct initial solution creator
AlgorithmStartsListener createInitialSolution = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,constraintManager);
@ -491,24 +493,22 @@ public class VehicleRoutingAlgorithms {
* define stateUpdates
*/
//reset stateManager
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new StateUpdates.ResetStateManager(stateManager)));
//update states
// metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateStates(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts()));
StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged routeChangedListener = new StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged(vrp.getTransportCosts());
stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager));
stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager));
stateManager.addActivityVisitor(new UpdateActivityTimes(vrp.getTransportCosts()));
stateManager.addActivityVisitor(new UpdateLoadAtActivityLevel(stateManager));
routeChangedListener.addInsertionStartsListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager));
routeChangedListener.addJobInsertedListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager));
stateManager.addActivityVisitor(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
routeChangedListener.addVisitor(new StateUpdates.UpdateActivityTimes(vrp.getTransportCosts()));
routeChangedListener.addVisitor(new StateUpdates.UpdateLoadAtActivityLevel(stateManager));
routeChangedListener.addVisitor(new StateUpdates.UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
stateManager.addActivityVisitor(new UpdateOccuredDeliveriesAtActivityLevel(stateManager));
stateManager.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
stateManager.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager));
routeChangedListener.addVisitor(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager));
routeChangedListener.addVisitor(new StateUpdates.UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
routeChangedListener.addVisitor(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(stateManager);
metaAlgorithm.getAlgorithmListeners().addListener(stateManager);
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(routeChangedListener);
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(vehicleFleetManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new ResetAndIniFleetManager(vehicleFleetManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new VehicleSwitched(vehicleFleetManager));
@ -526,16 +526,16 @@ public class VehicleRoutingAlgorithms {
return metaAlgorithm;
}
private static SolutionCostCalculator getCostCalculator(final StateManagerImpl stateManager) {
private static SolutionCostCalculator getCostCalculator(final StateManager stateManager) {
SolutionCostCalculator calc = new SolutionCostCalculator() {
@Override
public void calculateCosts(VehicleRoutingProblemSolution solution) {
public double getCosts(VehicleRoutingProblemSolution solution) {
double costs = 0.0;
for(VehicleRoute route : solution.getRoutes()){
costs += stateManager.getRouteState(route, StateTypes.COSTS).toDouble() + getFixedCosts(route.getVehicle());
costs += stateManager.getRouteState(route, StateFactory.COSTS).toDouble() + getFixedCosts(route.getVehicle());
}
solution.setCost(costs);
return costs;
}
private double getFixedCosts(Vehicle vehicle) {
@ -549,11 +549,11 @@ public class VehicleRoutingAlgorithms {
private static VehicleFleetManager createFleetManager(final VehicleRoutingProblem vrp) {
if(vrp.getFleetSize().equals(FleetSize.INFINITE)){
return new InfiniteVehicles(vrp.getVehicles());
return new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
}
else if(vrp.getFleetSize().equals(FleetSize.FINITE)){
return new VehicleFleetManagerImpl(vrp.getVehicles());
return new FiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
}
throw new IllegalStateException("fleet size can only be infinite or finite. " +
"makes sure your config file contains one of these options");
@ -626,7 +626,7 @@ public class VehicleRoutingAlgorithms {
metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners);
}
private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, final StateManagerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, final StateManager routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
List<HierarchicalConfiguration> modConfigs = config.configurationsAt("construction.insertion");
if(modConfigs == null) return null;
if(modConfigs.isEmpty()) return null;
@ -651,9 +651,11 @@ public class VehicleRoutingAlgorithms {
@Override
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
CreateInitialSolution createInitialSolution = new CreateInitialSolution(finalInsertionStrategy, getCostCalculator(routeStates));
createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false);
VehicleRoutingProblemSolution vrpSol = createInitialSolution.createInitialSolution(vrp);
InsertionInitialSolutionFactory insertionInitialSolutionFactory = new InsertionInitialSolutionFactory(finalInsertionStrategy, getCostCalculator(routeStates));
// CreateInitialSolution createInitialSolution = new CreateInitialSolution(finalInsertionStrategy, getCostCalculator(routeStates));
//
// createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false);
VehicleRoutingProblemSolution vrpSol = insertionInitialSolutionFactory.createSolution(vrp);
solutions.add(vrpSol);
}
};
@ -721,7 +723,7 @@ public class VehicleRoutingAlgorithms {
}
private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager,
final StateManagerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
final StateManager routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
String moduleName = moduleConfig.getString("[@name]");
if(moduleName == null) throw new IllegalStateException("module(-name) is missing.");
String moduleId = moduleConfig.getString("[@id]");
@ -823,7 +825,7 @@ public class VehicleRoutingAlgorithms {
"\n\tgendreauPostOpt");
}
private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StateManagerImpl routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) {
private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StateManager routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) {
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
@ -833,7 +835,7 @@ public class VehicleRoutingAlgorithms {
return ruin;
}
private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final StateManagerImpl routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) {
private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final StateManager routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) {
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
@ -843,10 +845,12 @@ public class VehicleRoutingAlgorithms {
return ruin;
}
private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManager routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads, constraintManager);
return insertion;
}
}

View file

@ -17,6 +17,7 @@
package algorithms;
import basics.route.Vehicle;
import basics.route.VehicleFleetManager;
import basics.route.VehicleRoute;

View file

@ -25,20 +25,21 @@ import algorithms.InsertionData.NoInsertionFound;
import basics.Job;
import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleFleetManager;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculator{
final class VehicleTypeDependentJobInsertionCalculator implements JobInsertionCostsCalculator{
private Logger logger = Logger.getLogger(CalculatesVehTypeDepServiceInsertion.class);
private Logger logger = Logger.getLogger(VehicleTypeDependentJobInsertionCalculator.class);
private final VehicleFleetManager fleetManager;
private final JobInsertionCalculator insertionCalculator;
private final JobInsertionCostsCalculator insertionCalculator;
public CalculatesVehTypeDepServiceInsertion(final VehicleFleetManager fleetManager, final JobInsertionCalculator jobInsertionCalc) {
public VehicleTypeDependentJobInsertionCalculator(final VehicleFleetManager fleetManager, final JobInsertionCostsCalculator jobInsertionCalc) {
this.fleetManager = fleetManager;
this.insertionCalculator = jobInsertionCalc;
logger.info("inialise " + this);
@ -49,10 +50,10 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
return "[name=vehicleTypeDependentServiceInsertion]";
}
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle vehicle, double newVehicleDepartureTime, final Driver driver, final double bestKnownCost) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle vehicle, double newVehicleDepartureTime, final Driver driver, final double bestKnownCost) {
Vehicle selectedVehicle = currentRoute.getVehicle();
Driver selectedDriver = currentRoute.getDriver();
InsertionData bestIData = InsertionData.noInsertionFound();
InsertionData bestIData = InsertionData.createEmptyInsertionData();
double bestKnownCost_ = bestKnownCost;
Collection<Vehicle> relevantVehicles = new ArrayList<Vehicle>();
if(!(selectedVehicle instanceof NoVehicle)) {
@ -65,7 +66,7 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
for(Vehicle v : relevantVehicles){
double depTime = v.getEarliestDeparture();
InsertionData iData = insertionCalculator.calculate(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
InsertionData iData = insertionCalculator.getInsertionData(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
if(iData instanceof NoInsertionFound) {
if(bestIData instanceof NoInsertionFound) bestIData = iData;
continue;

View file

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

View file

@ -25,4 +25,5 @@ import basics.route.VehicleRoute;
public interface InsertionStartsListener extends InsertionListener {
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
}

View file

@ -0,0 +1,39 @@
package basics.algo;
import java.util.Collection;
import basics.Job;
import basics.route.VehicleRoute;
/**
* Listener that listens to the ruin-process. It informs whoever is interested about start, end and about a removal of a job.
*
* @author schroeder
*
*/
public interface RuinListener extends SearchStrategyModuleListener{
/**
* informs about ruin-start.
*
* @param routes
*/
public void ruinStarts(Collection<VehicleRoute> routes);
/**
* informs about ruin-end.
*
* @param routes
* @param unassignedJobs
*/
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs);
/**
* informs if a {@link Job} has been removed from a {@link VehicleRoute}.
*
* @param job
* @param fromRoute
*/
public void removed(Job job, VehicleRoute fromRoute);
}

View file

@ -0,0 +1,57 @@
/*******************************************************************************
* 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 basics.algo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import basics.Job;
import basics.route.VehicleRoute;
public class RuinListeners {
private Collection<RuinListener> ruinListeners = new ArrayList<RuinListener>();
public void ruinStarts(Collection<VehicleRoute> routes){
for(RuinListener l : ruinListeners) l.ruinStarts(routes);
}
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs){
for(RuinListener l : ruinListeners) l.ruinEnds(routes, unassignedJobs);
}
public void removed(Job job, VehicleRoute fromRoute){
for(RuinListener l : ruinListeners) l.removed(job, fromRoute);
}
public void addListener(RuinListener ruinListener){
ruinListeners.add(ruinListener);
}
public void removeListener(RuinListener ruinListener){
ruinListeners.remove(ruinListener);
}
public Collection<RuinListener> getListeners(){
return Collections.unmodifiableCollection(ruinListeners);
}
}

View file

@ -125,7 +125,8 @@ public class SearchStrategy {
VehicleRoutingProblemSolution newSolution = module.runAndGetSolution(lastSolution);
lastSolution = newSolution;
}
solutionCostCalculator.calculateCosts(lastSolution);
double costs = solutionCostCalculator.getCosts(lastSolution);
lastSolution.setCost(costs);
boolean solutionAccepted = solutionAcceptor.acceptSolution(solutions, lastSolution);
DiscoveredSolution discoveredSolution = new DiscoveredSolution(lastSolution, solutionAccepted, getName());
return discoveredSolution;

View file

@ -21,10 +21,11 @@ import basics.VehicleRoutingProblemSolution;
public interface SolutionCostCalculator {
/**
* This assumes that the solution is modified by setting its costs <br>
* <code>solution.setCost(costs);</code>
* Returns costs of solution.
*
* @param solution
* @return TODO
*/
public void calculateCosts(VehicleRoutingProblemSolution solution);
public double getCosts(VehicleRoutingProblemSolution solution);
}

View file

@ -14,12 +14,10 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package basics.route;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
interface ActivityVisitor {
public interface ActivityVisitor {
public void begin(VehicleRoute route);

View file

@ -0,0 +1,20 @@
package basics.route;
import java.util.Collection;
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);
}
}

View file

@ -0,0 +1,20 @@
package basics.route;
import java.util.Collection;
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);
}
}

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package basics.route;
import java.util.ArrayList;
import java.util.Collection;
@ -24,26 +24,14 @@ import java.util.Map;
import org.apache.log4j.Logger;
import basics.route.Vehicle;
class InfiniteVehicles implements VehicleFleetManager{
// static class TypeKeyComparator implements Comparator<TypeKey>{
//
// @Override
// public int compare(TypeKey k1, TypeKey k2) {
// double k1_fix = k1.type.getVehicleCostParams().fix;
// double k2_fix = k2.type.getVehicleCostParams().fix;
// return (int)(k1_fix - k2_fix);
// }
//
// }
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){
extractTypes(vehicles);
@ -57,12 +45,11 @@ class InfiniteVehicles implements VehicleFleetManager{
private void extractTypes(Collection<Vehicle> 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);
sortedTypes.add(typeKey);
}
// Collections.sort(sortedTypes, new TypeKeyComparator());
}
@ -95,8 +82,8 @@ class InfiniteVehicles implements VehicleFleetManager{
@Override
public Collection<Vehicle> getAvailableVehicles(String withoutThisType, String locationId) {
Collection<Vehicle> vehicles = new ArrayList<Vehicle>();
TypeKey thisKey = new TypeKey(withoutThisType,locationId);
for(TypeKey key : types.keySet()){
VehicleTypeKey thisKey = new VehicleTypeKey(withoutThisType,locationId);
for(VehicleTypeKey key : types.keySet()){
if(!key.equals(thisKey)){
vehicles.add(types.get(key));
}

View file

@ -14,12 +14,10 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package basics.route;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
interface ReverseActivityVisitor {
public interface ReverseActivityVisitor {
public void begin(VehicleRoute route);

View file

@ -14,16 +14,14 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package basics.route;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class ReverseRouteActivityVisitor implements RouteVisitor{
public class ReverseRouteActivityVisitor implements RouteVisitor{
private Collection<ReverseActivityVisitor> visitors = new ArrayList<ReverseActivityVisitor>();

View file

@ -14,15 +14,13 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package basics.route;
import java.util.ArrayList;
import java.util.Collection;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class RouteActivityVisitor implements RouteVisitor{
public class RouteActivityVisitor implements RouteVisitor{
private Collection<ActivityVisitor> visitors = new ArrayList<ActivityVisitor>();

View file

@ -14,11 +14,10 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package basics.route;
import basics.route.VehicleRoute;
interface RouteVisitor {
public interface RouteVisitor {
public void visit(VehicleRoute route);

View file

@ -113,6 +113,12 @@ public class TourActivities {
return Collections.unmodifiableSet(jobs);
}
/**
* Returns true if job is in jobList, otherwise false.
*
* @param job
* @return
*/
public boolean servesJob(Job job) {
return jobs.contains(job);
}
@ -146,13 +152,24 @@ public class TourActivities {
}
}
}
if(jobRemoved != activityRemoved) throw new IllegalStateException("job removed, but belonging activity not.");
assert jobRemoved == activityRemoved : "job removed, but belonging activity not.";
return activityRemoved;
}
/**
* Inserts the specified activity add the specified insertionIndex. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
* <p>If specified activity instanceof JobActivity, it adds job to jobList.
* <p>If insertionIndex > tourActivitiies.size(), it just adds the specified act at the end.
*
* @param insertionIndex
* @param act
* @throws IndexOutOfBoundsException if insertionIndex < 0;
*/
public void addActivity(int insertionIndex, TourActivity act) {
assert insertionIndex >= 0 : "insertionIndex == 0, this cannot be";
if(tourActivities.contains(act)) throw new IllegalStateException("act " + act + " already in tour. cannot add act twice.");
assert insertionIndex >= 0 : "insertionIndex < 0, this cannot be";
/*
* if 1 --> between start and act(0) --> act(0)
* if 2 && 2 <= acts.size --> between act(0) and act(1) --> act(1)
@ -166,9 +183,15 @@ public class TourActivities {
}
/**
<<<<<<< HEAD
* adds activity.
*
* @throw {@link IllegalStateException} if same activity is added twice.
=======
* Adds specified activity at the end of activity-list.
* <p>If act instanceof JobActivity, it adds underlying job also.
* @throws IllegalStateException if activity-list already contains act.
>>>>>>> refs/remotes/choose_remote_name/relaxAPI
* @param act
*/
public void addActivity(TourActivity act){
@ -184,6 +207,11 @@ public class TourActivities {
}
}
/**
* Returns number of jobs.
*
* @return
*/
public int jobSize() {
return jobs.size();
}

View file

@ -14,27 +14,23 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package basics.route;
import java.util.Collection;
class StateTypes {
public interface VehicleFleetManager {
// final static StateId LOAD = new StateIdImpl("load");
final static String LOAD = "load";
final static String LOAD_AT_DEPOT = "loadAtDepot";
final static String DURATION = "duration";
final static String LATEST_OPERATION_START_TIME = "latestOST";
final static String EARLIEST_OPERATION_START_TIME = "earliestOST";
public abstract void lock(Vehicle vehicle);
public abstract void unlock(Vehicle vehicle);
public abstract boolean isLocked(Vehicle vehicle);
public abstract void unlockAll();
public abstract Collection<Vehicle> getAvailableVehicles();
public Collection<Vehicle> getAvailableVehicles(String withoutThisType, String locationId);
static final String COSTS = "costs";
final static String FUTURE_PICKS = "futurePicks";
final static String PAST_DELIVERIES = "pastDeliveries";
}

View file

@ -0,0 +1,7 @@
package basics.route;
public interface VehicleFleetManagerFactory {
public VehicleFleetManager createFleetManager();
}

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package basics.route;
import java.util.ArrayList;
import java.util.Collection;
@ -27,12 +27,11 @@ import java.util.Set;
import org.apache.log4j.Logger;
import basics.route.PenaltyVehicleType;
import basics.route.Vehicle;
import basics.route.VehicleImpl.NoVehicle;
class VehicleFleetManagerImpl implements VehicleFleetManager {
public VehicleFleetManagerImpl newInstance(Collection<Vehicle> vehicles){
@ -54,11 +53,11 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
static class TypeContainer {
private TypeKey type;
private VehicleTypeKey type;
private ArrayList<Vehicle> vehicleList;
public TypeContainer(TypeKey type) {
public TypeContainer(VehicleTypeKey type) {
super();
this.type = type;
vehicleList = new ArrayList<Vehicle>();
@ -92,9 +91,9 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
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;
@ -122,8 +121,8 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
}
private void makeMap() {
typeMapOfAvailableVehicles = new HashMap<TypeKey, TypeContainer>();
penaltyVehicles = new HashMap<VehicleFleetManager.TypeKey, Vehicle>();
typeMapOfAvailableVehicles = new HashMap<VehicleTypeKey, TypeContainer>();
penaltyVehicles = new HashMap<VehicleTypeKey, Vehicle>();
for(Vehicle v : vehicles){
addVehicle(v);
}
@ -135,11 +134,11 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
}
String typeId = v.getType().getTypeId();
if(v.getType() instanceof PenaltyVehicleType){
TypeKey typeKey = new TypeKey(typeId,v.getLocationId());
VehicleTypeKey typeKey = new VehicleTypeKey(typeId,v.getLocationId());
penaltyVehicles.put(typeKey, v);
}
else{
TypeKey typeKey = new TypeKey(v.getType().getTypeId(),v.getLocationId());
VehicleTypeKey typeKey = new VehicleTypeKey(v.getType().getTypeId(),v.getLocationId());
if(!typeMapOfAvailableVehicles.containsKey(typeKey)){
typeMapOfAvailableVehicles.put(typeKey, new TypeContainer(typeKey));
}
@ -150,7 +149,7 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
private void removeVehicle(Vehicle v){
//it might be better to introduce a class PenaltyVehicle
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)){
typeMapOfAvailableVehicles.get(key).remove(v);
}
@ -167,7 +166,7 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
@Override
public Collection<Vehicle> getAvailableVehicles() {
List<Vehicle> vehicles = new ArrayList<Vehicle>();
for(TypeKey key : typeMapOfAvailableVehicles.keySet()){
for(VehicleTypeKey key : typeMapOfAvailableVehicles.keySet()){
if(!typeMapOfAvailableVehicles.get(key).isEmpty()){
vehicles.add(typeMapOfAvailableVehicles.get(key).getVehicle());
}
@ -193,8 +192,8 @@ class VehicleFleetManagerImpl implements VehicleFleetManager {
@Override
public Collection<Vehicle> getAvailableVehicles(String withoutThisType, String withThisLocationId) {
List<Vehicle> vehicles = new ArrayList<Vehicle>();
TypeKey thisKey = new TypeKey(withoutThisType,withThisLocationId);
for(TypeKey key : typeMapOfAvailableVehicles.keySet()){
VehicleTypeKey thisKey = new VehicleTypeKey(withoutThisType,withThisLocationId);
for(VehicleTypeKey key : typeMapOfAvailableVehicles.keySet()){
if(key.equals(thisKey)) continue;
if(!typeMapOfAvailableVehicles.get(key).isEmpty()){
vehicles.add(typeMapOfAvailableVehicles.get(key).getVehicle());

View file

@ -0,0 +1,48 @@
package basics.route;
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;
}
}

View file

@ -14,13 +14,14 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package util;
import basics.costs.ForwardTransportTime;
import basics.route.ActivityVisitor;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class ActivityTimeTracker implements ActivityVisitor{
public class ActivityTimeTracker implements ActivityVisitor{
private ForwardTransportTime transportTime;

Some files were not shown because too many files have changed in this diff Show more