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

Merge branch 'master' into vrpWithBackhauls

Conflicts:
	jsprit-examples/src/main/java/examples/SolomonExample.java
This commit is contained in:
oblonski 2013-08-25 18:11:40 +02:00
commit f4a7254036
99 changed files with 4371 additions and 2349 deletions

View file

@ -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 <a href="http://www.matsim.org" target="blank_">MATSim</a>
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.
[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/ba53806a8cc8ff439c1a51d152245dee "githalytics.com")](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
[![](https://cruel-carlota.pagodabox.com/ba53806a8cc8ff439c1a51d152245dee "githalytics.com")](http://githalytics.com/jsprit/jsprit)

View file

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

View file

@ -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<InsertionListener> listener = new ArrayList<InsertionListener>();
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<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate){
for(InsertionListener l : listener){
if(l instanceof InsertionStartsListener){
((InsertionStartsListener)l).informInsertionStarts(vehicleRoutes,nOfJobs2Recreate);
}
}
}
public void informInsertionEndsListeners(Collection<VehicleRoute> vehicleRoutes) {
for(InsertionListener l : listener){
if(l instanceof InsertionEndsListener){
((InsertionEndsListener)l).informInsertionEnds(vehicleRoutes);
}
}
}
public Collection<InsertionListener> getListener() {
return Collections.unmodifiableCollection(listener);
}
public void addListener(InsertionListener l){
log.info("add insertion-listener " + l);
listener.add(l);
}
public void addAllListener(List<InsertionListener> list) {
for(InsertionListener l : list) addListener(l);
}
}

View file

@ -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<BackwardInTimeListener> listeners = new ArrayList<BackwardInTimeListener>();
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.
*
* <p>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); }
}
}

View file

@ -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<String, VehicleRoute> 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<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs, double result2beat) {
public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
insertionsListeners.informInsertionStarts(vehicleRoutes,unassignedJobs);
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
Collections.shuffle(unassignedJobList, random);
informInsertionStarts(vehicleRoutes,unassignedJobs.size());
int inserted = 0;
List<String> reasons = new ArrayList<String>();
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<InsertionListener> getListeners() {
return Collections.unmodifiableCollection(insertionsListeners.getListeners());
}
@Override
public void addListener(InsertionListener insertionListener) {
insertionsListeners.addListener(insertionListener);
}
}

View file

@ -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<VehicleRoute> routes = new ArrayList<VehicleRoute>();
}
private static Logger logger = Logger.getLogger(BestInsertionConcurrent.class);
private Random random = RandomNumberGeneration.getRandom();
private RouteAlgorithm routeAlgorithm;
// private ExecutorService executor;
private int nuOfBatches;
private ExecutorCompletionService<Insertion> 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<Insertion>(executor);
}
@Override
public String toString() {
return "[name=concurrentBestInsertion]";
}
@Override
public void run(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs, double result2beat) {
List<Job> unassignedJobList = new ArrayList<Job>(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<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches);
for(final Batch batch : batches){
completionService.submit(new Callable<Insertion>() {
@Override
public Insertion call() throws Exception {
return getBestInsertion(batch,unassignedJob);
}
});
}
try{
for(int i=0;i<batches.size();i++){
Future<Insertion> futureIData = completionService.take();
Insertion insertion = futureIData.get();
if(insertion == null) continue;
if(insertion.getInsertionData().getInsertionCost() < bestInsertionCost){
bestInsertion = insertion;
bestInsertionCost = insertion.getInsertionData().getInsertionCost();
}
}
}
catch(InterruptedException e){
Thread.currentThread().interrupt();
}
catch (ExecutionException e) {
e.printStackTrace();
logger.error(e.getCause().toString());
System.exit(1);
}
if(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<Batch> distributeRoutes(Collection<VehicleRoute> vehicleRoutes, int nuOfBatches) {
List<Batch> batches = new ArrayList<Batch>();
for(int i=0;i<nuOfBatches;i++) batches.add(new Batch());
/*
* if route.size < nuOfBatches add as much routes as empty batches are available
* else add one empty route anyway
*/
// if(vehicleRoutes.size()<nuOfBatches){
// int nOfNewRoutes = nuOfBatches-vehicleRoutes.size();
// for(int i=0;i<nOfNewRoutes;i++){
// vehicleRoutes.add(VehicleRoute.emptyRoute());
//
//
///**
// *
// * @author stefan schroeder
// *
// */
//
//final class BestInsertionConcurrent implements InsertionStrategy{
//
// public static BestInsertionConcurrent newInstance(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads){
// return new BestInsertionConcurrent(routeAlgorithm, executor, nuOfThreads);
// }
//
// static class Batch {
// List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
//
// }
//
// private static Logger logger = Logger.getLogger(BestInsertionConcurrent.class);
//
// private Random random = RandomNumberGeneration.getRandom();
//
// private RouteAlgorithm routeAlgorithm;
//
//// private ExecutorService executor;
//
// private int nuOfBatches;
//
// private ExecutorCompletionService<Insertion> 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<Insertion>(executor);
// }
//
// @Override
// public String toString() {
// return "[name=concurrentBestInsertion]";
// }
//
// @Override
// public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
// List<Job> unassignedJobList = new ArrayList<Job>(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<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches);
//
// for(final Batch batch : batches){
// completionService.submit(new Callable<Insertion>() {
//
// @Override
// public Insertion call() throws Exception {
// return getBestInsertion(batch,unassignedJob);
// }
//
// });
//
// }
//
// try{
// for(int i=0;i<batches.size();i++){
// Future<Insertion> futureIData = completionService.take();
// Insertion insertion = futureIData.get();
// if(insertion == null) continue;
// if(insertion.getInsertionData().getInsertionCost() < bestInsertionCost){
// bestInsertion = insertion;
// bestInsertionCost = insertion.getInsertionData().getInsertionCost();
// }
// }
// }
// catch(InterruptedException e){
// Thread.currentThread().interrupt();
// }
// catch (ExecutionException e) {
// e.printStackTrace();
// logger.error(e.getCause().toString());
// System.exit(1);
// }
//
// if(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<Batch> distributeRoutes(Collection<VehicleRoute> vehicleRoutes, int nuOfBatches) {
// List<Batch> batches = new ArrayList<Batch>();
// for(int i=0;i<nuOfBatches;i++) batches.add(new Batch());
// /*
// * if route.size < nuOfBatches add as much routes as empty batches are available
// * else add one empty route anyway
// */
//// if(vehicleRoutes.size()<nuOfBatches){
//// int nOfNewRoutes = nuOfBatches-vehicleRoutes.size();
//// for(int i=0;i<nOfNewRoutes;i++){
//// vehicleRoutes.add(VehicleRoute.emptyRoute());
//// }
//// }
//// else{
// vehicleRoutes.add(VehicleRoute.emptyRoute());
//// }
// /*
// * distribute routes to batches equally
// */
// int count = 0;
// for(VehicleRoute route : vehicleRoutes){
// if(count == nuOfBatches) count=0;
// batches.get(count).routes.add(route);
// count++;
// }
/*
* distribute routes to batches equally
*/
int count = 0;
for(VehicleRoute route : vehicleRoutes){
if(count == nuOfBatches) count=0;
batches.get(count).routes.add(route);
count++;
}
return batches;
}
@Override
public RouteAlgorithm getRouteAlgorithm() {
return routeAlgorithm;
}
}
// return batches;
// }
//
//
// @Override
// public void removeListener(InsertionListener insertionListener) {
// // TODO Auto-generated method stub
//
// }
//
// @Override
// public Collection<InsertionListener> getListeners() {
// // TODO Auto-generated method stub
// return null;
// }
//
// @Override
// public void addListener(InsertionListener insertionListener) {
// // TODO Auto-generated method stub
//
// }
//
//}

View file

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

View file

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

View file

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

View file

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

View file

@ -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<memorySize;i++){
InsertionData data = bestInsertionsQueue.poll();
if(data == null){
@ -262,7 +267,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
/**
* compute cost-diff of tour with and without new activity --> insertion_costs
*/
double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - 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<TourActivity> 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();
}
/**

View file

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

View file

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

View file

@ -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<VehicleRoute> routes, int nOfJobs2Recreate) {
double completenessRatio = (1-((double)nOfJobs2Recreate/(double)vrp.getJobs().values().size()));
public void informInsertionStarts(Collection<VehicleRoute> routes, Collection<Job> 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);
}

View file

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

View file

@ -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<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate) {
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
List<VehicleRoute> newRoutes = new ArrayList<VehicleRoute>();
for(VehicleRoute route : vehicleRoutes){
if(route.isEmpty()) continue;

View file

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

View file

@ -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<ForwardInTimeListener> listeners = new ArrayList<ForwardInTimeListeners.ForwardInTimeListener>();
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); }
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads){
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> 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<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();
List<PrioritizedVRAListener> algoListeners = new ArrayList<PrioritizedVRAListener>();
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)));

View file

@ -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<InsertionListener> listeners = new ArrayList<InsertionListener>();
public Collection<InsertionListener> 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<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs){
for(InsertionListener l : listeners){
if(l instanceof InsertionStartsListener){
((InsertionStartsListener)l).informInsertionStarts(vehicleRoutes, unassignedJobs);
}
}
}
public void informInsertionEndsListeners(Collection<VehicleRoute> 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<InsertionListener> listeners) {
for(InsertionListener l : listeners) addListener(l);
}
}

View file

@ -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<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs, double result2beat);
public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
public void addListener(InsertionListener insertionListener);
public void removeListener(InsertionListener insertionListener);
public Collection<InsertionListener> getListeners();
}

View file

@ -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<TourActivity> reverseActIter = vehicleRoute.getTourActivities().reverseActivityIterator();
TourActivity prevAct;
prevAct = vehicleRoute.getEnd();
double latestArrivalTimeAtPrevAct = prevAct.getTheoreticalLatestOperationStartTime();
while(reverseActIter.hasNext()){
TourActivity currAct = reverseActIter.next();
double latestDepTimeAtCurrAct = latestArrivalTimeAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), latestArrivalTimeAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle());
double potentialLatestArrivalTimeAtCurrAct = latestDepTimeAtCurrAct - currAct.getOperationTime();
double latestArrivalTime = Math.min(currAct.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct);
listeners.prevActivity(currAct, latestDepTimeAtCurrAct, latestArrivalTime);
prevAct = currAct;
latestArrivalTimeAtPrevAct = latestArrivalTime;
}
TourActivity currAct = vehicleRoute.getStart();
double latestDepTimeAtCurrAct = latestArrivalTimeAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), latestArrivalTimeAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle());
listeners.end(vehicleRoute.getStart(), latestDepTimeAtCurrAct);
}
public void addListener(BackwardInTimeListener l){ listeners.addListener(l); }
}

View file

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

View file

@ -76,14 +76,14 @@ class JobObserver implements JobInsertedListener, BeforeJobInsertionListener, Al
Collection<Info> infos = new ArrayList<Info>();
@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));

View file

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

View file

@ -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<RemoverListener> remListeners = new ArrayList<RemoverListener>();
@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<RemoverListener> getRemListeners() {
return remListeners;
}
}

View file

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

View file

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

View file

@ -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.
*
* <p>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.
*
* <p>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.
// *
// * <p>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.
// *
// * <p>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();
//// }
//// else
// if(job instanceof Service){
// twStart = ((Service) job).getTimeWindow().getStart();
// twEnd = ((Service) job).getTimeWindow().getEnd();
// }
// else
if(job instanceof Service){
twStart = ((Service) job).getTimeWindow().getStart();
twEnd = ((Service) job).getTimeWindow().getEnd();
}
return (twEnd-twStart)*tw_scoringParam;
}
@Override
public String toString() {
return "[name=timeWindowScorer][scoringParam="+tw_scoringParam+"]";
}
}
public static RegretInsertion newInstance(RouteAlgorithm routeAlgorithm) {
return new RegretInsertion(routeAlgorithm);
}
private Logger logger = Logger.getLogger(RegretInsertion.class);
private RouteAlgorithm routeAlgorithm;
private ScoringFunction scoringFunction = new TimeWindowScorer();
/**
* Sets the scoring function.
*
* <p>By default, the this.TimeWindowScorer is used.
*
* @param scoringFunction
*/
public void setScoringFunction(ScoringFunction scoringFunction) {
this.scoringFunction = scoringFunction;
}
public RegretInsertion(RouteAlgorithm routeAlgorithm) {
super();
this.routeAlgorithm = routeAlgorithm;
logger.info("initialise " + this);
}
@Override
public String toString() {
return "[name=regretInsertion][additionalScorer="+scoringFunction+"]";
}
public RouteAlgorithm getRouteAlgorithm(){
return routeAlgorithm;
}
/**
* Runs insertion.
*
* <p>Before inserting a job, all unassigned jobs are scored according to its best- and secondBest-insertion plus additional scoring variables.
*
*/
@Override
public void run(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs, double resultToBeat) {
List<Job> jobs = new ArrayList<Job>(unassignedJobs);
informInsertionStarts(routes,unassignedJobs.size());
int inserted = 0;
while(!jobs.isEmpty()){
List<Job> unassignedJobList = new ArrayList<Job>(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((unassignedJobList.size()-inserted), 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);
}
}
// return (twEnd-twStart)*tw_scoringParam;
// }
//
// @Override
// public String toString() {
// return "[name=timeWindowScorer][scoringParam="+tw_scoringParam+"]";
// }
//
// }
//
// public static RegretInsertion newInstance(RouteAlgorithm routeAlgorithm) {
// return new RegretInsertion(routeAlgorithm);
// }
//
// private Logger logger = Logger.getLogger(RegretInsertion.class);
//
// private RouteAlgorithm routeAlgorithm;
//
// private ScoringFunction scoringFunction = new TimeWindowScorer();
//
// /**
// * Sets the scoring function.
// *
// * <p>By default, the this.TimeWindowScorer is used.
// *
// * @param scoringFunction
// */
// public void setScoringFunction(ScoringFunction scoringFunction) {
// this.scoringFunction = scoringFunction;
// }
//
// public RegretInsertion(RouteAlgorithm routeAlgorithm) {
// super();
// this.routeAlgorithm = routeAlgorithm;
// logger.info("initialise " + this);
// }
//
// @Override
// public String toString() {
// return "[name=regretInsertion][additionalScorer="+scoringFunction+"]";
// }
//
// public RouteAlgorithm getRouteAlgorithm(){
// return routeAlgorithm;
// }
//
// /**
// * Runs insertion.
// *
// * <p>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<VehicleRoute> routes, Collection<Job> unassignedJobs) {
// List<Job> jobs = new ArrayList<Job>(unassignedJobs);
//// informInsertionStarts(routes,unassignedJobs);
// int inserted = 0;
// while(!jobs.isEmpty()){
// List<Job> unassignedJobList = new ArrayList<Job>(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<InsertionListener> getListeners() {
// // TODO Auto-generated method stub
// return null;
// }
//
// @Override
// public void addListener(InsertionListener insertionListener) {
// // TODO Auto-generated method stub
//
// }
//
//}

View file

@ -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<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate) {
// List<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
// for(VehicleRoute route : routes){
// if(route.isEmpty()) { vehicleRoutes.remove(route); }
// }
// List<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
// for(VehicleRoute route : routes){
// if(route.isEmpty()) {
// fleetManager.unlock(route.getVehicle());
// vehicleRoutes.remove(route);
// }
// }
}
@Override
public String toString() {
return "[name=removeEmptyVehicles]";

View file

@ -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<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate) {
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
vehicleFleetManager.unlockAll();
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
for(VehicleRoute route : routes){
if(route.isEmpty()){
vehicleRoutes.remove(route);
}
else{
// if(route.isEmpty()){
// vehicleRoutes.remove(route);
// }
// else{
vehicleFleetManager.lock(route.getVehicle());
}
// }
}
}

View file

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

View file

@ -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<RouteAlgorithmListener> listeners = new ArrayList<RouteAlgorithmListener>();
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<RouteAlgorithmListener> getListeners() {
return listeners;
}
public void setAlgoDescription(String algoDescription) {
this.algoDescription = algoDescription;
}
}

View file

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

View file

@ -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<RuinListener> ruinListeners = new ArrayList<RuinListener>();
void ruinStarts(Collection<VehicleRoute> routes){
for(RuinListener l : ruinListeners) l.ruinStarts(routes);
}
void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs){
for(RuinListener l : ruinListeners) l.ruinEnds(routes, unassignedJobs);
}
void removed(Job job, VehicleRoute fromRoute){
for(RuinListener l : ruinListeners) l.removed(job, fromRoute);
}
void addListener(RuinListener ruinListener){
ruinListeners.add(ruinListener);
}
void removeListener(RuinListener ruinListener){
ruinListeners.remove(ruinListener);
}
Collection<RuinListener> getListeners(){
return Collections.unmodifiableCollection(ruinListeners);
}
}

View file

@ -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<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved){
ruinListeners.ruinStarts(vehicleRoutes);
List<Job> unassignedJobs = new ArrayList<Job>();
TreeSet<ReferencedJob> tree = distanceNodeTree.get(targetJob.getId());
Iterator<ReferencedJob> 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<RuinListener> getListeners() {
return ruinListeners.getListeners();
}
}

View file

@ -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<Job> ruin(Collection<VehicleRoute> vehicleRoutes) {
ruinListeners.ruinStarts(vehicleRoutes);
List<Job> unassignedJobs = new ArrayList<Job>();
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<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
ruinListeners.ruinStarts(vehicleRoutes);
List<Job> unassignedJobs = new ArrayList<Job>();
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<VehicleRoute> vehicleRoutes,int nOfJobs2BeRemoved, List<Job> unassignedJobs) {
private void ruin(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2BeRemoved, List<Job> unassignedJobs) {
LinkedList<Job> availableJobs = new LinkedList<Job>(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<VehicleRoute> 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<RuinListener> getListeners() {
return ruinListeners.getListeners();
}
}

View file

@ -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<VehicleRoute> routes);
/**
* informs about ruin-end.
*
* @param routes
* @param unassignedJobs
*/
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs);
/**
* informs if a {@link Job} has been removed from a {@link VehicleRoute}.
*
* @param job
* @param fromRoute
*/
public void removed(Job job, VehicleRoute fromRoute);
}
/**
* Ruins a current solution, i.e. 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<Job> ruin(Collection<VehicleRoute> vehicleRoutes);
/**
* Removes targetJob as well as its neighbors with a size of (nOfJobs2BeRemoved-1).
*/
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved);
/**
* Adds a ruin-listener.
*
* @param {@link RuinListener}
*/
public void addListener(RuinListener ruinListener);
public void removeListener(RuinListener ruinListener);
public Collection<RuinListener> getListeners();
}

View file

@ -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<VehicleRoute, States> getRouteStates();
// void put(VehicleRoute route, States states);
// Map<TourActivity, States> getActivityStates();
// void put(TourActivity act, States states);
State getActivityState(TourActivity act, String stateType);
State getRouteState(VehicleRoute route, String stateType);
}

View file

@ -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<String,State> states = new HashMap<String, State>();
public void putState(String key, State state) {
states.put(key, state);
}
@Override
public State getState(String key) {
return states.get(key);
}
}
private Map<VehicleRoute,States> vehicleRouteStates = new HashMap<VehicleRoute, StateManager.States>();
private Map<TourActivity,States> activityStates = new HashMap<TourActivity, StateManager.States>();
public Map<VehicleRoute, States> 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<TourActivity, States> 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);
}
}

View file

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

View file

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

View file

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

View file

@ -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<VehicleRoute> vehicleRoutes, Collection<Job> 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<VehicleRoute> vehicleRoutes) {
// IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts);
// forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
for(VehicleRoute route : vehicleRoutes){
if(route.isEmpty()) continue;
route.getVehicleRouteCostCalculator().reset();
route.getVehicleRouteCostCalculator().addOtherCost(states.getRouteState(route, StateTypes.COSTS).toDouble());
route.getVehicleRouteCostCalculator().price(route.getVehicle());
// forwardInTime.iterate(route);
}
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
int load = 0;
for(Job j : route.getTourActivities().getJobs()){
load += j.getCapacityDemand();
}
states.putRouteState(route, StateTypes.LOAD, new StateImpl(load));
}
}
}

View file

@ -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<VehicleRoute> routes) {}
@Override
public void ruinEnds(Collection<VehicleRoute> routes,Collection<Job> unassignedJobs) {
for(VehicleRoute route : routes) {
iterateForward.iterate(route);
iterateBackward.iterate(route);
}
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {}
}

View file

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

View file

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

View file

@ -24,6 +24,6 @@ import basics.route.VehicleRoute;
interface VehicleRouteUpdater {
public boolean updateRoute(VehicleRoute vehicleRoute);
public void iterate(VehicleRoute vehicleRoute);
}

View file

@ -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<AbstractInsertionStrategy>{
static class InsertionStrategyKey implements AbstractKey<InsertionStrategy>{
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<AbstractInsertionStrategy> getType() {
return AbstractInsertionStrategy.class;
public Class<InsertionStrategy> 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<VehicleRoutingProblemSolution> 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<InsertionListener> 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<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
List<HierarchicalConfiguration> 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<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
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<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager,
final StateManagerImpl routeStates, Set<PrioritizedVRAListener> 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<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
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<Job> 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<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
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<PrioritizedVRAListener> 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<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads) {
InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads);
return insertion;
}

View file

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

View file

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

View file

@ -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<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate);
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
}

View file

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

View file

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

View file

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

View file

@ -26,6 +26,11 @@ public class PenaltyVehicleType implements VehicleType{
return type.getVehicleCostParams();
}
@Override
public double getMaxVelocity() {
return type.getMaxVelocity();
}
}

View file

@ -76,15 +76,9 @@ public class TourActivities {
}
private final ArrayList<TourActivity> tourActivities = new ArrayList<TourActivity>();
// private final LinkedList<TourActivity> tourActivities = new LinkedList<TourActivity>();
// private final TreeList tourActivities = new TreeList();
private final Set<Job> jobs = new HashSet<Job>();
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

View file

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

View file

@ -8,6 +8,8 @@ public interface VehicleType {
public String getTypeId();
public int getCapacity();
public double getMaxVelocity();
public VehicleCostParams getVehicleCostParams();

View file

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

View file

@ -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}.
* <p>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<RelationKey,Double> times = new HashMap<RelationKey, Double>();
private boolean distancesSet = false;
private boolean timesSet = false;
/**
* Creates a new builder returning the matrix-builder.
* <p>If you want to consider symmetric matrices, set isSymmetric to true.
* @param isSymmetric
* @return
*/
public static Builder newInstance(boolean isSymmetric){
return new Builder(isSymmetric);
}
@ -92,8 +116,16 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
this.isSymmetric = isSymmetric;
}
/**
* Adds a transport-distance for a particular relation.
* @param from
* @param to
* @param distance
* @return
*/
public Builder addTransportDistance(String from, String to, double distance){
RelationKey key = RelationKey.newKey(from, to);
if(!distancesSet) distancesSet = true;
if(distances.containsKey(key)){
log.warn("distance from " + from + " to " + to + " already exists. This overrides distance.");
}
@ -101,8 +133,16 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
return this;
}
/**
* Adds transport-time for a particular relation.
* @param from
* @param to
* @param time
* @return
*/
public Builder addTransportTime(String from, String to, double time){
RelationKey key = RelationKey.newKey(from, to);
if(!timesSet) timesSet = true;
if(times.containsKey(key)){
log.warn("transport-time from " + from + " to " + to + " already exists. This overrides distance.");
}
@ -110,6 +150,10 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
return this;
}
/**
* Builds the matrix.
* @return
*/
public VehicleRoutingTransportCostsMatrix build(){
return new VehicleRoutingTransportCostsMatrix(this);
}
@ -121,10 +165,16 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
private boolean isSymmetric;
private boolean timesSet;
private boolean distancesSet;
private VehicleRoutingTransportCostsMatrix(Builder builder){
this.isSymmetric = builder.isSymmetric;
distances.putAll(builder.distances);
times.putAll(builder.times);
timesSet = builder.timesSet;
distancesSet = builder.distancesSet;
}
@ -136,6 +186,7 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
private double getTime(String fromId, String toId) {
if(fromId.equals(toId)) return 0.0;
if(!timesSet) return 0.0;
RelationKey key = RelationKey.newKey(fromId, toId);
if(!isSymmetric){
if(times.containsKey(key)) return times.get(key);
@ -153,6 +204,7 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
private double getDistance(String fromId, String toId) {
if(fromId.equals(toId)) return 0.0;
if(!distancesSet) return 0.0;
RelationKey key = RelationKey.newKey(fromId, toId);
if(!isSymmetric){
if(distances.containsKey(key)) return distances.get(key);

View file

@ -166,14 +166,16 @@
<xs:group name="gendreau_group">
<xs:sequence>
<xs:element name="itertions" type="xs:integer"/>
<xs:element name="iterations" type="xs:integer"/>
<xs:element name="share" type="xs:double"/>
<xs:element name="ruin" type="ruinType"/>
<xs:element name="insertion" type="insertionType"/>
</xs:sequence>
</xs:group>
<xs:complexType name="ruinType">
<xs:sequence>
<xs:element name="share" minOccurs="1" maxOccurs="1">
<xs:element name="share" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:double">
<xs:minInclusive value="0.0"/>

View file

@ -36,7 +36,6 @@ import algorithms.selectors.SelectRandomlyTest;
GendreauPostOptTest.class,
TestAlgorithmReader.class,
// TestAux.class,
TestCalculatesActivityInsertion.class,
TestCalculatesServiceInsertion.class,
TestCalculatesServiceInsertionOnRouteLevel.class,
TestSchrimpf.class,

View file

@ -0,0 +1,99 @@
package algorithms;
import static org.junit.Assert.*;
import java.util.Collection;
import org.junit.Before;
import org.junit.Test;
import util.Solutions;
import algorithms.HardConstraints.HardActivityLevelConstraint;
import algorithms.acceptors.AcceptNewIfBetterThanWorst;
import algorithms.selectors.SelectBest;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.IterationStartsListener;
import basics.algo.SearchStrategy;
import basics.algo.SearchStrategyManager;
import basics.io.VrpXMLReader;
import basics.route.TourActivity;
public class BuildCVRPAlgoFromScratchTest {
VehicleRoutingProblem vrp;
VehicleRoutingAlgorithm vra;
@Before
public void setup(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder).read("src/test/resources/vrpnc1-jsprit.xml");
vrp = builder.build();
final StateManagerImpl stateManager = new StateManagerImpl();
HardActivityLevelConstraint hardActLevelConstraint = new HardActivityLevelConstraint() {
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity act, double arrTime) {
return true;
}
};
MarginalsCalculus marginalCalculus = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), hardActLevelConstraint);
CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardLoadConstraint(stateManager));
VehicleFleetManager fleetManager = new InfiniteVehicles(vrp.getVehicles());
JobInsertionCalculator finalServiceInsertion = new CalculatesVehTypeDepServiceInsertion(fleetManager, serviceInsertion);
BestInsertion bestInsertion = new BestInsertion(finalServiceInsertion);
RuinRadial radial = new RuinRadial(vrp, 0.15, new JobDistanceAvgCosts(vrp.getTransportCosts()));
RuinRandom random = new RuinRandom(vrp, 0.25);
SearchStrategy randomStrategy = new SearchStrategy(new SelectBest(), new AcceptNewIfBetterThanWorst(1));
RuinAndRecreateModule randomModule = new RuinAndRecreateModule("randomRuin_bestInsertion", bestInsertion, random);
randomStrategy.addModule(randomModule);
SearchStrategy radialStrategy = new SearchStrategy(new SelectBest(), new AcceptNewIfBetterThanWorst(1));
RuinAndRecreateModule radialModule = new RuinAndRecreateModule("radialRuin_bestInsertion", bestInsertion, radial);
radialStrategy.addModule(radialModule);
SearchStrategyManager strategyManager = new SearchStrategyManager();
strategyManager.addStrategy(radialStrategy, 0.5);
strategyManager.addStrategy(randomStrategy, 0.5);
vra = new VehicleRoutingAlgorithm(vrp, strategyManager);
//listeners
IterationStartsListener clearStateManager = new IterationStartsListener() {
@Override
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
stateManager.clear();
}
};
vra.getAlgorithmListeners().addListener(clearStateManager);
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(fleetManager));
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UdateCostsAtRouteLevel(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts()));
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateLoadAtRouteLevel(stateManager));
VehicleRoutingProblemSolution iniSolution = new CreateInitialSolution(bestInsertion).createInitialSolution(vrp);
// System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size());
vra.addInitialSolution(iniSolution);
vra.setNuOfIterations(2000);
// vra.setPrematureBreak(200);
}
@Test
public void testVRA(){
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
System.out.println("costs="+Solutions.getBest(solutions).getCost()+";#routes="+Solutions.getBest(solutions).getRoutes().size());
assertEquals(530.0, Solutions.getBest(solutions).getCost(),15.0);
assertEquals(5, Solutions.getBest(solutions).getRoutes().size());
}
}

View file

@ -37,15 +37,16 @@ import basics.Job;
import basics.Service;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver;
import basics.route.DriverImpl;
import basics.route.ServiceActivity;
import basics.route.TimeWindow;
import basics.route.TourActivities;
import basics.route.Vehicle;
import basics.route.VehicleImpl;
import basics.route.VehicleRoute;
import basics.route.VehicleType;
import basics.route.VehicleTypeImpl;
public class GendreauPostOptTest {
@ -60,6 +61,8 @@ public class GendreauPostOptTest {
VehicleRoutingTransportCosts cost;
VehicleRoutingActivityCosts activityCosts;
VehicleRoutingProblem vrp;
Service job1;
@ -68,15 +71,13 @@ public class GendreauPostOptTest {
Service job3;
private RouteStates states;
private StateManagerImpl states;
private List<Vehicle> vehicles;
private TourStateUpdater updater;
private VehicleFleetManagerImpl fleetManager;
private RouteAlgorithmImpl routeAlgorithm;
private JobInsertionCalculator insertionCalc;
@Before
public void setUp(){
@ -146,32 +147,18 @@ public class GendreauPostOptTest {
// Collection<Vehicle> vehicles = Arrays.asList(lightVehicle1,lightVehicle2, heavyVehicle);
fleetManager = new VehicleFleetManagerImpl(vehicles);
states = new RouteStates();
states = new StateManagerImpl();
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
activityCosts = new ExampleActivityCostFunction();
CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(cost, new MarginalsCalculusTriangleInequality(cost, activityCosts, new HardConstraints.HardTimeWindowConstraint(states)), new HardConstraints.HardLoadConstraint(states));
CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(cost, activityCosts);
standardServiceInsertion.setActivityStates(states);
CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(standardServiceInsertion, states);
withFixCost.setWeightOfFixCost(1.2);
final JobInsertionCalculator vehicleTypeDepInsertionCost = new CalculatesVehTypeDepServiceInsertion(fleetManager, withFixCost);
updater = new TourStateUpdater(states, cost, activityCosts);
insertionCalc = new CalculatesVehTypeDepServiceInsertion(fleetManager, withFixCost);
routeAlgorithm = RouteAlgorithmImpl.newInstance(vehicleTypeDepInsertionCost, updater);
routeAlgorithm.setActivityStates(states);
if(fleetManager != null){
routeAlgorithm.getListeners().add(new RouteAlgorithm.VehicleSwitchedListener() {
@Override
public void vehicleSwitched(Vehicle oldVehicle, Vehicle newVehicle) {
fleetManager.unlock(oldVehicle);
fleetManager.lock(newVehicle);
}
});
}
// updater = new TourStateUpdater(states, cost, activityCosts);
}
@ -181,18 +168,19 @@ public class GendreauPostOptTest {
jobs.add(job1);
jobs.add(job2);
states.initialiseStateOfJobs(jobs);
vrp = VehicleRoutingProblem.Builder.newInstance().addAllJobs(jobs).addAllVehicles(vehicles).setRoutingCost(cost).build();
TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(job1, true));
tour.addActivity(states.getActivity(job2, true));
tour.addActivity(ServiceActivity.newInstance(job1));
tour.addActivity(ServiceActivity.newInstance(job2));
VehicleRoute route = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),heavyVehicle);
updater.updateRoute(route);
fleetManager.lock(heavyVehicle);
UpdateStates stateUpdater = new UpdateStates(states, vrp.getTransportCosts(), vrp.getActivityCosts());
stateUpdater.update(route);
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
routes.add(route);
// routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle()));
@ -202,10 +190,16 @@ public class GendreauPostOptTest {
assertEquals(110.0, sol.getCost(), 0.5);
RuinRadial radialRuin = RuinRadial.newInstance(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()), new JobRemoverImpl(), updater);
AbstractInsertionStrategy insertionStrategy = new BestInsertion(routeAlgorithm);
GendreauPostOpt postOpt = new GendreauPostOpt(vrp, radialRuin, insertionStrategy);
RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()));
radialRuin.addListener(stateUpdater);
InsertionStrategy insertionStrategy = new BestInsertion(insertionCalc);
insertionStrategy.addListener(stateUpdater);
insertionStrategy.addListener(new VehicleSwitched(fleetManager));
Gendreau postOpt = new Gendreau(vrp, radialRuin, insertionStrategy);
postOpt.setFleetManager(fleetManager);
VehicleRoutingProblemSolution newSolution = postOpt.runAndGetSolution(sol);
assertEquals(2,RouteUtils.getNuOfActiveRoutes(newSolution.getRoutes()));
@ -220,32 +214,32 @@ public class GendreauPostOptTest {
jobs.add(job2);
jobs.add(job3);
states.initialiseStateOfJobs(jobs);
vrp = VehicleRoutingProblem.Builder.newInstance().addAllJobs(jobs).addAllVehicles(vehicles).setRoutingCost(cost).build();
TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(job1, true));
tour.addActivity(states.getActivity(job2, true));
tour.addActivity(states.getActivity(job3, true));
tour.addActivity(ServiceActivity.newInstance(job1));
tour.addActivity(ServiceActivity.newInstance(job2));
tour.addActivity(ServiceActivity.newInstance(job3));
VehicleRoute route = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),heavyVehicle);
updater.updateRoute(route);
UpdateStates stateUpdater = new UpdateStates(states, vrp.getTransportCosts(), vrp.getActivityCosts());
stateUpdater.update(route);
fleetManager.lock(heavyVehicle);
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
routes.add(route);
// routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle()));
// routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle()));
VehicleRoutingProblemSolution sol = new VehicleRoutingProblemSolution(routes, route.getCost());
assertEquals(110.0, sol.getCost(), 0.5);
RuinRadial radialRuin = RuinRadial.newInstance(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()), new JobRemoverImpl(), updater);
AbstractInsertionStrategy insertionStrategy = new BestInsertion(routeAlgorithm);
GendreauPostOpt postOpt = new GendreauPostOpt(vrp, radialRuin, insertionStrategy);
RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()));
InsertionStrategy insertionStrategy = new BestInsertion(insertionCalc);
insertionStrategy.addListener(stateUpdater);
insertionStrategy.addListener(new VehicleSwitched(fleetManager));
Gendreau postOpt = new Gendreau(vrp, radialRuin, insertionStrategy);
postOpt.setShareOfJobsToRuin(1.0);
postOpt.setNuOfIterations(1);
postOpt.setFleetManager(fleetManager);
@ -256,18 +250,6 @@ public class GendreauPostOptTest {
assertEquals(2,newSolution.getRoutes().size());
assertEquals(80.0,newSolution.getCost(),0.5);
}
private Vehicle getNoVehicle() {
return new VehicleImpl.NoVehicle();
}
private Driver getDriver() {
return DriverImpl.noDriver();
}
private TourActivities getEmptyTour() {
return new TourActivities();
}
private Service getService(String to, double serviceTime) {
Service s = Service.Builder.newInstance(to, 0).setLocationId(to).setServiceTime(serviceTime).setTimeWindow(TimeWindow.newInstance(0.0, 20.0)).build();

View file

@ -0,0 +1,218 @@
package algorithms;
import static org.junit.Assert.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import org.junit.Test;
import util.Solutions;
import util.VehicleRoutingTransportCostsMatrix;
import util.VehicleRoutingTransportCostsMatrix.Builder;
import basics.Service;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblem.FleetSize;
import basics.VehicleRoutingProblemSolution;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleImpl;
import basics.route.VehicleTypeImpl;
public class RefuseCollectionTest {
static class RelationKey {
static RelationKey newKey(String from, String to){
int fromInt = Integer.parseInt(from);
int toInt = Integer.parseInt(to);
if(fromInt < toInt){
return new RelationKey(from, to);
}
else {
return new RelationKey(to, from);
}
}
final String from;
final String to;
public RelationKey(String from, String to) {
super();
this.from = from;
this.to = to;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((from == null) ? 0 : from.hashCode());
result = prime * result + ((to == null) ? 0 : to.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RelationKey other = (RelationKey) obj;
if (from == null) {
if (other.from != null)
return false;
} else if (!from.equals(other.from))
return false;
if (to == null) {
if (other.to != null)
return false;
} else if (!to.equals(other.to))
return false;
return true;
}
}
static class RoutingCosts implements VehicleRoutingTransportCosts {
private Map<RelationKey,Integer> distances;
public RoutingCosts(Map<RelationKey, Integer> distances) {
super();
this.distances = distances;
}
@Override
public double getTransportTime(String fromId, String toId, double departureTime, Driver driver, Vehicle vehicle) {
return getTransportCost(fromId, toId, departureTime, driver, vehicle);
}
@Override
public double getBackwardTransportTime(String fromId, String toId, double arrivalTime, Driver driver, Vehicle vehicle) {
return getTransportCost(fromId, toId, arrivalTime, driver, vehicle);
}
@Override
public double getTransportCost(String fromId, String toId,double departureTime, Driver driver, Vehicle vehicle) {
if(fromId.equals(toId)) return 0.0;
RelationKey key = RelationKey.newKey(fromId, toId);
return distances.get(key);
}
@Override
public double getBackwardTransportCost(String fromId, String toId,double arrivalTime, Driver driver, Vehicle vehicle) {
return getTransportCost(fromId, toId, arrivalTime, driver, vehicle);
}
}
@Test
public void testAlgo(){
/*
* create vehicle-type and vehicle
*/
VehicleTypeImpl.Builder typeBuilder = VehicleTypeImpl.Builder.newInstance("vehicle-type", 23);
typeBuilder.setCostPerDistance(1.0);
VehicleTypeImpl bigType = typeBuilder.build();
VehicleImpl.Builder vehicleBuilder = VehicleImpl.Builder.newInstance("vehicle");
vehicleBuilder.setLocationId("1");
vehicleBuilder.setType(bigType);
Vehicle bigVehicle = vehicleBuilder.build();
/*
* start building the problem
*/
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
vrpBuilder.setFleetSize(FleetSize.INFINITE);
vrpBuilder.addVehicle(bigVehicle);
/*
* create cost-matrix
*/
VehicleRoutingTransportCostsMatrix.Builder matrixBuilder = VehicleRoutingTransportCostsMatrix.Builder.newInstance(true);
/*
* read demand quantities
*/
try {
readDemandQuantities(vrpBuilder);
readDistances(matrixBuilder);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
vrpBuilder.setRoutingCost(matrixBuilder.build());
VehicleRoutingProblem vrp = vrpBuilder.build();
VehicleRoutingAlgorithm vra = new GreedySchrimpfFactory().createAlgorithm(vrp);
vra.setPrematureBreak(100);
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
assertEquals(397.0,Solutions.getBest(solutions).getCost(),0.01);
assertEquals(2,Solutions.getBest(solutions).getRoutes().size());
}
private static void readDemandQuantities(VehicleRoutingProblem.Builder vrpBuilder) throws FileNotFoundException, IOException {
BufferedReader reader = new BufferedReader(new FileReader(new File("src/test/resources/refuseCollectionExample_Quantities")));
String line = null;
boolean firstLine = true;
while((line = reader.readLine()) != null){
if(firstLine) {
firstLine = false;
continue;
}
String[] lineTokens = line.split(",");
/*
* build service
*/
Service service = Service.Builder.newInstance(lineTokens[0], Integer.parseInt(lineTokens[1])).setLocationId(lineTokens[0]).build();
/*
* and add it to problem
*/
vrpBuilder.addService(service);
}
reader.close();
}
private static void readDistances(Builder matrixBuilder) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(new File("src/test/resources/refuseCollectionExample_Distances")));
String line = null;
boolean firstLine = true;
while((line = reader.readLine()) != null){
if(firstLine) {
firstLine = false;
continue;
}
String[] lineTokens = line.split(",");
matrixBuilder.addTransportDistance(lineTokens[0],lineTokens[1], Integer.parseInt(lineTokens[2]));
}
reader.close();
}
}

View file

@ -169,6 +169,24 @@ public class TestAlgorithmReader {
// TODO Auto-generated method stub
return null;
}
@Override
public void addListener(RuinListener ruinListener) {
// TODO Auto-generated method stub
}
@Override
public void removeListener(RuinListener ruinListener) {
// TODO Auto-generated method stub
}
@Override
public Collection<RuinListener> getListeners() {
// TODO Auto-generated method stub
return null;
}
};
@ -233,21 +251,21 @@ public class TestAlgorithmReader {
assertEquals(3, nOfModules);
}
@Test
public void whenCreatingAlgorithm_regretInsertionIsReadCorrectly(){
VehicleRoutingAlgorithm algo = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "src/test/resources/configWithRegretInsertion.xml");
int nOfModules = 0;
for(SearchStrategy strat : algo.getSearchStrategyManager().getStrategies()){
for(SearchStrategyModule module : strat.getSearchStrategyModules()){
if(module.getName().contains("ruin_and_recreate")){
nOfModules++;
}
}
}
assertEquals(3, nOfModules);
}
// @Test
// public void whenCreatingAlgorithm_regretInsertionIsReadCorrectly(){
// VehicleRoutingAlgorithm algo = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "src/test/resources/configWithRegretInsertion.xml");
// int nOfModules = 0;
// for(SearchStrategy strat : algo.getSearchStrategyManager().getStrategies()){
// for(SearchStrategyModule module : strat.getSearchStrategyModules()){
// if(module.getName().contains("ruin_and_recreate")){
// nOfModules++;
// }
// }
//
// }
// assertEquals(3, nOfModules);
//
// }
//
}

View file

@ -1,286 +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 static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import algorithms.RouteStates.ActivityState;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
public class TestCalculatesActivityInsertion {
VehicleRoutingTransportCosts costs;
Vehicle newVehicle;
private RouteStates states;
private CalculatesActivityInsertionWithHardTimeWindows insertionCalculator;
@Before
public void setup(){
costs = mock(VehicleRoutingTransportCosts.class);
newVehicle = mock(Vehicle.class);
when(costs.getTransportCost("depot", "1", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("depot", "2", 0.0, null, null)).thenReturn(20.0);
when(costs.getTransportCost("depot", "3", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("1", "2", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("1", "3", 0.0, null, null)).thenReturn(20.0);
when(costs.getTransportCost("2", "3", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("1", "depot", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("2", "depot", 0.0, null, null)).thenReturn(20.0);
when(costs.getTransportCost("3", "depot", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("2", "1", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("3", "1", 0.0, null, null)).thenReturn(20.0);
when(costs.getTransportCost("3", "2", 0.0, null, null)).thenReturn(10.0);
when(costs.getTransportCost("depot", "1", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("depot", "2", 0.0, null, newVehicle)).thenReturn(40.0);
when(costs.getTransportCost("depot", "3", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("1", "2", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("1", "3", 0.0, null, newVehicle)).thenReturn(40.0);
when(costs.getTransportCost("2", "3", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("1", "depot", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("2", "depot", 0.0, null, newVehicle)).thenReturn(40.0);
when(costs.getTransportCost("3", "depot", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("2", "1", 0.0, null, newVehicle)).thenReturn(20.0);
when(costs.getTransportCost("3", "1", 0.0, null, newVehicle)).thenReturn(40.0);
when(costs.getTransportCost("3", "2", 0.0, null, newVehicle)).thenReturn(20.0);
states = new RouteStates();
insertionCalculator = new CalculatesActivityInsertionWithHardTimeWindows(states,costs,activityCosts());
}
private ExampleActivityCostFunction activityCosts() {
return new ExampleActivityCostFunction();
}
public TourActivity getActivityMock(String id, double earliestOperationStart, double currCost){
TourActivity act = mock(TourActivity.class);
when(act.getLocationId()).thenReturn(id);
states.getActivityStates().put(act, new ActivityState(act));
states.getState(act).setEarliestOperationStart(earliestOperationStart);
states.getState(act).setCurrentCost(currCost);
// when(act.getEarliestOperationStartTime()).thenReturn(earliestOperationStart);
// when(act.getCurrentCost()).thenReturn(currCost);
return act;
}
@Test
public void whenInsertingANewJob_itCalculatesMarginalCostChanges(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity prevAct = getActivityMock("1", 0.0, 10.0);
TourActivity nextAct = getActivityMock("3", 0.0, 30.0);
TourActivity act2insert = getActivityMock("2", 0.0, 0.0);
TourActivity end = getActivityMock("depot", 0.0, 40.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(prevAct);
vehicleRoute.getTourActivities().addActivity(nextAct);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,prevAct,nextAct,end);
when(tour.getActivities()).thenReturn(activities);
// when(states.getRouteState(vehicleRoute).getCosts()).thenReturn(40.0);
double c = insertionCalculator.calculate(vehicleRoute, prevAct, nextAct, act2insert, null, null);
assertEquals(0.0,c,0.2);
}
@Test
public void whenInsertingANewJob_itCalculatesMarginalCostChanges2(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity act1 = getActivityMock("1", 0.0, 10.0);
TourActivity act3 = getActivityMock("3", 0.0, 0.0);
TourActivity act2 = getActivityMock("2", 0.0, 20.0);
TourActivity end = getActivityMock("depot", 0.0, 40.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(act1);
vehicleRoute.getTourActivities().addActivity(act2);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,act1,act2,end);
when(tour.getActivities()).thenReturn(activities);
double c = insertionCalculator.calculate(vehicleRoute, act1, act2, act3, null, null);
assertEquals(20.0,c,0.2);
}
@Test
public void whenInsertingANewJob_itCalculatesMarginalCostChanges3(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity act1 = getActivityMock("1", 0.0, 10.0);
TourActivity act3 = getActivityMock("3", 0.0, 0.0);
TourActivity act2 = getActivityMock("2", 0.0, 0.0);
TourActivity end = getActivityMock("depot", 0.0, 20.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(act1);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,act1,end);
when(tour.getActivities()).thenReturn(activities);
double c = insertionCalculator.calculate(vehicleRoute, start, act1, act3, null, null);
assertEquals(20.0,c,0.2);
}
@Test
public void whenInsertingANewJobWithANewVehicle_itCalculatesLocalMarginalCostChanges(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity act1 = getActivityMock("1", 0.0, 10.0);
TourActivity act3 = getActivityMock("3", 0.0, 0.0);
TourActivity act2 = getActivityMock("2", 0.0, 20.0);
TourActivity end = getActivityMock("depot", 0.0, 40.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(act1);
vehicleRoute.getTourActivities().addActivity(act2);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,act1,act2,end);
when(tour.getActivities()).thenReturn(activities);
double c = insertionCalculator.calculate(vehicleRoute, act1, act2, act3, null, newVehicle);
assertEquals(50.0,c,0.2);
}
@Test
public void whenInsertingANewJobWithANewVehicle_itCalculatesLocalMarginalCostChangesAndAfterInsertionCostChanges(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity act1 = getActivityMock("1", 0.0, 10.0);
TourActivity act3 = getActivityMock("3", 0.0, 0.0);
TourActivity act2 = getActivityMock("2", 0.0, 20.0);
TourActivity end = getActivityMock("depot", 0.0, 40.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(act1);
vehicleRoute.getTourActivities().addActivity(act2);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,act1,act2,end);
when(tour.getActivities()).thenReturn(activities);
double c = insertionCalculator.calculate(vehicleRoute, act1, act2, act3, null, newVehicle);
assertEquals(50.0,c,0.2);
}
//already on route-level
// @Test
// public void whenInsertingANewJobWithANewVehicle_itCalculatesTotalMarginalCostChanges(){
// Tour tour = mock(Tour.class);
// TourActivity start = getActivityMock("depot", 0.0, 0.0);
// TourActivity act1 = getActivityMock("1", 0.0, 10.0);
// TourActivity act3 = getActivityMock("3", 0.0, 0.0);
// TourActivity act2 = getActivityMock("2", 0.0, 20.0);
// TourActivity end = getActivityMock("depot", 0.0, 40.0);
//
// List<TourActivity> activities = Arrays.asList(start,act1,act2,end);
// when(tour.getActivities()).thenReturn(activities);
//
// double c = insertionCalculator.calculate(tour, act1, act2, act3, null, newVehicle);
// assertEquals(80.0,c,0.2);
// }
@Test
public void whenInsertingANewJobWithANewVehicle_itCalculatesTotalMarginalCostChanges2(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity act1 = getActivityMock("1", 0.0, 10.0);
TourActivity act3 = getActivityMock("3", 0.0, 0.0);
TourActivity act2 = getActivityMock("2", 0.0, 20.0);
TourActivity end = getActivityMock("depot", 0.0, 40.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(act1);
vehicleRoute.getTourActivities().addActivity(act2);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,act1,act2,end);
when(tour.getActivities()).thenReturn(activities);
double c = insertionCalculator.calculate(vehicleRoute, act2, end, act3, null, newVehicle);
assertEquals(20.0,c,0.2);
}
@Test
public void whenInsertingANewJobWithANewVehicle_itCalculatesTotalMarginalCostChanges3(){
VehicleRoute vehicleRoute = VehicleRoute.emptyRoute();
TourActivities tour = mock(TourActivities.class);
TourActivity start = getActivityMock("depot", 0.0, 0.0);
TourActivity act1 = getActivityMock("1", 0.0, 10.0);
TourActivity act3 = getActivityMock("3", 0.0, 0.0);
TourActivity act2 = getActivityMock("2", 0.0, 20.0);
TourActivity end = getActivityMock("depot", 0.0, 40.0);
vehicleRoute.getTourActivities().addActivity(start);
vehicleRoute.getTourActivities().addActivity(act1);
vehicleRoute.getTourActivities().addActivity(act2);
vehicleRoute.getTourActivities().addActivity(end);
List<TourActivity> activities = Arrays.asList(start,act1,act2,end);
when(tour.getActivities()).thenReturn(activities);
double c = insertionCalculator.calculate(vehicleRoute, start, act1, act3, null, newVehicle);
assertEquals(50.0,c,0.2);
}
}

View file

@ -36,6 +36,7 @@ import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DriverImpl;
import basics.route.ServiceActivity;
import basics.route.TimeWindow;
import basics.route.TourActivities;
import basics.route.TourActivity;
@ -61,12 +62,12 @@ public class TestCalculatesServiceInsertion {
private Service third;
private RouteStates states;
private TourStateUpdater tourStateUpdater;
private StateManagerImpl states;
private NoDriver driver;
private UpdateStates stateUpdater;
@Before
public void setup(){
Logger.getRootLogger().setLevel(Level.DEBUG);
@ -151,17 +152,13 @@ public class TestCalculatesServiceInsertion {
jobs.add(second);
jobs.add(third);
states = new RouteStates();
states.initialiseStateOfJobs(jobs);
states = new StateManagerImpl();
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
serviceInsertion = new CalculatesServiceInsertion(costs, activityCosts);
serviceInsertion.setActivityStates(states);
tourStateUpdater = new TourStateUpdater(states, costs, activityCosts);
serviceInsertion = new CalculatesServiceInsertion(costs, new MarginalsCalculusTriangleInequality(costs, activityCosts, new HardConstraints.HardTimeWindowConstraint(states)), new HardConstraints.HardLoadConstraint(states));
stateUpdater = new UpdateStates(states, costs, activityCosts);
}
@ -176,7 +173,7 @@ public class TestCalculatesServiceInsertion {
TourActivities tour = new TourActivities();
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route);
stateUpdater.update(route);
InsertionData iData = serviceInsertion.calculate(route, first, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(20.0, iData.getInsertionCost(), 0.2);
@ -186,10 +183,10 @@ public class TestCalculatesServiceInsertion {
@Test
public void whenInsertingTheSecondJobInAnNonEmptyTourWithVehicle_itCalculatesMarginalCostChanges(){
TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first, true));
tour.addActivity(ServiceActivity.newInstance(first));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route);
stateUpdater.update(route);
InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(20.0, iData.getInsertionCost(), 0.2);
@ -199,12 +196,12 @@ public class TestCalculatesServiceInsertion {
@Test
public void whenInsertingThirdJobWithVehicle_itCalculatesMarginalCostChanges(){
TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first,true));
tour.addActivity(states.getActivity(second,true));
tour.addActivity(ServiceActivity.newInstance(first));
tour.addActivity(ServiceActivity.newInstance(second));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route);
stateUpdater.update(route);
InsertionData iData = serviceInsertion.calculate(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(0.0, iData.getInsertionCost(), 0.2);
@ -214,12 +211,12 @@ public class TestCalculatesServiceInsertion {
@Test
public void whenInsertingThirdJobWithNewVehicle_itCalculatesMarginalCostChanges(){
TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first,true));
tour.addActivity(states.getActivity(second,true));
tour.addActivity(ServiceActivity.newInstance(first));
tour.addActivity(ServiceActivity.newInstance(second));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route);
stateUpdater.update(route);
InsertionData iData = serviceInsertion.calculate(route, third, newVehicle, newVehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(20.0, iData.getInsertionCost(), 0.2);
@ -229,11 +226,11 @@ public class TestCalculatesServiceInsertion {
@Test
public void whenInsertingASecondJobWithAVehicle_itCalculatesLocalMarginalCostChanges(){
TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first,true));
tour.addActivity(states.getActivity(third,true));
tour.addActivity(ServiceActivity.newInstance(first));
tour.addActivity(ServiceActivity.newInstance(third));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route);
stateUpdater.update(route);
InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(0.0, iData.getInsertionCost(), 0.2);
@ -243,13 +240,13 @@ public class TestCalculatesServiceInsertion {
@Test
public void whenInsertingASecondJobWithANewVehicle_itCalculatesLocalMarginalCostChanges(){
TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first,true));
tour.addActivity(states.getActivity(third,true));
tour.addActivity(ServiceActivity.newInstance(first));
tour.addActivity(ServiceActivity.newInstance(third));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
// route.addActivity(states.getActivity(first,true));
// route.addActivity(states.getActivity(third,true));
tourStateUpdater.updateRoute(route);
stateUpdater.update(route);
InsertionData iData = serviceInsertion.calculate(route, second, newVehicle, newVehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(20.0, iData.getInsertionCost(), 0.2);

View file

@ -39,6 +39,7 @@ import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver;
import basics.route.DriverImpl;
import basics.route.ServiceActivity;
import basics.route.TimeWindow;
import basics.route.TourActivities;
import basics.route.TourActivity;
@ -64,12 +65,12 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
private Service third;
private RouteStates states;
private TourStateUpdater tourStateUpdater;
private StateManagerImpl states;
private NoDriver driver;
private UpdateStates updateStates;
@Before
public void setup(){
Logger.getRootLogger().setLevel(Level.DEBUG);
@ -142,15 +143,14 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
jobs.add(second);
jobs.add(third);
states = new RouteStates();
states.initialiseStateOfJobs(jobs);
states = new StateManagerImpl();
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
serviceInsertion = new CalculatesServiceInsertionOnRouteLevel(costs,activityCosts);
serviceInsertion.setNuOfActsForwardLooking(4);
serviceInsertion.setActivityStates(states);
serviceInsertion.setStates(states);
tourStateUpdater = new TourStateUpdater(states, costs, activityCosts);
updateStates = new UpdateStates(states, costs, activityCosts);
@ -167,48 +167,21 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
TourActivities tour = new TourActivities();
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route);
updateStates.update(route);
InsertionData iData = serviceInsertion.calculate(route, first, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(20.0, iData.getInsertionCost(), 0.2);
assertEquals(0, iData.getDeliveryInsertionIndex());
}
// @Test
// public void whenInsertingTheSecondJobInAnNonEmptyTourWithVehicle_itCalculatesMarginalCostChanges(){
// TourActivities tour = new TourActivities();
// tour.addActivity(states.getActivity(first, true));
//
// VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
// tourStateUpdater.updateRoute(route);
//
// InsertionData iData = serviceInsertion.calculate(route, second, vehicle, null, Double.MAX_VALUE);
// assertEquals(20.0, iData.getInsertionCost(), 0.2);
// assertEquals(1, iData.getDeliveryInsertionIndex());
// }
// @Test
// public void whenInsertingTheSecotndJobInAnNonEmptyTourWithNewVehicle_itCalculatesMarginalCostChanges(){
// TourActivities tour = new TourActivities();
// tour.addActivity(states.getActivity(first, true));
//
// VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
// tourStateUpdater.updateRoute(route);
//
// InsertionData iData = serviceInsertion.calculate(route, second, newVehicle, null, Double.MAX_VALUE);
// assertEquals(40.0, iData.getInsertionCost(), 0.2);
// assertEquals(1, iData.getDeliveryInsertionIndex());
// }
@Test
public void whenInsertingThirdJobWithVehicle_itCalculatesMarginalCostChanges(){
TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first,true));
tour.addActivity(states.getActivity(second,true));
tour.addActivity(ServiceActivity.newInstance(first));
tour.addActivity(ServiceActivity.newInstance(second));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route);
updateStates.update(route);
InsertionData iData = serviceInsertion.calculate(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(0.0, iData.getInsertionCost(), 0.2);
@ -218,12 +191,11 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
@Test
public void whenInsertingThirdJobWithNewVehicle_itCalculatesMarginalCostChanges(){
TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first,true));
tour.addActivity(states.getActivity(second,true));
tour.addActivity(ServiceActivity.newInstance(first));
tour.addActivity(ServiceActivity.newInstance(second));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route);
updateStates.update(route);
InsertionData iData = serviceInsertion.calculate(route, third, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(40.0, iData.getInsertionCost(), 0.2);
@ -233,11 +205,11 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
@Test
public void whenInsertingASecondJobWithAVehicle_itCalculatesLocalMarginalCostChanges(){
TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first,true));
tour.addActivity(states.getActivity(third,true));
tour.addActivity(ServiceActivity.newInstance(first));
tour.addActivity(ServiceActivity.newInstance(third));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route);
updateStates.update(route);
InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(0.0, iData.getInsertionCost(), 0.2);
@ -247,30 +219,15 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
@Test
public void whenInsertingASecondJobWithANewVehicle_itCalculatesLocalMarginalCostChanges(){
TourActivities tour = new TourActivities();
tour.addActivity(states.getActivity(first,true));
tour.addActivity(states.getActivity(third,true));
tour.addActivity(ServiceActivity.newInstance(first));
tour.addActivity(ServiceActivity.newInstance(third));
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
tourStateUpdater.updateRoute(route);
updateStates.update(route);
InsertionData iData = serviceInsertion.calculate(route, second, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
assertEquals(40.0, iData.getInsertionCost(), 0.2);
assertEquals(2, iData.getDeliveryInsertionIndex());
}
// @Test
// public void whenInsertingFirstJobWithANewVehicle_itCalculatesLocalMarginalCostChanges(){
// TourActivities tour = new TourActivities();
// tour.addActivity(states.getActivity(third,true));
// tour.addActivity(states.getActivity(second,true));
//
// VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
// tourStateUpdater.updateRoute(route);
//
// InsertionData iData = serviceInsertion.calculate(route, second, newVehicle, null, Double.MAX_VALUE);
// assertEquals(40.0, iData.getInsertionCost(), 0.2);
// assertEquals(2, iData.getDeliveryInsertionIndex());
// }
}

View file

@ -0,0 +1,196 @@
package algorithms;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Collection;
import org.junit.Before;
import org.junit.Test;
import util.Coordinate;
import util.ManhattanDistanceCalculator;
import basics.Job;
import basics.Service;
import basics.costs.DefaultVehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver;
import basics.route.DriverImpl;
import basics.route.ServiceActivity;
import basics.route.TimeWindow;
import basics.route.TourActivities;
import basics.route.Vehicle;
import basics.route.VehicleImpl;
import basics.route.VehicleRoute;
import basics.route.VehicleTypeImpl;
public class TestIterateRouteForwardInTime {
TourActivities tour;
Driver driver;
Vehicle vehicle;
TourActivities anotherTour;
RouteStates states;
private VehicleRoute vehicleRoute;
private VehicleRoutingTransportCosts cost;
ServiceActivity firstAct;
ServiceActivity secondAct;
@Before
public void setUp(){
cost = new VehicleRoutingTransportCosts() {
@Override
public double getBackwardTransportTime(String fromId, String toId,
double arrivalTime, Driver driver, Vehicle vehicle) {
return getTransportCost(fromId, toId, arrivalTime, driver, vehicle);
}
@Override
public double getBackwardTransportCost(String fromId, String toId,
double arrivalTime, Driver driver, Vehicle vehicle) {
return getTransportCost(fromId, toId, arrivalTime, driver, vehicle);
}
@Override
public double getTransportCost(String fromId, String toId, double departureTime, Driver driver, Vehicle vehicle) {
String[] fromTokens = fromId.split(",");
String[] toTokens = toId.split(",");
double fromX = Double.parseDouble(fromTokens[0]);
double fromY = Double.parseDouble(fromTokens[1]);
double toX = Double.parseDouble(toTokens[0]);
double toY = Double.parseDouble(toTokens[1]);
return ManhattanDistanceCalculator.calculateDistance(new Coordinate(fromX, fromY), new Coordinate(toX, toY));
}
@Override
public double getTransportTime(String fromId, String toId, double departureTime, Driver driver, Vehicle vehicle) {
return getTransportCost(fromId, toId, departureTime, driver, vehicle);
}
};
Service firstService = Service.Builder.newInstance("1", 5).setLocationId("10,0").setTimeWindow(TimeWindow.newInstance(0, 20)).build();
Service secondService = Service.Builder.newInstance("2", 5).setLocationId("0,10").setTimeWindow(TimeWindow.newInstance(0, 50)).build();
Collection<Job> services = new ArrayList<Job>();
services.add(firstService);
services.add(secondService);
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("test", 0).build();
vehicle = VehicleImpl.Builder.newInstance("testvehicle").setType(type).setLocationId("0,0")
.setEarliestStart(0.0).setLatestArrival(50.0).build();
tour = new TourActivities();
firstAct = ServiceActivity.newInstance(firstService);
tour.addActivity(firstAct);
secondAct = ServiceActivity.newInstance(secondService);
tour.addActivity(secondAct);
vehicleRoute = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),vehicle);
}
@Test
public void whenIteratingWithoutUpdate_itShouldUpdateNothing() {
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
forwardInTime.iterate(vehicleRoute);
assertEquals(0.0,firstAct.getArrTime(),0.1);
assertEquals(0.0,firstAct.getEndTime(),0.1);
assertEquals(0.0,secondAct.getArrTime(),0.1);
assertEquals(0.0,secondAct.getEndTime(),0.1);
}
@Test
public void whenIteratingWithActivityTimeUpdater_itShouldUpdateActivityTimes() {
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
forwardInTime.addListener(new UpdateActivityTimes());
forwardInTime.iterate(vehicleRoute);
assertEquals(10.0,firstAct.getArrTime(),0.1);
assertEquals(10.0,firstAct.getEndTime(),0.1);
assertEquals(30.0,secondAct.getArrTime(),0.1);
assertEquals(30.0,secondAct.getEndTime(),0.1);
}
@Test
public void whenIteratingWithLoadUpdateAtActLocations_itShouldUpdateLoad() {
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
StateManagerImpl states = new StateManagerImpl();
forwardInTime.addListener(new UpdateLoadAtAllLevels(states));
forwardInTime.iterate(vehicleRoute);
assertEquals(5.0, states.getActivityStates(firstAct).getState(StateTypes.LOAD).toDouble(), 0.01);
assertEquals(10.0, states.getActivityStates(secondAct).getState(StateTypes.LOAD).toDouble(), 0.01);
}
@Test
public void testStatesOfAct0(){
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
forwardInTime.iterate(vehicleRoute);
assertEquals(0.0, vehicleRoute.getStart().getEndTime(),0.05);
assertEquals(vehicleRoute.getVehicle().getLocationId(), vehicleRoute.getStart().getLocationId());
assertEquals(vehicleRoute.getVehicle().getEarliestDeparture(), vehicleRoute.getStart().getTheoreticalEarliestOperationStartTime(),0.05);
assertEquals(vehicleRoute.getVehicle().getLatestArrival(), vehicleRoute.getStart().getTheoreticalLatestOperationStartTime(),0.05);
}
@Test
public void testStatesOfAct1(){
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
StateManagerImpl states = new StateManagerImpl();
forwardInTime.addListener(new UpdateLoadAtAllLevels(states));
forwardInTime.addListener(new UpdateEarliestStartTimeWindowAtActLocations(states));
forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, states));
forwardInTime.iterate(vehicleRoute);
assertEquals(10.0, states.getActivityStates(firstAct).getState(StateTypes.COSTS).toDouble(),0.05);
assertEquals(5.0, states.getActivityStates(firstAct).getState(StateTypes.LOAD).toDouble(),0.05);
assertEquals(10.0, states.getActivityStates(firstAct).getState(StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05);
// assertEquals(20.0, states.getState(tour.getActivities().get(0)).getLatestOperationStart(),0.05);
}
@Test
public void testStatesOfAct2(){
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
StateManagerImpl states = new StateManagerImpl();
forwardInTime.addListener(new UpdateLoadAtAllLevels(states));
forwardInTime.addListener(new UpdateEarliestStartTimeWindowAtActLocations(states));
forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, states));
forwardInTime.iterate(vehicleRoute);
assertEquals(30.0, states.getActivityStates(secondAct).getState(StateTypes.COSTS).toDouble(),0.05);
assertEquals(10.0, states.getActivityStates(secondAct).getState(StateTypes.LOAD).toDouble(),0.05);
assertEquals(30.0, states.getActivityStates(secondAct).getState(StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05);
// assertEquals(40.0, states.getState(tour.getActivities().get(1)).getLatestOperationStart(),0.05);
}
@Test
public void testStatesOfAct3(){
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
StateManagerImpl states = new StateManagerImpl();
forwardInTime.addListener(new UpdateActivityTimes());
forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, states));
forwardInTime.iterate(vehicleRoute);
assertEquals(40.0, states.getRouteStates(vehicleRoute).getState(StateTypes.COSTS).toDouble(), 0.05);
assertEquals(40.0, vehicleRoute.getEnd().getArrTime(),0.05);
assertEquals(50.0, vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime(),0.05);
}
}

View file

@ -32,6 +32,7 @@ import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver;
import basics.route.DriverImpl;
import basics.route.ServiceActivity;
import basics.route.TimeWindow;
import basics.route.TourActivities;
import basics.route.Vehicle;
@ -51,9 +52,9 @@ public class TestTourStateUpdaterWithService {
TourActivities anotherTour;
TourStateUpdater tdTourStatusProcessor;
UpdateStates updateStates;
RouteStates states;
StateManagerImpl states;
private VehicleRoute vehicleRoute;
@ -100,33 +101,32 @@ public class TestTourStateUpdaterWithService {
services.add(firstService);
services.add(secondService);
states = new RouteStates();
states.initialiseStateOfJobs(services);
states = new StateManagerImpl();
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("test", 0).build();
vehicle = VehicleImpl.Builder.newInstance("testvehicle").setType(type).setLocationId("0,0")
.setEarliestStart(0.0).setLatestArrival(50.0).build();
tour = new TourActivities();
tour.addActivity(states.getActivity(firstService,true));
tour.addActivity(states.getActivity(secondService,true));
tour.addActivity(ServiceActivity.newInstance(firstService));
tour.addActivity(ServiceActivity.newInstance(secondService));
tdTourStatusProcessor = new TourStateUpdater(states, cost, new ExampleActivityCostFunction());
updateStates = new UpdateStates(states, cost, new ExampleActivityCostFunction());
vehicleRoute = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),vehicle);
}
@Test
public void testCalculatedCost() {
tdTourStatusProcessor.updateRoute(vehicleRoute);
assertEquals(40.0, states.getRouteState(vehicleRoute).getCosts(), 0.05);
assertEquals(10, states.getRouteState(vehicleRoute).getLoad());
updateStates.update(vehicleRoute);
assertEquals(40.0, states.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble(), 0.05);
assertEquals(10, states.getRouteState(vehicleRoute, StateTypes.LOAD).toDouble(), 0.05);
}
@Test
public void testStatesOfAct0(){
tdTourStatusProcessor.updateRoute(vehicleRoute);
updateStates.update(vehicleRoute);
assertEquals(0.0, vehicleRoute.getStart().getEndTime(),0.05);
assertEquals(vehicleRoute.getVehicle().getLocationId(), vehicleRoute.getStart().getLocationId());
assertEquals(vehicleRoute.getVehicle().getEarliestDeparture(), vehicleRoute.getStart().getTheoreticalEarliestOperationStartTime(),0.05);
@ -136,112 +136,31 @@ public class TestTourStateUpdaterWithService {
@Test
public void testStatesOfAct1(){
tdTourStatusProcessor.updateRoute(vehicleRoute);
assertEquals(10.0, states.getState(tour.getActivities().get(0)).getCurrentCost(),0.05);
assertEquals(5.0, states.getState(tour.getActivities().get(0)).getCurrentLoad(),0.05);
assertEquals(10.0, states.getState(tour.getActivities().get(0)).getEarliestOperationStart(),0.05);
assertEquals(20.0, states.getState(tour.getActivities().get(0)).getLatestOperationStart(),0.05);
updateStates.update(vehicleRoute);
assertEquals(10.0, states.getActivityState(tour.getActivities().get(0), StateTypes.COSTS).toDouble(),0.05);
assertEquals(5.0, states.getActivityState(tour.getActivities().get(0), StateTypes.LOAD).toDouble(),0.05);
// assertEquals(10.0, states.getActivityState(tour.getActivities().get(0), StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05);
assertEquals(20.0, states.getActivityState(tour.getActivities().get(0), StateTypes.LATEST_OPERATION_START_TIME).toDouble(),0.05);
}
@Test
public void testStatesOfAct2(){
tdTourStatusProcessor.updateRoute(vehicleRoute);
assertEquals(30.0, states.getState(tour.getActivities().get(1)).getCurrentCost(),0.05);
assertEquals(10.0, states.getState(tour.getActivities().get(1)).getCurrentLoad(),0.05);
assertEquals(30.0, states.getState(tour.getActivities().get(1)).getEarliestOperationStart(),0.05);
assertEquals(40.0, states.getState(tour.getActivities().get(1)).getLatestOperationStart(),0.05);
updateStates.update(vehicleRoute);
assertEquals(30.0, states.getActivityState(tour.getActivities().get(1), StateTypes.COSTS).toDouble(),0.05);
assertEquals(10.0, states.getActivityState(tour.getActivities().get(1), StateTypes.LOAD).toDouble(),0.05);
// assertEquals(10.0, states.getActivityState(tour.getActivities().get(0), StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05);
assertEquals(40.0, states.getActivityState(tour.getActivities().get(1), StateTypes.LATEST_OPERATION_START_TIME).toDouble(),0.05);
}
@Test
public void testStatesOfAct3(){
tdTourStatusProcessor.updateRoute(vehicleRoute);
assertEquals(40.0, states.getRouteState(vehicleRoute).getCosts(), 0.05);
assertEquals(40.0, vehicleRoute.getEnd().getEndTime(),0.05);
updateStates.update(vehicleRoute);
assertEquals(40.0, states.getRouteState(vehicleRoute, StateTypes.COSTS).toDouble(), 0.05);
assertEquals(40.0, vehicleRoute.getEnd().getArrTime(),0.05);
assertEquals(50.0, vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime(),0.05);
}
// public void testEarliestArrStart() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(0.0, tour.getActivities().get(0)
// .getEarliestOperationStartTime());
// }
//
// public void testLatestArrStart() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(0.0, tour.getActivities().get(0)
// .getLatestOperationStartTime());
// }
//
// public void testEarliestArrAtFirstPickup() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(10.0, tour.getActivities().get(1)
// .getEarliestOperationStartTime());
// }
//
// public void testEarliestArrAtFirstPickupWithTDCost() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(10.0, tour.getActivities().get(1)
// .getEarliestOperationStartTime());
// }
//
// public void testLatestArrAtFirstPickup() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(10.0, tour.getActivities().get(1)
// .getLatestOperationStartTime());
// }
//
// public void testLatestArrAtFirstPickupWithTDCost() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(12.0, tour.getActivities().get(1)
// .getLatestOperationStartTime());
// }
//
// public void testEarliestArrAtSecondPickup() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(30.0, tour.getActivities().get(2)
// .getEarliestOperationStartTime());
// }
//
// public void testEarliestArrAtSecondPickupWithTDCosts() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(30.0, tour.getActivities().get(2)
// .getEarliestOperationStartTime());
// }
//
// public void testLatestArrAtSecondPickup() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(30.0, tour.getActivities().get(2)
// .getLatestOperationStartTime());
// }
//
// public void testLatestArrAtSecondPickupWithTDCosts() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(30.0, tour.getActivities().get(2)
// .getLatestOperationStartTime());
// }
//
// public void testEarliestArrAtEnd() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(40.0, tour.getActivities().get(5)
// .getEarliestOperationStartTime());
// }
//
// public void testEarliestArrAtEndWithTDCosts() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(35.0, tour.getActivities().get(5)
// .getEarliestOperationStartTime());
// }
//
// public void testLatestArrAtEnd() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(Double.MAX_VALUE, tour.getActivities().get(5)
// .getLatestOperationStartTime());
// }
//
// public void testLatestArrAtEndWithTDCosts() {
// tdTourStatusProcessor.calculate(tour, vehicle, driver);
// assertEquals(Double.MAX_VALUE, tour.getActivities().get(5)
// .getLatestOperationStartTime());
// }
}

View file

@ -0,0 +1,46 @@
from,to,distance
1,2,25
1,3,43
1,4,57
1,5,43
1,6,61
1,7,29
1,8,41
1,9,48
1,10,71
2,3,29
2,4,34
2,5,43
2,6,68
2,7,49
2,8,66
2,9,48
2,10,91
3,4,52
3,5,72
3,6,96
3,7,72
3,8,81
3,9,89
3,10,114
4,5,45
4,6,71
4,7,71
4,8,95
4,9,99
4,10,108
5,6,27
5,7,36
5,8,65
5,9,65
5,10,65
6,7,40
6,8,66
6,9,62
6,10,46
7,8,31
7,9,31
7,10,43
8,9,11
8,10,46
9,10,36

View file

@ -0,0 +1,10 @@
node,quantity
2,4
3,6
4,5
5,4
6,7
7,3
8,5
9,4
10,4

View file

@ -0,0 +1,635 @@
<?xml version="1.0" encoding="UTF-8"?>
<problem xmlns="http://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com vrp_xml_schema.xsd">
<problemType>
<fleetSize>INFINITE</fleetSize>
<fleetComposition>HOMOGENEOUS</fleetComposition>
</problemType>
<vehicles>
<vehicle>
<id>christophidesVehicle</id>
<typeId>christophidesType</typeId>
<location>
<id>[x=30.0][y=40.0]</id>
<coord x="30.0" y="40.0"/>
</location>
<timeSchedule>
<start>0.0</start>
<end>999999.0</end>
</timeSchedule>
</vehicle>
</vehicles>
<vehicleTypes>
<type>
<id>christophidesType</id>
<capacity>160</capacity>
<costs>
<fixed>0.0</fixed>
<distance>1.0</distance>
<time>0.0</time>
</costs>
</type>
</vehicleTypes>
<services>
<service id="35" type="service">
<locationId>[x=62.0][y=63.0]</locationId>
<coord x="62.0" y="63.0"/>
<capacity-demand>17</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="36" type="service">
<locationId>[x=63.0][y=69.0]</locationId>
<coord x="63.0" y="69.0"/>
<capacity-demand>6</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="33" type="service">
<locationId>[x=46.0][y=10.0]</locationId>
<coord x="46.0" y="10.0"/>
<capacity-demand>23</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="34" type="service">
<locationId>[x=61.0][y=33.0]</locationId>
<coord x="61.0" y="33.0"/>
<capacity-demand>26</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="39" type="service">
<locationId>[x=59.0][y=15.0]</locationId>
<coord x="59.0" y="15.0"/>
<capacity-demand>14</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="37" type="service">
<locationId>[x=32.0][y=22.0]</locationId>
<coord x="32.0" y="22.0"/>
<capacity-demand>9</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="38" type="service">
<locationId>[x=45.0][y=35.0]</locationId>
<coord x="45.0" y="35.0"/>
<capacity-demand>15</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="43" type="service">
<locationId>[x=5.0][y=64.0]</locationId>
<coord x="5.0" y="64.0"/>
<capacity-demand>11</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="42" type="service">
<locationId>[x=21.0][y=10.0]</locationId>
<coord x="21.0" y="10.0"/>
<capacity-demand>13</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="41" type="service">
<locationId>[x=10.0][y=17.0]</locationId>
<coord x="10.0" y="17.0"/>
<capacity-demand>27</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="40" type="service">
<locationId>[x=5.0][y=6.0]</locationId>
<coord x="5.0" y="6.0"/>
<capacity-demand>7</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="22" type="service">
<locationId>[x=42.0][y=57.0]</locationId>
<coord x="42.0" y="57.0"/>
<capacity-demand>8</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="23" type="service">
<locationId>[x=16.0][y=57.0]</locationId>
<coord x="16.0" y="57.0"/>
<capacity-demand>16</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="24" type="service">
<locationId>[x=8.0][y=52.0]</locationId>
<coord x="8.0" y="52.0"/>
<capacity-demand>10</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="25" type="service">
<locationId>[x=7.0][y=38.0]</locationId>
<coord x="7.0" y="38.0"/>
<capacity-demand>28</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="26" type="service">
<locationId>[x=27.0][y=68.0]</locationId>
<coord x="27.0" y="68.0"/>
<capacity-demand>7</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="27" type="service">
<locationId>[x=30.0][y=48.0]</locationId>
<coord x="30.0" y="48.0"/>
<capacity-demand>15</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="28" type="service">
<locationId>[x=43.0][y=67.0]</locationId>
<coord x="43.0" y="67.0"/>
<capacity-demand>14</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="29" type="service">
<locationId>[x=58.0][y=48.0]</locationId>
<coord x="58.0" y="48.0"/>
<capacity-demand>6</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="3" type="service">
<locationId>[x=52.0][y=64.0]</locationId>
<coord x="52.0" y="64.0"/>
<capacity-demand>16</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="2" type="service">
<locationId>[x=49.0][y=49.0]</locationId>
<coord x="49.0" y="49.0"/>
<capacity-demand>30</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="1" type="service">
<locationId>[x=37.0][y=52.0]</locationId>
<coord x="37.0" y="52.0"/>
<capacity-demand>7</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="7" type="service">
<locationId>[x=17.0][y=63.0]</locationId>
<coord x="17.0" y="63.0"/>
<capacity-demand>19</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="30" type="service">
<locationId>[x=58.0][y=27.0]</locationId>
<coord x="58.0" y="27.0"/>
<capacity-demand>19</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="6" type="service">
<locationId>[x=21.0][y=47.0]</locationId>
<coord x="21.0" y="47.0"/>
<capacity-demand>15</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="5" type="service">
<locationId>[x=40.0][y=30.0]</locationId>
<coord x="40.0" y="30.0"/>
<capacity-demand>21</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="32" type="service">
<locationId>[x=38.0][y=46.0]</locationId>
<coord x="38.0" y="46.0"/>
<capacity-demand>12</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="4" type="service">
<locationId>[x=20.0][y=26.0]</locationId>
<coord x="20.0" y="26.0"/>
<capacity-demand>9</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="31" type="service">
<locationId>[x=37.0][y=69.0]</locationId>
<coord x="37.0" y="69.0"/>
<capacity-demand>11</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="9" type="service">
<locationId>[x=52.0][y=33.0]</locationId>
<coord x="52.0" y="33.0"/>
<capacity-demand>11</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="8" type="service">
<locationId>[x=31.0][y=62.0]</locationId>
<coord x="31.0" y="62.0"/>
<capacity-demand>23</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="19" type="service">
<locationId>[x=13.0][y=13.0]</locationId>
<coord x="13.0" y="13.0"/>
<capacity-demand>9</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="17" type="service">
<locationId>[x=27.0][y=23.0]</locationId>
<coord x="27.0" y="23.0"/>
<capacity-demand>3</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="18" type="service">
<locationId>[x=17.0][y=33.0]</locationId>
<coord x="17.0" y="33.0"/>
<capacity-demand>41</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="15" type="service">
<locationId>[x=36.0][y=16.0]</locationId>
<coord x="36.0" y="16.0"/>
<capacity-demand>10</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="16" type="service">
<locationId>[x=52.0][y=41.0]</locationId>
<coord x="52.0" y="41.0"/>
<capacity-demand>15</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="13" type="service">
<locationId>[x=5.0][y=25.0]</locationId>
<coord x="5.0" y="25.0"/>
<capacity-demand>23</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="14" type="service">
<locationId>[x=12.0][y=42.0]</locationId>
<coord x="12.0" y="42.0"/>
<capacity-demand>21</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="11" type="service">
<locationId>[x=42.0][y=41.0]</locationId>
<coord x="42.0" y="41.0"/>
<capacity-demand>19</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="12" type="service">
<locationId>[x=31.0][y=32.0]</locationId>
<coord x="31.0" y="32.0"/>
<capacity-demand>29</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="21" type="service">
<locationId>[x=62.0][y=42.0]</locationId>
<coord x="62.0" y="42.0"/>
<capacity-demand>8</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="20" type="service">
<locationId>[x=57.0][y=58.0]</locationId>
<coord x="57.0" y="58.0"/>
<capacity-demand>28</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="49" type="service">
<locationId>[x=48.0][y=28.0]</locationId>
<coord x="48.0" y="28.0"/>
<capacity-demand>18</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="48" type="service">
<locationId>[x=25.0][y=55.0]</locationId>
<coord x="25.0" y="55.0"/>
<capacity-demand>17</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="45" type="service">
<locationId>[x=39.0][y=10.0]</locationId>
<coord x="39.0" y="10.0"/>
<capacity-demand>10</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="44" type="service">
<locationId>[x=30.0][y=15.0]</locationId>
<coord x="30.0" y="15.0"/>
<capacity-demand>16</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="47" type="service">
<locationId>[x=25.0][y=32.0]</locationId>
<coord x="25.0" y="32.0"/>
<capacity-demand>25</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="46" type="service">
<locationId>[x=32.0][y=39.0]</locationId>
<coord x="32.0" y="39.0"/>
<capacity-demand>5</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="10" type="service">
<locationId>[x=51.0][y=21.0]</locationId>
<coord x="51.0" y="21.0"/>
<capacity-demand>5</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="50" type="service">
<locationId>[x=56.0][y=37.0]</locationId>
<coord x="56.0" y="37.0"/>
<capacity-demand>10</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
</services>
</problem>

View file

@ -22,10 +22,12 @@
<algorithm xmlns="http://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com algorithm_schema.xsd">
<iterations>10000</iterations>
<iterations>2000</iterations>
<construction>
<insertion name="bestInsertion"/>
<insertion name="bestInsertion">
<level forwardLooking="2" memory="1">route</level>
</insertion>
</construction>
<strategy>
@ -33,10 +35,8 @@
<searchStrategies>
<searchStrategy name="radialRuinAndRecreate">
<selector name="selectBest"/>
<acceptor name="schrimpfAcceptance">
<alpha>0.1</alpha>
<warmup>100</warmup>
</acceptor>
<acceptor name="acceptNewRemoveWorst"/>
<modules>
<module name="ruin_and_recreate">
<ruin name="randomRuin">
@ -51,7 +51,7 @@
<searchStrategy name="radialRuinAndRecreate">
<selector name="selectBest"/>
<acceptor name="schrimpfAcceptance"/>
<acceptor name="acceptNewRemoveWorst"/>
<modules>
<module name="ruin_and_recreate">
@ -67,7 +67,7 @@
<searchStrategy name="radialRuinAndRecreate">
<selector name="selectBest"/>
<acceptor name="schrimpfAcceptance"/>
<acceptor name="acceptNewRemoveWorst"/>
<modules>
<module name="ruin_and_recreate">
<ruin id="2" name="radialRuin">

View file

@ -6,7 +6,9 @@
<iterations>2000</iterations>
<construction>
<insertion name="bestInsertion"/>
<insertion name="bestInsertion">
</insertion>
</construction>
<strategy>

View file

@ -0,0 +1,635 @@
<?xml version="1.0" encoding="UTF-8"?>
<problem xmlns="http://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com vrp_xml_schema.xsd">
<problemType>
<fleetSize>INFINITE</fleetSize>
<fleetComposition>HOMOGENEOUS</fleetComposition>
</problemType>
<vehicles>
<vehicle>
<id>christophidesVehicle</id>
<typeId>christophidesType</typeId>
<location>
<id>[x=30.0][y=40.0]</id>
<coord x="30.0" y="40.0"/>
</location>
<timeSchedule>
<start>0.0</start>
<end>999999.0</end>
</timeSchedule>
</vehicle>
</vehicles>
<vehicleTypes>
<type>
<id>christophidesType</id>
<capacity>160</capacity>
<costs>
<fixed>0.0</fixed>
<distance>1.0</distance>
<time>0.0</time>
</costs>
</type>
</vehicleTypes>
<services>
<service id="35" type="service">
<locationId>[x=62.0][y=63.0]</locationId>
<coord x="62.0" y="63.0"/>
<capacity-demand>17</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="36" type="service">
<locationId>[x=63.0][y=69.0]</locationId>
<coord x="63.0" y="69.0"/>
<capacity-demand>6</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="33" type="service">
<locationId>[x=46.0][y=10.0]</locationId>
<coord x="46.0" y="10.0"/>
<capacity-demand>23</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="34" type="service">
<locationId>[x=61.0][y=33.0]</locationId>
<coord x="61.0" y="33.0"/>
<capacity-demand>26</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="39" type="service">
<locationId>[x=59.0][y=15.0]</locationId>
<coord x="59.0" y="15.0"/>
<capacity-demand>14</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="37" type="service">
<locationId>[x=32.0][y=22.0]</locationId>
<coord x="32.0" y="22.0"/>
<capacity-demand>9</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="38" type="service">
<locationId>[x=45.0][y=35.0]</locationId>
<coord x="45.0" y="35.0"/>
<capacity-demand>15</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="43" type="service">
<locationId>[x=5.0][y=64.0]</locationId>
<coord x="5.0" y="64.0"/>
<capacity-demand>11</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="42" type="service">
<locationId>[x=21.0][y=10.0]</locationId>
<coord x="21.0" y="10.0"/>
<capacity-demand>13</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="41" type="service">
<locationId>[x=10.0][y=17.0]</locationId>
<coord x="10.0" y="17.0"/>
<capacity-demand>27</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="40" type="service">
<locationId>[x=5.0][y=6.0]</locationId>
<coord x="5.0" y="6.0"/>
<capacity-demand>7</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="22" type="service">
<locationId>[x=42.0][y=57.0]</locationId>
<coord x="42.0" y="57.0"/>
<capacity-demand>8</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="23" type="service">
<locationId>[x=16.0][y=57.0]</locationId>
<coord x="16.0" y="57.0"/>
<capacity-demand>16</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="24" type="service">
<locationId>[x=8.0][y=52.0]</locationId>
<coord x="8.0" y="52.0"/>
<capacity-demand>10</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="25" type="service">
<locationId>[x=7.0][y=38.0]</locationId>
<coord x="7.0" y="38.0"/>
<capacity-demand>28</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="26" type="service">
<locationId>[x=27.0][y=68.0]</locationId>
<coord x="27.0" y="68.0"/>
<capacity-demand>7</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="27" type="service">
<locationId>[x=30.0][y=48.0]</locationId>
<coord x="30.0" y="48.0"/>
<capacity-demand>15</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="28" type="service">
<locationId>[x=43.0][y=67.0]</locationId>
<coord x="43.0" y="67.0"/>
<capacity-demand>14</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="29" type="service">
<locationId>[x=58.0][y=48.0]</locationId>
<coord x="58.0" y="48.0"/>
<capacity-demand>6</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="3" type="service">
<locationId>[x=52.0][y=64.0]</locationId>
<coord x="52.0" y="64.0"/>
<capacity-demand>16</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="2" type="service">
<locationId>[x=49.0][y=49.0]</locationId>
<coord x="49.0" y="49.0"/>
<capacity-demand>30</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="1" type="service">
<locationId>[x=37.0][y=52.0]</locationId>
<coord x="37.0" y="52.0"/>
<capacity-demand>7</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="7" type="service">
<locationId>[x=17.0][y=63.0]</locationId>
<coord x="17.0" y="63.0"/>
<capacity-demand>19</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="30" type="service">
<locationId>[x=58.0][y=27.0]</locationId>
<coord x="58.0" y="27.0"/>
<capacity-demand>19</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="6" type="service">
<locationId>[x=21.0][y=47.0]</locationId>
<coord x="21.0" y="47.0"/>
<capacity-demand>15</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="5" type="service">
<locationId>[x=40.0][y=30.0]</locationId>
<coord x="40.0" y="30.0"/>
<capacity-demand>21</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="32" type="service">
<locationId>[x=38.0][y=46.0]</locationId>
<coord x="38.0" y="46.0"/>
<capacity-demand>12</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="4" type="service">
<locationId>[x=20.0][y=26.0]</locationId>
<coord x="20.0" y="26.0"/>
<capacity-demand>9</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="31" type="service">
<locationId>[x=37.0][y=69.0]</locationId>
<coord x="37.0" y="69.0"/>
<capacity-demand>11</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="9" type="service">
<locationId>[x=52.0][y=33.0]</locationId>
<coord x="52.0" y="33.0"/>
<capacity-demand>11</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="8" type="service">
<locationId>[x=31.0][y=62.0]</locationId>
<coord x="31.0" y="62.0"/>
<capacity-demand>23</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="19" type="service">
<locationId>[x=13.0][y=13.0]</locationId>
<coord x="13.0" y="13.0"/>
<capacity-demand>9</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="17" type="service">
<locationId>[x=27.0][y=23.0]</locationId>
<coord x="27.0" y="23.0"/>
<capacity-demand>3</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="18" type="service">
<locationId>[x=17.0][y=33.0]</locationId>
<coord x="17.0" y="33.0"/>
<capacity-demand>41</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="15" type="service">
<locationId>[x=36.0][y=16.0]</locationId>
<coord x="36.0" y="16.0"/>
<capacity-demand>10</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="16" type="service">
<locationId>[x=52.0][y=41.0]</locationId>
<coord x="52.0" y="41.0"/>
<capacity-demand>15</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="13" type="service">
<locationId>[x=5.0][y=25.0]</locationId>
<coord x="5.0" y="25.0"/>
<capacity-demand>23</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="14" type="service">
<locationId>[x=12.0][y=42.0]</locationId>
<coord x="12.0" y="42.0"/>
<capacity-demand>21</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="11" type="service">
<locationId>[x=42.0][y=41.0]</locationId>
<coord x="42.0" y="41.0"/>
<capacity-demand>19</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="12" type="service">
<locationId>[x=31.0][y=32.0]</locationId>
<coord x="31.0" y="32.0"/>
<capacity-demand>29</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="21" type="service">
<locationId>[x=62.0][y=42.0]</locationId>
<coord x="62.0" y="42.0"/>
<capacity-demand>8</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="20" type="service">
<locationId>[x=57.0][y=58.0]</locationId>
<coord x="57.0" y="58.0"/>
<capacity-demand>28</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="49" type="service">
<locationId>[x=48.0][y=28.0]</locationId>
<coord x="48.0" y="28.0"/>
<capacity-demand>18</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="48" type="service">
<locationId>[x=25.0][y=55.0]</locationId>
<coord x="25.0" y="55.0"/>
<capacity-demand>17</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="45" type="service">
<locationId>[x=39.0][y=10.0]</locationId>
<coord x="39.0" y="10.0"/>
<capacity-demand>10</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="44" type="service">
<locationId>[x=30.0][y=15.0]</locationId>
<coord x="30.0" y="15.0"/>
<capacity-demand>16</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="47" type="service">
<locationId>[x=25.0][y=32.0]</locationId>
<coord x="25.0" y="32.0"/>
<capacity-demand>25</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="46" type="service">
<locationId>[x=32.0][y=39.0]</locationId>
<coord x="32.0" y="39.0"/>
<capacity-demand>5</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="10" type="service">
<locationId>[x=51.0][y=21.0]</locationId>
<coord x="51.0" y="21.0"/>
<capacity-demand>5</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="50" type="service">
<locationId>[x=56.0][y=37.0]</locationId>
<coord x="56.0" y="37.0"/>
<capacity-demand>10</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
</services>
</problem>

View file

@ -0,0 +1,52 @@
50 160 999999 0
30 40
37 52 7
49 49 30
52 64 16
20 26 9
40 30 21
21 47 15
17 63 19
31 62 23
52 33 11
51 21 5
42 41 19
31 32 29
5 25 23
12 42 21
36 16 10
52 41 15
27 23 3
17 33 41
13 13 9
57 58 28
62 42 8
42 57 8
16 57 16
8 52 10
7 38 28
27 68 7
30 48 15
43 67 14
58 48 6
58 27 19
37 69 11
38 46 12
46 10 23
61 33 26
62 63 17
63 69 6
32 22 9
45 35 15
59 15 14
5 6 7
10 17 27
21 10 13
5 64 11
30 15 16
39 10 10
32 39 5
25 32 25
25 55 17
48 28 18
56 37 10

View file

@ -0,0 +1,16 @@
package examples;
import readers.ChristofidesReader;
import basics.VehicleRoutingProblem;
import basics.io.VrpXMLWriter;
public class CVRPExample {
public static void main(String[] args) {
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new ChristofidesReader(builder).read("input/vrpnc1.txt");
VehicleRoutingProblem vrp = builder.build();
new VrpXMLWriter(vrp).write("input/vrpnc1-jsprit.xml");
}
}

View file

@ -20,6 +20,8 @@
******************************************************************************/
package examples;
import java.io.File;
import readers.SolomonReader;
import algorithms.GreedySchrimpfFactory;
import algorithms.SchrimpfFactory;
@ -35,7 +37,16 @@ public class CompareAlgorithmExample {
* @param args
*/
public static void main(String[] args) {
/*
* some preparation - create output folder
*/
File dir = new File("output");
// if the directory does not exist, create it
if (!dir.exists()){
System.out.println("creating directory ./output");
boolean result = dir.mkdir();
if(result) System.out.println("./output created");
}
/*
* Build the problem.
*

View file

@ -1,5 +1,6 @@
package examples;
import java.io.File;
import java.util.Collection;
import util.Solutions;
@ -32,7 +33,16 @@ public class CostMatrixExample {
* @param args
*/
public static void main(String[] args) {
/*
* some preparation - create output folder
*/
File dir = new File("output");
// if the directory does not exist, create it
if (!dir.exists()){
System.out.println("creating directory ./output");
boolean result = dir.mkdir();
if(result) System.out.println("./output created");
}
VehicleType type = VehicleTypeImpl.Builder.newInstance("type", 2).setCostPerDistance(1).setCostPerTime(2).build();
Vehicle vehicle = VehicleImpl.Builder.newInstance("vehicle").setLocationId("0").setType(type).build();

View file

@ -1,5 +1,6 @@
package examples;
import java.io.File;
import java.util.Arrays;
import java.util.Collection;
@ -18,7 +19,6 @@ import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
import basics.io.VrpXMLReader;
import basics.route.Vehicle;
import basics.route.VehicleImpl;
import basics.route.VehicleType;
import basics.route.VehicleTypeImpl;
public class MultipleDepotExample {
@ -27,7 +27,16 @@ public class MultipleDepotExample {
* @param args
*/
public static void main(String[] args) {
/*
* some preparation - create output folder
*/
File dir = new File("output");
// if the directory does not exist, create it
if (!dir.exists()){
System.out.println("creating directory ./output");
boolean result = dir.mkdir();
if(result) System.out.println("./output created");
}
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
/*
* Read cordeau-instance p01, BUT only its services without any vehicles

View file

@ -1,5 +1,6 @@
package examples;
import java.io.File;
import java.util.Arrays;
import java.util.Collection;
@ -29,6 +30,16 @@ public class MultipleDepotExampleWithPenaltyVehicles {
* @param args
*/
public static void main(String[] args) {
/*
* some preparation - create output folder
*/
File dir = new File("output");
// if the directory does not exist, create it
if (!dir.exists()){
System.out.println("creating directory ./output");
boolean result = dir.mkdir();
if(result) System.out.println("./output created");
}
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
/*

View file

@ -155,6 +155,16 @@ public class RefuseCollectionExample {
* @throws IOException
*/
public static void main(String[] args) throws IOException {
/*
* some preparation - create output folder
*/
File dir = new File("output");
// if the directory does not exist, create it
if (!dir.exists()){
System.out.println("creating directory ./output");
boolean result = dir.mkdir();
if(result) System.out.println("./output created");
}
/*
* create vehicle-type and vehicle

View file

@ -20,6 +20,7 @@
******************************************************************************/
package examples;
import java.io.File;
import java.util.Collection;
import util.Coordinate;
@ -42,6 +43,16 @@ import basics.route.VehicleTypeImpl;
public class SimpleExample {
public static void main(String[] args) {
/*
* some preparation - create output folder
*/
File dir = new File("output");
// if the directory does not exist, create it
if (!dir.exists()){
System.out.println("creating directory ./output");
boolean result = dir.mkdir();
if(result) System.out.println("./output created");
}
/*
* get a vehicle type-builder and build a type with the typeId "vehicleType" and a capacity of 2

View file

@ -20,12 +20,12 @@
******************************************************************************/
package examples;
import java.io.File;
import java.util.Collection;
import readers.SolomonReader;
import algorithms.SchrimpfFactory;
import algorithms.VehicleRoutingAlgorithms;
import algorithms.selectors.SelectBest;
import analysis.AlgorithmSearchProgressChartListener;
import analysis.SolutionPlotter;
import analysis.SolutionPrinter;
import analysis.SolutionPrinter.Print;
@ -36,7 +36,16 @@ import basics.VehicleRoutingProblemSolution;
public class SolomonExample {
public static void main(String[] args) {
/*
* some preparation - create output folder
*/
File dir = new File("output");
// if the directory does not exist, create it
if (!dir.exists()){
System.out.println("creating directory ./output");
boolean result = dir.mkdir();
if(result) System.out.println("./output created");
}
/*
* Build the problem.
@ -62,8 +71,10 @@ public class SolomonExample {
*
* The algorithm can be defined and configured in an xml-file.
*/
VehicleRoutingAlgorithm vra = new SchrimpfFactory().createAlgorithm(vrp);
vra.getAlgorithmListeners().addListener(new AlgorithmSearchProgressChartListener("output/sol_progress.png"));
// VehicleRoutingAlgorithm vra = new SchrimpfFactory().createAlgorithm(vrp);
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_solomon.xml");
vra.setPrematureBreak(100);
// vra.getAlgorithmListeners().addListener(new AlgorithmSearchProgressChartListener("output/sol_progress.png"));
/*
* Solve the problem.
*

View file

@ -42,7 +42,7 @@
<developers>
<developer>
<name>Stefan Schroeder</name>
<email>4sschroeder@gmail.com</email>
<email>jsprit.vehicle.routing@gmail.com</email>
</developer>
</developers>