mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
pdp
This commit is contained in:
parent
dfe25738bf
commit
e912979bbb
25 changed files with 30297 additions and 1169 deletions
|
|
@ -34,7 +34,7 @@ import basics.costs.VehicleRoutingTransportCosts;
|
||||||
* @author stefan schroeder
|
* @author stefan schroeder
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class AvgJobDistance implements JobDistance {
|
public class AvgJobDistance implements JobDistance {
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(AvgJobDistance.class);
|
private static Logger log = Logger.getLogger(AvgJobDistance.class);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,9 +137,8 @@ final class BestInsertion implements InsertionStrategy{
|
||||||
vehicleRoutes.add(newRoute);
|
vehicleRoutes.add(newRoute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// logger.info("insert " + unassignedJob + " pickup@" + bestInsertion.getInsertionData().getPickupInsertionIndex() + " delivery@" + bestInsertion.getInsertionData().getDeliveryInsertionIndex());
|
||||||
inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||||
|
|
||||||
}
|
}
|
||||||
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
|
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,11 @@ public class BestInsertionBuilder implements InsertionStrategyBuilder{
|
||||||
constraintManager.addConstraint(new HardPickupAndDeliveryLoadRouteLevelConstraint(stateManager));
|
constraintManager.addConstraint(new HardPickupAndDeliveryLoadRouteLevelConstraint(stateManager));
|
||||||
if(vrp.getProblemConstraints().contains(Constraint.DELIVERIES_FIRST)){
|
if(vrp.getProblemConstraints().contains(Constraint.DELIVERIES_FIRST)){
|
||||||
constraintManager.addConstraint(new HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager));
|
constraintManager.addConstraint(new HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager));
|
||||||
|
constraintManager.addConstraint(new HardPickupAndDeliveryShipmentActivityLevelConstraint(stateManager,true));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
constraintManager.addConstraint(new HardPickupAndDeliveryActivityLevelConstraint(stateManager));
|
constraintManager.addConstraint(new HardPickupAndDeliveryActivityLevelConstraint(stateManager));
|
||||||
|
constraintManager.addConstraint(new HardPickupAndDeliveryShipmentActivityLevelConstraint(stateManager,true));
|
||||||
}
|
}
|
||||||
stateManager.addActivityVisitor(new UpdateOccuredDeliveriesAtActivityLevel(stateManager));
|
stateManager.addActivityVisitor(new UpdateOccuredDeliveriesAtActivityLevel(stateManager));
|
||||||
stateManager.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager));
|
stateManager.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager));
|
||||||
|
|
|
||||||
263
jsprit-core/src/main/java/algorithms/BestInsertionConc.java
Normal file
263
jsprit-core/src/main/java/algorithms/BestInsertionConc.java
Normal file
|
|
@ -0,0 +1,263 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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 java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import util.RandomNumberGeneration;
|
||||||
|
import algorithms.InsertionData.NoInsertionFound;
|
||||||
|
import basics.Job;
|
||||||
|
import basics.algo.InsertionListener;
|
||||||
|
import basics.route.Driver;
|
||||||
|
import basics.route.Vehicle;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author stefan schroeder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class BestInsertionConc implements InsertionStrategy{
|
||||||
|
|
||||||
|
static class Batch {
|
||||||
|
List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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(BestInsertionConc.class);
|
||||||
|
|
||||||
|
private Random random = RandomNumberGeneration.getRandom();
|
||||||
|
|
||||||
|
private final static double NO_NEW_DEPARTURE_TIME_YET = -12345.12345;
|
||||||
|
|
||||||
|
private final static Vehicle NO_NEW_VEHICLE_YET = null;
|
||||||
|
|
||||||
|
private final static Driver NO_NEW_DRIVER_YET = null;
|
||||||
|
|
||||||
|
private InsertionListeners insertionsListeners;
|
||||||
|
|
||||||
|
private Inserter inserter;
|
||||||
|
|
||||||
|
private JobInsertionCostsCalculator bestInsertionCostCalculator;
|
||||||
|
|
||||||
|
private boolean minVehiclesFirst = false;
|
||||||
|
|
||||||
|
private int nuOfBatches;
|
||||||
|
|
||||||
|
private ExecutorService executor;
|
||||||
|
|
||||||
|
private ExecutorCompletionService<Insertion> completionService;
|
||||||
|
|
||||||
|
public void setRandom(Random random) {
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BestInsertionConc(JobInsertionCostsCalculator jobInsertionCalculator, ExecutorService executorService, int nuOfBatches) {
|
||||||
|
super();
|
||||||
|
this.insertionsListeners = new InsertionListeners();
|
||||||
|
this.executor = executorService;
|
||||||
|
this.nuOfBatches = nuOfBatches;
|
||||||
|
inserter = new Inserter(insertionsListeners);
|
||||||
|
bestInsertionCostCalculator = jobInsertionCalculator;
|
||||||
|
completionService = new ExecutorCompletionService<Insertion>(executor);
|
||||||
|
logger.info("initialise " + this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[name=bestInsertion]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
|
insertionsListeners.informInsertionStarts(vehicleRoutes,unassignedJobs);
|
||||||
|
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
||||||
|
Collections.shuffle(unassignedJobList, random);
|
||||||
|
for(final Job unassignedJob : unassignedJobList){
|
||||||
|
|
||||||
|
|
||||||
|
Insertion bestInsertion = null;
|
||||||
|
double bestInsertionCost = Double.MAX_VALUE;
|
||||||
|
|
||||||
|
List<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches);
|
||||||
|
|
||||||
|
for(final Batch batch : batches){
|
||||||
|
completionService.submit(new Callable<Insertion>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Insertion call() throws Exception {
|
||||||
|
return getBestInsertion(batch,unassignedJob);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
for(int i=0;i<batches.size();i++){
|
||||||
|
Future<Insertion> futureIData = completionService.take();
|
||||||
|
Insertion insertion = futureIData.get();
|
||||||
|
if(insertion == null) continue;
|
||||||
|
if(insertion.getInsertionData().getInsertionCost() < bestInsertionCost){
|
||||||
|
bestInsertion = insertion;
|
||||||
|
bestInsertionCost = insertion.getInsertionData().getInsertionCost();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(InterruptedException e){
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
catch (ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
logger.error(e.getCause().toString());
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(!minVehiclesFirst){
|
||||||
|
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
||||||
|
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();
|
||||||
|
vehicleRoutes.add(newRoute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(bestInsertion == null){
|
||||||
|
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
bestInsertion = new Insertion(newRoute,bestI);
|
||||||
|
vehicleRoutes.add(newRoute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// logger.info("insert " + unassignedJob + " pickup@" + bestInsertion.getInsertionData().getPickupInsertionIndex() + " delivery@" + bestInsertion.getInsertionData().getDeliveryInsertionIndex());
|
||||||
|
inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||||
|
}
|
||||||
|
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getErrorMsg(Job unassignedJob) {
|
||||||
|
return "given the vehicles, could not insert job\n" +
|
||||||
|
"\t" + unassignedJob +
|
||||||
|
"\n\tthis might have the following reasons:\n" +
|
||||||
|
"\t- no vehicle has the capacity to transport the job [check whether there is at least one vehicle that is capable to transport the job]\n" +
|
||||||
|
"\t- the time-window cannot be met, even in a commuter tour the time-window is missed [check whether it is possible to reach the time-window on the shortest path or make hard time-windows soft]\n" +
|
||||||
|
"\t- if you deal with finite vehicles, and the available vehicles are already fully employed, no vehicle can be found anymore to transport the job [add penalty-vehicles]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeListener(InsertionListener insertionListener) {
|
||||||
|
insertionsListeners.removeListener(insertionListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<InsertionListener> getListeners() {
|
||||||
|
return Collections.unmodifiableCollection(insertionsListeners.getListeners());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addListener(InsertionListener insertionListener) {
|
||||||
|
insertionsListeners.addListener(insertionListener);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
|
||||||
|
Insertion bestInsertion = null;
|
||||||
|
double bestInsertionCost = Double.MAX_VALUE;
|
||||||
|
for(VehicleRoute vehicleRoute : batch.routes){
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if(iData.getInsertionCost() < bestInsertionCost){
|
||||||
|
bestInsertion = new Insertion(vehicleRoute,iData);
|
||||||
|
bestInsertionCost = iData.getInsertionCost();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bestInsertion;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Batch> distributeRoutes(Collection<VehicleRoute> vehicleRoutes, int nuOfBatches) {
|
||||||
|
List<Batch> batches = new ArrayList<Batch>();
|
||||||
|
for(int i=0;i<nuOfBatches;i++) batches.add(new Batch());
|
||||||
|
/*
|
||||||
|
* if route.size < nuOfBatches add as much routes as empty batches are available
|
||||||
|
* else add one empty route anyway
|
||||||
|
*/
|
||||||
|
if(vehicleRoutes.size()<nuOfBatches){
|
||||||
|
int nOfNewRoutes = nuOfBatches-vehicleRoutes.size();
|
||||||
|
for(int i=0;i<nOfNewRoutes;i++){
|
||||||
|
vehicleRoutes.add(VehicleRoute.emptyRoute());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
vehicleRoutes.add(VehicleRoute.emptyRoute());
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* distribute routes to batches equally
|
||||||
|
*/
|
||||||
|
int count = 0;
|
||||||
|
for(VehicleRoute route : vehicleRoutes){
|
||||||
|
if(count == nuOfBatches) count=0;
|
||||||
|
batches.get(count).routes.add(route);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return batches;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,8 @@ package algorithms;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import basics.Service;
|
||||||
|
import basics.Shipment;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.algo.InsertionListener;
|
import basics.algo.InsertionListener;
|
||||||
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
||||||
|
|
@ -221,11 +223,7 @@ class CalculatorBuilder {
|
||||||
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateGetter statesManager){
|
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateGetter statesManager){
|
||||||
if(constraintManager == null) throw new IllegalStateException("constraint-manager is null");
|
if(constraintManager == null) throw new IllegalStateException("constraint-manager is null");
|
||||||
|
|
||||||
//<<<<<<< HEAD
|
|
||||||
// ActivityInsertionCostsCalculator defaultCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager);
|
|
||||||
// JobInsertionCalculator standardServiceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), defaultCalc, constraintManager);
|
|
||||||
//
|
|
||||||
//=======
|
|
||||||
ActivityInsertionCostsCalculator actInsertionCalc;
|
ActivityInsertionCostsCalculator actInsertionCalc;
|
||||||
if(activityInsertionCostCalculator == null){
|
if(activityInsertionCostCalculator == null){
|
||||||
actInsertionCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts());
|
actInsertionCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||||
|
|
@ -234,10 +232,16 @@ class CalculatorBuilder {
|
||||||
actInsertionCalc = activityInsertionCostCalculator;
|
actInsertionCalc = activityInsertionCostCalculator;
|
||||||
}
|
}
|
||||||
|
|
||||||
JobInsertionCostsCalculator standardServiceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
|
ShipmentInsertionCalculator shipmentInsertion = new ShipmentInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
|
||||||
//>>>>>>> refs/remotes/choose_remote_name/relaxAPI
|
ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
|
||||||
((ServiceInsertionCalculator) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
|
|
||||||
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion);
|
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
|
||||||
|
switcher.put(Shipment.class, shipmentInsertion);
|
||||||
|
switcher.put(Service.class, serviceInsertion);
|
||||||
|
|
||||||
|
// JobInsertionCostsCalculator standardServiceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
|
||||||
|
// ((ServiceInsertionCalculator) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
|
||||||
|
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(switcher);
|
||||||
|
|
||||||
return calcPlusListeners;
|
return calcPlusListeners;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package algorithms;
|
||||||
|
|
||||||
|
public class ConcurrentVehicleRoutingAlgorithmWrapper {
|
||||||
|
|
||||||
|
|
||||||
|
private int nuOfThreads;
|
||||||
|
|
||||||
|
public ConcurrentVehicleRoutingAlgorithmWrapper(int nuOfThreads) {
|
||||||
|
super();
|
||||||
|
this.nuOfThreads = nuOfThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import basics.route.DeliverShipment;
|
import basics.route.DeliverShipment;
|
||||||
import basics.route.PickupShipment;
|
import basics.route.PickupShipment;
|
||||||
import basics.route.Start;
|
import basics.route.Start;
|
||||||
|
|
@ -7,6 +9,8 @@ import basics.route.TourActivity;
|
||||||
|
|
||||||
class HardPickupAndDeliveryShipmentActivityLevelConstraint implements HardActivityLevelConstraint {
|
class HardPickupAndDeliveryShipmentActivityLevelConstraint implements HardActivityLevelConstraint {
|
||||||
|
|
||||||
|
private static Logger logger = Logger.getLogger(HardPickupAndDeliveryShipmentActivityLevelConstraint.class);
|
||||||
|
|
||||||
private StateManager stateManager;
|
private StateManager stateManager;
|
||||||
|
|
||||||
private boolean backhaul = false;
|
private boolean backhaul = false;
|
||||||
|
|
@ -24,16 +28,22 @@ class HardPickupAndDeliveryShipmentActivityLevelConstraint implements HardActivi
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
|
public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
|
||||||
|
// logger.info(prevAct + " - " + newAct + " - " + nextAct);
|
||||||
if(!(newAct instanceof PickupShipment) && !(newAct instanceof DeliverShipment)){
|
if(!(newAct instanceof PickupShipment) && !(newAct instanceof DeliverShipment)){
|
||||||
return ConstraintsStatus.FULFILLED;
|
return ConstraintsStatus.FULFILLED;
|
||||||
}
|
}
|
||||||
if(backhaul){
|
if(backhaul){
|
||||||
// if(newAct instanceof PickupShipment && nextAct instanceof DeliverShipment){ return false; }
|
if(newAct instanceof PickupShipment && prevAct instanceof DeliverShipment){
|
||||||
if(newAct instanceof DeliverShipment && prevAct instanceof PickupShipment){ return ConstraintsStatus.NOT_FULFILLED; }
|
// logger.info("NOT_FULFILLED_BREAK");
|
||||||
|
return ConstraintsStatus.NOT_FULFILLED_BREAK; }
|
||||||
|
if(newAct instanceof DeliverShipment && nextAct instanceof PickupShipment){
|
||||||
|
// logger.info("NOT_FULFILLED");
|
||||||
|
return ConstraintsStatus.NOT_FULFILLED; }
|
||||||
}
|
}
|
||||||
int loadAtPrevAct;
|
int loadAtPrevAct;
|
||||||
// int futurePicks;
|
// int futurePicks;
|
||||||
// int pastDeliveries;
|
// int pastDeliveries;
|
||||||
|
|
||||||
if(prevAct instanceof Start){
|
if(prevAct instanceof Start){
|
||||||
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_BEGINNING).toDouble();
|
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_BEGINNING).toDouble();
|
||||||
// futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble();
|
// futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble();
|
||||||
|
|
@ -46,15 +56,18 @@ class HardPickupAndDeliveryShipmentActivityLevelConstraint implements HardActivi
|
||||||
}
|
}
|
||||||
if(newAct instanceof PickupShipment){
|
if(newAct instanceof PickupShipment){
|
||||||
if(loadAtPrevAct + newAct.getCapacityDemand() > iFacts.getNewVehicle().getCapacity()){
|
if(loadAtPrevAct + newAct.getCapacityDemand() > iFacts.getNewVehicle().getCapacity()){
|
||||||
|
// logger.info("NOT_FULFILLED");
|
||||||
return ConstraintsStatus.NOT_FULFILLED;
|
return ConstraintsStatus.NOT_FULFILLED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(newAct instanceof DeliverShipment){
|
if(newAct instanceof DeliverShipment){
|
||||||
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) > iFacts.getNewVehicle().getCapacity()){
|
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) > iFacts.getNewVehicle().getCapacity()){
|
||||||
|
// logger.info("NOT_FULFILLED_BREAK");
|
||||||
return ConstraintsStatus.NOT_FULFILLED_BREAK;
|
return ConstraintsStatus.NOT_FULFILLED_BREAK;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// logger.info("FULFILLED");
|
||||||
return ConstraintsStatus.FULFILLED;
|
return ConstraintsStatus.FULFILLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import algorithms.InsertionData.NoInsertionFound;
|
import algorithms.InsertionData.NoInsertionFound;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ import basics.route.TourActivity;
|
||||||
* @author stefan
|
* @author stefan
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCalculator{
|
public class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCalculator{
|
||||||
|
|
||||||
private VehicleRoutingTransportCosts routingCosts;
|
private VehicleRoutingTransportCosts routingCosts;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,8 +154,9 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{
|
||||||
prevAct_deliveryLoop = activities.get(j);
|
prevAct_deliveryLoop = activities.get(j);
|
||||||
}
|
}
|
||||||
if(!deliverShipmentLoopBroken){ //check insertion between lastAct and endOfTour
|
if(!deliverShipmentLoopBroken){ //check insertion between lastAct and endOfTour
|
||||||
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,end,prevActEndTime_deliveryLoop);
|
ConstraintsStatus deliverShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, end, prevActEndTime_deliveryLoop);
|
||||||
if(deliveryAIC != null){
|
if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
|
||||||
|
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,end,prevActEndTime_deliveryLoop);
|
||||||
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
|
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
|
||||||
if(totalActivityInsertionCosts < bestCost){
|
if(totalActivityInsertionCosts < bestCost){
|
||||||
bestCost = totalActivityInsertionCosts;
|
bestCost = totalActivityInsertionCosts;
|
||||||
|
|
@ -170,19 +171,24 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{
|
||||||
prevAct = activities.get(i);
|
prevAct = activities.get(i);
|
||||||
}
|
}
|
||||||
if(!pickupShipmentLoopBroken){ //check insertion of pickupShipment and deliverShipment at just before tour ended
|
if(!pickupShipmentLoopBroken){ //check insertion of pickupShipment and deliverShipment at just before tour ended
|
||||||
ActivityInsertionCosts pickupAIC = calculate(insertionContext,prevAct,pickupShipment,end,prevActEndTime);
|
ConstraintsStatus pickupShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, pickupShipment, end, prevActEndTime);
|
||||||
if(pickupAIC != null){ //evaluate delivery
|
if(pickupShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
|
||||||
|
ActivityInsertionCosts pickupAIC = calculate(insertionContext,prevAct,pickupShipment,end,prevActEndTime);
|
||||||
|
|
||||||
TourActivity prevAct_deliveryLoop = pickupShipment;
|
TourActivity prevAct_deliveryLoop = pickupShipment;
|
||||||
double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), pickupShipment.getLocationId(), prevActEndTime, newDriver, newVehicle);
|
double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), pickupShipment.getLocationId(), prevActEndTime, newDriver, newVehicle);
|
||||||
double shipmentPickupEndTime = CalculationUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment);
|
double shipmentPickupEndTime = CalculationUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment);
|
||||||
double prevActEndTime_deliveryLoop = shipmentPickupEndTime;
|
double prevActEndTime_deliveryLoop = shipmentPickupEndTime;
|
||||||
|
|
||||||
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,end,prevActEndTime_deliveryLoop);
|
ConstraintsStatus deliverShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, end, prevActEndTime_deliveryLoop);
|
||||||
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
|
if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
|
||||||
if(totalActivityInsertionCosts < bestCost){
|
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,end,prevActEndTime_deliveryLoop);
|
||||||
bestCost = totalActivityInsertionCosts;
|
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
|
||||||
pickupInsertionIndex = activities.size();
|
if(totalActivityInsertionCosts < bestCost){
|
||||||
deliveryInsertionIndex = activities.size();
|
bestCost = totalActivityInsertionCosts;
|
||||||
|
pickupInsertionIndex = activities.size();
|
||||||
|
deliveryInsertionIndex = activities.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -190,6 +196,7 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{
|
||||||
return InsertionData.createEmptyInsertionData();
|
return InsertionData.createEmptyInsertionData();
|
||||||
}
|
}
|
||||||
InsertionData insertionData = new InsertionData(bestCost, pickupInsertionIndex, deliveryInsertionIndex, newVehicle, newDriver);
|
InsertionData insertionData = new InsertionData(bestCost, pickupInsertionIndex, deliveryInsertionIndex, newVehicle, newDriver);
|
||||||
|
// logger.info("pickupIndex="+pickupInsertionIndex + ";deliveryIndex=" + deliveryInsertionIndex);
|
||||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||||
return insertionData;
|
return insertionData;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
import algorithms.StateManager.StateImpl;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import basics.route.ActivityVisitor;
|
import basics.route.ActivityVisitor;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
@ -17,6 +18,9 @@ import basics.route.VehicleRoute;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class UpdateLoadAtActivityLevel implements ActivityVisitor, StateUpdater {
|
class UpdateLoadAtActivityLevel implements ActivityVisitor, StateUpdater {
|
||||||
|
|
||||||
|
private static Logger logger = Logger.getLogger(UpdateLoadAtActivityLevel.class);
|
||||||
|
|
||||||
private StateManager stateManager;
|
private StateManager stateManager;
|
||||||
private int currentLoad = 0;
|
private int currentLoad = 0;
|
||||||
private VehicleRoute route;
|
private VehicleRoute route;
|
||||||
|
|
@ -48,6 +52,7 @@ class UpdateLoadAtActivityLevel implements ActivityVisitor, StateUpdater {
|
||||||
@Override
|
@Override
|
||||||
public void begin(VehicleRoute route) {
|
public void begin(VehicleRoute route) {
|
||||||
currentLoad = (int) stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble();
|
currentLoad = (int) stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble();
|
||||||
|
// logger.info(route + " load@beginning=" + currentLoad);
|
||||||
this.route = route;
|
this.route = route;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,12 +60,14 @@ class UpdateLoadAtActivityLevel implements ActivityVisitor, StateUpdater {
|
||||||
public void visit(TourActivity act) {
|
public void visit(TourActivity act) {
|
||||||
currentLoad += act.getCapacityDemand();
|
currentLoad += act.getCapacityDemand();
|
||||||
stateManager.putActivityState(act, StateFactory.LOAD, StateFactory.createState(currentLoad));
|
stateManager.putActivityState(act, StateFactory.LOAD, StateFactory.createState(currentLoad));
|
||||||
|
// logger.info(act + " load@act=" + currentLoad + " vehcap=" + route.getVehicle().getCapacity());
|
||||||
assert currentLoad <= route.getVehicle().getCapacity() : "currentLoad at activity must not be > vehicleCapacity";
|
assert currentLoad <= route.getVehicle().getCapacity() : "currentLoad at activity must not be > vehicleCapacity";
|
||||||
assert currentLoad >= 0 : "currentLoad at act must not be < 0";
|
assert currentLoad >= 0 : "currentLoad at act must not be < 0";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void finish() {
|
public void finish() {
|
||||||
|
// logger.info("end of " + route);
|
||||||
// stateManager.putRouteState(route, StateFactory., state)
|
// stateManager.putRouteState(route, StateFactory., state)
|
||||||
currentLoad = 0;
|
currentLoad = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
import algorithms.StateManager.StateImpl;
|
|
||||||
import basics.Delivery;
|
import basics.Delivery;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Pickup;
|
import basics.Pickup;
|
||||||
|
|
|
||||||
|
|
@ -133,10 +133,6 @@ public class Shipment implements Job{
|
||||||
return demand;
|
return demand;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSize() {
|
|
||||||
return demand;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPickupLocation() {
|
public String getPickupLocation() {
|
||||||
return pickupLocation;
|
return pickupLocation;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -326,6 +326,11 @@ public class VrpXMLReader{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String pickupTWStart = shipmentConfig.getString("pickup.timeWindows.timeWindow(0).start");
|
||||||
|
// String pickupTWEnd = shipmentConfig.getString("pickup.timeWindows.timeWindow(0).end");
|
||||||
|
// TimeWindow pickupTW = TimeWindow.newInstance(Double.parseDouble(pickupTWStart), Double.parseDouble(pickupTWEnd));
|
||||||
|
// builder.setPickupTimeWindow(pickupTW);
|
||||||
|
|
||||||
String deliveryLocationId = shipmentConfig.getString("delivery.locationId");
|
String deliveryLocationId = shipmentConfig.getString("delivery.locationId");
|
||||||
builder.setDeliveryLocation(deliveryLocationId);
|
builder.setDeliveryLocation(deliveryLocationId);
|
||||||
|
|
||||||
|
|
@ -341,6 +346,12 @@ public class VrpXMLReader{
|
||||||
builder.setPickupLocation(deliveryCoord.toString());
|
builder.setPickupLocation(deliveryCoord.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String delTWStart = shipmentConfig.getString("delivery.timeWindows.timeWindow(0).start");
|
||||||
|
String delTWEnd = shipmentConfig.getString("delivery.timeWindows.timeWindow(0).end");
|
||||||
|
TimeWindow delTW = TimeWindow.newInstance(Double.parseDouble(delTWStart), Double.parseDouble(delTWEnd));
|
||||||
|
builder.setDeliveryTimeWindow(delTW);
|
||||||
|
|
||||||
Shipment shipment = builder.build();
|
Shipment shipment = builder.build();
|
||||||
vrpBuilder.addJob(shipment);
|
vrpBuilder.addJob(shipment);
|
||||||
shipmentMap .put(shipment.getId(),shipment);
|
shipmentMap .put(shipment.getId(),shipment);
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ public final class DeliverShipment implements DeliveryActivity{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCapacityDemand() {
|
public int getCapacityDemand() {
|
||||||
return shipment.getSize()*-1;
|
return shipment.getCapacityDemand()*-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ public final class PickupShipment implements PickupActivity{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCapacityDemand() {
|
public int getCapacityDemand() {
|
||||||
return shipment.getSize();
|
return shipment.getCapacityDemand();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,10 @@ public class VehicleTypeImpl implements VehicleType {
|
||||||
|
|
||||||
private double maxVelocity;
|
private double maxVelocity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use builder instead
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public static VehicleTypeImpl newInstance(String typeId, int capacity, VehicleTypeImpl.VehicleCostParams para){
|
public static VehicleTypeImpl newInstance(String typeId, int capacity, VehicleTypeImpl.VehicleCostParams para){
|
||||||
return new VehicleTypeImpl(typeId, capacity, para);
|
return new VehicleTypeImpl(typeId, capacity, para);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import java.awt.image.CropImageFilter;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -11,7 +9,6 @@ import org.junit.Test;
|
||||||
import util.Coordinate;
|
import util.Coordinate;
|
||||||
import util.CrowFlyCosts;
|
import util.CrowFlyCosts;
|
||||||
import util.Locations;
|
import util.Locations;
|
||||||
import util.ManhattanCosts;
|
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.Shipment;
|
import basics.Shipment;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,18 +17,17 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import util.Solutions;
|
import util.Solutions;
|
||||||
import algorithms.StateManager.StateImpl;
|
|
||||||
import algorithms.acceptors.AcceptNewIfBetterThanWorst;
|
import algorithms.acceptors.AcceptNewIfBetterThanWorst;
|
||||||
import algorithms.selectors.SelectBest;
|
import algorithms.selectors.SelectBest;
|
||||||
import basics.Delivery;
|
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Pickup;
|
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.Shipment;
|
import basics.Shipment;
|
||||||
import basics.VehicleRoutingAlgorithm;
|
import basics.VehicleRoutingAlgorithm;
|
||||||
|
|
@ -44,7 +43,6 @@ import basics.io.VrpXMLWriter;
|
||||||
import basics.route.InfiniteFleetManagerFactory;
|
import basics.route.InfiniteFleetManagerFactory;
|
||||||
import basics.route.ReverseRouteActivityVisitor;
|
import basics.route.ReverseRouteActivityVisitor;
|
||||||
import basics.route.RouteActivityVisitor;
|
import basics.route.RouteActivityVisitor;
|
||||||
import basics.route.TourActivity;
|
|
||||||
import basics.route.VehicleFleetManager;
|
import basics.route.VehicleFleetManager;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
@ -56,6 +54,8 @@ public class BuildPDVRPWithShipmentsAlgoFromScratchTest {
|
||||||
|
|
||||||
static Logger log = Logger.getLogger(BuildPDVRPWithShipmentsAlgoFromScratchTest.class);
|
static Logger log = Logger.getLogger(BuildPDVRPWithShipmentsAlgoFromScratchTest.class);
|
||||||
|
|
||||||
|
ExecutorService executorService;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup(){
|
public void setup(){
|
||||||
|
|
||||||
|
|
@ -80,7 +80,7 @@ public class BuildPDVRPWithShipmentsAlgoFromScratchTest {
|
||||||
ConstraintManager constraintManager = new ConstraintManager();
|
ConstraintManager constraintManager = new ConstraintManager();
|
||||||
constraintManager.addConstraint(new HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts()));
|
constraintManager.addConstraint(new HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts()));
|
||||||
constraintManager.addConstraint(new HardPickupAndDeliveryActivityLevelConstraint(stateManager));
|
constraintManager.addConstraint(new HardPickupAndDeliveryActivityLevelConstraint(stateManager));
|
||||||
constraintManager.addConstraint(new HardPickupAndDeliveryShipmentActivityLevelConstraint(stateManager));
|
constraintManager.addConstraint(new HardPickupAndDeliveryShipmentActivityLevelConstraint(stateManager,true));
|
||||||
constraintManager.addConstraint(new HardPickupAndDeliveryLoadRouteLevelConstraint(stateManager));
|
constraintManager.addConstraint(new HardPickupAndDeliveryLoadRouteLevelConstraint(stateManager));
|
||||||
|
|
||||||
ActivityInsertionCostsCalculator marginalCalculus = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts());
|
ActivityInsertionCostsCalculator marginalCalculus = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||||
|
|
@ -98,8 +98,11 @@ public class BuildPDVRPWithShipmentsAlgoFromScratchTest {
|
||||||
|
|
||||||
BestInsertion bestInsertion = new BestInsertion(finalServiceInsertion);
|
BestInsertion bestInsertion = new BestInsertion(finalServiceInsertion);
|
||||||
|
|
||||||
RuinRadial radial = new RuinRadial(vrp, 0.15, new AvgJobDistance(vrp.getTransportCosts()));
|
executorService = Executors.newFixedThreadPool(2);;
|
||||||
RuinRandom random = new RuinRandom(vrp, 0.25);
|
// BestInsertionConc bestInsertion = new BestInsertionConc(finalServiceInsertion, executorService, 2);
|
||||||
|
|
||||||
|
RuinRadial radial = new RuinRadial(vrp, 0.3, new AvgJobDistance(vrp.getTransportCosts()));
|
||||||
|
RuinRandom random = new RuinRandom(vrp, 0.5);
|
||||||
|
|
||||||
SolutionCostCalculator solutionCostCalculator = new SolutionCostCalculator() {
|
SolutionCostCalculator solutionCostCalculator = new SolutionCostCalculator() {
|
||||||
|
|
||||||
|
|
@ -142,63 +145,41 @@ public class BuildPDVRPWithShipmentsAlgoFromScratchTest {
|
||||||
iterateBackward.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
|
iterateBackward.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
|
||||||
iterateBackward.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager));
|
iterateBackward.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager));
|
||||||
|
|
||||||
|
JobInsertedListener updateWhenJobHasBeenInserted = new JobInsertedListener() {
|
||||||
|
|
||||||
InsertionStartsListener loadVehicleInDepot = new InsertionStartsListener() {
|
@Override
|
||||||
|
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||||
|
iterateForward.visit(inRoute);
|
||||||
|
iterateBackward.visit(inRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
InsertionStartsListener updateRoutesWhenInsertionStarts = new InsertionStartsListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
for(VehicleRoute route : vehicleRoutes){
|
for(VehicleRoute route : vehicleRoutes){
|
||||||
int loadAtDepot = 0;
|
|
||||||
int loadAtEnd = 0;
|
|
||||||
for(Job j : route.getTourActivities().getJobs()){
|
|
||||||
if(j instanceof Delivery){
|
|
||||||
loadAtDepot += j.getCapacityDemand();
|
|
||||||
}
|
|
||||||
if(j instanceof Pickup){
|
|
||||||
loadAtEnd += j.getCapacityDemand();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stateManager.putRouteState(route, StateFactory.LOAD_AT_BEGINNING, new StateImpl(loadAtDepot));
|
|
||||||
stateManager.putRouteState(route, StateFactory.LOAD, new StateImpl(loadAtEnd));
|
|
||||||
iterateForward.visit(route);
|
iterateForward.visit(route);
|
||||||
iterateBackward.visit(route);
|
iterateBackward.visit(route);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(fleetManager));
|
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(fleetManager));
|
||||||
|
|
||||||
JobInsertedListener updateLoadAfterJobHasBeenInserted = new JobInsertedListener() {
|
bestInsertion.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager));
|
||||||
|
bestInsertion.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager));
|
||||||
@Override
|
bestInsertion.addListener(updateWhenJobHasBeenInserted);
|
||||||
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
bestInsertion.addListener(updateRoutesWhenInsertionStarts);
|
||||||
// log.info("insert job " + job2insert.getClass().toString() + " job " + job2insert + "" + job2insert.getCapacityDemand() + " in route " + inRoute.getTourActivities());
|
|
||||||
|
|
||||||
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, new StateImpl(loadAtDepot + job2insert.getCapacityDemand()));
|
|
||||||
}
|
|
||||||
if(job2insert instanceof Pickup){
|
|
||||||
int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_END).toDouble();
|
|
||||||
// log.info("loadAtEnd="+loadAtEnd);
|
|
||||||
stateManager.putRouteState(inRoute, StateFactory.LOAD_AT_END, new StateImpl(loadAtEnd + job2insert.getCapacityDemand()));
|
|
||||||
}
|
|
||||||
iterateForward.visit(inRoute);
|
|
||||||
iterateBackward.visit(inRoute);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bestInsertion.addListener(loadVehicleInDepot);
|
|
||||||
bestInsertion.addListener(updateLoadAfterJobHasBeenInserted);
|
|
||||||
|
|
||||||
VehicleRoutingProblemSolution iniSolution = new InsertionInitialSolutionFactory(bestInsertion, solutionCostCalculator).createSolution(vrp);
|
VehicleRoutingProblemSolution iniSolution = new InsertionInitialSolutionFactory(bestInsertion, solutionCostCalculator).createSolution(vrp);
|
||||||
// System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size());
|
// System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size());
|
||||||
vra.addInitialSolution(iniSolution);
|
vra.addInitialSolution(iniSolution);
|
||||||
|
|
||||||
vra.setNuOfIterations(100);
|
vra.setNuOfIterations(1000);
|
||||||
vra.setPrematureBreak(100);
|
// vra.setPrematureBreak(500);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,20 +187,27 @@ public class BuildPDVRPWithShipmentsAlgoFromScratchTest {
|
||||||
public void test(){
|
public void test(){
|
||||||
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
|
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
|
||||||
VehicleRoutingProblemSolution best = Solutions.getBest(solutions);
|
VehicleRoutingProblemSolution best = Solutions.getBest(solutions);
|
||||||
System.out.println(best.getCost());
|
|
||||||
for(VehicleRoute r : best.getRoutes()){
|
executorService.shutdown();
|
||||||
System.out.println(r);
|
// Wait until all threads are finish
|
||||||
System.out.println("#jobs="+r.getTourActivities().jobSize());
|
// executorService.awaitTermination();
|
||||||
System.out.println(r.getStart());
|
|
||||||
for(TourActivity act : r.getTourActivities().getActivities()){
|
// for(VehicleRoute r : best.getRoutes()){
|
||||||
System.out.println(act);
|
// System.out.println(r);
|
||||||
}
|
// System.out.println("#jobs="+r.getTourActivities().jobSize());
|
||||||
System.out.println(r.getEnd());
|
// System.out.println(r.getStart());
|
||||||
}
|
// for(TourActivity act : r.getTourActivities().getActivities()){
|
||||||
|
// System.out.println(act);
|
||||||
|
// }
|
||||||
|
// System.out.println(r.getEnd());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
System.out.println("total="+best.getCost());
|
||||||
|
System.out.println("#routes="+best.getRoutes().size());
|
||||||
|
|
||||||
// for()
|
// for()
|
||||||
|
|
||||||
new VrpXMLWriter(vrp, solutions).write("src/test/resources/pd_solomon_c101_sol.xml");
|
new VrpXMLWriter(vrp, solutions).write("src/test/resources/pdp_sol.xml");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
package algorithms;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import algorithms.HardActivityLevelConstraint.ConstraintsStatus;
|
||||||
|
import basics.Service;
|
||||||
|
import basics.Shipment;
|
||||||
|
import basics.route.DeliverShipment;
|
||||||
|
import basics.route.PickupService;
|
||||||
|
import basics.route.PickupShipment;
|
||||||
|
import basics.route.Vehicle;
|
||||||
|
|
||||||
|
public class HardPickupAndDeliveryShipmentActivityConstraintTest {
|
||||||
|
|
||||||
|
Vehicle vehicle;
|
||||||
|
|
||||||
|
StateManager stateManager;
|
||||||
|
|
||||||
|
Shipment shipment;
|
||||||
|
|
||||||
|
HardPickupAndDeliveryShipmentActivityLevelConstraint constraint;
|
||||||
|
|
||||||
|
InsertionContext iFacts;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void doBefore(){
|
||||||
|
vehicle = mock(Vehicle.class);
|
||||||
|
when(vehicle.getCapacity()).thenReturn(2);
|
||||||
|
stateManager = new StateManager();
|
||||||
|
shipment = mock(Shipment.class);
|
||||||
|
when(shipment.getCapacityDemand()).thenReturn(1);
|
||||||
|
iFacts = new InsertionContext(null, null, vehicle, null, 0.0);
|
||||||
|
constraint = new HardPickupAndDeliveryShipmentActivityLevelConstraint(stateManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenPickupActivityIsInsertedAndLoadIsSufficient_returnFullFilled(){
|
||||||
|
PickupService pickupService = new PickupService(mock(Service.class));
|
||||||
|
PickupService anotherService = new PickupService(mock(Service.class));
|
||||||
|
PickupShipment pickupShipment = new PickupShipment(shipment);
|
||||||
|
|
||||||
|
assertEquals(ConstraintsStatus.FULFILLED,constraint.fulfilled(iFacts, pickupService, pickupShipment, anotherService, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenPickupActivityIsInsertedAndLoadIsNotSufficient_returnNOT_FullFilled(){
|
||||||
|
PickupService pickupService = new PickupService(mock(Service.class));
|
||||||
|
PickupService anotherService = new PickupService(mock(Service.class));
|
||||||
|
PickupShipment pickupShipment = new PickupShipment(shipment);
|
||||||
|
|
||||||
|
stateManager.putActivityState(pickupService, StateFactory.LOAD, StateFactory.createState(2));
|
||||||
|
assertEquals(ConstraintsStatus.NOT_FULFILLED,constraint.fulfilled(iFacts, pickupService, pickupShipment, anotherService, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenDeliveryActivityIsInsertedAndLoadIsNotSufficient_returnNOT_FullFilled_BREAK(){
|
||||||
|
PickupService pickupService = new PickupService(mock(Service.class));
|
||||||
|
PickupService anotherService = new PickupService(mock(Service.class));
|
||||||
|
DeliverShipment pickupShipment = new DeliverShipment(shipment);
|
||||||
|
|
||||||
|
stateManager.putActivityState(pickupService, StateFactory.LOAD, StateFactory.createState(2));
|
||||||
|
assertEquals(ConstraintsStatus.NOT_FULFILLED_BREAK,constraint.fulfilled(iFacts, pickupService, pickupShipment, anotherService, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenDeliveryActivityIsInsertedAndLoadIsSufficient_returnFullFilled(){
|
||||||
|
PickupService pickupService = new PickupService(mock(Service.class));
|
||||||
|
PickupService anotherService = new PickupService(mock(Service.class));
|
||||||
|
DeliverShipment pickupShipment = new DeliverShipment(shipment);
|
||||||
|
|
||||||
|
stateManager.putActivityState(pickupService, StateFactory.LOAD, StateFactory.createState(1));
|
||||||
|
assertEquals(ConstraintsStatus.FULFILLED,constraint.fulfilled(iFacts, pickupService, pickupShipment, anotherService, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
@ -8,11 +9,12 @@ import org.junit.Test;
|
||||||
import util.Coordinate;
|
import util.Coordinate;
|
||||||
import util.Locations;
|
import util.Locations;
|
||||||
import util.ManhattanCosts;
|
import util.ManhattanCosts;
|
||||||
import algorithms.HardActivityLevelConstraint.ConstraintsStatus;
|
|
||||||
import basics.Shipment;
|
import basics.Shipment;
|
||||||
import basics.costs.VehicleRoutingActivityCosts;
|
import basics.costs.VehicleRoutingActivityCosts;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
import basics.route.Driver;
|
import basics.route.Driver;
|
||||||
|
import basics.route.DriverImpl;
|
||||||
|
import basics.route.RouteActivityVisitor;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
import basics.route.VehicleImpl;
|
import basics.route.VehicleImpl;
|
||||||
|
|
@ -70,7 +72,7 @@ public class ShipmentInsertionCalculatorTest {
|
||||||
|
|
||||||
};
|
};
|
||||||
routingCosts = new ManhattanCosts(locations);
|
routingCosts = new ManhattanCosts(locations);
|
||||||
VehicleType type = VehicleTypeImpl.Builder.newInstance("t", 1).setCostPerDistance(1).build();
|
VehicleType type = VehicleTypeImpl.Builder.newInstance("t", 2).setCostPerDistance(1).build();
|
||||||
vehicle = VehicleImpl.Builder.newInstance("v").setLocationId("0,0").setType(type).build();
|
vehicle = VehicleImpl.Builder.newInstance("v").setLocationId("0,0").setType(type).build();
|
||||||
activityInsertionCostsCalculator = new LocalActivityInsertionCostsCalculator(routingCosts, activityCosts);
|
activityInsertionCostsCalculator = new LocalActivityInsertionCostsCalculator(routingCosts, activityCosts);
|
||||||
createInsertionCalculator(hardRouteLevelConstraint);
|
createInsertionCalculator(hardRouteLevelConstraint);
|
||||||
|
|
@ -156,4 +158,38 @@ public class ShipmentInsertionCalculatorTest {
|
||||||
assertEquals(1,iData.getDeliveryInsertionIndex());
|
assertEquals(1,iData.getDeliveryInsertionIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInstertingShipmentWithLoadConstraintWhereCapIsNotSufficient_capConstraintsAreFulfilled(){
|
||||||
|
Shipment shipment = Shipment.Builder.newInstance("s", 1).setPickupLocation("0,10").setDeliveryLocation("10,0").build();
|
||||||
|
Shipment shipment2 = Shipment.Builder.newInstance("s2", 1).setPickupLocation("10,10").setDeliveryLocation("0,0").build();
|
||||||
|
Shipment shipment3 = Shipment.Builder.newInstance("s3", 1).setPickupLocation("0,0").setDeliveryLocation("9,9").build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
VehicleRoute route = VehicleRoute.emptyRoute();
|
||||||
|
route.setVehicle(vehicle, 0.0);
|
||||||
|
|
||||||
|
Inserter inserter = new Inserter(new InsertionListeners());
|
||||||
|
|
||||||
|
inserter.insertJob(shipment, new InsertionData(0,0,0,vehicle,null), route);
|
||||||
|
inserter.insertJob(shipment2, new InsertionData(0,1,2,vehicle,null), route);
|
||||||
|
|
||||||
|
StateManager stateManager = new StateManager();
|
||||||
|
|
||||||
|
RouteActivityVisitor routeActVisitor = new RouteActivityVisitor();
|
||||||
|
routeActVisitor.addActivityVisitor(new UpdateLoadAtActivityLevel(stateManager));
|
||||||
|
routeActVisitor.visit(route);
|
||||||
|
|
||||||
|
ConstraintManager constraintManager = new ConstraintManager();
|
||||||
|
|
||||||
|
constraintManager.addConstraint(new HardPickupAndDeliveryShipmentActivityLevelConstraint(stateManager,true));
|
||||||
|
ShipmentInsertionCalculator insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityInsertionCostsCalculator,
|
||||||
|
hardRouteLevelConstraint, constraintManager);
|
||||||
|
|
||||||
|
|
||||||
|
InsertionData iData = insertionCalculator.getInsertionData(route, shipment3, vehicle, 0.0, DriverImpl.noDriver(), Double.MAX_VALUE);
|
||||||
|
assertTrue(iData instanceof InsertionData.NoInsertionFound);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ public class ShipmentTest {
|
||||||
public void whenShipmentIsInstantiatedWithASizeOf10_theSizeShouldBe10(){
|
public void whenShipmentIsInstantiatedWithASizeOf10_theSizeShouldBe10(){
|
||||||
Shipment one = Shipment.Builder.newInstance("s", 10).setPickupLocation("foo").
|
Shipment one = Shipment.Builder.newInstance("s", 10).setPickupLocation("foo").
|
||||||
setDeliveryLocation("foofoo").setPickupServiceTime(10).setDeliveryServiceTime(20).build();
|
setDeliveryLocation("foofoo").setPickupServiceTime(10).setDeliveryServiceTime(20).build();
|
||||||
assertEquals(10,one.getSize());
|
assertEquals(10,one.getCapacityDemand());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -44,7 +44,7 @@ public class ShipmentTest {
|
||||||
.setDeliveryLocation("foofoo").setDeliveryServiceTime(20).setDeliveryCoord(Coordinate.newInstance(1, 1)).
|
.setDeliveryLocation("foofoo").setDeliveryServiceTime(20).setDeliveryCoord(Coordinate.newInstance(1, 1)).
|
||||||
setDeliveryTimeWindow(TimeWindow.newInstance(1.0, 2.0)).build();
|
setDeliveryTimeWindow(TimeWindow.newInstance(1.0, 2.0)).build();
|
||||||
assertEquals("s",one.getId());
|
assertEquals("s",one.getId());
|
||||||
assertEquals(10,one.getSize());
|
assertEquals(10,one.getCapacityDemand());
|
||||||
assertEquals("foo",one.getPickupLocation());
|
assertEquals("foo",one.getPickupLocation());
|
||||||
assertEquals(0,one.getPickupCoord().getX(),0.01);
|
assertEquals(0,one.getPickupCoord().getX(),0.01);
|
||||||
assertEquals(1.0,one.getPickupServiceTime(),0.01);
|
assertEquals(1.0,one.getPickupServiceTime(),0.01);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
25035
jsprit-core/src/test/resources/pdp.xml
Normal file
25035
jsprit-core/src/test/resources/pdp.xml
Normal file
File diff suppressed because it is too large
Load diff
3612
jsprit-core/src/test/resources/pdp_sol.xml
Normal file
3612
jsprit-core/src/test/resources/pdp_sol.xml
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue