diff --git a/README.md b/README.md
index 81598599..e5999392 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,14 @@ It is lightweight and easy-to-use, and based on heuristics currently solving
Modifying the algorithms and visualising the discovered solutions is as easy and handy as
reading classical VRP instances to benchmark your algorithm.
+Additionally, jsprit can be used along with MATSim
+to solve the above problem-types in real networks (i.e. without preprocessing transport times and costs). A variety of least cost path algorithms such as Dijkstra and A*
+can be used, and a dynamic and interactive visualiser greatly enhances the analysis.
+
+##In Development
+- VRP with Backhauls
+- Pickup and Delivery
+
##License
This program is free software; you can redistribute it and/or
@@ -29,6 +37,15 @@ Please visit [jsprit-wiki](https://github.com/jsprit/jsprit/wiki) to learn more.
[Add the latest snapshot to your pom](https://github.com/jsprit/jsprit/wiki/Add-latest-snapshot-to-your-pom).
-##[About](https://github.com/jsprit/jsprit/wiki/About)
+##About
+The jsprit-project is created and maintained by Stefan Schröder. It is motivated by two issues.
-[](http://githalytics.com/jsprit/jsprit)
+First, there is an almost endless list of papers and algorithms to tackle vehicle routing problems, **BUT** there are (as far as I know) only a [very few open source implementations](https://github.com/jsprit/jsprit/wiki/Other-Projects) of one of these thousands algorithms.
+
+Second, it is motivated by my PhD-project at [KIT](http://www.kit.edu/english/index.php) where I apply vehicle routing algorithms to solve behavioural models of freight agents to assess (freight) transport policy measures.
+
+It is mainly inspired by my research group at [KIT-ECON](http://netze.econ.kit.edu/21.php), and by an awesome open-source project called [MATSim](www.matsim.org) and its developers.
+
+Email: jsprit.vehicle.routing@gmail.com
+
+[](http://githalytics.com/jsprit/jsprit)
diff --git a/jsprit-analysis/src/main/java/analysis/SolutionPlotter.java b/jsprit-analysis/src/main/java/analysis/SolutionPlotter.java
index 69ccd03f..3e7fab1e 100644
--- a/jsprit-analysis/src/main/java/analysis/SolutionPlotter.java
+++ b/jsprit-analysis/src/main/java/analysis/SolutionPlotter.java
@@ -41,7 +41,9 @@ import org.jfree.data.xy.XYSeriesCollection;
import util.Coordinate;
import util.Locations;
+import basics.Delivery;
import basics.Job;
+import basics.Pickup;
import basics.Service;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
@@ -264,13 +266,33 @@ public class SolutionPlotter {
}
coll.addSeries(vehicleSeries);
- XYSeries jobSeries = new XYSeries("service", false, true);
+ XYSeries serviceSeries = new XYSeries("service", false, true);
+ XYSeries pickupSeries = new XYSeries("pickup", false, true);
+ XYSeries deliverySeries = new XYSeries("delivery", false, true);
for(Job job : services){
- Service service = (Service)job;
- Coordinate coord = service.getCoord();
- jobSeries.add(coord.getX(), coord.getY());
+ if(job instanceof Pickup){
+ Pickup service = (Pickup)job;
+ Coordinate coord = service.getCoord();
+ pickupSeries.add(coord.getX(), coord.getY());
+ }
+ else if(job instanceof Delivery){
+ Delivery service = (Delivery)job;
+ Coordinate coord = service.getCoord();
+ deliverySeries.add(coord.getX(), coord.getY());
+ }
+ else if(job instanceof Service){
+ Service service = (Service)job;
+ Coordinate coord = service.getCoord();
+ serviceSeries.add(coord.getX(), coord.getY());
+ }
+ else{
+ throw new IllegalStateException("job instanceof " + job.getClass().toString() + ". this is not supported.");
+ }
+
}
- coll.addSeries(jobSeries);
+ if(!serviceSeries.isEmpty()) coll.addSeries(serviceSeries);
+ if(!pickupSeries.isEmpty()) coll.addSeries(pickupSeries);
+ if(!deliverySeries.isEmpty()) coll.addSeries(deliverySeries);
return coll;
}
diff --git a/jsprit-core/src/main/java/algorithms/AbstractInsertionStrategy.java b/jsprit-core/src/main/java/algorithms/AbstractInsertionStrategy.java
deleted file mode 100644
index f2dfca54..00000000
--- a/jsprit-core/src/main/java/algorithms/AbstractInsertionStrategy.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2013 Stefan Schroeder
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributors:
- * Stefan Schroeder - initial API and implementation
- ******************************************************************************/
-package algorithms;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-
-import basics.Job;
-import basics.algo.InsertionEndsListener;
-import basics.algo.InsertionListener;
-import basics.algo.InsertionStartsListener;
-import basics.algo.JobInsertedListener;
-import basics.route.VehicleRoute;
-
-
-
-
-abstract class AbstractInsertionStrategy implements InsertionStrategy{
-
- private static Logger log = Logger.getLogger(AbstractInsertionStrategy.class);
-
- private Collection listener = new ArrayList();
-
- public abstract RouteAlgorithm getRouteAlgorithm();
-
- public void informJobInserted(int nOfJobs2Recreate, Job insertedJob, VehicleRoute insertedIn){
- for(InsertionListener l : listener){
- if(l instanceof JobInsertedListener){
- ((JobInsertedListener)l).informJobInserted(nOfJobs2Recreate, insertedJob, insertedIn);
- }
- }
- }
-
- public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route){
- for(InsertionListener l : listener){
- if(l instanceof BeforeJobInsertionListener){
- ((BeforeJobInsertionListener)l).informBeforeJobInsertion(job, data, route);
- }
- }
- }
-
- public void informInsertionStarts(Collection vehicleRoutes, int nOfJobs2Recreate){
- for(InsertionListener l : listener){
- if(l instanceof InsertionStartsListener){
- ((InsertionStartsListener)l).informInsertionStarts(vehicleRoutes,nOfJobs2Recreate);
- }
- }
- }
-
- public void informInsertionEndsListeners(Collection vehicleRoutes) {
- for(InsertionListener l : listener){
- if(l instanceof InsertionEndsListener){
- ((InsertionEndsListener)l).informInsertionEnds(vehicleRoutes);
- }
- }
- }
-
- public Collection getListener() {
- return Collections.unmodifiableCollection(listener);
- }
-
- public void addListener(InsertionListener l){
- log.info("add insertion-listener " + l);
- listener.add(l);
- }
-
- public void addAllListener(List list) {
- for(InsertionListener l : list) addListener(l);
- }
-
-
-
-}
diff --git a/jsprit-core/src/main/java/algorithms/BackwardInTimeListeners.java b/jsprit-core/src/main/java/algorithms/BackwardInTimeListeners.java
new file mode 100644
index 00000000..effaa07a
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/BackwardInTimeListeners.java
@@ -0,0 +1,52 @@
+package algorithms;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import basics.route.End;
+import basics.route.Start;
+import basics.route.TourActivity;
+import basics.route.VehicleRoute;
+
+class BackwardInTimeListeners {
+
+ interface BackwardInTimeListener{
+
+ public void start(VehicleRoute route, End end, double latestArrivalTime);
+
+ public void prevActivity(TourActivity act, double latestDepartureTime, double latestOperationStartTime);
+
+ public void end(Start start, double latestDepartureTime);
+
+ }
+
+ private Collection listeners = new ArrayList();
+
+ public void addListener(BackwardInTimeListener l){
+ listeners.add(l);
+ }
+
+ public void start(VehicleRoute route, End end, double latestArrivalTime){
+ for(BackwardInTimeListener l : listeners){ l.start(route, end, latestArrivalTime); }
+ }
+
+ /**
+ * Informs listener about nextActivity.
+ *
+ *
LatestDepartureTime is the theoretical latest departureTime to meet the latestOperationStartTimeWindow at the nextActivity (forward in time), i.e.
+ * assume act_i and act_j are two successive activities and the latestDepTime of act_j is 10pm. With a travelTime from act_i to act_j of 1h the latestDepartureTime at act_i is 9pm.
+ * However, the latestOperationStartTime of act_i is 8pm, then (with a serviceTime of 0) the latestOperationStartTime at act_i amounts to 8pm.
+ *
+ * @param act
+ * @param latestDepartureTime
+ * @param latestArrivalTime
+ */
+ public void prevActivity(TourActivity act, double latestDepartureTime, double latestArrivalTime){
+ for(BackwardInTimeListener l : listeners){ l.prevActivity(act,latestDepartureTime,latestArrivalTime); }
+ }
+
+ public void end(Start start, double latestDepartureTime){
+ for(BackwardInTimeListener l : listeners){ l.end(start, latestDepartureTime); }
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/BestInsertion.java b/jsprit-core/src/main/java/algorithms/BestInsertion.java
index aec62ea0..bee3394b 100644
--- a/jsprit-core/src/main/java/algorithms/BestInsertion.java
+++ b/jsprit-core/src/main/java/algorithms/BestInsertion.java
@@ -15,9 +15,7 @@ package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Random;
import org.apache.log4j.Logger;
@@ -25,6 +23,9 @@ 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;
@@ -35,44 +36,37 @@ import basics.route.VehicleRoute;
*
*/
-final class BestInsertion extends AbstractInsertionStrategy{
-
- public static BestInsertion newInstance(RouteAlgorithm routeAlgorithm){
- return new BestInsertion(routeAlgorithm);
- }
+final class BestInsertion implements InsertionStrategy{
private static Logger logger = Logger.getLogger(BestInsertion.class);
private Random random = RandomNumberGeneration.getRandom();
- private RouteAlgorithm routeAlgorithm;
+ private final static double NO_NEW_DEPARTURE_TIME_YET = -12345.12345;
- public void setExperimentalPreferredRoute(Map experimentalPreferredRoute) {
- }
+ 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 JobInsertionCalculator bestInsertionCostCalculator;
- private boolean allowUnassignedJobs = false;
-
- private boolean fixRouteSet = false;
-
private boolean minVehiclesFirst = false;
-
- public void setFixRouteSet(boolean fixRouteSet) {
- this.fixRouteSet = fixRouteSet;
- }
public void setRandom(Random random) {
this.random = random;
}
- public BestInsertion(RouteAlgorithm routeAlgorithm) {
+ public BestInsertion(JobInsertionCalculator jobInsertionCalculator) {
super();
- this.routeAlgorithm = routeAlgorithm;
+ this.insertionsListeners = new InsertionListeners();
+ inserter = new Inserter(insertionsListeners);
+ bestInsertionCostCalculator = jobInsertionCalculator;
logger.info("initialise " + this);
}
-
- public RouteAlgorithm getRouteAlgorithm(){
- return routeAlgorithm;
- }
@Override
public String toString() {
@@ -80,19 +74,15 @@ final class BestInsertion extends AbstractInsertionStrategy{
}
@Override
- public void run(Collection vehicleRoutes, Collection unassignedJobs, double result2beat) {
+ public void insertJobs(Collection vehicleRoutes, Collection unassignedJobs) {
+ insertionsListeners.informInsertionStarts(vehicleRoutes,unassignedJobs);
List unassignedJobList = new ArrayList(unassignedJobs);
Collections.shuffle(unassignedJobList, random);
- informInsertionStarts(vehicleRoutes,unassignedJobs.size());
- int inserted = 0;
- List reasons = new ArrayList();
- for(Job unassignedJob : unassignedJobList){
-
- VehicleRoute insertIn = null;
+ for(Job unassignedJob : unassignedJobList){
Insertion bestInsertion = null;
double bestInsertionCost = Double.MAX_VALUE;
for(VehicleRoute vehicleRoute : vehicleRoutes){
- InsertionData iData = routeAlgorithm.calculateBestInsertion(vehicleRoute, unassignedJob, bestInsertionCost);
+ InsertionData iData = bestInsertionCostCalculator.calculate(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if(iData instanceof NoInsertionFound) {
continue;
}
@@ -103,56 +93,54 @@ final class BestInsertion extends AbstractInsertionStrategy{
}
if(!minVehiclesFirst){
VehicleRoute newRoute = VehicleRoute.emptyRoute();
- InsertionData newIData = routeAlgorithm.calculateBestInsertion(newRoute, unassignedJob, Double.MAX_VALUE);
+ InsertionData newIData = bestInsertionCostCalculator.calculate(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){
- informBeforeJobInsertion(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
- insertIn = bestInsertion.getRoute();
-// logger.debug("insert job="+unassignedJob+" at index=" + bestInsertion.getInsertionData().getInsertionIndex() + " delta cost=" + bestInsertion.getInsertionData().getInsertionCost());
- routeAlgorithm.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
- }
- else {
- if(fixRouteSet){
- if(allowUnassignedJobs) logger.warn("cannot insert job yet " + unassignedJob);
- else throw new IllegalStateException("given the vehicles, could not insert job\n");
+ }
+ 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);
+ if(bestI instanceof InsertionData.NoInsertionFound){
+ throw new IllegalStateException(getErrorMsg(unassignedJob));
}
else{
- VehicleRoute newRoute = VehicleRoute.emptyRoute();
- InsertionData bestI = routeAlgorithm.calculateBestInsertion(newRoute, unassignedJob, Double.MAX_VALUE);
- if(bestI instanceof InsertionData.NoInsertionFound){
- if(allowUnassignedJobs){
- logger.warn("cannot insert job yet " + unassignedJob);
- }
- else {
- for(String s : reasons){
- System.out.println("reason="+s);
- }
- throw new IllegalStateException("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]"
- );
- }
- }
- else{
- insertIn = newRoute;
- informBeforeJobInsertion(unassignedJob,bestI,newRoute);
- routeAlgorithm.insertJob(unassignedJob,bestI,newRoute);
- vehicleRoutes.add(newRoute);
- }
+ bestInsertion = new Insertion(newRoute,bestI);
+ vehicleRoutes.add(newRoute);
}
}
- inserted++;
- informJobInserted((unassignedJobList.size()-inserted), unassignedJob, insertIn);
+
+ inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
+
}
- informInsertionEndsListeners(vehicleRoutes);
+ 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 getListeners() {
+ return Collections.unmodifiableCollection(insertionsListeners.getListeners());
+ }
+
+ @Override
+ public void addListener(InsertionListener insertionListener) {
+ insertionsListeners.addListener(insertionListener);
+
}
}
diff --git a/jsprit-core/src/main/java/algorithms/BestInsertionConcurrent.java b/jsprit-core/src/main/java/algorithms/BestInsertionConcurrent.java
index cfe56404..4f41d2e0 100644
--- a/jsprit-core/src/main/java/algorithms/BestInsertionConcurrent.java
+++ b/jsprit-core/src/main/java/algorithms/BestInsertionConcurrent.java
@@ -30,170 +30,185 @@ import org.apache.log4j.Logger;
import util.RandomNumberGeneration;
import algorithms.InsertionData.NoInsertionFound;
import basics.Job;
+import basics.algo.InsertionListener;
import basics.route.VehicleRoute;
-
-
-/**
- *
- * @author stefan schroeder
- *
- */
-
-final class BestInsertionConcurrent extends AbstractInsertionStrategy{
-
- public static BestInsertionConcurrent newInstance(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads){
- return new BestInsertionConcurrent(routeAlgorithm, executor, nuOfThreads);
- }
-
- static class Batch {
- List routes = new ArrayList();
-
- }
-
- private static Logger logger = Logger.getLogger(BestInsertionConcurrent.class);
-
- private Random random = RandomNumberGeneration.getRandom();
-
- private RouteAlgorithm routeAlgorithm;
-
-// private ExecutorService executor;
-
- private int nuOfBatches;
-
- private ExecutorCompletionService completionService;
-
- public void setRandom(Random random) {
- this.random = random;
- }
-
- private BestInsertionConcurrent(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads) {
- super();
- this.routeAlgorithm = routeAlgorithm;
-// this.executor = executor;
- logger.info("initialise " + this);
- this.nuOfBatches = nuOfThreads;
- completionService = new ExecutorCompletionService(executor);
- }
-
- @Override
- public String toString() {
- return "[name=concurrentBestInsertion]";
- }
-
- @Override
- public void run(Collection vehicleRoutes, Collection unassignedJobs, double result2beat) {
- List unassignedJobList = new ArrayList(unassignedJobs);
- Collections.shuffle(unassignedJobList, random);
- informInsertionStarts(vehicleRoutes,unassignedJobs.size());
- int inserted = 0;
- for(final Job unassignedJob : unassignedJobList){
- VehicleRoute insertIn = null;
- Insertion bestInsertion = null;
- double bestInsertionCost = Double.MAX_VALUE;
-
- List batches = distributeRoutes(vehicleRoutes,nuOfBatches);
-
- for(final Batch batch : batches){
- completionService.submit(new Callable() {
-
- @Override
- public Insertion call() throws Exception {
- return getBestInsertion(batch,unassignedJob);
- }
-
- });
-
- }
-
- try{
- for(int i=0;i 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(bestInsertion != null){
- informBeforeJobInsertion(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
- insertIn = bestInsertion.getRoute();
-// logger.debug("insert job="+unassignedJob+" at index=" + bestInsertion.getInsertionData().getInsertionIndex() + " delta cost=" + bestInsertion.getInsertionData().getInsertionCost());
- routeAlgorithm.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
- }
- else {
-// VehicleRoute newRoute = VehicleRoute.emptyRoute();
-// InsertionData bestI = routeAlgorithm.calculateBestInsertion(newRoute, unassignedJob, Double.MAX_VALUE);
-// if(bestI instanceof InsertionData.NoInsertionFound)
- throw new IllegalStateException("given the vehicles, could not create a valid solution.\n\tthe reason might be" +
- " inappropriate vehicle capacity.\n\tthe job that does not fit in any vehicle anymore is \n\t" + unassignedJob);
-// insertIn = newRoute;
-// informBeforeJobInsertion(unassignedJob,bestI,newRoute);
-// routeAlgorithm.insertJob(unassignedJob,bestI,newRoute);
-// vehicleRoutes.add(newRoute);
- }
- inserted++;
- informJobInserted((unassignedJobList.size()-inserted), unassignedJob, insertIn);
- }
- informInsertionEndsListeners(vehicleRoutes);
- }
-
- private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
- Insertion bestInsertion = null;
- double bestInsertionCost = Double.MAX_VALUE;
- for(VehicleRoute vehicleRoute : batch.routes){
- InsertionData iData = routeAlgorithm.calculateBestInsertion(vehicleRoute, unassignedJob, bestInsertionCost);
- if(iData instanceof NoInsertionFound) continue;
- if(iData.getInsertionCost() < bestInsertionCost){
- bestInsertion = new Insertion(vehicleRoute,iData);
- bestInsertionCost = iData.getInsertionCost();
- }
- }
- return bestInsertion;
- }
-
- private List distributeRoutes(Collection vehicleRoutes, int nuOfBatches) {
- List batches = new ArrayList();
- for(int i=0;i routes = new ArrayList();
+//
+// }
+//
+// private static Logger logger = Logger.getLogger(BestInsertionConcurrent.class);
+//
+// private Random random = RandomNumberGeneration.getRandom();
+//
+// private RouteAlgorithm routeAlgorithm;
+//
+//// private ExecutorService executor;
+//
+// private int nuOfBatches;
+//
+// private ExecutorCompletionService completionService;
+//
+// public void setRandom(Random random) {
+// this.random = random;
+// }
+//
+// private BestInsertionConcurrent(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads) {
+// super();
+// this.routeAlgorithm = routeAlgorithm;
+//// this.executor = executor;
+// logger.info("initialise " + this);
+// this.nuOfBatches = nuOfThreads;
+// completionService = new ExecutorCompletionService(executor);
+// }
+//
+// @Override
+// public String toString() {
+// return "[name=concurrentBestInsertion]";
+// }
+//
+// @Override
+// public void insertJobs(Collection vehicleRoutes, Collection unassignedJobs) {
+// List unassignedJobList = new ArrayList(unassignedJobs);
+// Collections.shuffle(unassignedJobList, random);
+//// informInsertionStarts(vehicleRoutes,unassignedJobs.size());
+// int inserted = 0;
+// for(final Job unassignedJob : unassignedJobList){
+// VehicleRoute insertIn = null;
+// Insertion bestInsertion = null;
+// double bestInsertionCost = Double.MAX_VALUE;
+//
+// List batches = distributeRoutes(vehicleRoutes,nuOfBatches);
+//
+// for(final Batch batch : batches){
+// completionService.submit(new Callable() {
+//
+// @Override
+// public Insertion call() throws Exception {
+// return getBestInsertion(batch,unassignedJob);
+// }
+//
+// });
+//
+// }
+//
+// try{
+// for(int i=0;i 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(bestInsertion != null){
+//// informBeforeJobInsertion(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
+// insertIn = bestInsertion.getRoute();
+//// logger.debug("insert job="+unassignedJob+" at index=" + bestInsertion.getInsertionData().getInsertionIndex() + " delta cost=" + bestInsertion.getInsertionData().getInsertionCost());
+// routeAlgorithm.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
+// }
+// else {
+//// VehicleRoute newRoute = VehicleRoute.emptyRoute();
+//// InsertionData bestI = routeAlgorithm.calculateBestInsertion(newRoute, unassignedJob, Double.MAX_VALUE);
+//// if(bestI instanceof InsertionData.NoInsertionFound)
+// throw new IllegalStateException("given the vehicles, could not create a valid solution.\n\tthe reason might be" +
+// " inappropriate vehicle capacity.\n\tthe job that does not fit in any vehicle anymore is \n\t" + unassignedJob);
+//// insertIn = newRoute;
+//// informBeforeJobInsertion(unassignedJob,bestI,newRoute);
+//// routeAlgorithm.insertJob(unassignedJob,bestI,newRoute);
+//// vehicleRoutes.add(newRoute);
+// }
+// inserted++;
+//// informJobInserted((unassignedJobList.size()-inserted), unassignedJob, insertIn);
+// }
+//// informInsertionEndsListeners(vehicleRoutes);
+// }
+//
+// private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
+// Insertion bestInsertion = null;
+// double bestInsertionCost = Double.MAX_VALUE;
+// for(VehicleRoute vehicleRoute : batch.routes){
+// InsertionData iData = routeAlgorithm.calculateBestInsertion(vehicleRoute, unassignedJob, bestInsertionCost);
+// if(iData instanceof NoInsertionFound) continue;
+// if(iData.getInsertionCost() < bestInsertionCost){
+// bestInsertion = new Insertion(vehicleRoute,iData);
+// bestInsertionCost = iData.getInsertionCost();
// }
// }
-// else{
- vehicleRoutes.add(VehicleRoute.emptyRoute());
+// return bestInsertion;
+// }
+//
+// private List distributeRoutes(Collection vehicleRoutes, int nuOfBatches) {
+// List batches = new ArrayList();
+// for(int i=0;i getListeners() {
+// // TODO Auto-generated method stub
+// return null;
+// }
+//
+// @Override
+// public void addListener(InsertionListener insertionListener) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+//}
diff --git a/jsprit-core/src/main/java/algorithms/CalcUtils.java b/jsprit-core/src/main/java/algorithms/CalcUtils.java
new file mode 100644
index 00000000..c295881f
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/CalcUtils.java
@@ -0,0 +1,14 @@
+package algorithms;
+
+import basics.route.TourActivity;
+
+class CalcUtils {
+
+ static double getStartTimeAtAct(double startTimeAtPrevAct, double tpTime_prevAct_nextAct, TourActivity nextAct){
+ return Math.max(startTimeAtPrevAct + tpTime_prevAct_nextAct, nextAct.getTheoreticalEarliestOperationStartTime()) + nextAct.getOperationTime();
+ }
+
+ static double getStartTimeAtAct(double nextActArrTime, TourActivity nextAct){
+ return Math.max(nextActArrTime, nextAct.getTheoreticalEarliestOperationStartTime()) + nextAct.getOperationTime();
+ }
+}
diff --git a/jsprit-core/src/main/java/algorithms/CalculatesActivityInsertionWithHardTimeWindows.java b/jsprit-core/src/main/java/algorithms/CalculatesActivityInsertionWithHardTimeWindows.java
deleted file mode 100644
index 3eaf5dc6..00000000
--- a/jsprit-core/src/main/java/algorithms/CalculatesActivityInsertionWithHardTimeWindows.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 Stefan Schroeder.
- * eMail: stefan.schroeder@kit.edu
- *
- * 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
- *
- * Contributors:
- * Stefan Schroeder - initial API and implementation
- ******************************************************************************/
-package algorithms;
-
-import org.apache.log4j.Logger;
-
-import algorithms.RouteStates.ActivityState;
-import basics.costs.VehicleRoutingActivityCosts;
-import basics.costs.VehicleRoutingTransportCosts;
-import basics.route.Driver;
-import basics.route.End;
-import basics.route.Start;
-import basics.route.TourActivity;
-import basics.route.Vehicle;
-import basics.route.VehicleRoute;
-
-
-
-final class CalculatesActivityInsertionWithHardTimeWindows {
-
- private static Logger logger = Logger.getLogger(CalculatesActivityInsertionWithHardTimeWindows.class);
-
- private RouteStates routeStates;
-
- private VehicleRoutingTransportCosts routingCosts;
-
- private VehicleRoutingActivityCosts activityCosts;
-
- public CalculatesActivityInsertionWithHardTimeWindows(RouteStates activityStates, VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts){
- this.routeStates = activityStates;
- this.routingCosts = routingCosts;
- this.activityCosts = activityCosts;
- logger.info("initialise " + this);
- }
-
- public double calculate(VehicleRoute vehicleRoute, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, Driver driver, Vehicle vehicle) {
- boolean prevIsStart = false;
-
- if(prevAct instanceof Start){
- prevIsStart = true;
- }
-
- double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle);
- double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle);
-
- double newAct_arrTime = prevAct.getEndTime() + tp_time_prevAct_newAct;
- double newAct_operationStartTime = Math.max(newAct_arrTime, newAct.getTheoreticalEarliestOperationStartTime());
-
- double newAct_endTime = newAct_operationStartTime + newAct.getOperationTime();
-
- double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, driver, vehicle);
-
- double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, driver, vehicle);
- double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, driver, vehicle);
-
- double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct;
- double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, driver, vehicle);
-
- double activityInsertionCosts;
-
- double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct;
-
- if(nextAct_arrTime > getLatestOperationStart(nextAct)){
- activityInsertionCosts = Double.MAX_VALUE;
- }
- else if(vehicleRoute.isEmpty()){
- activityInsertionCosts = totalCosts;
- }
- else{
- double oldCostOfPrevAct;
- if(prevIsStart) oldCostOfPrevAct = 0.0;
- else oldCostOfPrevAct = state(prevAct).getCurrentCost();
- double oldCostOfNextAct;
- if(nextAct instanceof End) oldCostOfNextAct = routeStates.getRouteState(vehicleRoute).getCosts();
- else oldCostOfNextAct = state(nextAct).getCurrentCost();
- activityInsertionCosts = (totalCosts) - (oldCostOfNextAct-oldCostOfPrevAct);
- }
- return activityInsertionCosts;
- }
-
- private ActivityState state(TourActivity act) {
- return routeStates.getState(act);
- }
-
- private double getLatestOperationStart(TourActivity act) {
- if(state(act) != null){
- return state(act).getLatestOperationStart();
- }
- return act.getTheoreticalLatestOperationStartTime();
- }
-
- @Override
- public String toString() {
- return "[name=calculatesHardTimeWindowActivityInsertion]";
- }
-
-}
diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java
index c2c133a2..ed8dc4e9 100644
--- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java
+++ b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java
@@ -15,37 +15,27 @@ package algorithms;
import org.apache.log4j.Logger;
import util.Neighborhood;
-
-import algorithms.RouteStates.ActivityState;
+import algorithms.HardConstraints.HardRouteLevelConstraint;
+import algorithms.MarginalsCalculus.Marginals;
import basics.Job;
import basics.Service;
-import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver;
import basics.route.End;
import basics.route.ServiceActivity;
import basics.route.Start;
-import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.Vehicle;
-import basics.route.VehicleRoute;
import basics.route.VehicleImpl.NoVehicle;
+import basics.route.VehicleRoute;
final class CalculatesServiceInsertion implements JobInsertionCalculator{
-
+
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertion.class);
-
- private RouteStates routeStates;
-
- private VehicleRoutingTransportCosts routingCosts;
-
- private VehicleRoutingActivityCosts activityCosts;
-
- private Start start;
-
- private End end;
+
+ private HardRouteLevelConstraint hardRouteLevelConstraint;
private Neighborhood neighborhood = new Neighborhood() {
@@ -55,25 +45,20 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
}
};
+ private MarginalsCalculus marginalCalculus;
+ private VehicleRoutingTransportCosts transportCosts;
public void setNeighborhood(Neighborhood neighborhood) {
this.neighborhood = neighborhood;
logger.info("initialise neighborhood " + neighborhood);
}
-
- public void setActivityStates(RouteStates actStates){
- this.routeStates = actStates;
- }
-
- public ActivityState state(TourActivity act){
- return routeStates.getState(act);
- }
- public CalculatesServiceInsertion(VehicleRoutingTransportCosts vehicleRoutingTransportCosts, VehicleRoutingActivityCosts vehicleRoutingActivityCosts) {
+ public CalculatesServiceInsertion(VehicleRoutingTransportCosts routingCosts, MarginalsCalculus marginalsCalculus, HardRouteLevelConstraint hardRouteLevelConstraint) {
super();
- this.routingCosts = vehicleRoutingTransportCosts;
- this.activityCosts = vehicleRoutingActivityCosts;
+ this.marginalCalculus = marginalsCalculus;
+ this.hardRouteLevelConstraint = hardRouteLevelConstraint;
+ this.transportCosts = routingCosts;
logger.info("initialise " + this);
}
@@ -92,42 +77,53 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing.");
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing.");
- TourActivities tour = currentRoute.getTourActivities();
- double bestCost = bestKnownCosts;
- Service service = (Service)jobToInsert;
-
- if(routeStates.getRouteState(currentRoute).getLoad() + service.getCapacityDemand() > newVehicle.getCapacity()){
+ InsertionContext insertionContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
+ if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
return InsertionData.noInsertionFound();
}
+
+ double bestCost = bestKnownCosts;
+ Marginals bestMarginals = null;
+ Service service = (Service)jobToInsert;
int insertionIndex = InsertionData.NO_INDEX;
-
TourActivity deliveryAct2Insert = ServiceActivity.newInstance(service);
-// TourActivity deliveryAct2Insert = actStates.getActivity(service, true);
- initialiseStartAndEnd(newVehicle, newVehicleDepartureTime);
+ 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 prevCostInOriginalTour = 0.0;
+ double prevActStartTime = newVehicleDepartureTime;
int actIndex = 0;
- for(TourActivity nextAct : tour.getActivities()){
- double nextCostInOriginalTour = state(nextAct).getCurrentCost();
+
+ for(TourActivity nextAct : currentRoute.getTourActivities().getActivities()){
+ if(deliveryAct2Insert.getTheoreticalLatestOperationStartTime() < prevAct.getTheoreticalEarliestOperationStartTime()){
+ break;
+ }
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
- double mc = calculate(tour, prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle, bestCost, nextCostInOriginalTour - prevCostInOriginalTour);
- if(mc < bestCost){
- bestCost = mc;
- insertionIndex = actIndex;
+ Marginals mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
+ if(mc != null){
+ if(mc.getAdditionalCosts() < bestCost){
+ bestCost = mc.getAdditionalCosts();
+ bestMarginals = mc;
+ insertionIndex = actIndex;
+ }
}
}
- prevCostInOriginalTour = nextCostInOriginalTour;
prevAct = nextAct;
+ prevActStartTime = CalcUtils.getStartTimeAtAct(prevActStartTime, transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle), nextAct);
actIndex++;
}
End nextAct = end;
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
- double mc = calculate(tour, prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle, bestCost, routeStates.getRouteState(currentRoute).getCosts() - prevCostInOriginalTour);
- if(mc < bestCost){
- bestCost = mc;
- insertionIndex = actIndex;
+ Marginals mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
+ if(mc != null) {
+ if(mc.getAdditionalCosts() < bestCost){
+ bestCost = mc.getAdditionalCosts();
+ bestMarginals = mc;
+ insertionIndex = actIndex;
+ }
}
}
@@ -136,74 +132,12 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
}
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
+ insertionData.setAdditionalTime(bestMarginals.getAdditionalTime());
return insertionData;
}
- private void initialiseStartAndEnd(final Vehicle newVehicle,
- double newVehicleDepartureTime) {
- if(start == null){
- start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
- start.setEndTime(newVehicleDepartureTime);
- }
- else{
- start.setLocationId(newVehicle.getLocationId());
- start.setTheoreticalEarliestOperationStartTime(newVehicle.getEarliestDeparture());
- start.setTheoreticalLatestOperationStartTime(newVehicle.getLatestArrival());
- start.setEndTime(newVehicleDepartureTime);
- }
+ public Marginals calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double departureTimeAtPrevAct) {
+ return marginalCalculus.calculate(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
- if(end == null){
- end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival());
- }
- else{
- end.setLocationId(newVehicle.getLocationId());
- end.setTheoreticalEarliestOperationStartTime(newVehicleDepartureTime);
- end.setTheoreticalLatestOperationStartTime(newVehicle.getLatestArrival());
- }
- }
-
- public double calculate(TourActivities tour, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, Driver driver, Vehicle vehicle, double bestKnownCosts, double costWithoutNewJob) {
-
- double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle);
- double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle);
-
- double newAct_arrTime = prevAct.getEndTime() + tp_time_prevAct_newAct;
- double newAct_operationStartTime = Math.max(newAct_arrTime, newAct.getTheoreticalEarliestOperationStartTime());
-
- double newAct_endTime = newAct_operationStartTime + newAct.getOperationTime();
-
- double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, driver, vehicle);
-
- if((tp_costs_prevAct_newAct + act_costs_newAct - costWithoutNewJob) > bestKnownCosts){
- return Double.MAX_VALUE;
- }
-
- double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, driver, vehicle);
- double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, driver, vehicle);
-
- double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct;
- double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, driver, vehicle);
-
- double activityInsertionCosts;
-
- double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct;
-
- if(totalCosts - costWithoutNewJob > bestKnownCosts){
- activityInsertionCosts = Double.MAX_VALUE;
- }
- if(nextAct_arrTime > getLatestOperationStart(nextAct)){
- activityInsertionCosts = Double.MAX_VALUE;
- }
- else{
- activityInsertionCosts = totalCosts - costWithoutNewJob;
- }
- return activityInsertionCosts;
- }
-
- private double getLatestOperationStart(TourActivity act) {
- if(state(act) != null){
- return state(act).getLatestOperationStart();
- }
- return act.getTheoreticalLatestOperationStartTime();
}
}
diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionConsideringFixCost.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionConsideringFixCost.java
index d763a3b7..1961ec84 100644
--- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionConsideringFixCost.java
+++ b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionConsideringFixCost.java
@@ -23,6 +23,8 @@ package algorithms;
import org.apache.log4j.Logger;
import algorithms.InsertionData.NoInsertionFound;
+import algorithms.StateManager.State;
+import algorithms.StateManager.States;
import basics.Job;
import basics.route.Driver;
import basics.route.Vehicle;
@@ -41,12 +43,12 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
private double solution_completeness_ratio = 0.5;
- private RouteStates routeStates;
+ private StateManager states;
- public CalculatesServiceInsertionConsideringFixCost(final JobInsertionCalculator standardInsertionCalculator, RouteStates routeStates) {
+ public CalculatesServiceInsertionConsideringFixCost(final JobInsertionCalculator standardInsertionCalculator, StateManager activityStates2) {
super();
this.standardServiceInsertion = standardInsertionCalculator;
- this.routeStates = routeStates;
+ this.states = activityStates2;
logger.info("inialise " + this);
}
@@ -84,7 +86,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
}
private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
- double load = routeStates.getRouteState(route).getLoad() + job.getCapacityDemand();
+ double load = getCurrentLoad(route) + job.getCapacityDemand();
double currentFix = 0.0;
if(route.getVehicle() != null){
if(!(route.getVehicle() instanceof NoVehicle)){
@@ -98,7 +100,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
}
private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
- int currentLoad = routeStates.getRouteState(route).getLoad();
+ int currentLoad = getCurrentLoad(route);
double load = currentLoad + job.getCapacityDemand();
double currentRelFix = 0.0;
if(route.getVehicle() != null){
@@ -113,4 +115,8 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
return relativeFixCost;
}
+ private int getCurrentLoad(VehicleRoute route) {
+ return (int) states.getRouteState(route, StateTypes.LOAD).toDouble();
+ }
+
}
diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java
index 366d5885..1d0d900c 100644
--- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java
+++ b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java
@@ -31,6 +31,7 @@ import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver;
import basics.route.End;
+import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.TourActivities;
import basics.route.TourActivity;
@@ -50,7 +51,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
- private RouteStates routeStates;
+ private StateManager states;
private int nuOfActsForwardLooking = 0;
@@ -89,14 +90,10 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
logger.info("initialise " + this);
}
- public void setActivityStates(RouteStates actStates){
- this.routeStates = actStates;
- }
- public ActivityState state(TourActivity act){
- return routeStates.getState(act);
+ public void setStates(StateManager activityStates2){
+ this.states = activityStates2;
}
-
void setNuOfActsForwardLooking(int nOfActsForwardLooking) {
this.nuOfActsForwardLooking = nOfActsForwardLooking;
@@ -138,14 +135,14 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
/**
* pre-check whether vehicle-capacity of new vehicle is sufficient to load service.
*/
- if(routeStates.getRouteState(currentRoute).getLoad() + service.getCapacityDemand() > newVehicle.getCapacity()){
+ if(states.getRouteState(currentRoute, StateTypes.LOAD).toDouble() + service.getCapacityDemand() > newVehicle.getCapacity()){
return InsertionData.noInsertionFound();
}
/**
* some inis
*/
- TourActivity serviceAct2Insert = routeStates.getActivity(service, true);
+ TourActivity serviceAct2Insert = ServiceActivity.newInstance(service);
int best_insertion_index = InsertionData.NO_INDEX;
initialiseStartAndEnd(newVehicle, newVehicleDepartureTime);
@@ -245,6 +242,14 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
*
*/
+ if(memorySize==0){
+ InsertionData insertion = bestInsertionsQueue.poll();
+ if(insertion != null){
+ best_insertion_index = insertion.getDeliveryInsertionIndex();
+ best_insertion_costs = insertion.getInsertionCost();
+ }
+ }
+
for(int i=0;i insertion_costs
*/
- double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - routeStates.getRouteState(currentRoute).getCosts();
+ double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - states.getRouteState(currentRoute,StateTypes.COSTS).toDouble();
/**
* if better than best known, make it the best known
@@ -307,9 +312,9 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
private double pathCost_oldVehicle(VehicleRoute vehicleRoute, List path) {
TourActivity act = path.get(path.size()-1);
if(act instanceof End){
- return routeStates.getRouteState(vehicleRoute).getCosts();
+ return states.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble();
}
- return state(act).getCurrentCost();
+ return states.getActivityState(act,StateTypes.COSTS).toDouble();
}
/**
diff --git a/jsprit-core/src/main/java/algorithms/CalculatesVehTypeDepServiceInsertion.java b/jsprit-core/src/main/java/algorithms/CalculatesVehTypeDepServiceInsertion.java
index 369a359d..264ee753 100644
--- a/jsprit-core/src/main/java/algorithms/CalculatesVehTypeDepServiceInsertion.java
+++ b/jsprit-core/src/main/java/algorithms/CalculatesVehTypeDepServiceInsertion.java
@@ -67,16 +67,7 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
else{
relevantVehicles.addAll(fleetManager.getAvailableVehicles());
}
-//
-// for(TypeKey typeKey : fleetManager.getAvailableVehicleTypes()){
-// if(!(currentRoute.getVehicle() instanceof NoVehicle)){
-// TypeKey key = makeTypeKey(currentRoute.getVehicle().getType(),currentRoute.getVehicle().getLocationId());
-// if(typeKey.equals(key)){
-// continue;
-// }
-// }
-// relevantVehicles.add(fleetManager.getEmptyVehicle(typeKey));
-// }
+
for(Vehicle v : relevantVehicles){
double depTime = v.getEarliestDeparture();
InsertionData iData = insertionCalculator.calculate(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
@@ -92,8 +83,4 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
return bestIData;
}
-// private TypeKey makeTypeKey(VehicleType type, String locationId) {
-// return new TypeKey(type,locationId);
-// }
-
}
diff --git a/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java b/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java
index ec278889..6ab8e4c0 100644
--- a/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java
+++ b/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java
@@ -22,18 +22,10 @@ package algorithms;
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.configuration.XMLConfiguration;
-
-import util.NeighborhoodImpl;
import basics.VehicleRoutingProblem;
-import basics.VehicleRoutingProblem.FleetComposition;
import basics.algo.InsertionListener;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
-import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
-import basics.costs.VehicleRoutingActivityCosts;
@@ -70,7 +62,7 @@ class CalculatorBuilder {
private VehicleRoutingProblem vrp;
- private RouteStates activityStates;
+ private StateManager states;
private boolean local = true;
@@ -107,12 +99,12 @@ class CalculatorBuilder {
/**
* Sets activityStates. MUST be set.
+ * @param states TODO
*
- * @param activityStates
* @return
*/
- public CalculatorBuilder setActivityStates(RouteStates activityStates){
- this.activityStates = activityStates;
+ public CalculatorBuilder setStates(StateManager states){
+ this.states = states;
return this;
}
@@ -184,21 +176,21 @@ class CalculatorBuilder {
*/
public JobInsertionCalculator build(){
if(vrp == null) throw new IllegalStateException("vehicle-routing-problem is null, but it must be set (this.setVehicleRoutingProblem(vrp))");
- if(activityStates == null) throw new IllegalStateException("activity states is null, but is must be set (this.setActivityStates(states))");
+ 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;
CalculatorPlusListeners standardLocal = null;
if(local){
- standardLocal = createStandardLocal(vrp, activityStates);
+ standardLocal = createStandardLocal(vrp, states);
}
else{
- standardLocal = createStandardRoute(vrp, activityStates,forwardLooking,memory);
+ standardLocal = createStandardRoute(vrp, states,forwardLooking,memory);
}
baseCalculator = standardLocal.getCalculator();
addAlgorithmListeners(standardLocal.getAlgorithmListener());
addInsertionListeners(standardLocal.getInsertionListener());
if(considerFixedCost){
- CalculatorPlusListeners withFixed = createCalculatorConsideringFixedCosts(vrp, baseCalculator, activityStates, weightOfFixedCost);
+ CalculatorPlusListeners withFixed = createCalculatorConsideringFixedCosts(vrp, baseCalculator, states, weightOfFixedCost);
baseCalculator = withFixed.getCalculator();
addAlgorithmListeners(withFixed.getAlgorithmListener());
addInsertionListeners(withFixed.getInsertionListener());
@@ -206,7 +198,7 @@ class CalculatorBuilder {
if(timeScheduling){
baseCalculator = new CalculatesServiceInsertionWithTimeScheduling(baseCalculator,timeSlice,neighbors);
}
- return createFinalInsertion(fleetManager, baseCalculator, activityStates);
+ return createFinalInsertion(fleetManager, baseCalculator, states);
}
private void addInsertionListeners(List list) {
@@ -221,35 +213,36 @@ class CalculatorBuilder {
}
}
- private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, RouteStates activityStates){
- JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), vrp.getActivityCosts());
- ((CalculatesServiceInsertion) standardServiceInsertion).setActivityStates(activityStates);
+ private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateManager activityStates2){
+ MarginalsCalculus defaultCalc = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), new HardConstraints.HardTimeWindowConstraint(activityStates2) );
+ JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), defaultCalc, new HardConstraints.HardLoadConstraint(activityStates2));
+
((CalculatesServiceInsertion) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion);
return calcPlusListeners;
}
- private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCalculator baseCalculator, RouteStates activityStates, double weightOfFixedCosts){
- final CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(baseCalculator, activityStates);
+ private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCalculator baseCalculator, StateManager activityStates2, double weightOfFixedCosts){
+ final CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(baseCalculator, activityStates2);
withFixCost.setWeightOfFixCost(weightOfFixedCosts);
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost);
calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost));
return calcPlusListeners;
}
- private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, RouteStates activityStates, int forwardLooking, int solutionMemory){
+ private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, StateManager activityStates2, int forwardLooking, int solutionMemory){
int after = forwardLooking;
JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts());
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNuOfActsForwardLooking(after);
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setMemorySize(solutionMemory);
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood());
- ((CalculatesServiceInsertionOnRouteLevel) jobInsertionCalculator).setActivityStates(activityStates);
+ ((CalculatesServiceInsertionOnRouteLevel) jobInsertionCalculator).setStates(activityStates2);
CalculatorPlusListeners calcPlusListener = new CalculatorPlusListeners(jobInsertionCalculator);
return calcPlusListener;
}
- private JobInsertionCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCalculator baseCalc, RouteStates routeStates){
+ private JobInsertionCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCalculator baseCalc, StateManager activityStates2){
return new CalculatesVehTypeDepServiceInsertion(fleetManager, baseCalc);
}
diff --git a/jsprit-core/src/main/java/algorithms/ConfigureFixCostCalculator.java b/jsprit-core/src/main/java/algorithms/ConfigureFixCostCalculator.java
index 179164da..08759adf 100644
--- a/jsprit-core/src/main/java/algorithms/ConfigureFixCostCalculator.java
+++ b/jsprit-core/src/main/java/algorithms/ConfigureFixCostCalculator.java
@@ -42,6 +42,8 @@ final class ConfigureFixCostCalculator implements InsertionStartsListener, JobIn
VehicleRoutingProblem vrp;
CalculatesServiceInsertionConsideringFixCost calcConsideringFix;
+
+ private int nuOfJobsToRecreate;
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, CalculatesServiceInsertionConsideringFixCost calcConsideringFix) {
super();
@@ -55,15 +57,17 @@ final class ConfigureFixCostCalculator implements InsertionStartsListener, JobIn
}
@Override
- public void informInsertionStarts(Collection routes, int nOfJobs2Recreate) {
- double completenessRatio = (1-((double)nOfJobs2Recreate/(double)vrp.getJobs().values().size()));
+ public void informInsertionStarts(Collection routes, Collection unassignedJobs) {
+ this.nuOfJobsToRecreate = unassignedJobs.size();
+ double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)vrp.getJobs().values().size()));
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
// log.debug("initialise completenessRatio to " + completenessRatio);
}
@Override
- public void informJobInserted(int nOfJobsStill2Recreate, Job job2insert, VehicleRoute insertedIn) {
- double completenessRatio = (1-((double)nOfJobsStill2Recreate/(double)vrp.getJobs().values().size()));
+ public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
+ nuOfJobsToRecreate--;
+ double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)vrp.getJobs().values().size()));
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
// log.debug("set completenessRatio to " + completenessRatio);
}
diff --git a/jsprit-core/src/main/java/algorithms/CreateInitialSolution.java b/jsprit-core/src/main/java/algorithms/CreateInitialSolution.java
index dcaee915..e0b1cd6d 100644
--- a/jsprit-core/src/main/java/algorithms/CreateInitialSolution.java
+++ b/jsprit-core/src/main/java/algorithms/CreateInitialSolution.java
@@ -51,7 +51,7 @@ final class CreateInitialSolution implements InitialSolutionFactory {
private static final Logger logger = Logger.getLogger(CreateInitialSolution.class);
- private final AbstractInsertionStrategy insertion;
+ private final InsertionStrategy insertion;
private boolean generateAsMuchAsRoutesAsVehiclesExist = false;
@@ -59,9 +59,9 @@ final class CreateInitialSolution implements InitialSolutionFactory {
this.generateAsMuchAsRoutesAsVehiclesExist = generateAsMuchAsRoutesAsVehiclesExist;
}
- public CreateInitialSolution(AbstractInsertionStrategy insertion) {
+ public CreateInitialSolution(InsertionStrategy insertionStrategy) {
super();
- this.insertion = insertion;
+ this.insertion = insertionStrategy;
}
@Override
@@ -73,7 +73,7 @@ final class CreateInitialSolution implements InitialSolutionFactory {
vehicleRoutes.add(VehicleRoute.newInstance(TourActivities.emptyTour(), DriverImpl.noDriver(), vehicle));
}
}
- insertion.run(vehicleRoutes, getUnassignedJobs(vrp), Double.MAX_VALUE);
+ insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp));
double totalCost = getTotalCost(vehicleRoutes);
logger.info("creation done");
return new VehicleRoutingProblemSolution(vehicleRoutes, totalCost);
diff --git a/jsprit-core/src/main/java/algorithms/FindCheaperVehicle.java b/jsprit-core/src/main/java/algorithms/FindCheaperVehicle.java
index 9a19f579..807cc36a 100644
--- a/jsprit-core/src/main/java/algorithms/FindCheaperVehicle.java
+++ b/jsprit-core/src/main/java/algorithms/FindCheaperVehicle.java
@@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import basics.Job;
import basics.algo.InsertionStartsListener;
import basics.route.VehicleRoute;
@@ -37,7 +38,7 @@ class FindCheaperVehicle implements InsertionStartsListener{
}
@Override
- public void informInsertionStarts(Collection vehicleRoutes, int nOfJobs2Recreate) {
+ public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs) {
List newRoutes = new ArrayList();
for(VehicleRoute route : vehicleRoutes){
if(route.isEmpty()) continue;
diff --git a/jsprit-core/src/main/java/algorithms/FindCheaperVehicleAlgo.java b/jsprit-core/src/main/java/algorithms/FindCheaperVehicleAlgo.java
index a154edd5..680a2525 100644
--- a/jsprit-core/src/main/java/algorithms/FindCheaperVehicleAlgo.java
+++ b/jsprit-core/src/main/java/algorithms/FindCheaperVehicleAlgo.java
@@ -106,7 +106,7 @@ final class FindCheaperVehicleAlgo {
throw new IllegalStateException(e);
}
TourActivities newTour = TourActivities.copyOf(vehicleRoute.getTourActivities());
- tourStateCalculator.updateRoute(vehicleRoute);
+ tourStateCalculator.iterate(vehicleRoute);
return VehicleRoute.newInstance(newTour,vehicleRoute.getDriver(),bestVehicle);
}
return vehicleRoute;
diff --git a/jsprit-core/src/main/java/algorithms/ForwardInTimeListeners.java b/jsprit-core/src/main/java/algorithms/ForwardInTimeListeners.java
new file mode 100644
index 00000000..0f8b68d6
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/ForwardInTimeListeners.java
@@ -0,0 +1,41 @@
+package algorithms;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import basics.route.End;
+import basics.route.Start;
+import basics.route.TourActivity;
+import basics.route.VehicleRoute;
+
+class ForwardInTimeListeners {
+
+ interface ForwardInTimeListener{
+
+ public void start(VehicleRoute route, Start start, double departureTime);
+
+ public void nextActivity(TourActivity act, double arrTime,double endTime);
+
+ public void end(End end, double arrivalTime);
+
+ }
+
+ private Collection listeners = new ArrayList();
+
+ public void addListener(ForwardInTimeListener l){
+ listeners.add(l);
+ }
+
+ public void start(VehicleRoute route, Start start, double departureTime){
+ for(ForwardInTimeListener l : listeners){ l.start(route, start, departureTime); }
+ }
+
+ public void nextActivity(TourActivity act, double arrTime, double endTime){
+ for(ForwardInTimeListener l : listeners){ l.nextActivity(act,arrTime,endTime); }
+ }
+
+ public void end(End end, double arrivalTime){
+ for(ForwardInTimeListener l : listeners){ l.end(end, arrivalTime); }
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/GendreauPostOpt.java b/jsprit-core/src/main/java/algorithms/Gendreau.java
similarity index 83%
rename from jsprit-core/src/main/java/algorithms/GendreauPostOpt.java
rename to jsprit-core/src/main/java/algorithms/Gendreau.java
index c7560cee..70125dc4 100644
--- a/jsprit-core/src/main/java/algorithms/GendreauPostOpt.java
+++ b/jsprit-core/src/main/java/algorithms/Gendreau.java
@@ -21,6 +21,7 @@
package algorithms;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -30,20 +31,19 @@ import java.util.Set;
import org.apache.log4j.Logger;
+import util.RandomNumberGeneration;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.SearchStrategyModule;
import basics.algo.SearchStrategyModuleListener;
import basics.route.TourActivity;
-import basics.route.VehicleRoute;
import basics.route.TourActivity.JobActivity;
+import basics.route.VehicleRoute;
-import util.RandomNumberGeneration;
+final class Gendreau implements SearchStrategyModule{
-final class GendreauPostOpt implements SearchStrategyModule{
-
- private final static Logger log = Logger.getLogger(GendreauPostOpt.class);
+ private final static Logger log = Logger.getLogger(Gendreau.class);
private final static String NAME = "gendreauPostOpt";
@@ -51,9 +51,9 @@ final class GendreauPostOpt implements SearchStrategyModule{
private final VehicleRoutingProblem vrp;
- private final AbstractInsertionStrategy insertionStrategy;
+ private final InsertionStrategy insertionStrategy;
- private final RouteAlgorithm routeAlgorithm;
+ private final Inserter inserter;
private VehicleFleetManager fleetManager;
@@ -67,9 +67,11 @@ final class GendreauPostOpt implements SearchStrategyModule{
this.shareOfJobsToRuin = shareOfJobsToRuin;
}
- public GendreauPostOpt(VehicleRoutingProblem vrp, RuinStrategy ruin, AbstractInsertionStrategy insertionStrategy) {
+ public Gendreau(VehicleRoutingProblem vrp, RuinStrategy ruin, InsertionStrategy insertionStrategy) {
super();
- this.routeAlgorithm = insertionStrategy.getRouteAlgorithm();
+ InsertionListeners insertionListeners = new InsertionListeners();
+ insertionListeners.addAllListeners(insertionStrategy.getListeners());
+ inserter = new Inserter(insertionListeners);
this.ruin = ruin;
this.vrp = vrp;
this.insertionStrategy = insertionStrategy;
@@ -77,7 +79,7 @@ final class GendreauPostOpt implements SearchStrategyModule{
@Override
public String toString() {
- return "[name=gendreauPostOpt][iterations="+nOfIterations+"][share2ruin="+shareOfJobsToRuin+"]";
+ return "[name=gendreau][iterations="+nOfIterations+"][share2ruin="+shareOfJobsToRuin+"]";
}
public void setRandom(Random random) {
@@ -119,16 +121,18 @@ final class GendreauPostOpt implements SearchStrategyModule{
VehicleRoute emptyRoute1 = VehicleRoute.emptyRoute();
copiedRoutes.add(emptyRoute1);
- routeAlgorithm.insertJob(targetJob, routeAlgorithm.calculateBestInsertion(emptyRoute1, targetJob, Double.MAX_VALUE), emptyRoute1);
+ insertionStrategy.insertJobs(Arrays.asList(emptyRoute1), Arrays.asList(targetJob));
+// routeAlgorithm.insertJob(targetJob, routeAlgorithm.calculateBestInsertion(emptyRoute1, targetJob, Double.MAX_VALUE), emptyRoute1);
unassignedJobs.remove(targetJob);
VehicleRoute emptyRoute2 = VehicleRoute.emptyRoute();
copiedRoutes.add(emptyRoute2);
Job job2 = jobsInRoute.get(1);
- routeAlgorithm.insertJob(job2, routeAlgorithm.calculateBestInsertion(emptyRoute2, job2, Double.MAX_VALUE), emptyRoute2);
+ insertionStrategy.insertJobs(Arrays.asList(emptyRoute2), Arrays.asList(job2));
+// routeAlgorithm.insertJob(job2, routeAlgorithm.calculateBestInsertion(emptyRoute2, job2, Double.MAX_VALUE), emptyRoute2);
unassignedJobs.remove(job2);
- insertionStrategy.run(copiedRoutes, unassignedJobs, Double.MAX_VALUE);
+ insertionStrategy.insertJobs(copiedRoutes, unassignedJobs);
double cost = getCost(copiedRoutes);
if(cost < bestSolution.getCost()){
diff --git a/jsprit-core/src/main/java/algorithms/HardConstraints.java b/jsprit-core/src/main/java/algorithms/HardConstraints.java
new file mode 100644
index 00000000..28caccfb
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/HardConstraints.java
@@ -0,0 +1,59 @@
+package algorithms;
+
+import basics.Service;
+import basics.route.TourActivity;
+
+class HardConstraints {
+
+ interface HardRouteLevelConstraint {
+
+ public boolean fulfilled(InsertionContext insertionContext);
+
+ }
+
+ interface HardActivityLevelConstraint {
+
+ public boolean fulfilled(InsertionContext iFacts, TourActivity act, double arrTime);
+
+ }
+
+ 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;
+ }
+ }
+
+ static class HardTimeWindowConstraint implements HardActivityLevelConstraint {
+
+ private StateManager states;
+
+ public HardTimeWindowConstraint(StateManager states) {
+ super();
+ this.states = states;
+ }
+
+ @Override
+ public boolean fulfilled(InsertionContext iFacts, TourActivity act, double arrTime) {
+ if(arrTime > states.getActivityState(act, StateTypes.LATEST_OPERATION_START_TIME).toDouble()){
+ return false;
+ }
+ return true;
+ }
+
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/Inserter.java b/jsprit-core/src/main/java/algorithms/Inserter.java
new file mode 100644
index 00000000..24845c01
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/Inserter.java
@@ -0,0 +1,36 @@
+package algorithms;
+
+import algorithms.InsertionData.NoInsertionFound;
+import basics.Job;
+import basics.Service;
+import basics.route.ServiceActivity;
+import basics.route.VehicleRoute;
+
+class Inserter {
+
+ private InsertionListeners insertionListeners;
+
+ public Inserter(InsertionListeners insertionListeners) {
+ this.insertionListeners = insertionListeners;
+ }
+
+ public void insertJob(Job job, InsertionData insertionData, VehicleRoute vehicleRoute){
+ insertionListeners.informBeforeJobInsertion(job, insertionData, vehicleRoute);
+
+ if(insertionData == null || (insertionData instanceof NoInsertionFound)) throw new IllegalStateException("insertionData null. cannot insert job.");
+ if(job == null) throw new IllegalStateException("cannot insert null-job");
+ if(!(vehicleRoute.getVehicle().getId().toString().equals(insertionData.getSelectedVehicle().getId().toString()))){
+ insertionListeners.informVehicleSwitched(vehicleRoute, vehicleRoute.getVehicle(), insertionData.getSelectedVehicle());
+ vehicleRoute.setVehicle(insertionData.getSelectedVehicle(), insertionData.getVehicleDepartureTime());
+ }
+// if(vehicleRoute.getDepartureTime() != vehicleRoute.g)
+ if(job instanceof Service) {
+ vehicleRoute.getTourActivities().addActivity(insertionData.getDeliveryInsertionIndex(), ServiceActivity.newInstance((Service)job));
+ vehicleRoute.setDepartureTime(insertionData.getVehicleDepartureTime());
+ }
+ else throw new IllegalStateException("neither service nor shipment. this is not supported.");
+
+ insertionListeners.informJobInserted(job, vehicleRoute, insertionData.getInsertionCost(), insertionData.getAdditionalTime());
+// updateTour(vehicleRoute);
+ }
+}
diff --git a/jsprit-core/src/main/java/algorithms/InsertionContext.java b/jsprit-core/src/main/java/algorithms/InsertionContext.java
new file mode 100644
index 00000000..245ac90a
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/InsertionContext.java
@@ -0,0 +1,63 @@
+package algorithms;
+
+import basics.Job;
+import basics.route.Driver;
+import basics.route.Vehicle;
+import basics.route.VehicleRoute;
+
+class InsertionContext {
+
+ private VehicleRoute route;
+ private Job job;
+ private Vehicle newVehicle;
+ private Driver newDriver;
+ private double newDepTime;
+
+ /**
+ * @return the route
+ */
+ public VehicleRoute getRoute() {
+ return route;
+ }
+
+ /**
+ * @return the job
+ */
+ public Job getJob() {
+ return job;
+ }
+
+ /**
+ * @return the newVehicle
+ */
+ public Vehicle getNewVehicle() {
+ return newVehicle;
+ }
+
+ /**
+ * @return the newDriver
+ */
+ public Driver getNewDriver() {
+ return newDriver;
+ }
+
+ /**
+ * @return the newDepTime
+ */
+ public double getNewDepTime() {
+ return newDepTime;
+ }
+
+ public InsertionContext(VehicleRoute route, Job job, Vehicle newVehicle,
+ Driver newDriver, double newDepTime) {
+ super();
+ this.route = route;
+ this.job = job;
+ this.newVehicle = newVehicle;
+ this.newDriver = newDriver;
+ this.newDepTime = newDepTime;
+ }
+
+
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/InsertionData.java b/jsprit-core/src/main/java/algorithms/InsertionData.java
index ddd6507f..462b1f13 100644
--- a/jsprit-core/src/main/java/algorithms/InsertionData.java
+++ b/jsprit-core/src/main/java/algorithms/InsertionData.java
@@ -55,6 +55,22 @@ class InsertionData {
private double departureTime;
+ private double additionalTime;
+
+ /**
+ * @return the additionalTime
+ */
+ public double getAdditionalTime() {
+ return additionalTime;
+ }
+
+ /**
+ * @param additionalTime the additionalTime to set
+ */
+ public void setAdditionalTime(double additionalTime) {
+ this.additionalTime = additionalTime;
+ }
+
public InsertionData(double insertionCost, int pickupInsertionIndex, int deliveryInsertionIndex, Vehicle vehicle, Driver driver){
this.insertionCost = insertionCost;
this.pickupInsertionIndex = pickupInsertionIndex;
diff --git a/jsprit-core/src/main/java/algorithms/InsertionFactory.java b/jsprit-core/src/main/java/algorithms/InsertionFactory.java
index b7cc4093..ed82df20 100644
--- a/jsprit-core/src/main/java/algorithms/InsertionFactory.java
+++ b/jsprit-core/src/main/java/algorithms/InsertionFactory.java
@@ -37,8 +37,8 @@ class InsertionFactory {
private static Logger log = Logger.getLogger(InsertionFactory.class);
- public static AbstractInsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
- VehicleFleetManager vehicleFleetManager, RouteStates activityStates, List algorithmListeners, ExecutorService executorService, int nuOfThreads){
+ public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
+ VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List algorithmListeners, ExecutorService executorService, int nuOfThreads){
boolean concurrentInsertion = false;
if(executorService != null) concurrentInsertion = true;
if(config.containsKey("[@name]")){
@@ -46,12 +46,12 @@ class InsertionFactory {
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
new IllegalStateException(insertionName + " is not supported. use either \"bestInsertion\" or \"regretInsertion\"");
}
- AbstractInsertionStrategy insertionStrategy = null;
+ InsertionStrategy insertionStrategy = null;
List insertionListeners = new ArrayList();
List algoListeners = new ArrayList();
CalculatorBuilder calcBuilder = new CalculatorBuilder(insertionListeners, algorithmListeners);
- calcBuilder.setActivityStates(activityStates);
+ calcBuilder.setStates(routeStates);
calcBuilder.setVehicleRoutingProblem(vrp);
calcBuilder.setVehicleFleetManager(vehicleFleetManager);
@@ -94,34 +94,23 @@ class InsertionFactory {
}
JobInsertionCalculator jic = calcBuilder.build();
- TourStateUpdater tourStateCalculator = new TourStateUpdater(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts());
- RouteAlgorithm routeAlgorithm = RouteAlgorithmImpl.newInstance(jic, tourStateCalculator);
- routeAlgorithm.getListeners().add(new VehicleSwitched(vehicleFleetManager));
- ((RouteAlgorithmImpl) routeAlgorithm).setActivityStates(activityStates);
+
if(insertionName.equals("bestInsertion")){
- if(concurrentInsertion){
- insertionStrategy = BestInsertionConcurrent.newInstance(routeAlgorithm,executorService,nuOfThreads);
- }
- else{
- insertionStrategy = BestInsertion.newInstance(routeAlgorithm);
- }
+ insertionStrategy = new BestInsertion(jic);
}
- else if(insertionName.equals("regretInsertion")){
- insertionStrategy = RegretInsertion.newInstance(routeAlgorithm);
- }
-// else if(insertionName.equals("concurrentBestInsertion")){
-// String processorsString = config.getString("[@processors]");
-// int processors = 1;
-// if(processorsString != null) processors = Integer.parseInt(processorsString);
-//// BestInsertionConcurrent.newInstance(routeAlgorithm,)
-//
-//
+// else if(insertionName.equals("regretInsertion")){
+// insertionStrategy = RegretInsertion.newInstance(routeAlgorithm);
// }
-// insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager));
+ insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager));
insertionStrategy.addListener(new ResetAndIniFleetManager(vehicleFleetManager));
- insertionStrategy.addAllListener(insertionListeners);
+ 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)));
diff --git a/jsprit-core/src/main/java/algorithms/InsertionListeners.java b/jsprit-core/src/main/java/algorithms/InsertionListeners.java
new file mode 100644
index 00000000..72183a1c
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/InsertionListeners.java
@@ -0,0 +1,74 @@
+package algorithms;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import basics.Job;
+import basics.algo.InsertionEndsListener;
+import basics.algo.InsertionListener;
+import basics.algo.InsertionStartsListener;
+import basics.algo.JobInsertedListener;
+import basics.route.Vehicle;
+import basics.route.VehicleRoute;
+
+class InsertionListeners {
+
+ private Collection listeners = new ArrayList();
+
+ public Collection getListeners(){
+ return listeners;
+ }
+
+ public void informJobInserted(Job insertedJob, VehicleRoute inRoute, double additionalCosts, double additionalTime){
+ for(InsertionListener l : listeners){
+ if(l instanceof JobInsertedListener){
+ ((JobInsertedListener)l).informJobInserted(insertedJob, inRoute, additionalCosts, additionalTime);
+ }
+ }
+ }
+
+ public void informVehicleSwitched(VehicleRoute route, Vehicle oldVehicle, Vehicle newVehicle){
+ for(InsertionListener l : listeners){
+ if(l instanceof VehicleSwitchedListener){
+ ((VehicleSwitchedListener) l).vehicleSwitched(route, oldVehicle, newVehicle);
+ }
+ }
+ }
+
+ public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route){
+ for(InsertionListener l : listeners){
+ if(l instanceof BeforeJobInsertionListener){
+ ((BeforeJobInsertionListener)l).informBeforeJobInsertion(job, data, route);
+ }
+ }
+ }
+
+ public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs){
+ for(InsertionListener l : listeners){
+ if(l instanceof InsertionStartsListener){
+ ((InsertionStartsListener)l).informInsertionStarts(vehicleRoutes, unassignedJobs);
+ }
+ }
+ }
+
+ public void informInsertionEndsListeners(Collection vehicleRoutes) {
+ for(InsertionListener l : listeners){
+ if(l instanceof InsertionEndsListener){
+ ((InsertionEndsListener)l).informInsertionEnds(vehicleRoutes);
+ }
+ }
+ }
+
+ public void addListener(InsertionListener insertionListener){
+ listeners.add(insertionListener);
+ }
+
+ public void removeListener(InsertionListener insertionListener){
+ listeners.remove(insertionListener);
+ }
+
+ public void addAllListeners(Collection listeners) {
+ for(InsertionListener l : listeners) addListener(l);
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/InsertionStrategy.java b/jsprit-core/src/main/java/algorithms/InsertionStrategy.java
index 7c56995b..4ebc9ffa 100644
--- a/jsprit-core/src/main/java/algorithms/InsertionStrategy.java
+++ b/jsprit-core/src/main/java/algorithms/InsertionStrategy.java
@@ -15,6 +15,7 @@ package algorithms;
import java.util.Collection;
import basics.Job;
+import basics.algo.InsertionListener;
import basics.route.VehicleRoute;
@@ -59,8 +60,13 @@ interface InsertionStrategy {
*
* @param vehicleRoutes
* @param unassignedJobs
- * @param result2beat
*/
- public void run(Collection vehicleRoutes, Collection unassignedJobs, double result2beat);
+ public void insertJobs(Collection vehicleRoutes, Collection unassignedJobs);
+
+ public void addListener(InsertionListener insertionListener);
+
+ public void removeListener(InsertionListener insertionListener);
+
+ public Collection getListeners();
}
diff --git a/jsprit-core/src/main/java/algorithms/IterateRouteBackwardInTime.java b/jsprit-core/src/main/java/algorithms/IterateRouteBackwardInTime.java
new file mode 100644
index 00000000..afafcde2
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/IterateRouteBackwardInTime.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Stefan Schroeder.
+ * eMail: stefan.schroeder@kit.edu
+ *
+ * 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
+ *
+ * Contributors:
+ * Stefan Schroeder - initial API and implementation
+ ******************************************************************************/
+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) {
+ listeners.start(vehicleRoute, vehicleRoute.getEnd(), vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime());
+
+ Iterator 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); }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/IterateRouteForwardInTime.java b/jsprit-core/src/main/java/algorithms/IterateRouteForwardInTime.java
new file mode 100644
index 00000000..868a84d7
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/IterateRouteForwardInTime.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Stefan Schroeder.
+ * eMail: stefan.schroeder@kit.edu
+ *
+ * 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
+ *
+ * Contributors:
+ * Stefan Schroeder - initial API and implementation
+ ******************************************************************************/
+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) {
+ 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);
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/JobObserver.java b/jsprit-core/src/main/java/algorithms/JobObserver.java
index 43641b04..0643bb36 100644
--- a/jsprit-core/src/main/java/algorithms/JobObserver.java
+++ b/jsprit-core/src/main/java/algorithms/JobObserver.java
@@ -76,14 +76,14 @@ class JobObserver implements JobInsertedListener, BeforeJobInsertionListener, Al
Collection infos = new ArrayList();
@Override
- public void informJobInserted(int nOfJobsStill2Recreate, Job job2insert, VehicleRoute insertedIn) {
+ public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
if(job2insert instanceof Service){
if(((Service) job2insert).getLocationId().equals(locationId)){
- double actualMC = insertedIn.getCost()-routeCostBefore;
- TourActivity act = getAct(job2insert,insertedIn);
+ double actualMC = inRoute.getCost()-routeCostBefore;
+ TourActivity act = getAct(job2insert,inRoute);
double error = (estimatedMC-actualMC);
- int tourSize = insertedIn.getTourActivities().getActivities().size();
- int insertionIndex = getIndexOf(job2insert, insertedIn);
+ int tourSize = inRoute.getTourActivities().getActivities().size();
+ int insertionIndex = getIndexOf(job2insert, inRoute);
// infos.add(new Info())
double depTime = state(act).getEarliestOperationStart()+act.getOperationTime();
infos.add(new Info(depTime,tourSize,insertionIndex,error));
diff --git a/jsprit-core/src/main/java/algorithms/JobRemover.java b/jsprit-core/src/main/java/algorithms/JobRemover.java
deleted file mode 100644
index c8d34d15..00000000
--- a/jsprit-core/src/main/java/algorithms/JobRemover.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2013 Stefan Schroeder
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributors:
- * Stefan Schroeder - initial API and implementation
- ******************************************************************************/
-package algorithms;
-
-import basics.Job;
-import basics.route.VehicleRoute;
-
-interface JobRemover {
-
- /**
- * Removes jobs from vehicRoute and return true if job has been successfully removed.
- *
- * @return true if job removed successfully, otherwise false
- */
- public boolean removeJobWithoutTourUpdate(Job job, VehicleRoute vehicleRoute);
-
-
-}
diff --git a/jsprit-core/src/main/java/algorithms/JobRemoverImpl.java b/jsprit-core/src/main/java/algorithms/JobRemoverImpl.java
deleted file mode 100644
index 737fca0a..00000000
--- a/jsprit-core/src/main/java/algorithms/JobRemoverImpl.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2013 Stefan Schroeder
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributors:
- * Stefan Schroeder - initial API and implementation
- ******************************************************************************/
-package algorithms;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import basics.Job;
-import basics.route.VehicleRoute;
-
-class JobRemoverImpl implements JobRemover{
-
- interface RemoverListener {
- public void informRemovedJob(Job j, VehicleRoute r);
- }
-
- private List remListeners = new ArrayList();
-
- @Override
- public boolean removeJobWithoutTourUpdate(Job job, VehicleRoute vehicleRoute) {
- boolean jobRemoved = vehicleRoute.getTourActivities().removeJob(job);
- if(jobRemoved) informRemovedJob(job,vehicleRoute);
- return jobRemoved;
- }
-
- private void informRemovedJob(Job job, VehicleRoute vehicleRoute) {
- for(RemoverListener l : remListeners) l.informRemovedJob(job, vehicleRoute);
- }
-
- public List getRemListeners() {
- return remListeners;
- }
-
-
-
-}
diff --git a/jsprit-core/src/main/java/algorithms/MarginalsCalculus.java b/jsprit-core/src/main/java/algorithms/MarginalsCalculus.java
new file mode 100644
index 00000000..d702de25
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/MarginalsCalculus.java
@@ -0,0 +1,35 @@
+package algorithms;
+
+import basics.route.TourActivity;
+
+interface MarginalsCalculus {
+
+ class Marginals {
+
+ private double additionalCosts;
+ private double additionalTime;
+ public Marginals(double additionalCosts, double additionalTime) {
+ super();
+ this.additionalCosts = additionalCosts;
+ this.additionalTime = additionalTime;
+ }
+ /**
+ * @return the additionalCosts
+ */
+ public double getAdditionalCosts() {
+ return additionalCosts;
+ }
+ /**
+ * @return the additionalTime
+ */
+ public double getAdditionalTime() {
+ return additionalTime;
+ }
+
+
+
+ }
+
+ Marginals calculate(InsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct);
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/MarginalsCalculusTriangleInequality.java b/jsprit-core/src/main/java/algorithms/MarginalsCalculusTriangleInequality.java
new file mode 100644
index 00000000..aeb6d2e5
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/MarginalsCalculusTriangleInequality.java
@@ -0,0 +1,71 @@
+package algorithms;
+
+import algorithms.HardConstraints.HardActivityLevelConstraint;
+import basics.costs.VehicleRoutingActivityCosts;
+import basics.costs.VehicleRoutingTransportCosts;
+import basics.route.TourActivity;
+
+class MarginalsCalculusTriangleInequality implements MarginalsCalculus{
+
+ private HardActivityLevelConstraint hardConstraint;
+
+ private VehicleRoutingTransportCosts routingCosts;
+ private VehicleRoutingActivityCosts activityCosts;
+
+ public MarginalsCalculusTriangleInequality(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint) {
+ super();
+ this.routingCosts = routingCosts;
+ this.activityCosts = actCosts;
+ this.hardConstraint = hardActivityLevelConstraint;
+ }
+
+ @Override
+ public Marginals calculate(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;
+
+ if(!hardConstraint.fulfilled(iFacts, newAct, newAct_arrTime)){
+ return null;
+ }
+
+ double newAct_endTime = CalcUtils.getStartTimeAtAct(newAct_arrTime, newAct);
+
+ double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
+
+ double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
+ double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
+
+ double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct;
+
+ if(!hardConstraint.fulfilled(iFacts, nextAct, nextAct_arrTime)){
+ return null;
+ }
+
+ double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
+
+ double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct;
+
+ double oldCosts;
+ double oldTime;
+ if(iFacts.getRoute().isEmpty()){
+ oldCosts = 0.0;
+ oldTime = 0.0;
+ }
+ else{
+ double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
+ double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getNewDriver(), iFacts.getNewVehicle());
+
+ double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
+ oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct;
+ oldTime = (nextAct.getArrTime() - iFacts.getRoute().getDepartureTime());
+ }
+
+ double additionalCosts = totalCosts - oldCosts;
+ double additionalTime = (nextAct_arrTime - iFacts.getNewDepTime()) - oldTime;
+
+ return new Marginals(additionalCosts,additionalTime);
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/RegretInsertion.java b/jsprit-core/src/main/java/algorithms/RegretInsertion.java
index 46ad780b..fd8806d7 100644
--- a/jsprit-core/src/main/java/algorithms/RegretInsertion.java
+++ b/jsprit-core/src/main/java/algorithms/RegretInsertion.java
@@ -1,210 +1,229 @@
-/*******************************************************************************
- * Copyright (c) 2011 Stefan Schroeder.
- * eMail: stefan.schroeder@kit.edu
- *
- * 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
- *
- * Contributors:
- * Stefan Schroeder - initial API and implementation
- ******************************************************************************/
-package algorithms;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-
-import algorithms.InsertionData.NoInsertionFound;
-import basics.Job;
-import basics.Service;
-import basics.route.VehicleRoute;
-
-
-/**
- * Insertion based an regret approach.
- *
- *
Basically calculates the insertion cost of the firstBest and the secondBest alternative. The score is then calculated as difference
- * between secondBest and firstBest, plus additional scoring variables that can defined in this.ScoringFunction.
- * The idea is that if the cost of the secondBest alternative is way higher than the first best, it seems to be important to insert this
- * customer immediatedly. If difference is not that high, it might not impact solution if this customer is inserted later.
- *
- * @author stefan schroeder
- *
- */
-final class RegretInsertion extends AbstractInsertionStrategy{
-
- /**
- * Scorer to include other impacts on score such as time-window length or distance to depot.
- *
- * @author schroeder
- *
- */
- static interface ScoringFunction {
-
- public double score(Job job);
-
- }
-
- /**
- * Scorer that includes the length of the time-window when scoring a job. The wider the time-window, the lower the score.
- *
- *
This is the default scorer, i.e.: score = (secondBest - firstBest) + this.TimeWindowScorer.score(job)
- *
- * @author schroeder
- *
- */
- static class TimeWindowScorer implements ScoringFunction {
-
- private double tw_scoringParam = - 0.1;
-
- @Override
- public double score(Job job) {
- double twStart = 0.0;
- double twEnd = 0.0;
-// if(job instanceof Shipment){
-// twStart = ((Shipment) job).getDeliveryTW().getStart();
-// twEnd = ((Shipment) job).getDeliveryTW().getEnd();
+///*******************************************************************************
+// * Copyright (c) 2011 Stefan Schroeder.
+// * eMail: stefan.schroeder@kit.edu
+// *
+// * 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
+// *
+// * Contributors:
+// * Stefan Schroeder - initial API and implementation
+// ******************************************************************************/
+//package algorithms;
+//
+//import java.util.ArrayList;
+//import java.util.Collection;
+//import java.util.List;
+//
+//import org.apache.log4j.Logger;
+//
+//import algorithms.InsertionData.NoInsertionFound;
+//import basics.Job;
+//import basics.Service;
+//import basics.algo.InsertionListener;
+//import basics.route.VehicleRoute;
+//
+//
+///**
+// * Insertion based an regret approach.
+// *
+// *
Basically calculates the insertion cost of the firstBest and the secondBest alternative. The score is then calculated as difference
+// * between secondBest and firstBest, plus additional scoring variables that can defined in this.ScoringFunction.
+// * The idea is that if the cost of the secondBest alternative is way higher than the first best, it seems to be important to insert this
+// * customer immediatedly. If difference is not that high, it might not impact solution if this customer is inserted later.
+// *
+// * @author stefan schroeder
+// *
+// */
+//final class RegretInsertion implements InsertionStrategy{
+//
+// /**
+// * Scorer to include other impacts on score such as time-window length or distance to depot.
+// *
+// * @author schroeder
+// *
+// */
+// static interface ScoringFunction {
+//
+// public double score(Job job);
+//
+// }
+//
+// /**
+// * Scorer that includes the length of the time-window when scoring a job. The wider the time-window, the lower the score.
+// *
+// *
Before inserting a job, all unassigned jobs are scored according to its best- and secondBest-insertion plus additional scoring variables.
+// *
+// */
+// @Override
+// public void insertJobs(Collection routes, Collection unassignedJobs) {
+// List jobs = new ArrayList(unassignedJobs);
+//// informInsertionStarts(routes,unassignedJobs);
+// int inserted = 0;
+// while(!jobs.isEmpty()){
+// List unassignedJobList = new ArrayList(jobs);
+// ScoredJob bestScoredJob = null;
+// double bestScore = -1*Double.MAX_VALUE;
+// VehicleRoute insertIn = null;
+//
+// for(Job unassignedJob : unassignedJobList){
+// InsertionData best = null;
+// InsertionData secondBest = null;
+// VehicleRoute bestRoute = null;
+//
+// double benchmark = Double.MAX_VALUE;
+// for(VehicleRoute route : routes){
+// if(secondBest != null){
+// benchmark = secondBest.getInsertionCost();
+// }
+// InsertionData iData = routeAlgorithm.calculateBestInsertion(route, unassignedJob, benchmark);
+// if(iData instanceof NoInsertionFound) continue;
+// if(best == null){
+// best = iData;
+// bestRoute = route;
+// }
+// else if(iData.getInsertionCost() < best.getInsertionCost()){
+// secondBest = best;
+// best = iData;
+// bestRoute = route;
+// }
+// else if(secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())){
+// secondBest = iData;
+// }
+// }
+// if(best == null){
+// break;
+// }
+// double score = score(unassignedJob,best,secondBest);
+// if(score > bestScore){
+// bestScoredJob = new ScoredJob(unassignedJob,score,best,bestRoute);
+// bestScore = score;
+// }
+// }
+// Job assignedJob;
+// if(bestScoredJob == null){
+// Job job = unassignedJobList.get(0);
+// VehicleRoute newRoute = VehicleRoute.emptyRoute();
+// InsertionData bestI = routeAlgorithm.calculateBestInsertion(newRoute, job, Double.MAX_VALUE);
+// if(bestI instanceof InsertionData.NoInsertionFound) throw new IllegalStateException("given the vehicles, could not create a valid solution");
+// insertIn=newRoute;
+// assignedJob=job;
+// routeAlgorithm.insertJob(job,bestI,newRoute);
+// routes.add(newRoute);
+// jobs.remove(job);
+//
+// }
+// else{
+// routeAlgorithm.insertJob(bestScoredJob.getJob(),bestScoredJob.getInsertionData(), bestScoredJob.getRoute());
+// insertIn=bestScoredJob.getRoute();
+// assignedJob=bestScoredJob.getJob();
+// jobs.remove(bestScoredJob.getJob());
+// }
+// inserted++;
+//// informJobInserted(assignedJob, insertIn);
+//
+// }
+// }
+//
+// private double score(Job unassignedJob, InsertionData best, InsertionData secondBest) {
+// if(best == null){
+// throw new IllegalStateException("cannot insert job " + unassignedJob.getId());
+// }
+// if(secondBest == null){
+// return Double.MAX_VALUE;
+// }
+// return (secondBest.getInsertionCost()-best.getInsertionCost()) + scoringFunction.score(unassignedJob);
+//
+// }
+//
+// @Override
+// public void removeListener(InsertionListener insertionListener) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+// @Override
+// public Collection getListeners() {
+// // TODO Auto-generated method stub
+// return null;
+// }
+//
+// @Override
+// public void addListener(InsertionListener insertionListener) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+//}
diff --git a/jsprit-core/src/main/java/algorithms/RemoveEmptyVehicles.java b/jsprit-core/src/main/java/algorithms/RemoveEmptyVehicles.java
index 49d12618..3a1e7f0b 100644
--- a/jsprit-core/src/main/java/algorithms/RemoveEmptyVehicles.java
+++ b/jsprit-core/src/main/java/algorithms/RemoveEmptyVehicles.java
@@ -26,11 +26,12 @@ import java.util.List;
import org.apache.log4j.Logger;
+import basics.Job;
import basics.algo.InsertionEndsListener;
import basics.algo.InsertionStartsListener;
import basics.route.VehicleRoute;
-class RemoveEmptyVehicles implements InsertionStartsListener, InsertionEndsListener{
+class RemoveEmptyVehicles implements InsertionEndsListener{
private static Logger log = Logger.getLogger(RemoveEmptyVehicles.class);
@@ -41,21 +42,6 @@ class RemoveEmptyVehicles implements InsertionStartsListener, InsertionEndsListe
this.fleetManager = fleetManager;
}
- @Override
- public void informInsertionStarts(Collection vehicleRoutes, int nOfJobs2Recreate) {
-// List routes = new ArrayList(vehicleRoutes);
-// for(VehicleRoute route : routes){
-// if(route.isEmpty()) { vehicleRoutes.remove(route); }
-// }
-// List routes = new ArrayList(vehicleRoutes);
-// for(VehicleRoute route : routes){
-// if(route.isEmpty()) {
-// fleetManager.unlock(route.getVehicle());
-// vehicleRoutes.remove(route);
-// }
-// }
- }
-
@Override
public String toString() {
return "[name=removeEmptyVehicles]";
diff --git a/jsprit-core/src/main/java/algorithms/ResetAndIniFleetManager.java b/jsprit-core/src/main/java/algorithms/ResetAndIniFleetManager.java
index be009119..ff94bbbc 100644
--- a/jsprit-core/src/main/java/algorithms/ResetAndIniFleetManager.java
+++ b/jsprit-core/src/main/java/algorithms/ResetAndIniFleetManager.java
@@ -25,6 +25,7 @@ import java.util.Collection;
import org.apache.log4j.Logger;
+import basics.Job;
import basics.algo.InsertionStartsListener;
import basics.route.VehicleRoute;
@@ -40,16 +41,16 @@ class ResetAndIniFleetManager implements InsertionStartsListener{
}
@Override
- public void informInsertionStarts(Collection vehicleRoutes, int nOfJobs2Recreate) {
+ public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs) {
vehicleFleetManager.unlockAll();
Collection routes = new ArrayList(vehicleRoutes);
for(VehicleRoute route : routes){
- if(route.isEmpty()){
- vehicleRoutes.remove(route);
- }
- else{
+// if(route.isEmpty()){
+// vehicleRoutes.remove(route);
+// }
+// else{
vehicleFleetManager.lock(route.getVehicle());
- }
+// }
}
}
diff --git a/jsprit-core/src/main/java/algorithms/RouteAlgorithm.java b/jsprit-core/src/main/java/algorithms/RouteAlgorithm.java
deleted file mode 100644
index 351a9fa6..00000000
--- a/jsprit-core/src/main/java/algorithms/RouteAlgorithm.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2013 Stefan Schroeder
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributors:
- * Stefan Schroeder - initial API and implementation
- ******************************************************************************/
-package algorithms;
-
-import java.util.Collection;
-
-import basics.Job;
-import basics.route.Vehicle;
-import basics.route.VehicleRoute;
-
-
-interface RouteAlgorithm {
-
- interface RouteAlgorithmListener {
-
- }
-
- interface JobRemovedListener extends RouteAlgorithmListener{
- public void removed(VehicleRoute route, Job job);
- }
-
- interface JobInsertedListener extends RouteAlgorithmListener{
- public void inserted(VehicleRoute route, Job job);
- }
-
- interface VehicleSwitchedListener extends RouteAlgorithmListener{
- public void vehicleSwitched(Vehicle oldVehicle, Vehicle newVehicle);
- }
-
- /**
- * Calculates the best insertion position and the corresponding marginal costs of inserting the job (according to the insertionCostCalculator).
- * This does not affect any input parameter, thus the vehicleRoute and its data will not be changed/affected.
- *
- * @param VehicleRoute, Job, double
- * @return InsertionData
- */
- public InsertionData calculateBestInsertion(VehicleRoute vehicleRoute, Job job, double bestKnownPrice);
-
- /**
- * Removes job from vehicleRoute and does not update the resulting tour. Thus the tour state might not be valid anymore.
- * Note that this changes vehicleRoute!
- *
- * @return true if job removed successfully, otherwise false
- */
- public boolean removeJobWithoutTourUpdate(Job job, VehicleRoute vehicleRoute);
-
- /**
- * Removes job from input parameter vehicleRoute AND updates the state of the resulting tour with tourStateCalc.
- * Note that this changes para vehicleRoute!
- */
- public boolean removeJob(Job job, VehicleRoute vehicleRoute);
-
- /**
- * Inserts job into vehicleRoute.getTour().
- * Please note, that this changes the parameter vehicleRoute!
- */
- public void insertJobWithoutTourUpdate(VehicleRoute vehicleRoute, Job job, InsertionData insertionData);
-
- /**
- * Inserts job into vehicleRoute.getTour().
- * Please note, that this changes the parameter vehicleRoute!
- */
- public void insertJob(Job job, InsertionData insertionData, VehicleRoute vehicleRoute);
-
- /**
- * Updates vehicleRoute, i.e. uses the tourStateCalculator to update for example timeWindows and loads on vehicleRoute.getTour()
- * Note that this changes the parameter vehicleRoute!
- */
- public void updateTour(VehicleRoute vehicleRoute);
-
- public Collection getListeners();
-
-
-}
diff --git a/jsprit-core/src/main/java/algorithms/RouteAlgorithmImpl.java b/jsprit-core/src/main/java/algorithms/RouteAlgorithmImpl.java
deleted file mode 100644
index 6510d054..00000000
--- a/jsprit-core/src/main/java/algorithms/RouteAlgorithmImpl.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 Stefan Schroeder.
- * eMail: stefan.schroeder@kit.edu
- *
- * 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
- *
- * Contributors:
- * Stefan Schroeder - initial API and implementation
- ******************************************************************************/
-package algorithms;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-import org.apache.log4j.Logger;
-
-import algorithms.RouteStates.ActivityState;
-import algorithms.InsertionData.NoInsertionFound;
-import basics.Job;
-import basics.Service;
-import basics.route.ServiceActivity;
-import basics.route.TourActivity;
-import basics.route.Vehicle;
-import basics.route.VehicleRoute;
-
-
-/**
- *
- * @author stefan schroeder
- *
- */
-
-final class RouteAlgorithmImpl implements RouteAlgorithm {
-
- private static Logger logger = Logger.getLogger(RouteAlgorithmImpl.class);
-
- static double NO_DEPARTURE_TIME = -12345.12345;
-
- private String algoDescription = "algorithm to remove and insert jobs from vehicleRoutes. it also calculates marginal costs of the best insertion of a " +
- "job into the given vehicle route";
-
- public static RouteAlgorithmImpl newInstance(JobInsertionCalculator jobInsertionCalculator, VehicleRouteUpdater tourStateCalculator){
- return new RouteAlgorithmImpl(jobInsertionCalculator, tourStateCalculator);
- }
-
- private Collection listeners = new ArrayList();
-
- private VehicleRouteUpdater tourCalculator;
-
- private JobInsertionCalculator insertionCostCalculator;
-
- private RouteStates actStates;
-
- public void setActivityStates(RouteStates actStates){
- this.actStates = actStates;
- }
-
- public ActivityState state(TourActivity act){
- return actStates.getState(act);
- }
-
- private RouteAlgorithmImpl(JobInsertionCalculator insertionCostCalculator, VehicleRouteUpdater tourCalculator){
- this.tourCalculator = tourCalculator;
- this.insertionCostCalculator = insertionCostCalculator;
- }
-
-
- public InsertionData calculateBestInsertion(VehicleRoute vehicleRoute, Job job, double bestKnownCost) {
- return insertionCostCalculator.calculate(vehicleRoute, job, null, NO_DEPARTURE_TIME, null, bestKnownCost);
- }
-
-
- public boolean removeJobWithoutTourUpdate(Job job, VehicleRoute vehicleRoute) {
- boolean removed = vehicleRoute.getTourActivities().removeJob(job);
- if(removed){
- jobRemoved(vehicleRoute,job);
- }
- return removed;
- }
-
- private void jobRemoved(VehicleRoute vehicleRoute, Job job) {
- for(RouteAlgorithmListener l : listeners){
- if(l instanceof JobRemovedListener){
- ((JobRemovedListener) l).removed(vehicleRoute, job);
- }
- }
- }
-
-
- public boolean removeJob(Job job, VehicleRoute vehicleRoute){
- boolean removed = removeJobWithoutTourUpdate(job, vehicleRoute);
- if(removed) updateTour(vehicleRoute);
- return removed;
- }
-
-
- public void updateTour(VehicleRoute vehicleRoute){
- boolean tourIsFeasible = tourCalculator.updateRoute(vehicleRoute);
- if(!tourIsFeasible){
- throw new IllegalStateException("At this point tour should be feasible. but it is not. \n currentTour=" + vehicleRoute.getTourActivities() +
- "\n error sources: check jobInsertionCostCalculators and actInsertionCalculators. somehow an insertion is made, althought a hard constraint is broken. Here, hard constraints refer to \n" +
- "hard time-window constraints. If you want to deal with such constraints, make sure a violation is penalized properly (such that it can never be the best insertion position). \n" +
- "If you use CalculatesServiceInsertion and CalculatesActivityInsertion, the only hard constraint is the vehicle-capacity constraints. A violation of time-windows must be penalized in \n" +
- "the vehicleRouteCostFunction. For example: in handleActivity(....) one can check whether the act start-time is higher than the latestOperationStartTime. If so penalize it with a very high value. \n" +
- "For example: \n" +
- "public void handleActivity(TourActivity tourAct, double startTime, double endTime) {\n" +
- "\tif(startTime > tourAct.getLatestOperationStartTime()){\n" +
- "\t\tcost += Double.MAX_VALUE;\n" +
- "\t}\n" +
- "});");
- }
- }
-
-
- @Override
- public void insertJobWithoutTourUpdate(VehicleRoute vehicleRoute, Job job, InsertionData insertionData) {
- if(insertionData == null || (insertionData instanceof NoInsertionFound)) throw new IllegalStateException("insertionData null. cannot insert job.");
- if(job == null) throw new IllegalStateException("cannot insert null-job");
- if(!(vehicleRoute.getVehicle().getId().toString().equals(insertionData.getSelectedVehicle().getId().toString()))){
- vehicleSwitched(vehicleRoute.getVehicle(),insertionData.getSelectedVehicle());
- vehicleRoute.setVehicle(insertionData.getSelectedVehicle(), insertionData.getVehicleDepartureTime());
- }
- if(job instanceof Service) {
- vehicleRoute.getTourActivities().addActivity(insertionData.getDeliveryInsertionIndex(), ServiceActivity.newInstance((Service)job));
- vehicleRoute.setDepartureTime(insertionData.getVehicleDepartureTime());
- }
- else throw new IllegalStateException("neither service nor shipment. this is not supported.");
- jobInserted(vehicleRoute,job);
- }
-
-
-
- private void vehicleSwitched(Vehicle oldVehicle, Vehicle newVehicle) {
- for(RouteAlgorithmListener l : listeners){
- if(l instanceof VehicleSwitchedListener){
- ((VehicleSwitchedListener) l).vehicleSwitched(oldVehicle,newVehicle);
- }
- }
- }
-
- private void jobInserted(VehicleRoute vehicleRoute, Job job) {
- for(RouteAlgorithmListener l : listeners){
- if(l instanceof JobInsertedListener){
- ((JobInsertedListener) l).inserted(vehicleRoute, job);
- }
- }
- }
-
-
- public void insertJob(Job job, InsertionData insertionData, VehicleRoute vehicleRoute){
- insertJobWithoutTourUpdate(vehicleRoute, job, insertionData);
- updateTour(vehicleRoute);
- }
-
- @Override
- public String toString() {
- return algoDescription;
- }
-
- public Collection getListeners() {
- return listeners;
- }
-
- public void setAlgoDescription(String algoDescription) {
- this.algoDescription = algoDescription;
- }
-
-}
diff --git a/jsprit-core/src/main/java/algorithms/RuinAndRecreateModule.java b/jsprit-core/src/main/java/algorithms/RuinAndRecreateModule.java
new file mode 100644
index 00000000..f6d12397
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/RuinAndRecreateModule.java
@@ -0,0 +1,59 @@
+package algorithms;
+
+import java.util.Collection;
+
+import util.RouteUtils;
+import algorithms.RuinStrategy.RuinListener;
+import basics.Job;
+import basics.VehicleRoutingProblemSolution;
+import basics.algo.InsertionListener;
+import basics.algo.SearchStrategyModule;
+import basics.algo.SearchStrategyModuleListener;
+
+class RuinAndRecreateModule implements SearchStrategyModule{
+
+ private InsertionStrategy insertion;
+
+ private RuinStrategy ruin;
+
+ private String moduleName;
+
+ public RuinAndRecreateModule(String moduleName, InsertionStrategy insertion, RuinStrategy ruin) {
+ super();
+ this.insertion = insertion;
+ this.ruin = ruin;
+ this.moduleName = moduleName;
+ }
+
+ @Override
+ public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
+ Collection ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
+ insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobs);
+ double totalCost = RouteUtils.getTotalCost(vrpSolution.getRoutes());
+ vrpSolution.setCost(totalCost);
+ return vrpSolution;
+ }
+
+ @Override
+ public String getName() {
+ return moduleName;
+ }
+
+ @Override
+ public void addModuleListener(SearchStrategyModuleListener moduleListener) {
+ if(moduleListener instanceof InsertionListener){
+ InsertionListener iListener = (InsertionListener) moduleListener;
+ if(!insertion.getListeners().contains(iListener)){
+ insertion.addListener(iListener);
+ }
+ }
+ if(moduleListener instanceof RuinListener){
+ RuinListener rListener = (RuinListener) moduleListener;
+ if(!ruin.getListeners().contains(rListener)){
+ ruin.addListener(rListener);
+ }
+ }
+
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/RuinListeners.java b/jsprit-core/src/main/java/algorithms/RuinListeners.java
new file mode 100644
index 00000000..08b91488
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/RuinListeners.java
@@ -0,0 +1,38 @@
+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 ruinListeners = new ArrayList();
+
+ void ruinStarts(Collection routes){
+ for(RuinListener l : ruinListeners) l.ruinStarts(routes);
+ }
+
+ void ruinEnds(Collection routes, Collection 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 getListeners(){
+ return Collections.unmodifiableCollection(ruinListeners);
+ }
+}
diff --git a/jsprit-core/src/main/java/algorithms/RuinRadial.java b/jsprit-core/src/main/java/algorithms/RuinRadial.java
index 82cb3ed6..2e293468 100644
--- a/jsprit-core/src/main/java/algorithms/RuinRadial.java
+++ b/jsprit-core/src/main/java/algorithms/RuinRadial.java
@@ -29,29 +29,11 @@ import util.RandomNumberGeneration;
import util.StopWatch;
import basics.Job;
import basics.VehicleRoutingProblem;
-import basics.VehicleRoutingProblemSolution;
-import basics.algo.SearchStrategyModule;
import basics.route.VehicleRoute;
final class RuinRadial implements RuinStrategy {
-
- private final static String NAME = "radialRuin";
-
- /**
- * returns a new creation of instance of ruinRadial
- * @param vrp
- * @param fraction TODO
- * @param jobDistance
- * @param jobRemover TODO
- * @param routeUpdater TODO
- * @return
- */
- static RuinRadial newInstance(VehicleRoutingProblem vrp, double fraction, JobDistance jobDistance, JobRemover jobRemover, VehicleRouteUpdater routeUpdater){
- return new RuinRadial(vrp, fraction, jobDistance, jobRemover, routeUpdater);
- }
-
static class ReferencedJob {
private Job job;
@@ -84,21 +66,18 @@ final class RuinRadial implements RuinStrategy {
private JobDistance jobDistance;
- private JobRemover jobRemover;
+ private RuinListeners ruinListeners;
- private VehicleRouteUpdater routeUpdater;
-
public void setRandom(Random random) {
this.random = random;
}
- public RuinRadial(VehicleRoutingProblem vrp, double fraction, JobDistance jobDistance, JobRemover jobRemover, VehicleRouteUpdater routeUpdater) {
+ public RuinRadial(VehicleRoutingProblem vrp, double fraction, JobDistance jobDistance) {
super();
this.vrp = vrp;
this.jobDistance = jobDistance;
- this.jobRemover = jobRemover;
- this.routeUpdater = routeUpdater;
this.fractionOfAllNodes2beRuined = fraction;
+ ruinListeners = new RuinListeners();
calculateDistancesFromJob2Job();
logger.info("intialise " + this);
}
@@ -158,6 +137,7 @@ final class RuinRadial implements RuinStrategy {
}
public Collection ruin(Collection vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved){
+ ruinListeners.ruinStarts(vehicleRoutes);
List unassignedJobs = new ArrayList();
TreeSet tree = distanceNodeTree.get(targetJob.getId());
Iterator descendingIterator = tree.descendingIterator();
@@ -169,15 +149,14 @@ final class RuinRadial implements RuinStrategy {
counter++;
boolean removed = false;
for (VehicleRoute route : vehicleRoutes) {
- removed = jobRemover.removeJobWithoutTourUpdate(job, route);
+ removed = route.getTourActivities().removeJob(job);;
if (removed) {
+ ruinListeners.removed(job,route);
break;
}
}
}
- for(VehicleRoute route : vehicleRoutes){
- routeUpdater.updateRoute(route);
- }
+ ruinListeners.ruinEnds(vehicleRoutes, unassignedJobs);
return unassignedJobs;
}
@@ -193,15 +172,20 @@ final class RuinRadial implements RuinStrategy {
* fractionOfAllNodes2beRuined);
}
-// @Override
-// public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
-// ruin(vrpSolution.getRoutes());
-// return vrpSolution;
-// }
-//
-// @Override
-// public String getName() {
-// return NAME;
-// }
+ @Override
+ public void addListener(RuinListener ruinListener) {
+ ruinListeners.addListener(ruinListener);
+ }
+
+ @Override
+ public void removeListener(RuinListener ruinListener) {
+ ruinListeners.removeListener(ruinListener);
+ }
+
+ @Override
+ public Collection getListeners() {
+ return ruinListeners.getListeners();
+ }
+
}
diff --git a/jsprit-core/src/main/java/algorithms/RuinRandom.java b/jsprit-core/src/main/java/algorithms/RuinRandom.java
index 9180f13a..3695a2dd 100644
--- a/jsprit-core/src/main/java/algorithms/RuinRandom.java
+++ b/jsprit-core/src/main/java/algorithms/RuinRandom.java
@@ -35,10 +35,6 @@ import basics.route.VehicleRoute;
*/
final class RuinRandom implements RuinStrategy {
-
- public static RuinRandom newInstance(VehicleRoutingProblem vrp, double fraction, JobRemover jobRemover, VehicleRouteUpdater routeUpdater){
- return new RuinRandom(vrp, fraction, jobRemover, routeUpdater);
- }
private Logger logger = Logger.getLogger(RuinRandom.class);
@@ -47,10 +43,8 @@ final class RuinRandom implements RuinStrategy {
private double fractionOfAllNodes2beRuined;
private Random random = RandomNumberGeneration.getRandom();
-
- private JobRemover jobRemover;
-
- private VehicleRouteUpdater vehicleRouteUpdater;
+
+ private RuinListeners ruinListeners;
public void setRandom(Random random) {
this.random = random;
@@ -61,15 +55,12 @@ final class RuinRandom implements RuinStrategy {
*
* @param vrp
* @param fraction which is the fraction of total c
- * @param jobRemover
- * @param vehicleRouteUpdater
*/
- public RuinRandom(VehicleRoutingProblem vrp, double fraction, JobRemover jobRemover, VehicleRouteUpdater vehicleRouteUpdater) {
+ public RuinRandom(VehicleRoutingProblem vrp, double fraction) {
super();
this.vrp = vrp;
- this.jobRemover = jobRemover;
- this.vehicleRouteUpdater = vehicleRouteUpdater;
this.fractionOfAllNodes2beRuined = fraction;
+ ruinListeners = new RuinListeners();
logger.info("initialise " + this);
logger.info("done");
}
@@ -81,9 +72,11 @@ final class RuinRandom implements RuinStrategy {
*/
@Override
public Collection ruin(Collection vehicleRoutes) {
+ ruinListeners.ruinStarts(vehicleRoutes);
List unassignedJobs = new ArrayList();
int nOfJobs2BeRemoved = selectNuOfJobs2BeRemoved();
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
+ ruinListeners.ruinEnds(vehicleRoutes, unassignedJobs);
return unassignedJobs;
}
@@ -92,19 +85,22 @@ final class RuinRandom implements RuinStrategy {
*/
@Override
public Collection ruin(Collection vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
+ ruinListeners.ruinStarts(vehicleRoutes);
List unassignedJobs = new ArrayList();
if(targetJob != null){
boolean removed = false;
for (VehicleRoute route : vehicleRoutes) {
- removed = jobRemover.removeJobWithoutTourUpdate(targetJob, route);
+ removed = route.getTourActivities().removeJob(targetJob);
if (removed) {
nOfJobs2BeRemoved--;
unassignedJobs.add(targetJob);
+ ruinListeners.removed(targetJob,route);
break;
}
}
}
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
+ ruinListeners.ruinEnds(vehicleRoutes, unassignedJobs);
return unassignedJobs;
}
@@ -113,27 +109,23 @@ final class RuinRandom implements RuinStrategy {
logger.info("fraction set " + this);
}
- private void ruin(Collection vehicleRoutes,int nOfJobs2BeRemoved, List unassignedJobs) {
+ private void ruin(Collection vehicleRoutes, int nOfJobs2BeRemoved, List unassignedJobs) {
LinkedList availableJobs = new LinkedList(vrp.getJobs().values());
for (int i = 0; i < nOfJobs2BeRemoved; i++) {
Job job = pickRandomJob(availableJobs);
unassignedJobs.add(job);
availableJobs.remove(job);
for (VehicleRoute route : vehicleRoutes) {
- boolean removed = jobRemover.removeJobWithoutTourUpdate(job, route);
- if (removed) break;
+ boolean removed = route.getTourActivities().removeJob(job);
+ if (removed) {
+ ruinListeners.removed(job,route);
+ break;
+ }
}
}
- updateRoutes(vehicleRoutes);
}
- private void updateRoutes(Collection vehicleRoutes) {
- for(VehicleRoute route : vehicleRoutes){
- vehicleRouteUpdater.updateRoute(route);
- }
- }
-
-
+
@Override
public String toString() {
return "[name=randomRuin][fraction="+fractionOfAllNodes2beRuined+"]";
@@ -148,4 +140,19 @@ final class RuinRandom implements RuinStrategy {
return (int) Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined);
}
+ @Override
+ public void addListener(RuinListener ruinListener) {
+ ruinListeners.addListener(ruinListener);
+ }
+
+ @Override
+ public void removeListener(RuinListener ruinListener) {
+ ruinListeners.removeListener(ruinListener);
+ }
+
+ @Override
+ public Collection getListeners() {
+ return ruinListeners.getListeners();
+ }
+
}
diff --git a/jsprit-core/src/main/java/algorithms/RuinStrategy.java b/jsprit-core/src/main/java/algorithms/RuinStrategy.java
index 67cf868a..603050d7 100644
--- a/jsprit-core/src/main/java/algorithms/RuinStrategy.java
+++ b/jsprit-core/src/main/java/algorithms/RuinStrategy.java
@@ -13,7 +13,6 @@
package algorithms;
import java.util.Collection;
-import java.util.List;
import basics.Job;
import basics.route.VehicleRoute;
@@ -29,19 +28,62 @@ import basics.route.VehicleRoute;
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 routes);
+
+ /**
+ * informs about ruin-end.
+ *
+ * @param routes
+ * @param unassignedJobs
+ */
+ public void ruinEnds(Collection routes, Collection 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. removes jobs from service providers and
- * returns a collection of these removed, and thus unassigned, jobs.
+ * Ruins a current solution, i.e. a collection of vehicle-routes and
+ * returns a collection of removed and thus unassigned jobs.
*
- * @param vehicleRoutes
- * @return
+ * @param {@link VehicleRoute}
+ * @return Collection of {@link Job}
*/
public Collection ruin(Collection vehicleRoutes);
+ /**
+ * Removes targetJob as well as its neighbors with a size of (nOfJobs2BeRemoved-1).
+ */
public Collection ruin(Collection vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved);
+
+ /**
+ * Adds a ruin-listener.
+ *
+ * @param {@link RuinListener}
+ */
+ public void addListener(RuinListener ruinListener);
+
+ public void removeListener(RuinListener ruinListener);
+
+ public Collection getListeners();
}
diff --git a/jsprit-core/src/main/java/algorithms/StateManager.java b/jsprit-core/src/main/java/algorithms/StateManager.java
new file mode 100644
index 00000000..e0734ae4
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/StateManager.java
@@ -0,0 +1,52 @@
+package algorithms;
+
+import basics.route.TourActivity;
+import basics.route.VehicleRoute;
+
+interface StateManager {
+
+ interface State {
+ double toDouble();
+ }
+
+ class StateImpl implements State{
+ double state;
+
+ public StateImpl(double state) {
+ super();
+ this.state = state;
+ }
+
+ @Override
+ public double toDouble() {
+ return state;
+ }
+
+// public void setState(double val){
+// state=val;
+// }
+ }
+
+ interface States {
+
+// void putState(String key, State state);
+
+ State getState(String key);
+
+ }
+
+
+
+// Map getRouteStates();
+
+// void put(VehicleRoute route, States states);
+
+// Map getActivityStates();
+
+// void put(TourActivity act, States states);
+
+ State getActivityState(TourActivity act, String stateType);
+
+ State getRouteState(VehicleRoute route, String stateType);
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/StateManagerImpl.java b/jsprit-core/src/main/java/algorithms/StateManagerImpl.java
new file mode 100644
index 00000000..b16f0d2c
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/StateManagerImpl.java
@@ -0,0 +1,121 @@
+package algorithms;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import basics.route.TourActivity;
+import basics.route.VehicleRoute;
+
+class StateManagerImpl implements StateManager{
+
+ static class StatesImpl implements States{
+
+ private Map states = new HashMap();
+
+ public void putState(String key, State state) {
+ states.put(key, state);
+ }
+
+ @Override
+ public State getState(String key) {
+ return states.get(key);
+ }
+
+ }
+
+ private Map vehicleRouteStates = new HashMap();
+
+ private Map activityStates = new HashMap();
+
+ public Map getRouteStates() {
+ return Collections.unmodifiableMap(vehicleRouteStates);
+ }
+
+ public States getRouteStates(VehicleRoute route){
+ return vehicleRouteStates.get(route);
+ }
+
+ public void put(VehicleRoute route, States states) {
+ vehicleRouteStates.put(route, states);
+ }
+
+ public Map getActivityStates() {
+ return Collections.unmodifiableMap(activityStates);
+ }
+
+ public States getActivityStates(TourActivity act){
+ return activityStates.get(act);
+ }
+
+ public void put(TourActivity act, States states) {
+ activityStates.put(act, states);
+ }
+
+ 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());
+ return null;
+ }
+
+ private State getDefaultRouteState(String stateType, VehicleRoute route){
+ 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);
+ 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);
+ }
+
+
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/StateTypes.java b/jsprit-core/src/main/java/algorithms/StateTypes.java
new file mode 100644
index 00000000..2306281d
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/StateTypes.java
@@ -0,0 +1,13 @@
+package algorithms;
+
+class StateTypes {
+ final static String LOAD = "load";
+
+ final static String DURATION = "duration";
+
+ final static String LATEST_OPERATION_START_TIME = "latestOST";
+
+ final static String EARLIEST_OPERATION_START_TIME = "earliestOST";
+
+ public static final String COSTS = "costs";
+}
diff --git a/jsprit-core/src/main/java/algorithms/TourConstraintEngine.java b/jsprit-core/src/main/java/algorithms/TourConstraintEngine.java
deleted file mode 100644
index 6cd3e758..00000000
--- a/jsprit-core/src/main/java/algorithms/TourConstraintEngine.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2013 Stefan Schroeder
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributors:
- * Stefan Schroeder - initial API and implementation
- ******************************************************************************/
-package algorithms;
-
-import basics.Job;
-import basics.route.VehicleRoute;
-
-class TourConstraintEngine {
-
-// void ini(VehicleRoute route, Job job){
-//
-// }
-//
-
-
-}
diff --git a/jsprit-core/src/main/java/algorithms/TourStateUpdater.java b/jsprit-core/src/main/java/algorithms/TourStateUpdater.java
deleted file mode 100644
index b46af2ec..00000000
--- a/jsprit-core/src/main/java/algorithms/TourStateUpdater.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 Stefan Schroeder.
- * eMail: stefan.schroeder@kit.edu
- *
- * 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
- *
- * Contributors:
- * Stefan Schroeder - initial API and implementation
- ******************************************************************************/
-package algorithms;
-
-import org.apache.log4j.Logger;
-
-import basics.costs.VehicleRoutingActivityCosts;
-import basics.costs.VehicleRoutingTransportCosts;
-import basics.route.VehicleRoute;
-
-
-
-
-
-/**
- * Updates tour state, i.e. the tour as well as each activity in that tour has a state such as currentLoad, currentCost, earliestOperationTime and
- * latestOperationTime. Each time the tour is changed (for instance by removing or adding an activity), tour and activity states
- * might change, thus this updater updates activity states.
- * This includes:
- * - update load and totalCost at tour-level
- * - update currentLoad and currentCost at activity-level
- * - update earliest- and latestOperationStart values at activity-level
- *
- * If ensureFeasibility is true, then it additionally checks whether the earliestOperationStartTime is higher than the latestOperationStartTime.
- * If it is, it returns a false value to indicate that the tour is not feasible. This makes only sense for hard-timewindows.
- *
- * If softTimeWindow is set to true, latestOperationStartTimes are not updated and the tour is always feasible.
- *
- * @author stefan schroeder
- *
- */
-
-class TourStateUpdater implements VehicleRouteUpdater{
-
-// public final static Counter counter = new Counter("#updateTWProcesses: ");
-
- private static Logger logger = Logger.getLogger(TourStateUpdater.class);
-
- private boolean ensureFeasibility = true;
-
- private UpdateTourStatesForwardInTime forwardUpdate;
-
- private UpdateTourStatesBackwardInTime backwardUpdate;
-
- private boolean updateTimeWindows = true;
-
- private RouteStates actStates;
-
- public TourStateUpdater(RouteStates activityStates, VehicleRoutingTransportCosts costs, VehicleRoutingActivityCosts costFunction) {
- super();
- forwardUpdate = new UpdateTourStatesForwardInTime(costs, costs, costFunction);
- backwardUpdate = new UpdateTourStatesBackwardInTime(costs);
- actStates=activityStates;
- forwardUpdate.setActivityStates(actStates);
- backwardUpdate.setActivityStates(actStates);
- }
-
- /*
- *
- */
- public boolean updateRoute(VehicleRoute vehicleRoute) {
- if(updateTimeWindows){
- backwardUpdate.checkFeasibility = ensureFeasibility;
- backwardUpdate.updateRoute(vehicleRoute);
- }
- forwardUpdate.updateRoute(vehicleRoute);
- boolean tourIsFeasible = true;
-
- return tourIsFeasible;
- }
-
- public void setTimeWindowUpdate(boolean updateTimeWindows) {
- this.updateTimeWindows = updateTimeWindows;
- logger.info("set timeWindowUpdate to " + updateTimeWindows);
- }
-
- public void setEnsureFeasibility(boolean ensureFeasibility) {
- this.ensureFeasibility = ensureFeasibility;
- }
-
-}
diff --git a/jsprit-core/src/main/java/algorithms/UdateCostsAtRouteLevel.java b/jsprit-core/src/main/java/algorithms/UdateCostsAtRouteLevel.java
new file mode 100644
index 00000000..b058549f
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/UdateCostsAtRouteLevel.java
@@ -0,0 +1,62 @@
+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.VehicleRoute;
+
+class UdateCostsAtRouteLevel implements JobInsertedListener, InsertionStartsListener, InsertionEndsListener{
+
+ private StateManagerImpl states;
+
+ private VehicleRoutingTransportCosts tpCosts;
+
+ private VehicleRoutingActivityCosts actCosts;
+
+ public UdateCostsAtRouteLevel(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 vehicleRoutes, Collection unassignedJobs) {
+ IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts);
+ forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
+ for(VehicleRoute route : vehicleRoutes){
+ forwardInTime.iterate(route);
+ }
+
+ }
+
+ @Override
+ public void informInsertionEnds(Collection 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);
+ }
+
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/UpdateActivityTimes.java b/jsprit-core/src/main/java/algorithms/UpdateActivityTimes.java
new file mode 100644
index 00000000..308739c6
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/UpdateActivityTimes.java
@@ -0,0 +1,31 @@
+package algorithms;
+
+import org.apache.log4j.Logger;
+
+import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
+import basics.route.End;
+import basics.route.Start;
+import basics.route.TourActivity;
+import basics.route.VehicleRoute;
+
+class UpdateActivityTimes implements ForwardInTimeListener{
+
+ private Logger log = Logger.getLogger(UpdateActivityTimes.class);
+
+ @Override
+ public void start(VehicleRoute route, Start start, double departureTime) {
+ start.setEndTime(departureTime);
+ }
+
+ @Override
+ public void nextActivity(TourActivity act, double arrTime, double endTime) {
+ act.setArrTime(arrTime);
+ act.setEndTime(endTime);
+ }
+
+ @Override
+ public void end(End end, double arrivalTime) {
+ end.setArrTime(arrivalTime);
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/UpdateCostsAtAllLevels.java b/jsprit-core/src/main/java/algorithms/UpdateCostsAtAllLevels.java
new file mode 100644
index 00000000..2cc6bcf7
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/UpdateCostsAtAllLevels.java
@@ -0,0 +1,84 @@
+package algorithms;
+
+import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
+import algorithms.StateManager.StateImpl;
+import basics.costs.ForwardTransportCost;
+import basics.costs.VehicleRoutingActivityCosts;
+import basics.route.End;
+import basics.route.Start;
+import basics.route.TourActivity;
+import basics.route.VehicleRoute;
+
+class UpdateCostsAtAllLevels implements ForwardInTimeListener{
+
+ 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;
+
+ public UpdateCostsAtAllLevels(VehicleRoutingActivityCosts activityCost, ForwardTransportCost transportCost, StateManagerImpl states) {
+ super();
+ this.activityCost = activityCost;
+ this.transportCost = transportCost;
+ this.states = states;
+ }
+
+ @Override
+ public void start(VehicleRoute route, Start start, double departureTime) {
+ vehicleRoute = route;
+ vehicleRoute.getVehicleRouteCostCalculator().reset();
+ prevAct = start;
+ startTimeAtPrevAct = departureTime;
+ }
+
+ @Override
+ public void nextActivity(TourActivity act, double arrTime, double endTime) {
+ double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), act.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
+ double actCost = activityCost.getActivityCost(act, arrTime, 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 = endTime;
+ }
+
+ @Override
+ public void end(End end, double arrivalTime) {
+ double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), end.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
+ double actCost = activityCost.getActivityCost(end, arrivalTime, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
+
+ vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
+ vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
+
+ totalOperationCost += transportCost;
+ totalOperationCost += actCost;
+
+ states.putRouteState(vehicleRoute, StateTypes.COSTS, new StateImpl(totalOperationCost));
+
+ //this is rather strange and likely to change
+ vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver());
+ vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle());
+ vehicleRoute.getVehicleRouteCostCalculator().finish();
+
+ startTimeAtPrevAct = 0.0;
+ prevAct = null;
+ vehicleRoute = null;
+ totalOperationCost = 0.0;
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/UpdateEarliestStartTimeWindowAtActLocations.java b/jsprit-core/src/main/java/algorithms/UpdateEarliestStartTimeWindowAtActLocations.java
new file mode 100644
index 00000000..1fab69ef
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/UpdateEarliestStartTimeWindowAtActLocations.java
@@ -0,0 +1,30 @@
+package algorithms;
+
+import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
+import algorithms.StateManager.StateImpl;
+import basics.route.End;
+import basics.route.Start;
+import basics.route.TourActivity;
+import basics.route.VehicleRoute;
+
+class UpdateEarliestStartTimeWindowAtActLocations implements ForwardInTimeListener{
+
+ private StateManagerImpl states;
+
+ public UpdateEarliestStartTimeWindowAtActLocations(StateManagerImpl states) {
+ super();
+ this.states = states;
+ }
+
+ @Override
+ public void start(VehicleRoute route, Start start, double departureTime) {}
+
+ @Override
+ public void nextActivity(TourActivity act, double arrTime, double endTime) {
+ states.putActivityState(act, StateTypes.EARLIEST_OPERATION_START_TIME, new StateImpl(Math.max(arrTime, act.getTheoreticalEarliestOperationStartTime())));
+ }
+
+ @Override
+ public void end(End end, double arrivalTime) {}
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/UpdateLatestOperationStartTimeAtActLocations.java b/jsprit-core/src/main/java/algorithms/UpdateLatestOperationStartTimeAtActLocations.java
new file mode 100644
index 00000000..6c65282e
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/UpdateLatestOperationStartTimeAtActLocations.java
@@ -0,0 +1,32 @@
+package algorithms;
+
+import algorithms.BackwardInTimeListeners.BackwardInTimeListener;
+import algorithms.StateManager.StateImpl;
+import basics.route.End;
+import basics.route.Start;
+import basics.route.TourActivity;
+import basics.route.VehicleRoute;
+
+class UpdateLatestOperationStartTimeAtActLocations implements BackwardInTimeListener{
+
+ private StateManagerImpl states;
+
+ public UpdateLatestOperationStartTimeAtActLocations(StateManagerImpl states) {
+ super();
+ this.states = states;
+ }
+
+ @Override
+ public void start(VehicleRoute route, End end, double latestArrivalTime) {}
+
+ @Override
+ public void prevActivity(TourActivity act,double latestDepartureTime, double latestOperationStartTime) {
+ states.putActivityState(act, StateTypes.LATEST_OPERATION_START_TIME, new StateImpl(latestOperationStartTime));
+ }
+
+ @Override
+ public void end(Start start, double latestDepartureTime) {}
+
+
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/UpdateLoadAtAllLevels.java b/jsprit-core/src/main/java/algorithms/UpdateLoadAtAllLevels.java
new file mode 100644
index 00000000..5de4cdc2
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/UpdateLoadAtAllLevels.java
@@ -0,0 +1,45 @@
+package algorithms;
+
+import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
+import algorithms.StateManager.StateImpl;
+import basics.route.End;
+import basics.route.Start;
+import basics.route.TourActivity;
+import basics.route.VehicleRoute;
+
+/**
+ * It does not update start and end activities.
+ *
+ * @author stefan
+ *
+ */
+class UpdateLoadAtAllLevels implements ForwardInTimeListener{
+
+ private double load = 0.0;
+
+ private StateManagerImpl states;
+
+ private VehicleRoute vehicleRoute;
+
+ public UpdateLoadAtAllLevels(StateManagerImpl states) {
+ super();
+ this.states = states;
+ }
+
+ @Override
+ public void start(VehicleRoute route, Start start, double departureTime) { vehicleRoute = route; }
+
+ @Override
+ public void nextActivity(TourActivity act, double arrTime, double endTime) {
+ load += (double)act.getCapacityDemand();
+ states.putActivityState(act, StateTypes.LOAD, new StateImpl(load));
+ }
+
+ @Override
+ public void end(End end, double arrivalTime) {
+ states.putRouteState(vehicleRoute, StateTypes.LOAD, new StateImpl(load));
+ load=0;
+ vehicleRoute = null;
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/UpdateLoadAtRouteLevel.java b/jsprit-core/src/main/java/algorithms/UpdateLoadAtRouteLevel.java
new file mode 100644
index 00000000..5ed2adc1
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/UpdateLoadAtRouteLevel.java
@@ -0,0 +1,42 @@
+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;
+
+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 vehicleRoutes, Collection 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));
+ }
+
+ }
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/UpdateStates.java b/jsprit-core/src/main/java/algorithms/UpdateStates.java
new file mode 100644
index 00000000..0d61558d
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/UpdateStates.java
@@ -0,0 +1,55 @@
+package algorithms;
+
+import java.util.Collection;
+
+import algorithms.RuinStrategy.RuinListener;
+import basics.Job;
+import basics.algo.JobInsertedListener;
+import basics.costs.VehicleRoutingActivityCosts;
+import basics.costs.VehicleRoutingTransportCosts;
+import basics.route.VehicleRoute;
+
+class UpdateStates implements JobInsertedListener, RuinListener{
+
+ private IterateRouteForwardInTime iterateForward;
+
+ private IterateRouteBackwardInTime iterateBackward;
+
+ public UpdateStates(StateManagerImpl states, VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts) {
+
+ iterateForward = new IterateRouteForwardInTime(routingCosts);
+ iterateForward.addListener(new UpdateActivityTimes());
+ iterateForward.addListener(new UpdateCostsAtAllLevels(activityCosts, routingCosts, states));
+ iterateForward.addListener(new UpdateLoadAtAllLevels(states));
+// iterateForward.addListener(new UpdateEarliestStartTimeWindowAtActLocations(states));
+
+ iterateBackward = new IterateRouteBackwardInTime(routingCosts);
+ iterateBackward.addListener(new UpdateLatestOperationStartTimeAtActLocations(states));
+ }
+
+ public void update(VehicleRoute route){
+ iterateForward.iterate(route);
+ iterateBackward.iterate(route);
+ }
+
+ @Override
+ public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
+ iterateForward.iterate(inRoute);
+ iterateBackward.iterate(inRoute);
+ }
+
+ @Override
+ public void ruinStarts(Collection routes) {}
+
+ @Override
+ public void ruinEnds(Collection routes,Collection unassignedJobs) {
+ for(VehicleRoute route : routes) {
+ iterateForward.iterate(route);
+ iterateBackward.iterate(route);
+ }
+ }
+
+ @Override
+ public void removed(Job job, VehicleRoute fromRoute) {}
+
+}
diff --git a/jsprit-core/src/main/java/algorithms/UpdateTourStatesBackwardInTime.java b/jsprit-core/src/main/java/algorithms/UpdateTourStatesBackwardInTime.java
deleted file mode 100644
index 19a8d5e3..00000000
--- a/jsprit-core/src/main/java/algorithms/UpdateTourStatesBackwardInTime.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 Stefan Schroeder.
- * eMail: stefan.schroeder@kit.edu
- *
- * 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
- *
- * Contributors:
- * Stefan Schroeder - initial API and implementation
- ******************************************************************************/
-package algorithms;
-
-import java.util.Iterator;
-
-import org.apache.log4j.Logger;
-
-import algorithms.RouteStates.ActivityState;
-import basics.costs.BackwardTransportTime;
-import basics.route.Start;
-import basics.route.TourActivities;
-import basics.route.TourActivity;
-import basics.route.VehicleRoute;
-
-
-
-
-
-
-/**
- *
- * @author stefan schroeder
- *
- */
-
-class UpdateTourStatesBackwardInTime implements VehicleRouteUpdater{
-
-// public static Counter counter = new Counter("#updateTWProcesses: ");
-
- private static Logger log = Logger.getLogger(UpdateTourStatesBackwardInTime.class);
-
- public boolean checkFeasibility = true;
-
- private BackwardTransportTime transportTime;
-
- private RouteStates actStates;
-
- public void setActivityStates(RouteStates actStates){
- this.actStates = actStates;
- }
-
- public ActivityState state(TourActivity act){
- return actStates.getState(act);
- }
-
- public UpdateTourStatesBackwardInTime(BackwardTransportTime transportTime) {
- super();
- this.transportTime = transportTime;
- }
-
- /*
- *
- */
- public boolean updateRoute(VehicleRoute vehicleRoute) {
- boolean ok = update(vehicleRoute);
- return ok;
- }
-
-
-
- private boolean update(VehicleRoute vehicleRoute) {
- TourActivities tour = vehicleRoute.getTourActivities();
- int tourSize = tour.getActivities().size();
- Iterator reverseActIter = vehicleRoute.getTourActivities().reverseActivityIterator();
- TourActivity prevAct;
- boolean feasible = true;
- prevAct = vehicleRoute.getEnd();
- double startAtPrevAct = prevAct.getTheoreticalLatestOperationStartTime();
- int count = 0;
- while(reverseActIter.hasNext()){
- TourActivity currAct = reverseActIter.next();
-
- double latestOperationStartTime = latestOperationStartTime(vehicleRoute, prevAct, currAct, startAtPrevAct);
- ActivityState state = state(currAct);
- state.setLatestOperationStart(latestOperationStartTime);
- prevAct = currAct;
- startAtPrevAct = latestOperationStartTime;
- count++;
- }
-// Start start = vehicleRoute.getStart();
-// double latestOperationStartTime = latestOperationStartTime(vehicleRoute, prevAct, start, startAtPrevAct);
- assert count == tourSize;
- return feasible;
- }
-
- private double latestOperationStartTime(VehicleRoute vehicleRoute,
- TourActivity prevAct, TourActivity currAct, double startAtPrevAct) {
- double latestDepTimeAtCurrAct = startAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), startAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle());
- double potentialLatestOperationStartTimeAtCurrAct = latestDepTimeAtCurrAct - currAct.getOperationTime();
- double latestOperationStartTime = Math.min(currAct.getTheoreticalLatestOperationStartTime(), potentialLatestOperationStartTimeAtCurrAct);
- return latestOperationStartTime;
- }
-
-}
diff --git a/jsprit-core/src/main/java/algorithms/UpdateTourStatesForwardInTime.java b/jsprit-core/src/main/java/algorithms/UpdateTourStatesForwardInTime.java
deleted file mode 100644
index 96732e5c..00000000
--- a/jsprit-core/src/main/java/algorithms/UpdateTourStatesForwardInTime.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 Stefan Schroeder.
- * eMail: stefan.schroeder@kit.edu
- *
- * 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
- *
- * Contributors:
- * Stefan Schroeder - initial API and implementation
- ******************************************************************************/
-package algorithms;
-
-import org.apache.log4j.Logger;
-
-import algorithms.RouteStates.ActivityState;
-import basics.costs.ForwardTransportCost;
-import basics.costs.ForwardTransportTime;
-import basics.costs.VehicleRoutingActivityCosts;
-import basics.route.Driver;
-import basics.route.End;
-import basics.route.ServiceActivity;
-import basics.route.TourActivities;
-import basics.route.TourActivity;
-import basics.route.Vehicle;
-import basics.route.VehicleRoute;
-
-
-/**
- *
- * @author sschroeder
- *
- */
-
-class UpdateTourStatesForwardInTime implements VehicleRouteUpdater{
-
-// public static Counter counter = new Counter("#updateTWProcesses: ");
- private static Logger log = Logger.getLogger(UpdateTourStatesForwardInTime.class);
-
- public boolean checkFeasibility = true;
-
- private VehicleRoutingActivityCosts activityCost;
-
- private ForwardTransportTime transportTime;
-
- private ForwardTransportCost transportCost;
-
- private RouteStates routeStates;
-
- private boolean activityStatesSet = false;
-
- public void setActivityStates(RouteStates actStates){
- this.routeStates = actStates;
- activityStatesSet = true;
- }
-
- public ActivityState state(TourActivity act){
- return routeStates.getState(act);
- }
-
- public UpdateTourStatesForwardInTime(ForwardTransportTime transportTime, ForwardTransportCost transportCost, VehicleRoutingActivityCosts activityCost) {
- super();
- this.transportTime = transportTime;
- this.transportCost = transportCost;
- this.activityCost = activityCost;
- }
-
- /**
- *
- *
- */
- public boolean updateRoute(VehicleRoute vehicleRoute) {
- vehicleRoute.getVehicleRouteCostCalculator().reset();
-
- Vehicle vehicle = vehicleRoute.getVehicle();
- Driver driver = vehicleRoute.getDriver();
-
- TourActivity prevAct = vehicleRoute.getStart();
-
- double startAtPrevAct = vehicleRoute.getStart().getEndTime();
-
- double totalOperationCost = 0.0;
- int totalLoadPicked = 0;
- int currentLoadState = 0;
-
- for(TourActivity currentAct : vehicleRoute.getTourActivities().getActivities()){
- totalLoadPicked += getPickedLoad(currentAct);
- currentLoadState += getCapDemand(currentAct);
-
- 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();
-
- currentAct.setArrTime(arrivalTimeAtCurrAct);
- currentAct.setEndTime(operationEndTime);
-
- double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
- double actCost = activityCost.getActivityCost(currentAct, arrivalTimeAtCurrAct, driver, vehicle);
-
- vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
- vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
-
- totalOperationCost += transportCost;
- totalOperationCost += actCost;
-
- if(activityStatesSet){
- ActivityState currentState = state(currentAct);
- currentState.setEarliestOperationStart(operationStartTime);
- currentState.setCurrentLoad(currentLoadState);
- currentState.setCurrentCost(totalOperationCost);
- }
-
- prevAct = currentAct;
- startAtPrevAct = operationEndTime;
- }
-
- End currentAct = vehicleRoute.getEnd();
- double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
- double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
- double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
-
- currentAct.setArrTime(arrivalTimeAtCurrAct);
- currentAct.setEndTime(arrivalTimeAtCurrAct);
-
- totalOperationCost += transportCost;
-
- routeStates.getRouteState(vehicleRoute).setCosts(totalOperationCost);
- routeStates.getRouteState(vehicleRoute).setLoad(totalLoadPicked);
-
- vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
-
- vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver());
- vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle());
- vehicleRoute.getVehicleRouteCostCalculator().finish();
- return true;
- }
-
- private int getCapDemand(TourActivity currentAct) {
- return currentAct.getCapacityDemand();
- }
-
- private double getPickedLoad(TourActivity currentAct) {
- if(currentAct instanceof ServiceActivity){
- return currentAct.getCapacityDemand();
- }
-// else if(currentAct instanceof Pickup){
-// return currentAct.getCapacityDemand();
-// }
- return 0.0;
- }
-
-}
diff --git a/jsprit-core/src/main/java/algorithms/VehicleRouteUpdater.java b/jsprit-core/src/main/java/algorithms/VehicleRouteUpdater.java
index ab0efa4e..174bff2a 100644
--- a/jsprit-core/src/main/java/algorithms/VehicleRouteUpdater.java
+++ b/jsprit-core/src/main/java/algorithms/VehicleRouteUpdater.java
@@ -24,6 +24,6 @@ import basics.route.VehicleRoute;
interface VehicleRouteUpdater {
- public boolean updateRoute(VehicleRoute vehicleRoute);
+ public void iterate(VehicleRoute vehicleRoute);
}
diff --git a/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java b/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java
index 71631a38..0f52a27c 100644
--- a/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java
+++ b/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java
@@ -36,7 +36,8 @@ import org.apache.commons.configuration.XMLConfiguration;
import org.apache.log4j.Logger;
import util.RouteUtils;
-import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractInsertionKey;
+import algorithms.RuinStrategy.RuinListener;
+import algorithms.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.RuinStrategyKey;
@@ -56,19 +57,21 @@ import basics.VehicleRoutingProblem.FleetSize;
import basics.VehicleRoutingProblemSolution;
import basics.algo.AlgorithmStartsListener;
import basics.algo.InsertionListener;
+import basics.algo.IterationStartsListener;
import basics.algo.IterationWithoutImprovementBreaker;
import basics.algo.PrematureAlgorithmBreaker;
import basics.algo.SearchStrategy;
+import basics.algo.SearchStrategy.DiscoveredSolution;
import basics.algo.SearchStrategyManager;
import basics.algo.SearchStrategyModule;
import basics.algo.SearchStrategyModuleListener;
import basics.algo.TimeBreaker;
import basics.algo.VariationCoefficientBreaker;
-import basics.algo.SearchStrategy.DiscoveredSolution;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
import basics.io.AlgorithmConfig;
import basics.io.AlgorithmConfigXmlReader;
+import basics.route.VehicleRoute;
@@ -258,11 +261,11 @@ public class VehicleRoutingAlgorithms {
}
- static class AbstractInsertionKey implements AbstractKey{
+ static class InsertionStrategyKey implements AbstractKey{
private ModKey modKey;
- public AbstractInsertionKey(ModKey modKey) {
+ public InsertionStrategyKey(ModKey modKey) {
super();
this.modKey = modKey;
}
@@ -284,7 +287,7 @@ public class VehicleRoutingAlgorithms {
return false;
if (getClass() != obj.getClass())
return false;
- AbstractInsertionKey other = (AbstractInsertionKey) obj;
+ InsertionStrategyKey other = (InsertionStrategyKey) obj;
if (modKey == null) {
if (other.modKey != null)
return false;
@@ -296,8 +299,8 @@ public class VehicleRoutingAlgorithms {
@Override
- public Class getType() {
- return AbstractInsertionStrategy.class;
+ public Class getType() {
+ return InsertionStrategy.class;
}
}
@@ -445,9 +448,21 @@ public class VehicleRoutingAlgorithms {
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier()));
- RouteStates routeStates = new RouteStates();
- routeStates.initialiseStateOfJobs(vrp.getJobs().values());
- algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, routeStates));
+ final StateManagerImpl routeStates = new StateManagerImpl();
+ IterationStartsListener resetStates = new IterationStartsListener() {
+
+ @Override
+ public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection solutions) {
+ routeStates.clear();
+ }
+ };
+ algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, resetStates));
+
+// insertionListeners.add(new UdateCostsAtRouteLevel(routeStates,vrp.getTransportCosts(),vrp.getActivityCosts()));
+
+// RouteStates routeStates = new RouteStates();
+// routeStates.initialiseStateOfJobs(vrp.getJobs().values());
+// algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, routeStates));
TypedMap definedClasses = new TypedMap();
@@ -533,16 +548,14 @@ public class VehicleRoutingAlgorithms {
private static void registerInsertionListeners(TypedMap definedClasses, List insertionListeners) {
for(AbstractKey> key : definedClasses.keySet()){
- if(key instanceof AbstractInsertionKey){
- AbstractInsertionKey insertionKey = (AbstractInsertionKey) key;
- AbstractInsertionStrategy insertionStrategy = definedClasses.get(insertionKey);
+ if(key instanceof InsertionStrategyKey){
+ InsertionStrategyKey insertionKey = (InsertionStrategyKey) key;
+ InsertionStrategy insertionStrategy = definedClasses.get(insertionKey);
for(InsertionListener l : insertionListeners){
- // log.info("add insertionListener " + l + " to " + insertionStrategy);
insertionStrategy.addListener(l);
}
}
}
- // log.warn("cannot register insertion listeners yet");
}
private static String getName(HierarchicalConfiguration strategyConfig) {
@@ -557,7 +570,7 @@ public class VehicleRoutingAlgorithms {
metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners);
}
- private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, RouteStates activityStates, Set algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
+ private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, Set algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
List modConfigs = config.configurationsAt("construction.insertion");
if(modConfigs == null) return null;
if(modConfigs.isEmpty()) return null;
@@ -568,15 +581,15 @@ public class VehicleRoutingAlgorithms {
String insertionId = modConfig.getString("[@id]");
if(insertionId == null) insertionId = "noId";
ModKey modKey = makeKey(insertionName,insertionId);
- AbstractInsertionKey insertionStrategyKey = new AbstractInsertionKey(modKey);
- AbstractInsertionStrategy insertionStrategy = definedClasses.get(insertionStrategyKey);
+ InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(modKey);
+ InsertionStrategy insertionStrategy = definedClasses.get(insertionStrategyKey);
if(insertionStrategy == null){
List prioListeners = new ArrayList();
- insertionStrategy = createInsertionStrategy(modConfig, vrp, vehicleFleetManager, activityStates, prioListeners, executorService, nuOfThreads);
+ insertionStrategy = createInsertionStrategy(modConfig, vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads);
algorithmListeners.addAll(prioListeners);
definedClasses.put(insertionStrategyKey,insertionStrategy);
}
- final AbstractInsertionStrategy finalInsertionStrategy = insertionStrategy;
+ final InsertionStrategy finalInsertionStrategy = insertionStrategy;
return new AlgorithmStartsListener() {
@@ -653,8 +666,8 @@ public class VehicleRoutingAlgorithms {
}
}
- private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager,
- RouteStates activityStates, Set algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
+ private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager,
+ final StateManagerImpl routeStates, Set algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
String moduleName = moduleConfig.getString("[@name]");
if(moduleName == null) throw new IllegalStateException("module(-name) is missing.");
String moduleId = moduleConfig.getString("[@id]");
@@ -675,7 +688,7 @@ public class VehicleRoutingAlgorithms {
final RuinStrategy ruin;
ModKey ruinKey = makeKey(ruin_name,ruin_id);
if(ruin_name.equals("randomRuin")){
- ruin = getRandomRuin(vrp, activityStates, definedClasses, ruinKey, shareToRuin);
+ ruin = getRandomRuin(vrp, routeStates, definedClasses, ruinKey, shareToRuin);
}
else if(ruin_name.equals("radialRuin")){
String ruin_distance = moduleConfig.getString("ruin.distance");
@@ -688,7 +701,7 @@ public class VehicleRoutingAlgorithms {
else throw new IllegalStateException("does not know ruin.distance " + ruin_distance + ". either ommit ruin.distance then the "
+ "default is used or use 'euclidean'");
}
- ruin = getRadialRuin(vrp, activityStates, definedClasses, ruinKey, shareToRuin, jobDistance);
+ ruin = getRadialRuin(vrp, routeStates, definedClasses, ruinKey, shareToRuin, jobDistance);
}
else throw new IllegalStateException("ruin[@name] " + ruin_name + " is not known. Use either randomRuin or radialRuin.");
@@ -697,16 +710,16 @@ public class VehicleRoutingAlgorithms {
String insertionId = moduleConfig.getString("insertion[@id]");
if(insertionId == null) insertionId = "noId";
ModKey insertionKey = makeKey(insertionName,insertionId);
- AbstractInsertionKey insertionStrategyKey = new AbstractInsertionKey(insertionKey);
- AbstractInsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
+ InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(insertionKey);
+ InsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
if(insertion == null){
List insertionConfigs = moduleConfig.configurationsAt("insertion");
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
List prioListeners = new ArrayList();
- insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, activityStates, prioListeners, executorService, nuOfThreads);
+ insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads);
algorithmListeners.addAll(prioListeners);
}
- final AbstractInsertionStrategy final_insertion = insertion;
+ final InsertionStrategy final_insertion = insertion;
SearchStrategyModule module = new SearchStrategyModule() {
private Logger logger = Logger.getLogger(SearchStrategyModule.class);
@@ -714,7 +727,7 @@ public class VehicleRoutingAlgorithms {
@Override
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
Collection ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
- final_insertion.run(vrpSolution.getRoutes(), ruinedJobs, Double.MAX_VALUE);
+ final_insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobs);
double totalCost = RouteUtils.getTotalCost(vrpSolution.getRoutes());
vrpSolution.setCost(totalCost);
return vrpSolution;
@@ -734,7 +747,7 @@ public class VehicleRoutingAlgorithms {
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
if(moduleListener instanceof InsertionListener){
InsertionListener iListener = (InsertionListener) moduleListener;
- if(!final_insertion.getListener().contains(iListener)){
+ if(!final_insertion.getListeners().contains(iListener)){
logger.info("register moduleListener " + moduleListener);
final_insertion.addListener(iListener);
}
@@ -746,41 +759,42 @@ public class VehicleRoutingAlgorithms {
return module;
}
- if(moduleName.equals("gendreauPostOpt")){
+ if(moduleName.equals("gendreau")){
int iterations = moduleConfig.getInt("iterations");
double share = moduleConfig.getDouble("share");
String ruinName = moduleConfig.getString("ruin[@name]");
- if(ruinName == null) throw new IllegalStateException("gendreauPostOpt.ruin[@name] is missing. set it to \"radialRuin\" or \"randomRuin\"");
+ if(ruinName == null) throw new IllegalStateException("gendreau.ruin[@name] is missing. set it to \"radialRuin\" or \"randomRuin\"");
String ruinId = moduleConfig.getString("ruin[@id]");
if(ruinId == null) ruinId = "noId";
ModKey ruinKey = makeKey(ruinName,ruinId);
RuinStrategyKey stratKey = new RuinStrategyKey(ruinKey);
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
- ruin = RuinRadial.newInstance(vrp, 0.3, new JobDistanceAvgCosts(vrp.getTransportCosts()), new JobRemoverImpl(), new TourStateUpdater(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
+ ruin = new RuinRadial(vrp, 0.3, new JobDistanceAvgCosts(vrp.getTransportCosts()));
+ ruin.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
definedClasses.put(stratKey, ruin);
}
String insertionName = moduleConfig.getString("insertion[@name]");
- if(insertionName == null) throw new IllegalStateException("gendreauPostOpt.insertion[@name] is missing. set it to \"regretInsertion\" or \"bestInsertion\"");
+ if(insertionName == null) throw new IllegalStateException("gendreau.insertion[@name] is missing. set it to \"regretInsertion\" or \"bestInsertion\"");
String insertionId = moduleConfig.getString("insertion[@id]");
if(insertionId == null) insertionId = "noId";
ModKey insertionKey = makeKey(insertionName,insertionId);
- AbstractInsertionKey insertionStrategyKey = new AbstractInsertionKey(insertionKey);
- AbstractInsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
+ InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(insertionKey);
+ InsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
if(insertion == null){
List insertionConfigs = moduleConfig.configurationsAt("insertion");
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
List prioListeners = new ArrayList();
- insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, activityStates, prioListeners, executorService, nuOfThreads);
+ insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads);
algorithmListeners.addAll(prioListeners);
}
- GendreauPostOpt postOpt = new GendreauPostOpt(vrp, ruin, insertion);
- postOpt.setShareOfJobsToRuin(share);
- postOpt.setNuOfIterations(iterations);
- postOpt.setFleetManager(vehicleFleetManager);
- definedClasses.put(strategyModuleKey, postOpt);
- return postOpt;
+ Gendreau gendreau = new Gendreau(vrp, ruin, insertion);
+ gendreau.setShareOfJobsToRuin(share);
+ gendreau.setNuOfIterations(iterations);
+ gendreau.setFleetManager(vehicleFleetManager);
+ definedClasses.put(strategyModuleKey, gendreau);
+ return gendreau;
}
throw new NullPointerException("no module found with moduleName=" + moduleName +
"\n\tcheck config whether the correct names are used" +
@@ -791,30 +805,30 @@ public class VehicleRoutingAlgorithms {
"\n\tgendreauPostOpt");
}
- private static RuinStrategy getRadialRuin(VehicleRoutingProblem vrp, RouteStates activityStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) {
+ private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StateManagerImpl routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) {
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
- ruin = RuinRadial.newInstance(vrp, shareToRuin, jobDistance, new JobRemoverImpl(), new TourStateUpdater(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
+ ruin = new RuinRadial(vrp, shareToRuin, jobDistance);
+ ruin.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
definedClasses.put(stratKey, ruin);
}
return ruin;
}
- private static RuinStrategy getRandomRuin(VehicleRoutingProblem vrp,
- RouteStates activityStates, TypedMap definedClasses,
- ModKey modKey, double shareToRuin) {
+ private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final StateManagerImpl routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) {
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
- ruin = RuinRandom.newInstance(vrp, shareToRuin, new JobRemoverImpl(), new TourStateUpdater(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
+ ruin = new RuinRandom(vrp, shareToRuin);
+ ruin.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
definedClasses.put(stratKey, ruin);
}
return ruin;
}
- private static AbstractInsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, RouteStates activityStates, List algorithmListeners, ExecutorService executorService, int nuOfThreads) {
- AbstractInsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, activityStates, algorithmListeners, executorService, nuOfThreads);
+ private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List algorithmListeners, ExecutorService executorService, int nuOfThreads) {
+ InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads);
return insertion;
}
diff --git a/jsprit-core/src/main/java/algorithms/VehicleSwitched.java b/jsprit-core/src/main/java/algorithms/VehicleSwitched.java
index cd0b6bb4..1ffabe42 100644
--- a/jsprit-core/src/main/java/algorithms/VehicleSwitched.java
+++ b/jsprit-core/src/main/java/algorithms/VehicleSwitched.java
@@ -21,7 +21,8 @@
package algorithms;
import basics.route.Vehicle;
-import algorithms.RouteAlgorithm.VehicleSwitchedListener;
+import basics.route.VehicleRoute;
+
class VehicleSwitched implements VehicleSwitchedListener{
@@ -32,7 +33,7 @@ class VehicleSwitched implements VehicleSwitchedListener{
}
@Override
- public void vehicleSwitched(Vehicle oldVehicle, Vehicle newVehicle) {
+ public void vehicleSwitched(VehicleRoute vehicleRoute, Vehicle oldVehicle, Vehicle newVehicle) {
fleetManager.unlock(oldVehicle);
fleetManager.lock(newVehicle);
}
diff --git a/jsprit-core/src/main/java/algorithms/VehicleSwitchedListener.java b/jsprit-core/src/main/java/algorithms/VehicleSwitchedListener.java
new file mode 100644
index 00000000..a3589f5d
--- /dev/null
+++ b/jsprit-core/src/main/java/algorithms/VehicleSwitchedListener.java
@@ -0,0 +1,11 @@
+package algorithms;
+
+import basics.algo.InsertionListener;
+import basics.route.Vehicle;
+import basics.route.VehicleRoute;
+
+interface VehicleSwitchedListener extends InsertionListener{
+
+ public void vehicleSwitched(VehicleRoute vehicleRoute, Vehicle oldVehicle, Vehicle newVehicle);
+
+}
diff --git a/jsprit-core/src/main/java/basics/algo/InsertionStartsListener.java b/jsprit-core/src/main/java/basics/algo/InsertionStartsListener.java
index a62459cd..8f8ea757 100644
--- a/jsprit-core/src/main/java/basics/algo/InsertionStartsListener.java
+++ b/jsprit-core/src/main/java/basics/algo/InsertionStartsListener.java
@@ -22,10 +22,11 @@ package basics.algo;
import java.util.Collection;
+import basics.Job;
import basics.route.VehicleRoute;
public interface InsertionStartsListener extends InsertionListener {
- public void informInsertionStarts(Collection vehicleRoutes, int nOfJobs2Recreate);
+ public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs);
}
diff --git a/jsprit-core/src/main/java/basics/algo/JobInsertedListener.java b/jsprit-core/src/main/java/basics/algo/JobInsertedListener.java
index 5cce5484..9df55225 100644
--- a/jsprit-core/src/main/java/basics/algo/JobInsertedListener.java
+++ b/jsprit-core/src/main/java/basics/algo/JobInsertedListener.java
@@ -30,5 +30,5 @@ import basics.route.VehicleRoute;
public interface JobInsertedListener extends InsertionListener{
- public void informJobInserted(int nOfJobsStill2Recreate, Job job2insert, VehicleRoute insertedIn);
+ public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime);
}
diff --git a/jsprit-core/src/main/java/basics/io/VrpXMLReader.java b/jsprit-core/src/main/java/basics/io/VrpXMLReader.java
index 308e633a..e7c93c63 100644
--- a/jsprit-core/src/main/java/basics/io/VrpXMLReader.java
+++ b/jsprit-core/src/main/java/basics/io/VrpXMLReader.java
@@ -274,7 +274,7 @@ public class VrpXMLReader{
if(distC != null) typeBuilder.setCostPerDistance(distC);
// if(start != null && end != null) typeBuilder.setTimeSchedule(new TimeSchedule(start, end));
VehicleTypeImpl type = typeBuilder.build();
- types.put(type.typeId, type);
+ types.put(type.getTypeId(), type);
vrpBuilder.addVehicleType(type);
}
diff --git a/jsprit-core/src/main/java/basics/route/End.java b/jsprit-core/src/main/java/basics/route/End.java
index b39aead4..ba3f6f2a 100644
--- a/jsprit-core/src/main/java/basics/route/End.java
+++ b/jsprit-core/src/main/java/basics/route/End.java
@@ -61,12 +61,15 @@ public final class End implements TourActivity {
this.locationId = locationId;
theoretical_earliestOperationStartTime = theoreticalStart;
theoretical_latestOperationStartTime = theoreticalEnd;
+ endTime = theoreticalEnd;
}
public End(End end) {
this.locationId = end.getLocationId();
theoretical_earliestOperationStartTime = end.getTheoreticalEarliestOperationStartTime();
theoretical_latestOperationStartTime = end.getTheoreticalLatestOperationStartTime();
+ arrTime = end.getArrTime();
+ endTime = end.getEndTime();
}
public double getTheoreticalEarliestOperationStartTime() {
diff --git a/jsprit-core/src/main/java/basics/route/PenaltyVehicleType.java b/jsprit-core/src/main/java/basics/route/PenaltyVehicleType.java
index 9963a00c..29582267 100644
--- a/jsprit-core/src/main/java/basics/route/PenaltyVehicleType.java
+++ b/jsprit-core/src/main/java/basics/route/PenaltyVehicleType.java
@@ -26,6 +26,11 @@ public class PenaltyVehicleType implements VehicleType{
return type.getVehicleCostParams();
}
+ @Override
+ public double getMaxVelocity() {
+ return type.getMaxVelocity();
+ }
+
}
diff --git a/jsprit-core/src/main/java/basics/route/TourActivities.java b/jsprit-core/src/main/java/basics/route/TourActivities.java
index eed81154..2524b13b 100644
--- a/jsprit-core/src/main/java/basics/route/TourActivities.java
+++ b/jsprit-core/src/main/java/basics/route/TourActivities.java
@@ -76,15 +76,9 @@ public class TourActivities {
}
private final ArrayList tourActivities = new ArrayList();
-// private final LinkedList tourActivities = new LinkedList();
-// private final TreeList tourActivities = new TreeList();
private final Set jobs = new HashSet();
- private int load = 0;
-
- private double cost = 0.0;
-
private ReverseActivityIterator backward;
private TourActivities(TourActivities tour2copy) {
@@ -125,7 +119,7 @@ public class TourActivities {
}
/**
- * Removes job AND belonging activity from tour.
+ * Removes job AND belonging activity from tour and returns true if job has been removed, otherwise false.
*
* @param job
* @return
diff --git a/jsprit-core/src/main/java/basics/route/VehicleRoute.java b/jsprit-core/src/main/java/basics/route/VehicleRoute.java
index e7bf3814..95c8f3e0 100644
--- a/jsprit-core/src/main/java/basics/route/VehicleRoute.java
+++ b/jsprit-core/src/main/java/basics/route/VehicleRoute.java
@@ -158,6 +158,11 @@ public class VehicleRoute {
start.setEndTime(vehicleDepTime);
}
+ public double getDepartureTime(){
+ if(start == null) throw new IllegalStateException("cannot get departureTime without having a vehicle on this route. use setVehicle(vehicle,departureTime) instead.");
+ return start.getEndTime();
+ }
+
private void setStartAndEnd(Vehicle vehicle, double vehicleDepTime) {
if(!(vehicle instanceof NoVehicle)){
if(start == null && end == null){
diff --git a/jsprit-core/src/main/java/basics/route/VehicleType.java b/jsprit-core/src/main/java/basics/route/VehicleType.java
index e0870532..9558ba62 100644
--- a/jsprit-core/src/main/java/basics/route/VehicleType.java
+++ b/jsprit-core/src/main/java/basics/route/VehicleType.java
@@ -8,6 +8,8 @@ public interface VehicleType {
public String getTypeId();
public int getCapacity();
+
+ public double getMaxVelocity();
public VehicleCostParams getVehicleCostParams();
diff --git a/jsprit-core/src/main/java/basics/route/VehicleTypeImpl.java b/jsprit-core/src/main/java/basics/route/VehicleTypeImpl.java
index aa3a7820..3e62c292 100644
--- a/jsprit-core/src/main/java/basics/route/VehicleTypeImpl.java
+++ b/jsprit-core/src/main/java/basics/route/VehicleTypeImpl.java
@@ -35,6 +35,7 @@ public class VehicleTypeImpl implements VehicleType {
private String id;
private int capacity;
+ private double maxVelo = Double.MAX_VALUE;
/**
* default cost values for default vehicle type
*/
@@ -48,6 +49,8 @@ public class VehicleTypeImpl implements VehicleType {
this.capacity = capacity;
}
+ public VehicleTypeImpl.Builder setMaxVelocity(double inMeterPerSeconds){ this.maxVelo = inMeterPerSeconds; return this; }
+
public VehicleTypeImpl.Builder setFixedCost(double fixedCost) { this.fixedCost = fixedCost; return this; }
public VehicleTypeImpl.Builder setCostPerDistance(double perDistance){ this.perDistance = perDistance; return this; }
@@ -86,9 +89,13 @@ public class VehicleTypeImpl implements VehicleType {
return true;
}
- public final String typeId;
- public final int capacity;
- public final VehicleTypeImpl.VehicleCostParams vehicleCostParams;
+ private final String typeId;
+
+ private final int capacity;
+
+ private final VehicleTypeImpl.VehicleCostParams vehicleCostParams;
+
+ private double maxVelocity;
public static VehicleTypeImpl newInstance(String typeId, int capacity, VehicleTypeImpl.VehicleCostParams para){
return new VehicleTypeImpl(typeId, capacity, para);
@@ -97,6 +104,7 @@ public class VehicleTypeImpl implements VehicleType {
private VehicleTypeImpl(VehicleTypeImpl.Builder builder){
typeId = builder.id;
capacity = builder.capacity;
+ maxVelocity = builder.maxVelo;
vehicleCostParams = new VehicleCostParams(builder.fixedCost, builder.perTime, builder.perDistance);
}
@@ -135,4 +143,9 @@ public class VehicleTypeImpl implements VehicleType {
public String toString() {
return "[typeId="+typeId+"][capacity="+capacity+"]" + vehicleCostParams;
}
+
+ @Override
+ public double getMaxVelocity() {
+ return maxVelocity;
+ }
}
\ No newline at end of file
diff --git a/jsprit-core/src/main/java/util/VehicleRoutingTransportCostsMatrix.java b/jsprit-core/src/main/java/util/VehicleRoutingTransportCostsMatrix.java
index 2832d66c..4410e18f 100644
--- a/jsprit-core/src/main/java/util/VehicleRoutingTransportCostsMatrix.java
+++ b/jsprit-core/src/main/java/util/VehicleRoutingTransportCostsMatrix.java
@@ -10,7 +10,16 @@ import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleTypeImpl.VehicleCostParams;
-
+/**
+ * CostMatrix that allows pre-compiled time and distance-matrices to be considered as {@link VehicleRoutingRoutingCosts}
+ * in the {@link VehicleRoutingProblem}.
+ *
Note that you can also use it with distance matrix only (or time matrix). But ones
+ * you set a particular distance, this expects distance-entries for all relations. This counts also
+ * for a particular time. If the method getTransportCosts(...) is then invoked for a relation, where no distance can be found, an
+ * IllegalStateException will be thrown. Thus if you want to only use distances only, do not use addTransportTime(...).
+ * @author schroeder
+ *
+ */
public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTransportCosts {
static class RelationKey {
@@ -74,7 +83,12 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
}
-
+ /**
+ * Builder that builds the matrix.
+ *
+ * @author schroeder
+ *
+ */
public static class Builder {
private static Logger log = Logger.getLogger(Builder.class);
@@ -84,6 +98,16 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
private Map times = new HashMap();
+ private boolean distancesSet = false;
+
+ private boolean timesSet = false;
+
+ /**
+ * Creates a new builder returning the matrix-builder.
+ *