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:
commit
f4a7254036
99 changed files with 4371 additions and 2349 deletions
21
README.md
21
README.md
|
|
@ -12,6 +12,14 @@ It is lightweight and easy-to-use, and based on heuristics currently solving
|
||||||
Modifying the algorithms and visualising the discovered solutions is as easy and handy as
|
Modifying the algorithms and visualising the discovered solutions is as easy and handy as
|
||||||
reading classical VRP instances to benchmark your algorithm.
|
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
|
##License
|
||||||
This program is free software; you can redistribute it and/or
|
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).
|
[Add the latest snapshot to your pom](https://github.com/jsprit/jsprit/wiki/Add-latest-snapshot-to-your-pom).
|
||||||
|
|
||||||
##[About](https://github.com/jsprit/jsprit/wiki/About)
|
##About
|
||||||
|
The jsprit-project is created and maintained by Stefan Schröder. It is motivated by two issues.
|
||||||
|
|
||||||
[](http://githalytics.com/jsprit/jsprit)
|
First, there is an almost endless list of papers and algorithms to tackle vehicle routing problems, **BUT** there are (as far as I know) only a [very few open source implementations](https://github.com/jsprit/jsprit/wiki/Other-Projects) of one of these thousands algorithms.
|
||||||
|
|
||||||
|
Second, it is motivated by my PhD-project at [KIT](http://www.kit.edu/english/index.php) where I apply vehicle routing algorithms to solve behavioural models of freight agents to assess (freight) transport policy measures.
|
||||||
|
|
||||||
|
It is mainly inspired by my research group at [KIT-ECON](http://netze.econ.kit.edu/21.php), and by an awesome open-source project called [MATSim](www.matsim.org) and its developers.
|
||||||
|
|
||||||
|
Email: jsprit.vehicle.routing@gmail.com
|
||||||
|
|
||||||
|
[](http://githalytics.com/jsprit/jsprit)
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,9 @@ import org.jfree.data.xy.XYSeriesCollection;
|
||||||
|
|
||||||
import util.Coordinate;
|
import util.Coordinate;
|
||||||
import util.Locations;
|
import util.Locations;
|
||||||
|
import basics.Delivery;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
|
import basics.Pickup;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import basics.VehicleRoutingProblemSolution;
|
||||||
|
|
@ -264,13 +266,33 @@ public class SolutionPlotter {
|
||||||
}
|
}
|
||||||
coll.addSeries(vehicleSeries);
|
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){
|
for(Job job : services){
|
||||||
|
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;
|
Service service = (Service)job;
|
||||||
Coordinate coord = service.getCoord();
|
Coordinate coord = service.getCoord();
|
||||||
jobSeries.add(coord.getX(), coord.getY());
|
serviceSeries.add(coord.getX(), coord.getY());
|
||||||
}
|
}
|
||||||
coll.addSeries(jobSeries);
|
else{
|
||||||
|
throw new IllegalStateException("job instanceof " + job.getClass().toString() + ". this is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(!serviceSeries.isEmpty()) coll.addSeries(serviceSeries);
|
||||||
|
if(!pickupSeries.isEmpty()) coll.addSeries(pickupSeries);
|
||||||
|
if(!deliverySeries.isEmpty()) coll.addSeries(deliverySeries);
|
||||||
return coll;
|
return coll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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); }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -15,9 +15,7 @@ package algorithms;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
@ -25,6 +23,9 @@ import org.apache.log4j.Logger;
|
||||||
import util.RandomNumberGeneration;
|
import util.RandomNumberGeneration;
|
||||||
import algorithms.InsertionData.NoInsertionFound;
|
import algorithms.InsertionData.NoInsertionFound;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
|
import basics.algo.InsertionListener;
|
||||||
|
import basics.route.Driver;
|
||||||
|
import basics.route.Vehicle;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -35,64 +36,53 @@ import basics.route.VehicleRoute;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
final class BestInsertion extends AbstractInsertionStrategy{
|
final class BestInsertion implements InsertionStrategy{
|
||||||
|
|
||||||
public static BestInsertion newInstance(RouteAlgorithm routeAlgorithm){
|
|
||||||
return new BestInsertion(routeAlgorithm);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Logger logger = Logger.getLogger(BestInsertion.class);
|
private static Logger logger = Logger.getLogger(BestInsertion.class);
|
||||||
|
|
||||||
private Random random = RandomNumberGeneration.getRandom();
|
private Random random = RandomNumberGeneration.getRandom();
|
||||||
|
|
||||||
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 boolean allowUnassignedJobs = false;
|
private final static Driver NO_NEW_DRIVER_YET = null;
|
||||||
|
|
||||||
private boolean fixRouteSet = false;
|
private InsertionListeners insertionsListeners;
|
||||||
|
|
||||||
|
private Inserter inserter;
|
||||||
|
|
||||||
|
private JobInsertionCalculator bestInsertionCostCalculator;
|
||||||
|
|
||||||
private boolean minVehiclesFirst = false;
|
private boolean minVehiclesFirst = false;
|
||||||
|
|
||||||
public void setFixRouteSet(boolean fixRouteSet) {
|
|
||||||
this.fixRouteSet = fixRouteSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRandom(Random random) {
|
public void setRandom(Random random) {
|
||||||
this.random = random;
|
this.random = random;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BestInsertion(RouteAlgorithm routeAlgorithm) {
|
public BestInsertion(JobInsertionCalculator jobInsertionCalculator) {
|
||||||
super();
|
super();
|
||||||
this.routeAlgorithm = routeAlgorithm;
|
this.insertionsListeners = new InsertionListeners();
|
||||||
|
inserter = new Inserter(insertionsListeners);
|
||||||
|
bestInsertionCostCalculator = jobInsertionCalculator;
|
||||||
logger.info("initialise " + this);
|
logger.info("initialise " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RouteAlgorithm getRouteAlgorithm(){
|
|
||||||
return routeAlgorithm;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[name=bestInsertion]";
|
return "[name=bestInsertion]";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
||||||
Collections.shuffle(unassignedJobList, random);
|
Collections.shuffle(unassignedJobList, random);
|
||||||
informInsertionStarts(vehicleRoutes,unassignedJobs.size());
|
|
||||||
int inserted = 0;
|
|
||||||
List<String> reasons = new ArrayList<String>();
|
|
||||||
for(Job unassignedJob : unassignedJobList){
|
for(Job unassignedJob : unassignedJobList){
|
||||||
|
|
||||||
VehicleRoute insertIn = null;
|
|
||||||
Insertion bestInsertion = null;
|
Insertion bestInsertion = null;
|
||||||
double bestInsertionCost = Double.MAX_VALUE;
|
double bestInsertionCost = Double.MAX_VALUE;
|
||||||
for(VehicleRoute vehicleRoute : vehicleRoutes){
|
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) {
|
if(iData instanceof NoInsertionFound) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -103,56 +93,54 @@ final class BestInsertion extends AbstractInsertionStrategy{
|
||||||
}
|
}
|
||||||
if(!minVehiclesFirst){
|
if(!minVehiclesFirst){
|
||||||
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
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){
|
if(newIData.getInsertionCost() < bestInsertionCost){
|
||||||
bestInsertion = new Insertion(newRoute,newIData);
|
bestInsertion = new Insertion(newRoute,newIData);
|
||||||
bestInsertionCost = newIData.getInsertionCost();
|
bestInsertionCost = newIData.getInsertionCost();
|
||||||
vehicleRoutes.add(newRoute);
|
vehicleRoutes.add(newRoute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(bestInsertion != null){
|
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");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
||||||
InsertionData bestI = routeAlgorithm.calculateBestInsertion(newRoute, unassignedJob, Double.MAX_VALUE);
|
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){
|
if(bestI instanceof InsertionData.NoInsertionFound){
|
||||||
if(allowUnassignedJobs){
|
throw new IllegalStateException(getErrorMsg(unassignedJob));
|
||||||
logger.warn("cannot insert job yet " + unassignedJob);
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
for(String s : reasons){
|
bestInsertion = new Insertion(newRoute,bestI);
|
||||||
System.out.println("reason="+s);
|
vehicleRoutes.add(newRoute);
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("given the vehicles, could not insert job\n" +
|
}
|
||||||
|
|
||||||
|
inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||||
|
|
||||||
|
}
|
||||||
|
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getErrorMsg(Job unassignedJob) {
|
||||||
|
return "given the vehicles, could not insert job\n" +
|
||||||
"\t" + unassignedJob +
|
"\t" + unassignedJob +
|
||||||
"\n\tthis might have the following reasons:\n" +
|
"\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- 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- 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]"
|
"\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);
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
insertIn = newRoute;
|
@Override
|
||||||
informBeforeJobInsertion(unassignedJob,bestI,newRoute);
|
public Collection<InsertionListener> getListeners() {
|
||||||
routeAlgorithm.insertJob(unassignedJob,bestI,newRoute);
|
return Collections.unmodifiableCollection(insertionsListeners.getListeners());
|
||||||
vehicleRoutes.add(newRoute);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
@Override
|
||||||
inserted++;
|
public void addListener(InsertionListener insertionListener) {
|
||||||
informJobInserted((unassignedJobList.size()-inserted), unassignedJob, insertIn);
|
insertionsListeners.addListener(insertionListener);
|
||||||
}
|
|
||||||
informInsertionEndsListeners(vehicleRoutes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,170 +30,185 @@ import org.apache.log4j.Logger;
|
||||||
import util.RandomNumberGeneration;
|
import util.RandomNumberGeneration;
|
||||||
import algorithms.InsertionData.NoInsertionFound;
|
import algorithms.InsertionData.NoInsertionFound;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
|
import basics.algo.InsertionListener;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
/**
|
///**
|
||||||
*
|
// *
|
||||||
* @author stefan schroeder
|
// * @author stefan schroeder
|
||||||
*
|
// *
|
||||||
*/
|
// */
|
||||||
|
//
|
||||||
final class BestInsertionConcurrent extends AbstractInsertionStrategy{
|
//final class BestInsertionConcurrent implements InsertionStrategy{
|
||||||
|
//
|
||||||
public static BestInsertionConcurrent newInstance(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads){
|
// public static BestInsertionConcurrent newInstance(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads){
|
||||||
return new BestInsertionConcurrent(routeAlgorithm, executor, 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());
|
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
|
// 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 {
|
// else {
|
||||||
vehicleRoutes.add(VehicleRoute.emptyRoute());
|
//// 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());
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//// else{
|
||||||
|
// vehicleRoutes.add(VehicleRoute.emptyRoute());
|
||||||
|
//// }
|
||||||
|
// /*
|
||||||
|
// * distribute routes to batches equally
|
||||||
|
// */
|
||||||
|
// int count = 0;
|
||||||
|
// for(VehicleRoute route : vehicleRoutes){
|
||||||
|
// if(count == nuOfBatches) count=0;
|
||||||
|
// batches.get(count).routes.add(route);
|
||||||
|
// count++;
|
||||||
|
// }
|
||||||
|
// return batches;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// @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
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
//}
|
//}
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
14
jsprit-core/src/main/java/algorithms/CalcUtils.java
Normal file
14
jsprit-core/src/main/java/algorithms/CalcUtils.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -15,21 +15,19 @@ package algorithms;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import util.Neighborhood;
|
import util.Neighborhood;
|
||||||
|
import algorithms.HardConstraints.HardRouteLevelConstraint;
|
||||||
import algorithms.RouteStates.ActivityState;
|
import algorithms.MarginalsCalculus.Marginals;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.costs.VehicleRoutingActivityCosts;
|
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
import basics.route.Driver;
|
import basics.route.Driver;
|
||||||
import basics.route.End;
|
import basics.route.End;
|
||||||
import basics.route.ServiceActivity;
|
import basics.route.ServiceActivity;
|
||||||
import basics.route.Start;
|
import basics.route.Start;
|
||||||
import basics.route.TourActivities;
|
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
import basics.route.VehicleRoute;
|
|
||||||
import basics.route.VehicleImpl.NoVehicle;
|
import basics.route.VehicleImpl.NoVehicle;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -37,15 +35,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertion.class);
|
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertion.class);
|
||||||
|
|
||||||
private RouteStates routeStates;
|
private HardRouteLevelConstraint hardRouteLevelConstraint;
|
||||||
|
|
||||||
private VehicleRoutingTransportCosts routingCosts;
|
|
||||||
|
|
||||||
private VehicleRoutingActivityCosts activityCosts;
|
|
||||||
|
|
||||||
private Start start;
|
|
||||||
|
|
||||||
private End end;
|
|
||||||
|
|
||||||
private Neighborhood neighborhood = new Neighborhood() {
|
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) {
|
public void setNeighborhood(Neighborhood neighborhood) {
|
||||||
this.neighborhood = neighborhood;
|
this.neighborhood = neighborhood;
|
||||||
logger.info("initialise neighborhood " + neighborhood);
|
logger.info("initialise neighborhood " + neighborhood);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setActivityStates(RouteStates actStates){
|
public CalculatesServiceInsertion(VehicleRoutingTransportCosts routingCosts, MarginalsCalculus marginalsCalculus, HardRouteLevelConstraint hardRouteLevelConstraint) {
|
||||||
this.routeStates = actStates;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActivityState state(TourActivity act){
|
|
||||||
return routeStates.getState(act);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CalculatesServiceInsertion(VehicleRoutingTransportCosts vehicleRoutingTransportCosts, VehicleRoutingActivityCosts vehicleRoutingActivityCosts) {
|
|
||||||
super();
|
super();
|
||||||
this.routingCosts = vehicleRoutingTransportCosts;
|
this.marginalCalculus = marginalsCalculus;
|
||||||
this.activityCosts = vehicleRoutingActivityCosts;
|
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
|
||||||
|
this.transportCosts = routingCosts;
|
||||||
logger.info("initialise " + this);
|
logger.info("initialise " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,118 +77,67 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
||||||
if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing.");
|
if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing.");
|
||||||
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing.");
|
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing.");
|
||||||
|
|
||||||
TourActivities tour = currentRoute.getTourActivities();
|
InsertionContext insertionContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
|
||||||
double bestCost = bestKnownCosts;
|
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
|
||||||
Service service = (Service)jobToInsert;
|
|
||||||
|
|
||||||
if(routeStates.getRouteState(currentRoute).getLoad() + service.getCapacityDemand() > newVehicle.getCapacity()){
|
|
||||||
return InsertionData.noInsertionFound();
|
return InsertionData.noInsertionFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double bestCost = bestKnownCosts;
|
||||||
|
Marginals bestMarginals = null;
|
||||||
|
Service service = (Service)jobToInsert;
|
||||||
int insertionIndex = InsertionData.NO_INDEX;
|
int insertionIndex = InsertionData.NO_INDEX;
|
||||||
|
|
||||||
TourActivity deliveryAct2Insert = ServiceActivity.newInstance(service);
|
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;
|
TourActivity prevAct = start;
|
||||||
double prevCostInOriginalTour = 0.0;
|
double prevActStartTime = newVehicleDepartureTime;
|
||||||
int actIndex = 0;
|
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())){
|
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);
|
Marginals mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
|
||||||
if(mc < bestCost){
|
if(mc != null){
|
||||||
bestCost = mc;
|
if(mc.getAdditionalCosts() < bestCost){
|
||||||
|
bestCost = mc.getAdditionalCosts();
|
||||||
|
bestMarginals = mc;
|
||||||
insertionIndex = actIndex;
|
insertionIndex = actIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prevCostInOriginalTour = nextCostInOriginalTour;
|
}
|
||||||
prevAct = nextAct;
|
prevAct = nextAct;
|
||||||
|
prevActStartTime = CalcUtils.getStartTimeAtAct(prevActStartTime, transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle), nextAct);
|
||||||
actIndex++;
|
actIndex++;
|
||||||
}
|
}
|
||||||
End nextAct = end;
|
End nextAct = end;
|
||||||
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
|
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);
|
Marginals mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
|
||||||
if(mc < bestCost){
|
if(mc != null) {
|
||||||
bestCost = mc;
|
if(mc.getAdditionalCosts() < bestCost){
|
||||||
|
bestCost = mc.getAdditionalCosts();
|
||||||
|
bestMarginals = mc;
|
||||||
insertionIndex = actIndex;
|
insertionIndex = actIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(insertionIndex == InsertionData.NO_INDEX) {
|
if(insertionIndex == InsertionData.NO_INDEX) {
|
||||||
return InsertionData.noInsertionFound();
|
return InsertionData.noInsertionFound();
|
||||||
}
|
}
|
||||||
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
|
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
|
||||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||||
|
insertionData.setAdditionalTime(bestMarginals.getAdditionalTime());
|
||||||
return insertionData;
|
return insertionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialiseStartAndEnd(final Vehicle newVehicle,
|
public Marginals calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double departureTimeAtPrevAct) {
|
||||||
double newVehicleDepartureTime) {
|
return marginalCalculus.calculate(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ package algorithms;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import algorithms.InsertionData.NoInsertionFound;
|
import algorithms.InsertionData.NoInsertionFound;
|
||||||
|
import algorithms.StateManager.State;
|
||||||
|
import algorithms.StateManager.States;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.route.Driver;
|
import basics.route.Driver;
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
|
|
@ -41,12 +43,12 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
|
||||||
|
|
||||||
private double solution_completeness_ratio = 0.5;
|
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();
|
super();
|
||||||
this.standardServiceInsertion = standardInsertionCalculator;
|
this.standardServiceInsertion = standardInsertionCalculator;
|
||||||
this.routeStates = routeStates;
|
this.states = activityStates2;
|
||||||
logger.info("inialise " + this);
|
logger.info("inialise " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,7 +86,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
|
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;
|
double currentFix = 0.0;
|
||||||
if(route.getVehicle() != null){
|
if(route.getVehicle() != null){
|
||||||
if(!(route.getVehicle() instanceof NoVehicle)){
|
if(!(route.getVehicle() instanceof NoVehicle)){
|
||||||
|
|
@ -98,7 +100,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
|
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 load = currentLoad + job.getCapacityDemand();
|
||||||
double currentRelFix = 0.0;
|
double currentRelFix = 0.0;
|
||||||
if(route.getVehicle() != null){
|
if(route.getVehicle() != null){
|
||||||
|
|
@ -113,4 +115,8 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
|
||||||
return relativeFixCost;
|
return relativeFixCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getCurrentLoad(VehicleRoute route) {
|
||||||
|
return (int) states.getRouteState(route, StateTypes.LOAD).toDouble();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import basics.costs.VehicleRoutingActivityCosts;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
import basics.route.Driver;
|
import basics.route.Driver;
|
||||||
import basics.route.End;
|
import basics.route.End;
|
||||||
|
import basics.route.ServiceActivity;
|
||||||
import basics.route.Start;
|
import basics.route.Start;
|
||||||
import basics.route.TourActivities;
|
import basics.route.TourActivities;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
|
|
@ -50,7 +51,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
|
|
||||||
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
|
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
|
||||||
|
|
||||||
private RouteStates routeStates;
|
private StateManager states;
|
||||||
|
|
||||||
private int nuOfActsForwardLooking = 0;
|
private int nuOfActsForwardLooking = 0;
|
||||||
|
|
||||||
|
|
@ -89,15 +90,11 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
logger.info("initialise " + this);
|
logger.info("initialise " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setActivityStates(RouteStates actStates){
|
|
||||||
this.routeStates = actStates;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActivityState state(TourActivity act){
|
public void setStates(StateManager activityStates2){
|
||||||
return routeStates.getState(act);
|
this.states = activityStates2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setNuOfActsForwardLooking(int nOfActsForwardLooking) {
|
void setNuOfActsForwardLooking(int nOfActsForwardLooking) {
|
||||||
this.nuOfActsForwardLooking = nOfActsForwardLooking;
|
this.nuOfActsForwardLooking = nOfActsForwardLooking;
|
||||||
logger.info("set [forwardLooking="+nOfActsForwardLooking+"]");
|
logger.info("set [forwardLooking="+nOfActsForwardLooking+"]");
|
||||||
|
|
@ -138,14 +135,14 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
/**
|
/**
|
||||||
* pre-check whether vehicle-capacity of new vehicle is sufficient to load service.
|
* 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();
|
return InsertionData.noInsertionFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* some inis
|
* some inis
|
||||||
*/
|
*/
|
||||||
TourActivity serviceAct2Insert = routeStates.getActivity(service, true);
|
TourActivity serviceAct2Insert = ServiceActivity.newInstance(service);
|
||||||
int best_insertion_index = InsertionData.NO_INDEX;
|
int best_insertion_index = InsertionData.NO_INDEX;
|
||||||
|
|
||||||
initialiseStartAndEnd(newVehicle, newVehicleDepartureTime);
|
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++){
|
for(int i=0;i<memorySize;i++){
|
||||||
InsertionData data = bestInsertionsQueue.poll();
|
InsertionData data = bestInsertionsQueue.poll();
|
||||||
if(data == null){
|
if(data == null){
|
||||||
|
|
@ -262,7 +267,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
/**
|
/**
|
||||||
* compute cost-diff of tour with and without new activity --> insertion_costs
|
* 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
|
* 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) {
|
private double pathCost_oldVehicle(VehicleRoute vehicleRoute, List<TourActivity> path) {
|
||||||
TourActivity act = path.get(path.size()-1);
|
TourActivity act = path.get(path.size()-1);
|
||||||
if(act instanceof End){
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -67,16 +67,7 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
|
||||||
else{
|
else{
|
||||||
relevantVehicles.addAll(fleetManager.getAvailableVehicles());
|
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){
|
for(Vehicle v : relevantVehicles){
|
||||||
double depTime = v.getEarliestDeparture();
|
double depTime = v.getEarliestDeparture();
|
||||||
InsertionData iData = insertionCalculator.calculate(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
|
InsertionData iData = insertionCalculator.calculate(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
|
||||||
|
|
@ -92,8 +83,4 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
|
||||||
return bestIData;
|
return bestIData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// private TypeKey makeTypeKey(VehicleType type, String locationId) {
|
|
||||||
// return new TypeKey(type,locationId);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,18 +22,10 @@ package algorithms;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.commons.configuration.XMLConfiguration;
|
|
||||||
|
|
||||||
import util.NeighborhoodImpl;
|
|
||||||
|
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblem.FleetComposition;
|
|
||||||
import basics.algo.InsertionListener;
|
import basics.algo.InsertionListener;
|
||||||
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
||||||
import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
|
|
||||||
import basics.costs.VehicleRoutingActivityCosts;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -70,7 +62,7 @@ class CalculatorBuilder {
|
||||||
|
|
||||||
private VehicleRoutingProblem vrp;
|
private VehicleRoutingProblem vrp;
|
||||||
|
|
||||||
private RouteStates activityStates;
|
private StateManager states;
|
||||||
|
|
||||||
private boolean local = true;
|
private boolean local = true;
|
||||||
|
|
||||||
|
|
@ -107,12 +99,12 @@ class CalculatorBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets activityStates. MUST be set.
|
* Sets activityStates. MUST be set.
|
||||||
|
* @param states TODO
|
||||||
*
|
*
|
||||||
* @param activityStates
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public CalculatorBuilder setActivityStates(RouteStates activityStates){
|
public CalculatorBuilder setStates(StateManager states){
|
||||||
this.activityStates = activityStates;
|
this.states = states;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,21 +176,21 @@ class CalculatorBuilder {
|
||||||
*/
|
*/
|
||||||
public JobInsertionCalculator build(){
|
public JobInsertionCalculator build(){
|
||||||
if(vrp == null) throw new IllegalStateException("vehicle-routing-problem is null, but it must be set (this.setVehicleRoutingProblem(vrp))");
|
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))");
|
if(fleetManager == null) throw new IllegalStateException("fleetManager is null, but it must be set (this.setVehicleFleetManager(fleetManager))");
|
||||||
JobInsertionCalculator baseCalculator = null;
|
JobInsertionCalculator baseCalculator = null;
|
||||||
CalculatorPlusListeners standardLocal = null;
|
CalculatorPlusListeners standardLocal = null;
|
||||||
if(local){
|
if(local){
|
||||||
standardLocal = createStandardLocal(vrp, activityStates);
|
standardLocal = createStandardLocal(vrp, states);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
standardLocal = createStandardRoute(vrp, activityStates,forwardLooking,memory);
|
standardLocal = createStandardRoute(vrp, states,forwardLooking,memory);
|
||||||
}
|
}
|
||||||
baseCalculator = standardLocal.getCalculator();
|
baseCalculator = standardLocal.getCalculator();
|
||||||
addAlgorithmListeners(standardLocal.getAlgorithmListener());
|
addAlgorithmListeners(standardLocal.getAlgorithmListener());
|
||||||
addInsertionListeners(standardLocal.getInsertionListener());
|
addInsertionListeners(standardLocal.getInsertionListener());
|
||||||
if(considerFixedCost){
|
if(considerFixedCost){
|
||||||
CalculatorPlusListeners withFixed = createCalculatorConsideringFixedCosts(vrp, baseCalculator, activityStates, weightOfFixedCost);
|
CalculatorPlusListeners withFixed = createCalculatorConsideringFixedCosts(vrp, baseCalculator, states, weightOfFixedCost);
|
||||||
baseCalculator = withFixed.getCalculator();
|
baseCalculator = withFixed.getCalculator();
|
||||||
addAlgorithmListeners(withFixed.getAlgorithmListener());
|
addAlgorithmListeners(withFixed.getAlgorithmListener());
|
||||||
addInsertionListeners(withFixed.getInsertionListener());
|
addInsertionListeners(withFixed.getInsertionListener());
|
||||||
|
|
@ -206,7 +198,7 @@ class CalculatorBuilder {
|
||||||
if(timeScheduling){
|
if(timeScheduling){
|
||||||
baseCalculator = new CalculatesServiceInsertionWithTimeScheduling(baseCalculator,timeSlice,neighbors);
|
baseCalculator = new CalculatesServiceInsertionWithTimeScheduling(baseCalculator,timeSlice,neighbors);
|
||||||
}
|
}
|
||||||
return createFinalInsertion(fleetManager, baseCalculator, activityStates);
|
return createFinalInsertion(fleetManager, baseCalculator, states);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addInsertionListeners(List<InsertionListener> list) {
|
private void addInsertionListeners(List<InsertionListener> list) {
|
||||||
|
|
@ -221,35 +213,36 @@ class CalculatorBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, RouteStates activityStates){
|
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateManager activityStates2){
|
||||||
JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), vrp.getActivityCosts());
|
MarginalsCalculus defaultCalc = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), new HardConstraints.HardTimeWindowConstraint(activityStates2) );
|
||||||
((CalculatesServiceInsertion) standardServiceInsertion).setActivityStates(activityStates);
|
JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), defaultCalc, new HardConstraints.HardLoadConstraint(activityStates2));
|
||||||
|
|
||||||
((CalculatesServiceInsertion) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
|
((CalculatesServiceInsertion) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
|
||||||
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion);
|
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion);
|
||||||
|
|
||||||
return calcPlusListeners;
|
return calcPlusListeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCalculator baseCalculator, RouteStates activityStates, double weightOfFixedCosts){
|
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCalculator baseCalculator, StateManager activityStates2, double weightOfFixedCosts){
|
||||||
final CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(baseCalculator, activityStates);
|
final CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(baseCalculator, activityStates2);
|
||||||
withFixCost.setWeightOfFixCost(weightOfFixedCosts);
|
withFixCost.setWeightOfFixCost(weightOfFixedCosts);
|
||||||
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost);
|
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost);
|
||||||
calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost));
|
calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost));
|
||||||
return calcPlusListeners;
|
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;
|
int after = forwardLooking;
|
||||||
JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts());
|
JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||||
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNuOfActsForwardLooking(after);
|
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNuOfActsForwardLooking(after);
|
||||||
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setMemorySize(solutionMemory);
|
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setMemorySize(solutionMemory);
|
||||||
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood());
|
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood());
|
||||||
((CalculatesServiceInsertionOnRouteLevel) jobInsertionCalculator).setActivityStates(activityStates);
|
((CalculatesServiceInsertionOnRouteLevel) jobInsertionCalculator).setStates(activityStates2);
|
||||||
CalculatorPlusListeners calcPlusListener = new CalculatorPlusListeners(jobInsertionCalculator);
|
CalculatorPlusListeners calcPlusListener = new CalculatorPlusListeners(jobInsertionCalculator);
|
||||||
return calcPlusListener;
|
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);
|
return new CalculatesVehTypeDepServiceInsertion(fleetManager, baseCalc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ final class ConfigureFixCostCalculator implements InsertionStartsListener, JobIn
|
||||||
|
|
||||||
CalculatesServiceInsertionConsideringFixCost calcConsideringFix;
|
CalculatesServiceInsertionConsideringFixCost calcConsideringFix;
|
||||||
|
|
||||||
|
private int nuOfJobsToRecreate;
|
||||||
|
|
||||||
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, CalculatesServiceInsertionConsideringFixCost calcConsideringFix) {
|
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, CalculatesServiceInsertionConsideringFixCost calcConsideringFix) {
|
||||||
super();
|
super();
|
||||||
this.vrp = vrp;
|
this.vrp = vrp;
|
||||||
|
|
@ -55,15 +57,17 @@ final class ConfigureFixCostCalculator implements InsertionStartsListener, JobIn
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> routes, int nOfJobs2Recreate) {
|
public void informInsertionStarts(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||||
double completenessRatio = (1-((double)nOfJobs2Recreate/(double)vrp.getJobs().values().size()));
|
this.nuOfJobsToRecreate = unassignedJobs.size();
|
||||||
|
double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)vrp.getJobs().values().size()));
|
||||||
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
|
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
|
||||||
// log.debug("initialise completenessRatio to " + completenessRatio);
|
// log.debug("initialise completenessRatio to " + completenessRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informJobInserted(int nOfJobsStill2Recreate, Job job2insert, VehicleRoute insertedIn) {
|
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
|
||||||
double completenessRatio = (1-((double)nOfJobsStill2Recreate/(double)vrp.getJobs().values().size()));
|
nuOfJobsToRecreate--;
|
||||||
|
double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)vrp.getJobs().values().size()));
|
||||||
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
|
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
|
||||||
// log.debug("set completenessRatio to " + completenessRatio);
|
// log.debug("set completenessRatio to " + completenessRatio);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ final class CreateInitialSolution implements InitialSolutionFactory {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(CreateInitialSolution.class);
|
private static final Logger logger = Logger.getLogger(CreateInitialSolution.class);
|
||||||
|
|
||||||
private final AbstractInsertionStrategy insertion;
|
private final InsertionStrategy insertion;
|
||||||
|
|
||||||
private boolean generateAsMuchAsRoutesAsVehiclesExist = false;
|
private boolean generateAsMuchAsRoutesAsVehiclesExist = false;
|
||||||
|
|
||||||
|
|
@ -59,9 +59,9 @@ final class CreateInitialSolution implements InitialSolutionFactory {
|
||||||
this.generateAsMuchAsRoutesAsVehiclesExist = generateAsMuchAsRoutesAsVehiclesExist;
|
this.generateAsMuchAsRoutesAsVehiclesExist = generateAsMuchAsRoutesAsVehiclesExist;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CreateInitialSolution(AbstractInsertionStrategy insertion) {
|
public CreateInitialSolution(InsertionStrategy insertionStrategy) {
|
||||||
super();
|
super();
|
||||||
this.insertion = insertion;
|
this.insertion = insertionStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -73,7 +73,7 @@ final class CreateInitialSolution implements InitialSolutionFactory {
|
||||||
vehicleRoutes.add(VehicleRoute.newInstance(TourActivities.emptyTour(), DriverImpl.noDriver(), vehicle));
|
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);
|
double totalCost = getTotalCost(vehicleRoutes);
|
||||||
logger.info("creation done");
|
logger.info("creation done");
|
||||||
return new VehicleRoutingProblemSolution(vehicleRoutes, totalCost);
|
return new VehicleRoutingProblemSolution(vehicleRoutes, totalCost);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import basics.Job;
|
||||||
import basics.algo.InsertionStartsListener;
|
import basics.algo.InsertionStartsListener;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
@ -37,7 +38,7 @@ class FindCheaperVehicle implements InsertionStartsListener{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate) {
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
List<VehicleRoute> newRoutes = new ArrayList<VehicleRoute>();
|
List<VehicleRoute> newRoutes = new ArrayList<VehicleRoute>();
|
||||||
for(VehicleRoute route : vehicleRoutes){
|
for(VehicleRoute route : vehicleRoutes){
|
||||||
if(route.isEmpty()) continue;
|
if(route.isEmpty()) continue;
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ final class FindCheaperVehicleAlgo {
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
TourActivities newTour = TourActivities.copyOf(vehicleRoute.getTourActivities());
|
TourActivities newTour = TourActivities.copyOf(vehicleRoute.getTourActivities());
|
||||||
tourStateCalculator.updateRoute(vehicleRoute);
|
tourStateCalculator.iterate(vehicleRoute);
|
||||||
return VehicleRoute.newInstance(newTour,vehicleRoute.getDriver(),bestVehicle);
|
return VehicleRoute.newInstance(newTour,vehicleRoute.getDriver(),bestVehicle);
|
||||||
}
|
}
|
||||||
return vehicleRoute;
|
return vehicleRoute;
|
||||||
|
|
|
||||||
|
|
@ -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); }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
@ -30,20 +31,19 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import util.RandomNumberGeneration;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import basics.VehicleRoutingProblemSolution;
|
||||||
import basics.algo.SearchStrategyModule;
|
import basics.algo.SearchStrategyModule;
|
||||||
import basics.algo.SearchStrategyModuleListener;
|
import basics.algo.SearchStrategyModuleListener;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
import basics.route.VehicleRoute;
|
|
||||||
import basics.route.TourActivity.JobActivity;
|
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(Gendreau.class);
|
||||||
|
|
||||||
private final static Logger log = Logger.getLogger(GendreauPostOpt.class);
|
|
||||||
|
|
||||||
private final static String NAME = "gendreauPostOpt";
|
private final static String NAME = "gendreauPostOpt";
|
||||||
|
|
||||||
|
|
@ -51,9 +51,9 @@ final class GendreauPostOpt implements SearchStrategyModule{
|
||||||
|
|
||||||
private final VehicleRoutingProblem vrp;
|
private final VehicleRoutingProblem vrp;
|
||||||
|
|
||||||
private final AbstractInsertionStrategy insertionStrategy;
|
private final InsertionStrategy insertionStrategy;
|
||||||
|
|
||||||
private final RouteAlgorithm routeAlgorithm;
|
private final Inserter inserter;
|
||||||
|
|
||||||
private VehicleFleetManager fleetManager;
|
private VehicleFleetManager fleetManager;
|
||||||
|
|
||||||
|
|
@ -67,9 +67,11 @@ final class GendreauPostOpt implements SearchStrategyModule{
|
||||||
this.shareOfJobsToRuin = shareOfJobsToRuin;
|
this.shareOfJobsToRuin = shareOfJobsToRuin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GendreauPostOpt(VehicleRoutingProblem vrp, RuinStrategy ruin, AbstractInsertionStrategy insertionStrategy) {
|
public Gendreau(VehicleRoutingProblem vrp, RuinStrategy ruin, InsertionStrategy insertionStrategy) {
|
||||||
super();
|
super();
|
||||||
this.routeAlgorithm = insertionStrategy.getRouteAlgorithm();
|
InsertionListeners insertionListeners = new InsertionListeners();
|
||||||
|
insertionListeners.addAllListeners(insertionStrategy.getListeners());
|
||||||
|
inserter = new Inserter(insertionListeners);
|
||||||
this.ruin = ruin;
|
this.ruin = ruin;
|
||||||
this.vrp = vrp;
|
this.vrp = vrp;
|
||||||
this.insertionStrategy = insertionStrategy;
|
this.insertionStrategy = insertionStrategy;
|
||||||
|
|
@ -77,7 +79,7 @@ final class GendreauPostOpt implements SearchStrategyModule{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[name=gendreauPostOpt][iterations="+nOfIterations+"][share2ruin="+shareOfJobsToRuin+"]";
|
return "[name=gendreau][iterations="+nOfIterations+"][share2ruin="+shareOfJobsToRuin+"]";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRandom(Random random) {
|
public void setRandom(Random random) {
|
||||||
|
|
@ -119,16 +121,18 @@ final class GendreauPostOpt implements SearchStrategyModule{
|
||||||
|
|
||||||
VehicleRoute emptyRoute1 = VehicleRoute.emptyRoute();
|
VehicleRoute emptyRoute1 = VehicleRoute.emptyRoute();
|
||||||
copiedRoutes.add(emptyRoute1);
|
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);
|
unassignedJobs.remove(targetJob);
|
||||||
|
|
||||||
VehicleRoute emptyRoute2 = VehicleRoute.emptyRoute();
|
VehicleRoute emptyRoute2 = VehicleRoute.emptyRoute();
|
||||||
copiedRoutes.add(emptyRoute2);
|
copiedRoutes.add(emptyRoute2);
|
||||||
Job job2 = jobsInRoute.get(1);
|
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);
|
unassignedJobs.remove(job2);
|
||||||
|
|
||||||
insertionStrategy.run(copiedRoutes, unassignedJobs, Double.MAX_VALUE);
|
insertionStrategy.insertJobs(copiedRoutes, unassignedJobs);
|
||||||
double cost = getCost(copiedRoutes);
|
double cost = getCost(copiedRoutes);
|
||||||
|
|
||||||
if(cost < bestSolution.getCost()){
|
if(cost < bestSolution.getCost()){
|
||||||
59
jsprit-core/src/main/java/algorithms/HardConstraints.java
Normal file
59
jsprit-core/src/main/java/algorithms/HardConstraints.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
36
jsprit-core/src/main/java/algorithms/Inserter.java
Normal file
36
jsprit-core/src/main/java/algorithms/Inserter.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
63
jsprit-core/src/main/java/algorithms/InsertionContext.java
Normal file
63
jsprit-core/src/main/java/algorithms/InsertionContext.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -55,6 +55,22 @@ class InsertionData {
|
||||||
|
|
||||||
private double departureTime;
|
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){
|
public InsertionData(double insertionCost, int pickupInsertionIndex, int deliveryInsertionIndex, Vehicle vehicle, Driver driver){
|
||||||
this.insertionCost = insertionCost;
|
this.insertionCost = insertionCost;
|
||||||
this.pickupInsertionIndex = pickupInsertionIndex;
|
this.pickupInsertionIndex = pickupInsertionIndex;
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@ class InsertionFactory {
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(InsertionFactory.class);
|
private static Logger log = Logger.getLogger(InsertionFactory.class);
|
||||||
|
|
||||||
public static AbstractInsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
|
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
|
||||||
VehicleFleetManager vehicleFleetManager, RouteStates activityStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads){
|
VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads){
|
||||||
boolean concurrentInsertion = false;
|
boolean concurrentInsertion = false;
|
||||||
if(executorService != null) concurrentInsertion = true;
|
if(executorService != null) concurrentInsertion = true;
|
||||||
if(config.containsKey("[@name]")){
|
if(config.containsKey("[@name]")){
|
||||||
|
|
@ -46,12 +46,12 @@ class InsertionFactory {
|
||||||
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
|
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
|
||||||
new IllegalStateException(insertionName + " is not supported. use either \"bestInsertion\" or \"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<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();
|
||||||
List<PrioritizedVRAListener> algoListeners = new ArrayList<PrioritizedVRAListener>();
|
List<PrioritizedVRAListener> algoListeners = new ArrayList<PrioritizedVRAListener>();
|
||||||
|
|
||||||
CalculatorBuilder calcBuilder = new CalculatorBuilder(insertionListeners, algorithmListeners);
|
CalculatorBuilder calcBuilder = new CalculatorBuilder(insertionListeners, algorithmListeners);
|
||||||
calcBuilder.setActivityStates(activityStates);
|
calcBuilder.setStates(routeStates);
|
||||||
calcBuilder.setVehicleRoutingProblem(vrp);
|
calcBuilder.setVehicleRoutingProblem(vrp);
|
||||||
calcBuilder.setVehicleFleetManager(vehicleFleetManager);
|
calcBuilder.setVehicleFleetManager(vehicleFleetManager);
|
||||||
|
|
||||||
|
|
@ -94,34 +94,23 @@ class InsertionFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
JobInsertionCalculator jic = calcBuilder.build();
|
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(insertionName.equals("bestInsertion")){
|
||||||
if(concurrentInsertion){
|
insertionStrategy = new BestInsertion(jic);
|
||||||
insertionStrategy = BestInsertionConcurrent.newInstance(routeAlgorithm,executorService,nuOfThreads);
|
|
||||||
}
|
}
|
||||||
else{
|
// else if(insertionName.equals("regretInsertion")){
|
||||||
insertionStrategy = BestInsertion.newInstance(routeAlgorithm);
|
// insertionStrategy = RegretInsertion.newInstance(routeAlgorithm);
|
||||||
}
|
|
||||||
}
|
|
||||||
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,)
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager));
|
insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager));
|
||||||
insertionStrategy.addListener(new ResetAndIniFleetManager(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(
|
// insertionStrategy.addListener(new FindCheaperVehicle(
|
||||||
// new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator)));
|
// new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator)));
|
||||||
|
|
||||||
|
|
|
||||||
74
jsprit-core/src/main/java/algorithms/InsertionListeners.java
Normal file
74
jsprit-core/src/main/java/algorithms/InsertionListeners.java
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,7 @@ package algorithms;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
|
import basics.algo.InsertionListener;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -59,8 +60,13 @@ interface InsertionStrategy {
|
||||||
*
|
*
|
||||||
* @param vehicleRoutes
|
* @param vehicleRoutes
|
||||||
* @param unassignedJobs
|
* @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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -76,14 +76,14 @@ class JobObserver implements JobInsertedListener, BeforeJobInsertionListener, Al
|
||||||
Collection<Info> infos = new ArrayList<Info>();
|
Collection<Info> infos = new ArrayList<Info>();
|
||||||
|
|
||||||
@Override
|
@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(job2insert instanceof Service){
|
||||||
if(((Service) job2insert).getLocationId().equals(locationId)){
|
if(((Service) job2insert).getLocationId().equals(locationId)){
|
||||||
double actualMC = insertedIn.getCost()-routeCostBefore;
|
double actualMC = inRoute.getCost()-routeCostBefore;
|
||||||
TourActivity act = getAct(job2insert,insertedIn);
|
TourActivity act = getAct(job2insert,inRoute);
|
||||||
double error = (estimatedMC-actualMC);
|
double error = (estimatedMC-actualMC);
|
||||||
int tourSize = insertedIn.getTourActivities().getActivities().size();
|
int tourSize = inRoute.getTourActivities().getActivities().size();
|
||||||
int insertionIndex = getIndexOf(job2insert, insertedIn);
|
int insertionIndex = getIndexOf(job2insert, inRoute);
|
||||||
// infos.add(new Info())
|
// infos.add(new Info())
|
||||||
double depTime = state(act).getEarliestOperationStart()+act.getOperationTime();
|
double depTime = state(act).getEarliestOperationStart()+act.getOperationTime();
|
||||||
infos.add(new Info(depTime,tourSize,insertionIndex,error));
|
infos.add(new Info(depTime,tourSize,insertionIndex,error));
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
35
jsprit-core/src/main/java/algorithms/MarginalsCalculus.java
Normal file
35
jsprit-core/src/main/java/algorithms/MarginalsCalculus.java
Normal 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,210 +1,229 @@
|
||||||
/*******************************************************************************
|
///*******************************************************************************
|
||||||
* Copyright (c) 2011 Stefan Schroeder.
|
// * Copyright (c) 2011 Stefan Schroeder.
|
||||||
* eMail: stefan.schroeder@kit.edu
|
// * eMail: stefan.schroeder@kit.edu
|
||||||
*
|
// *
|
||||||
* All rights reserved. This program and the accompanying materials
|
// * All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the GNU Public License v2.0
|
// * are made available under the terms of the GNU Public License v2.0
|
||||||
* which accompanies this distribution, and is available at
|
// * which accompanies this distribution, and is available at
|
||||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
// * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
*
|
// *
|
||||||
* Contributors:
|
// * Contributors:
|
||||||
* Stefan Schroeder - initial API and implementation
|
// * Stefan Schroeder - initial API and implementation
|
||||||
******************************************************************************/
|
// ******************************************************************************/
|
||||||
package algorithms;
|
//package algorithms;
|
||||||
|
//
|
||||||
import java.util.ArrayList;
|
//import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
//import java.util.Collection;
|
||||||
import java.util.List;
|
//import java.util.List;
|
||||||
|
//
|
||||||
import org.apache.log4j.Logger;
|
//import org.apache.log4j.Logger;
|
||||||
|
//
|
||||||
import algorithms.InsertionData.NoInsertionFound;
|
//import algorithms.InsertionData.NoInsertionFound;
|
||||||
import basics.Job;
|
//import basics.Job;
|
||||||
import basics.Service;
|
//import basics.Service;
|
||||||
import basics.route.VehicleRoute;
|
//import basics.algo.InsertionListener;
|
||||||
|
//import basics.route.VehicleRoute;
|
||||||
|
//
|
||||||
/**
|
//
|
||||||
* Insertion based an regret approach.
|
///**
|
||||||
*
|
// * 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.
|
// * <p>Basically calculates the insertion cost of the firstBest and the secondBest alternative. The score is then calculated as difference
|
||||||
* 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
|
// * between secondBest and firstBest, plus additional scoring variables that can defined in this.ScoringFunction.
|
||||||
* customer immediatedly. If difference is not that high, it might not impact solution if this customer is inserted later.
|
// * 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
|
// *
|
||||||
*
|
// * @author stefan schroeder
|
||||||
*/
|
// *
|
||||||
final class RegretInsertion extends AbstractInsertionStrategy{
|
// */
|
||||||
|
//final class RegretInsertion implements InsertionStrategy{
|
||||||
/**
|
//
|
||||||
* Scorer to include other impacts on score such as time-window length or distance to depot.
|
// /**
|
||||||
*
|
// * Scorer to include other impacts on score such as time-window length or distance to depot.
|
||||||
* @author schroeder
|
// *
|
||||||
*
|
// * @author schroeder
|
||||||
*/
|
// *
|
||||||
static interface ScoringFunction {
|
// */
|
||||||
|
// static interface ScoringFunction {
|
||||||
public double score(Job job);
|
//
|
||||||
|
// 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.
|
// /**
|
||||||
*
|
// * 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)
|
// *
|
||||||
*
|
// * <p>This is the default scorer, i.e.: score = (secondBest - firstBest) + this.TimeWindowScorer.score(job)
|
||||||
* @author schroeder
|
// *
|
||||||
*
|
// * @author schroeder
|
||||||
*/
|
// *
|
||||||
static class TimeWindowScorer implements ScoringFunction {
|
// */
|
||||||
|
// static class TimeWindowScorer implements ScoringFunction {
|
||||||
private double tw_scoringParam = - 0.1;
|
//
|
||||||
|
// private double tw_scoringParam = - 0.1;
|
||||||
@Override
|
//
|
||||||
public double score(Job job) {
|
// @Override
|
||||||
double twStart = 0.0;
|
// public double score(Job job) {
|
||||||
double twEnd = 0.0;
|
// double twStart = 0.0;
|
||||||
// if(job instanceof Shipment){
|
// double twEnd = 0.0;
|
||||||
// twStart = ((Shipment) job).getDeliveryTW().getStart();
|
//// if(job instanceof Shipment){
|
||||||
// twEnd = ((Shipment) job).getDeliveryTW().getEnd();
|
//// 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();
|
||||||
|
// }
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
//}
|
//}
|
||||||
// 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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,12 @@ import java.util.List;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
import basics.Job;
|
||||||
import basics.algo.InsertionEndsListener;
|
import basics.algo.InsertionEndsListener;
|
||||||
import basics.algo.InsertionStartsListener;
|
import basics.algo.InsertionStartsListener;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
class RemoveEmptyVehicles implements InsertionStartsListener, InsertionEndsListener{
|
class RemoveEmptyVehicles implements InsertionEndsListener{
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(RemoveEmptyVehicles.class);
|
private static Logger log = Logger.getLogger(RemoveEmptyVehicles.class);
|
||||||
|
|
||||||
|
|
@ -41,21 +42,6 @@ class RemoveEmptyVehicles implements InsertionStartsListener, InsertionEndsListe
|
||||||
this.fleetManager = fleetManager;
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[name=removeEmptyVehicles]";
|
return "[name=removeEmptyVehicles]";
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import java.util.Collection;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import basics.Job;
|
||||||
import basics.algo.InsertionStartsListener;
|
import basics.algo.InsertionStartsListener;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
@ -40,16 +41,16 @@ class ResetAndIniFleetManager implements InsertionStartsListener{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate) {
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
vehicleFleetManager.unlockAll();
|
vehicleFleetManager.unlockAll();
|
||||||
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
|
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
|
||||||
for(VehicleRoute route : routes){
|
for(VehicleRoute route : routes){
|
||||||
if(route.isEmpty()){
|
// if(route.isEmpty()){
|
||||||
vehicleRoutes.remove(route);
|
// vehicleRoutes.remove(route);
|
||||||
}
|
// }
|
||||||
else{
|
// else{
|
||||||
vehicleFleetManager.lock(route.getVehicle());
|
vehicleFleetManager.lock(route.getVehicle());
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
38
jsprit-core/src/main/java/algorithms/RuinListeners.java
Normal file
38
jsprit-core/src/main/java/algorithms/RuinListeners.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,30 +29,12 @@ import util.RandomNumberGeneration;
|
||||||
import util.StopWatch;
|
import util.StopWatch;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
|
||||||
import basics.algo.SearchStrategyModule;
|
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
final class RuinRadial implements RuinStrategy {
|
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 {
|
static class ReferencedJob {
|
||||||
private Job job;
|
private Job job;
|
||||||
private double distance;
|
private double distance;
|
||||||
|
|
@ -84,21 +66,18 @@ final class RuinRadial implements RuinStrategy {
|
||||||
|
|
||||||
private JobDistance jobDistance;
|
private JobDistance jobDistance;
|
||||||
|
|
||||||
private JobRemover jobRemover;
|
private RuinListeners ruinListeners;
|
||||||
|
|
||||||
private VehicleRouteUpdater routeUpdater;
|
|
||||||
|
|
||||||
public void setRandom(Random random) {
|
public void setRandom(Random random) {
|
||||||
this.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();
|
super();
|
||||||
this.vrp = vrp;
|
this.vrp = vrp;
|
||||||
this.jobDistance = jobDistance;
|
this.jobDistance = jobDistance;
|
||||||
this.jobRemover = jobRemover;
|
|
||||||
this.routeUpdater = routeUpdater;
|
|
||||||
this.fractionOfAllNodes2beRuined = fraction;
|
this.fractionOfAllNodes2beRuined = fraction;
|
||||||
|
ruinListeners = new RuinListeners();
|
||||||
calculateDistancesFromJob2Job();
|
calculateDistancesFromJob2Job();
|
||||||
logger.info("intialise " + this);
|
logger.info("intialise " + this);
|
||||||
}
|
}
|
||||||
|
|
@ -158,6 +137,7 @@ final class RuinRadial implements RuinStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved){
|
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved){
|
||||||
|
ruinListeners.ruinStarts(vehicleRoutes);
|
||||||
List<Job> unassignedJobs = new ArrayList<Job>();
|
List<Job> unassignedJobs = new ArrayList<Job>();
|
||||||
TreeSet<ReferencedJob> tree = distanceNodeTree.get(targetJob.getId());
|
TreeSet<ReferencedJob> tree = distanceNodeTree.get(targetJob.getId());
|
||||||
Iterator<ReferencedJob> descendingIterator = tree.descendingIterator();
|
Iterator<ReferencedJob> descendingIterator = tree.descendingIterator();
|
||||||
|
|
@ -169,15 +149,14 @@ final class RuinRadial implements RuinStrategy {
|
||||||
counter++;
|
counter++;
|
||||||
boolean removed = false;
|
boolean removed = false;
|
||||||
for (VehicleRoute route : vehicleRoutes) {
|
for (VehicleRoute route : vehicleRoutes) {
|
||||||
removed = jobRemover.removeJobWithoutTourUpdate(job, route);
|
removed = route.getTourActivities().removeJob(job);;
|
||||||
if (removed) {
|
if (removed) {
|
||||||
|
ruinListeners.removed(job,route);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(VehicleRoute route : vehicleRoutes){
|
ruinListeners.ruinEnds(vehicleRoutes, unassignedJobs);
|
||||||
routeUpdater.updateRoute(route);
|
|
||||||
}
|
|
||||||
return unassignedJobs;
|
return unassignedJobs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -193,15 +172,20 @@ final class RuinRadial implements RuinStrategy {
|
||||||
* fractionOfAllNodes2beRuined);
|
* fractionOfAllNodes2beRuined);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
@Override
|
||||||
// public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
|
public void addListener(RuinListener ruinListener) {
|
||||||
// ruin(vrpSolution.getRoutes());
|
ruinListeners.addListener(ruinListener);
|
||||||
// return vrpSolution;
|
}
|
||||||
// }
|
|
||||||
//
|
@Override
|
||||||
// @Override
|
public void removeListener(RuinListener ruinListener) {
|
||||||
// public String getName() {
|
ruinListeners.removeListener(ruinListener);
|
||||||
// return NAME;
|
}
|
||||||
// }
|
|
||||||
|
@Override
|
||||||
|
public Collection<RuinListener> getListeners() {
|
||||||
|
return ruinListeners.getListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,6 @@ import basics.route.VehicleRoute;
|
||||||
|
|
||||||
final class RuinRandom implements RuinStrategy {
|
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);
|
private Logger logger = Logger.getLogger(RuinRandom.class);
|
||||||
|
|
||||||
private VehicleRoutingProblem vrp;
|
private VehicleRoutingProblem vrp;
|
||||||
|
|
@ -48,9 +44,7 @@ final class RuinRandom implements RuinStrategy {
|
||||||
|
|
||||||
private Random random = RandomNumberGeneration.getRandom();
|
private Random random = RandomNumberGeneration.getRandom();
|
||||||
|
|
||||||
private JobRemover jobRemover;
|
private RuinListeners ruinListeners;
|
||||||
|
|
||||||
private VehicleRouteUpdater vehicleRouteUpdater;
|
|
||||||
|
|
||||||
public void setRandom(Random random) {
|
public void setRandom(Random random) {
|
||||||
this.random = random;
|
this.random = random;
|
||||||
|
|
@ -61,15 +55,12 @@ final class RuinRandom implements RuinStrategy {
|
||||||
*
|
*
|
||||||
* @param vrp
|
* @param vrp
|
||||||
* @param fraction which is the fraction of total c
|
* @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();
|
super();
|
||||||
this.vrp = vrp;
|
this.vrp = vrp;
|
||||||
this.jobRemover = jobRemover;
|
|
||||||
this.vehicleRouteUpdater = vehicleRouteUpdater;
|
|
||||||
this.fractionOfAllNodes2beRuined = fraction;
|
this.fractionOfAllNodes2beRuined = fraction;
|
||||||
|
ruinListeners = new RuinListeners();
|
||||||
logger.info("initialise " + this);
|
logger.info("initialise " + this);
|
||||||
logger.info("done");
|
logger.info("done");
|
||||||
}
|
}
|
||||||
|
|
@ -81,9 +72,11 @@ final class RuinRandom implements RuinStrategy {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes) {
|
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes) {
|
||||||
|
ruinListeners.ruinStarts(vehicleRoutes);
|
||||||
List<Job> unassignedJobs = new ArrayList<Job>();
|
List<Job> unassignedJobs = new ArrayList<Job>();
|
||||||
int nOfJobs2BeRemoved = selectNuOfJobs2BeRemoved();
|
int nOfJobs2BeRemoved = selectNuOfJobs2BeRemoved();
|
||||||
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
|
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
|
||||||
|
ruinListeners.ruinEnds(vehicleRoutes, unassignedJobs);
|
||||||
return unassignedJobs;
|
return unassignedJobs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,19 +85,22 @@ final class RuinRandom implements RuinStrategy {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
|
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
|
||||||
|
ruinListeners.ruinStarts(vehicleRoutes);
|
||||||
List<Job> unassignedJobs = new ArrayList<Job>();
|
List<Job> unassignedJobs = new ArrayList<Job>();
|
||||||
if(targetJob != null){
|
if(targetJob != null){
|
||||||
boolean removed = false;
|
boolean removed = false;
|
||||||
for (VehicleRoute route : vehicleRoutes) {
|
for (VehicleRoute route : vehicleRoutes) {
|
||||||
removed = jobRemover.removeJobWithoutTourUpdate(targetJob, route);
|
removed = route.getTourActivities().removeJob(targetJob);
|
||||||
if (removed) {
|
if (removed) {
|
||||||
nOfJobs2BeRemoved--;
|
nOfJobs2BeRemoved--;
|
||||||
unassignedJobs.add(targetJob);
|
unassignedJobs.add(targetJob);
|
||||||
|
ruinListeners.removed(targetJob,route);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
|
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
|
||||||
|
ruinListeners.ruinEnds(vehicleRoutes, unassignedJobs);
|
||||||
return unassignedJobs;
|
return unassignedJobs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,16 +116,12 @@ final class RuinRandom implements RuinStrategy {
|
||||||
unassignedJobs.add(job);
|
unassignedJobs.add(job);
|
||||||
availableJobs.remove(job);
|
availableJobs.remove(job);
|
||||||
for (VehicleRoute route : vehicleRoutes) {
|
for (VehicleRoute route : vehicleRoutes) {
|
||||||
boolean removed = jobRemover.removeJobWithoutTourUpdate(job, route);
|
boolean removed = route.getTourActivities().removeJob(job);
|
||||||
if (removed) break;
|
if (removed) {
|
||||||
|
ruinListeners.removed(job,route);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateRoutes(vehicleRoutes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
|
||||||
for(VehicleRoute route : vehicleRoutes){
|
|
||||||
vehicleRouteUpdater.updateRoute(route);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,4 +140,19 @@ final class RuinRandom implements RuinStrategy {
|
||||||
return (int) Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined);
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
@ -29,19 +28,62 @@ import basics.route.VehicleRoute;
|
||||||
|
|
||||||
interface RuinStrategy {
|
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 {
|
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
|
* Ruins a current solution, i.e. a collection of vehicle-routes and
|
||||||
* returns a collection of these removed, and thus unassigned, jobs.
|
* returns a collection of removed and thus unassigned jobs.
|
||||||
*
|
*
|
||||||
* @param vehicleRoutes
|
* @param {@link VehicleRoute}
|
||||||
* @return
|
* @return Collection of {@link Job}
|
||||||
*/
|
*/
|
||||||
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes);
|
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);
|
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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
52
jsprit-core/src/main/java/algorithms/StateManager.java
Normal file
52
jsprit-core/src/main/java/algorithms/StateManager.java
Normal 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);
|
||||||
|
|
||||||
|
}
|
||||||
121
jsprit-core/src/main/java/algorithms/StateManagerImpl.java
Normal file
121
jsprit-core/src/main/java/algorithms/StateManagerImpl.java
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
13
jsprit-core/src/main/java/algorithms/StateTypes.java
Normal file
13
jsprit-core/src/main/java/algorithms/StateTypes.java
Normal 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";
|
||||||
|
}
|
||||||
|
|
@ -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){
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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) {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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) {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
55
jsprit-core/src/main/java/algorithms/UpdateStates.java
Normal file
55
jsprit-core/src/main/java/algorithms/UpdateStates.java
Normal 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) {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -24,6 +24,6 @@ import basics.route.VehicleRoute;
|
||||||
|
|
||||||
interface VehicleRouteUpdater {
|
interface VehicleRouteUpdater {
|
||||||
|
|
||||||
public boolean updateRoute(VehicleRoute vehicleRoute);
|
public void iterate(VehicleRoute vehicleRoute);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ import org.apache.commons.configuration.XMLConfiguration;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import util.RouteUtils;
|
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.AbstractKey;
|
||||||
import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
|
import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
|
||||||
import algorithms.VehicleRoutingAlgorithms.TypedMap.RuinStrategyKey;
|
import algorithms.VehicleRoutingAlgorithms.TypedMap.RuinStrategyKey;
|
||||||
|
|
@ -56,19 +57,21 @@ import basics.VehicleRoutingProblem.FleetSize;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import basics.VehicleRoutingProblemSolution;
|
||||||
import basics.algo.AlgorithmStartsListener;
|
import basics.algo.AlgorithmStartsListener;
|
||||||
import basics.algo.InsertionListener;
|
import basics.algo.InsertionListener;
|
||||||
|
import basics.algo.IterationStartsListener;
|
||||||
import basics.algo.IterationWithoutImprovementBreaker;
|
import basics.algo.IterationWithoutImprovementBreaker;
|
||||||
import basics.algo.PrematureAlgorithmBreaker;
|
import basics.algo.PrematureAlgorithmBreaker;
|
||||||
import basics.algo.SearchStrategy;
|
import basics.algo.SearchStrategy;
|
||||||
|
import basics.algo.SearchStrategy.DiscoveredSolution;
|
||||||
import basics.algo.SearchStrategyManager;
|
import basics.algo.SearchStrategyManager;
|
||||||
import basics.algo.SearchStrategyModule;
|
import basics.algo.SearchStrategyModule;
|
||||||
import basics.algo.SearchStrategyModuleListener;
|
import basics.algo.SearchStrategyModuleListener;
|
||||||
import basics.algo.TimeBreaker;
|
import basics.algo.TimeBreaker;
|
||||||
import basics.algo.VariationCoefficientBreaker;
|
import basics.algo.VariationCoefficientBreaker;
|
||||||
import basics.algo.SearchStrategy.DiscoveredSolution;
|
|
||||||
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
||||||
import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
|
import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
|
||||||
import basics.io.AlgorithmConfig;
|
import basics.io.AlgorithmConfig;
|
||||||
import basics.io.AlgorithmConfigXmlReader;
|
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;
|
private ModKey modKey;
|
||||||
|
|
||||||
public AbstractInsertionKey(ModKey modKey) {
|
public InsertionStrategyKey(ModKey modKey) {
|
||||||
super();
|
super();
|
||||||
this.modKey = modKey;
|
this.modKey = modKey;
|
||||||
}
|
}
|
||||||
|
|
@ -284,7 +287,7 @@ public class VehicleRoutingAlgorithms {
|
||||||
return false;
|
return false;
|
||||||
if (getClass() != obj.getClass())
|
if (getClass() != obj.getClass())
|
||||||
return false;
|
return false;
|
||||||
AbstractInsertionKey other = (AbstractInsertionKey) obj;
|
InsertionStrategyKey other = (InsertionStrategyKey) obj;
|
||||||
if (modKey == null) {
|
if (modKey == null) {
|
||||||
if (other.modKey != null)
|
if (other.modKey != null)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -296,8 +299,8 @@ public class VehicleRoutingAlgorithms {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<AbstractInsertionStrategy> getType() {
|
public Class<InsertionStrategy> getType() {
|
||||||
return AbstractInsertionStrategy.class;
|
return InsertionStrategy.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -445,9 +448,21 @@ public class VehicleRoutingAlgorithms {
|
||||||
|
|
||||||
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier()));
|
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier()));
|
||||||
|
|
||||||
RouteStates routeStates = new RouteStates();
|
final StateManagerImpl routeStates = new StateManagerImpl();
|
||||||
routeStates.initialiseStateOfJobs(vrp.getJobs().values());
|
IterationStartsListener resetStates = new IterationStartsListener() {
|
||||||
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, routeStates));
|
|
||||||
|
@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();
|
TypedMap definedClasses = new TypedMap();
|
||||||
|
|
||||||
|
|
@ -533,16 +548,14 @@ public class VehicleRoutingAlgorithms {
|
||||||
|
|
||||||
private static void registerInsertionListeners(TypedMap definedClasses, List<InsertionListener> insertionListeners) {
|
private static void registerInsertionListeners(TypedMap definedClasses, List<InsertionListener> insertionListeners) {
|
||||||
for(AbstractKey<?> key : definedClasses.keySet()){
|
for(AbstractKey<?> key : definedClasses.keySet()){
|
||||||
if(key instanceof AbstractInsertionKey){
|
if(key instanceof InsertionStrategyKey){
|
||||||
AbstractInsertionKey insertionKey = (AbstractInsertionKey) key;
|
InsertionStrategyKey insertionKey = (InsertionStrategyKey) key;
|
||||||
AbstractInsertionStrategy insertionStrategy = definedClasses.get(insertionKey);
|
InsertionStrategy insertionStrategy = definedClasses.get(insertionKey);
|
||||||
for(InsertionListener l : insertionListeners){
|
for(InsertionListener l : insertionListeners){
|
||||||
// log.info("add insertionListener " + l + " to " + insertionStrategy);
|
|
||||||
insertionStrategy.addListener(l);
|
insertionStrategy.addListener(l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// log.warn("cannot register insertion listeners yet");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getName(HierarchicalConfiguration strategyConfig) {
|
private static String getName(HierarchicalConfiguration strategyConfig) {
|
||||||
|
|
@ -557,7 +570,7 @@ public class VehicleRoutingAlgorithms {
|
||||||
metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners);
|
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");
|
List<HierarchicalConfiguration> modConfigs = config.configurationsAt("construction.insertion");
|
||||||
if(modConfigs == null) return null;
|
if(modConfigs == null) return null;
|
||||||
if(modConfigs.isEmpty()) return null;
|
if(modConfigs.isEmpty()) return null;
|
||||||
|
|
@ -568,15 +581,15 @@ public class VehicleRoutingAlgorithms {
|
||||||
String insertionId = modConfig.getString("[@id]");
|
String insertionId = modConfig.getString("[@id]");
|
||||||
if(insertionId == null) insertionId = "noId";
|
if(insertionId == null) insertionId = "noId";
|
||||||
ModKey modKey = makeKey(insertionName,insertionId);
|
ModKey modKey = makeKey(insertionName,insertionId);
|
||||||
AbstractInsertionKey insertionStrategyKey = new AbstractInsertionKey(modKey);
|
InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(modKey);
|
||||||
AbstractInsertionStrategy insertionStrategy = definedClasses.get(insertionStrategyKey);
|
InsertionStrategy insertionStrategy = definedClasses.get(insertionStrategyKey);
|
||||||
if(insertionStrategy == null){
|
if(insertionStrategy == null){
|
||||||
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
|
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);
|
algorithmListeners.addAll(prioListeners);
|
||||||
definedClasses.put(insertionStrategyKey,insertionStrategy);
|
definedClasses.put(insertionStrategyKey,insertionStrategy);
|
||||||
}
|
}
|
||||||
final AbstractInsertionStrategy finalInsertionStrategy = insertionStrategy;
|
final InsertionStrategy finalInsertionStrategy = insertionStrategy;
|
||||||
|
|
||||||
return new AlgorithmStartsListener() {
|
return new AlgorithmStartsListener() {
|
||||||
|
|
||||||
|
|
@ -653,8 +666,8 @@ public class VehicleRoutingAlgorithms {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager,
|
private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager,
|
||||||
RouteStates activityStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
|
final StateManagerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
|
||||||
String moduleName = moduleConfig.getString("[@name]");
|
String moduleName = moduleConfig.getString("[@name]");
|
||||||
if(moduleName == null) throw new IllegalStateException("module(-name) is missing.");
|
if(moduleName == null) throw new IllegalStateException("module(-name) is missing.");
|
||||||
String moduleId = moduleConfig.getString("[@id]");
|
String moduleId = moduleConfig.getString("[@id]");
|
||||||
|
|
@ -675,7 +688,7 @@ public class VehicleRoutingAlgorithms {
|
||||||
final RuinStrategy ruin;
|
final RuinStrategy ruin;
|
||||||
ModKey ruinKey = makeKey(ruin_name,ruin_id);
|
ModKey ruinKey = makeKey(ruin_name,ruin_id);
|
||||||
if(ruin_name.equals("randomRuin")){
|
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")){
|
else if(ruin_name.equals("radialRuin")){
|
||||||
String ruin_distance = moduleConfig.getString("ruin.distance");
|
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 "
|
else throw new IllegalStateException("does not know ruin.distance " + ruin_distance + ". either ommit ruin.distance then the "
|
||||||
+ "default is used or use 'euclidean'");
|
+ "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.");
|
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]");
|
String insertionId = moduleConfig.getString("insertion[@id]");
|
||||||
if(insertionId == null) insertionId = "noId";
|
if(insertionId == null) insertionId = "noId";
|
||||||
ModKey insertionKey = makeKey(insertionName,insertionId);
|
ModKey insertionKey = makeKey(insertionName,insertionId);
|
||||||
AbstractInsertionKey insertionStrategyKey = new AbstractInsertionKey(insertionKey);
|
InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(insertionKey);
|
||||||
AbstractInsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
|
InsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
|
||||||
if(insertion == null){
|
if(insertion == null){
|
||||||
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
|
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
|
||||||
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
|
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
|
||||||
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
|
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);
|
algorithmListeners.addAll(prioListeners);
|
||||||
}
|
}
|
||||||
final AbstractInsertionStrategy final_insertion = insertion;
|
final InsertionStrategy final_insertion = insertion;
|
||||||
SearchStrategyModule module = new SearchStrategyModule() {
|
SearchStrategyModule module = new SearchStrategyModule() {
|
||||||
|
|
||||||
private Logger logger = Logger.getLogger(SearchStrategyModule.class);
|
private Logger logger = Logger.getLogger(SearchStrategyModule.class);
|
||||||
|
|
@ -714,7 +727,7 @@ public class VehicleRoutingAlgorithms {
|
||||||
@Override
|
@Override
|
||||||
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
|
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
|
||||||
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
|
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());
|
double totalCost = RouteUtils.getTotalCost(vrpSolution.getRoutes());
|
||||||
vrpSolution.setCost(totalCost);
|
vrpSolution.setCost(totalCost);
|
||||||
return vrpSolution;
|
return vrpSolution;
|
||||||
|
|
@ -734,7 +747,7 @@ public class VehicleRoutingAlgorithms {
|
||||||
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
|
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
|
||||||
if(moduleListener instanceof InsertionListener){
|
if(moduleListener instanceof InsertionListener){
|
||||||
InsertionListener iListener = (InsertionListener) moduleListener;
|
InsertionListener iListener = (InsertionListener) moduleListener;
|
||||||
if(!final_insertion.getListener().contains(iListener)){
|
if(!final_insertion.getListeners().contains(iListener)){
|
||||||
logger.info("register moduleListener " + moduleListener);
|
logger.info("register moduleListener " + moduleListener);
|
||||||
final_insertion.addListener(iListener);
|
final_insertion.addListener(iListener);
|
||||||
}
|
}
|
||||||
|
|
@ -746,41 +759,42 @@ public class VehicleRoutingAlgorithms {
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(moduleName.equals("gendreauPostOpt")){
|
if(moduleName.equals("gendreau")){
|
||||||
int iterations = moduleConfig.getInt("iterations");
|
int iterations = moduleConfig.getInt("iterations");
|
||||||
double share = moduleConfig.getDouble("share");
|
double share = moduleConfig.getDouble("share");
|
||||||
String ruinName = moduleConfig.getString("ruin[@name]");
|
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]");
|
String ruinId = moduleConfig.getString("ruin[@id]");
|
||||||
if(ruinId == null) ruinId = "noId";
|
if(ruinId == null) ruinId = "noId";
|
||||||
ModKey ruinKey = makeKey(ruinName,ruinId);
|
ModKey ruinKey = makeKey(ruinName,ruinId);
|
||||||
RuinStrategyKey stratKey = new RuinStrategyKey(ruinKey);
|
RuinStrategyKey stratKey = new RuinStrategyKey(ruinKey);
|
||||||
RuinStrategy ruin = definedClasses.get(stratKey);
|
RuinStrategy ruin = definedClasses.get(stratKey);
|
||||||
if(ruin == null){
|
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);
|
definedClasses.put(stratKey, ruin);
|
||||||
}
|
}
|
||||||
|
|
||||||
String insertionName = moduleConfig.getString("insertion[@name]");
|
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]");
|
String insertionId = moduleConfig.getString("insertion[@id]");
|
||||||
if(insertionId == null) insertionId = "noId";
|
if(insertionId == null) insertionId = "noId";
|
||||||
ModKey insertionKey = makeKey(insertionName,insertionId);
|
ModKey insertionKey = makeKey(insertionName,insertionId);
|
||||||
AbstractInsertionKey insertionStrategyKey = new AbstractInsertionKey(insertionKey);
|
InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(insertionKey);
|
||||||
AbstractInsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
|
InsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
|
||||||
if(insertion == null){
|
if(insertion == null){
|
||||||
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
|
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
|
||||||
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
|
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
|
||||||
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
|
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);
|
algorithmListeners.addAll(prioListeners);
|
||||||
}
|
}
|
||||||
GendreauPostOpt postOpt = new GendreauPostOpt(vrp, ruin, insertion);
|
Gendreau gendreau = new Gendreau(vrp, ruin, insertion);
|
||||||
postOpt.setShareOfJobsToRuin(share);
|
gendreau.setShareOfJobsToRuin(share);
|
||||||
postOpt.setNuOfIterations(iterations);
|
gendreau.setNuOfIterations(iterations);
|
||||||
postOpt.setFleetManager(vehicleFleetManager);
|
gendreau.setFleetManager(vehicleFleetManager);
|
||||||
definedClasses.put(strategyModuleKey, postOpt);
|
definedClasses.put(strategyModuleKey, gendreau);
|
||||||
return postOpt;
|
return gendreau;
|
||||||
}
|
}
|
||||||
throw new NullPointerException("no module found with moduleName=" + moduleName +
|
throw new NullPointerException("no module found with moduleName=" + moduleName +
|
||||||
"\n\tcheck config whether the correct names are used" +
|
"\n\tcheck config whether the correct names are used" +
|
||||||
|
|
@ -791,30 +805,30 @@ public class VehicleRoutingAlgorithms {
|
||||||
"\n\tgendreauPostOpt");
|
"\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);
|
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
|
||||||
RuinStrategy ruin = definedClasses.get(stratKey);
|
RuinStrategy ruin = definedClasses.get(stratKey);
|
||||||
if(ruin == null){
|
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);
|
definedClasses.put(stratKey, ruin);
|
||||||
}
|
}
|
||||||
return ruin;
|
return ruin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RuinStrategy getRandomRuin(VehicleRoutingProblem vrp,
|
private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final StateManagerImpl routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) {
|
||||||
RouteStates activityStates, TypedMap definedClasses,
|
|
||||||
ModKey modKey, double shareToRuin) {
|
|
||||||
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
|
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
|
||||||
RuinStrategy ruin = definedClasses.get(stratKey);
|
RuinStrategy ruin = definedClasses.get(stratKey);
|
||||||
if(ruin == null){
|
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);
|
definedClasses.put(stratKey, ruin);
|
||||||
}
|
}
|
||||||
return ruin;
|
return ruin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AbstractInsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, RouteStates activityStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads) {
|
private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads) {
|
||||||
AbstractInsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, activityStates, algorithmListeners, executorService, nuOfThreads);
|
InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads);
|
||||||
return insertion;
|
return insertion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,8 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
import algorithms.RouteAlgorithm.VehicleSwitchedListener;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
class VehicleSwitched implements VehicleSwitchedListener{
|
class VehicleSwitched implements VehicleSwitchedListener{
|
||||||
|
|
||||||
|
|
@ -32,7 +33,7 @@ class VehicleSwitched implements VehicleSwitchedListener{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void vehicleSwitched(Vehicle oldVehicle, Vehicle newVehicle) {
|
public void vehicleSwitched(VehicleRoute vehicleRoute, Vehicle oldVehicle, Vehicle newVehicle) {
|
||||||
fleetManager.unlock(oldVehicle);
|
fleetManager.unlock(oldVehicle);
|
||||||
fleetManager.lock(newVehicle);
|
fleetManager.lock(newVehicle);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -22,10 +22,11 @@ package basics.algo;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import basics.Job;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
public interface InsertionStartsListener extends InsertionListener {
|
public interface InsertionStartsListener extends InsertionListener {
|
||||||
|
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate);
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,5 +30,5 @@ import basics.route.VehicleRoute;
|
||||||
|
|
||||||
public interface JobInsertedListener extends InsertionListener{
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,7 @@ public class VrpXMLReader{
|
||||||
if(distC != null) typeBuilder.setCostPerDistance(distC);
|
if(distC != null) typeBuilder.setCostPerDistance(distC);
|
||||||
// if(start != null && end != null) typeBuilder.setTimeSchedule(new TimeSchedule(start, end));
|
// if(start != null && end != null) typeBuilder.setTimeSchedule(new TimeSchedule(start, end));
|
||||||
VehicleTypeImpl type = typeBuilder.build();
|
VehicleTypeImpl type = typeBuilder.build();
|
||||||
types.put(type.typeId, type);
|
types.put(type.getTypeId(), type);
|
||||||
vrpBuilder.addVehicleType(type);
|
vrpBuilder.addVehicleType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,12 +61,15 @@ public final class End implements TourActivity {
|
||||||
this.locationId = locationId;
|
this.locationId = locationId;
|
||||||
theoretical_earliestOperationStartTime = theoreticalStart;
|
theoretical_earliestOperationStartTime = theoreticalStart;
|
||||||
theoretical_latestOperationStartTime = theoreticalEnd;
|
theoretical_latestOperationStartTime = theoreticalEnd;
|
||||||
|
endTime = theoreticalEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
public End(End end) {
|
public End(End end) {
|
||||||
this.locationId = end.getLocationId();
|
this.locationId = end.getLocationId();
|
||||||
theoretical_earliestOperationStartTime = end.getTheoreticalEarliestOperationStartTime();
|
theoretical_earliestOperationStartTime = end.getTheoreticalEarliestOperationStartTime();
|
||||||
theoretical_latestOperationStartTime = end.getTheoreticalLatestOperationStartTime();
|
theoretical_latestOperationStartTime = end.getTheoreticalLatestOperationStartTime();
|
||||||
|
arrTime = end.getArrTime();
|
||||||
|
endTime = end.getEndTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getTheoreticalEarliestOperationStartTime() {
|
public double getTheoreticalEarliestOperationStartTime() {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,11 @@ public class PenaltyVehicleType implements VehicleType{
|
||||||
return type.getVehicleCostParams();
|
return type.getVehicleCostParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getMaxVelocity() {
|
||||||
|
return type.getMaxVelocity();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,15 +76,9 @@ public class TourActivities {
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ArrayList<TourActivity> tourActivities = new ArrayList<TourActivity>();
|
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 final Set<Job> jobs = new HashSet<Job>();
|
||||||
|
|
||||||
private int load = 0;
|
|
||||||
|
|
||||||
private double cost = 0.0;
|
|
||||||
|
|
||||||
private ReverseActivityIterator backward;
|
private ReverseActivityIterator backward;
|
||||||
|
|
||||||
private TourActivities(TourActivities tour2copy) {
|
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
|
* @param job
|
||||||
* @return
|
* @return
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,11 @@ public class VehicleRoute {
|
||||||
start.setEndTime(vehicleDepTime);
|
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) {
|
private void setStartAndEnd(Vehicle vehicle, double vehicleDepTime) {
|
||||||
if(!(vehicle instanceof NoVehicle)){
|
if(!(vehicle instanceof NoVehicle)){
|
||||||
if(start == null && end == null){
|
if(start == null && end == null){
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ public interface VehicleType {
|
||||||
|
|
||||||
public int getCapacity();
|
public int getCapacity();
|
||||||
|
|
||||||
|
public double getMaxVelocity();
|
||||||
|
|
||||||
public VehicleCostParams getVehicleCostParams();
|
public VehicleCostParams getVehicleCostParams();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -35,6 +35,7 @@ public class VehicleTypeImpl implements VehicleType {
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private int capacity;
|
private int capacity;
|
||||||
|
private double maxVelo = Double.MAX_VALUE;
|
||||||
/**
|
/**
|
||||||
* default cost values for default vehicle type
|
* default cost values for default vehicle type
|
||||||
*/
|
*/
|
||||||
|
|
@ -48,6 +49,8 @@ public class VehicleTypeImpl implements VehicleType {
|
||||||
this.capacity = capacity;
|
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 setFixedCost(double fixedCost) { this.fixedCost = fixedCost; return this; }
|
||||||
|
|
||||||
public VehicleTypeImpl.Builder setCostPerDistance(double perDistance){ this.perDistance = perDistance; return this; }
|
public VehicleTypeImpl.Builder setCostPerDistance(double perDistance){ this.perDistance = perDistance; return this; }
|
||||||
|
|
@ -86,9 +89,13 @@ public class VehicleTypeImpl implements VehicleType {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String typeId;
|
private final String typeId;
|
||||||
public final int capacity;
|
|
||||||
public final VehicleTypeImpl.VehicleCostParams vehicleCostParams;
|
private final int capacity;
|
||||||
|
|
||||||
|
private final VehicleTypeImpl.VehicleCostParams vehicleCostParams;
|
||||||
|
|
||||||
|
private double maxVelocity;
|
||||||
|
|
||||||
public static VehicleTypeImpl newInstance(String typeId, int capacity, VehicleTypeImpl.VehicleCostParams para){
|
public static VehicleTypeImpl newInstance(String typeId, int capacity, VehicleTypeImpl.VehicleCostParams para){
|
||||||
return new VehicleTypeImpl(typeId, capacity, para);
|
return new VehicleTypeImpl(typeId, capacity, para);
|
||||||
|
|
@ -97,6 +104,7 @@ public class VehicleTypeImpl implements VehicleType {
|
||||||
private VehicleTypeImpl(VehicleTypeImpl.Builder builder){
|
private VehicleTypeImpl(VehicleTypeImpl.Builder builder){
|
||||||
typeId = builder.id;
|
typeId = builder.id;
|
||||||
capacity = builder.capacity;
|
capacity = builder.capacity;
|
||||||
|
maxVelocity = builder.maxVelo;
|
||||||
vehicleCostParams = new VehicleCostParams(builder.fixedCost, builder.perTime, builder.perDistance);
|
vehicleCostParams = new VehicleCostParams(builder.fixedCost, builder.perTime, builder.perDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,4 +143,9 @@ public class VehicleTypeImpl implements VehicleType {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[typeId="+typeId+"][capacity="+capacity+"]" + vehicleCostParams;
|
return "[typeId="+typeId+"][capacity="+capacity+"]" + vehicleCostParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getMaxVelocity() {
|
||||||
|
return maxVelocity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10,7 +10,16 @@ import basics.route.Driver;
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
import basics.route.VehicleTypeImpl.VehicleCostParams;
|
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 {
|
public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTransportCosts {
|
||||||
|
|
||||||
static class RelationKey {
|
static class RelationKey {
|
||||||
|
|
@ -74,7 +83,12 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder that builds the matrix.
|
||||||
|
*
|
||||||
|
* @author schroeder
|
||||||
|
*
|
||||||
|
*/
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
private static Logger log = Logger.getLogger(Builder.class);
|
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 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){
|
public static Builder newInstance(boolean isSymmetric){
|
||||||
return new Builder(isSymmetric);
|
return new Builder(isSymmetric);
|
||||||
}
|
}
|
||||||
|
|
@ -92,8 +116,16 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
|
||||||
this.isSymmetric = isSymmetric;
|
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){
|
public Builder addTransportDistance(String from, String to, double distance){
|
||||||
RelationKey key = RelationKey.newKey(from, to);
|
RelationKey key = RelationKey.newKey(from, to);
|
||||||
|
if(!distancesSet) distancesSet = true;
|
||||||
if(distances.containsKey(key)){
|
if(distances.containsKey(key)){
|
||||||
log.warn("distance from " + from + " to " + to + " already exists. This overrides distance.");
|
log.warn("distance from " + from + " to " + to + " already exists. This overrides distance.");
|
||||||
}
|
}
|
||||||
|
|
@ -101,8 +133,16 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
|
||||||
return this;
|
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){
|
public Builder addTransportTime(String from, String to, double time){
|
||||||
RelationKey key = RelationKey.newKey(from, to);
|
RelationKey key = RelationKey.newKey(from, to);
|
||||||
|
if(!timesSet) timesSet = true;
|
||||||
if(times.containsKey(key)){
|
if(times.containsKey(key)){
|
||||||
log.warn("transport-time from " + from + " to " + to + " already exists. This overrides distance.");
|
log.warn("transport-time from " + from + " to " + to + " already exists. This overrides distance.");
|
||||||
}
|
}
|
||||||
|
|
@ -110,6 +150,10 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the matrix.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public VehicleRoutingTransportCostsMatrix build(){
|
public VehicleRoutingTransportCostsMatrix build(){
|
||||||
return new VehicleRoutingTransportCostsMatrix(this);
|
return new VehicleRoutingTransportCostsMatrix(this);
|
||||||
}
|
}
|
||||||
|
|
@ -121,10 +165,16 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
|
||||||
|
|
||||||
private boolean isSymmetric;
|
private boolean isSymmetric;
|
||||||
|
|
||||||
|
private boolean timesSet;
|
||||||
|
|
||||||
|
private boolean distancesSet;
|
||||||
|
|
||||||
private VehicleRoutingTransportCostsMatrix(Builder builder){
|
private VehicleRoutingTransportCostsMatrix(Builder builder){
|
||||||
this.isSymmetric = builder.isSymmetric;
|
this.isSymmetric = builder.isSymmetric;
|
||||||
distances.putAll(builder.distances);
|
distances.putAll(builder.distances);
|
||||||
times.putAll(builder.times);
|
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) {
|
private double getTime(String fromId, String toId) {
|
||||||
if(fromId.equals(toId)) return 0.0;
|
if(fromId.equals(toId)) return 0.0;
|
||||||
|
if(!timesSet) return 0.0;
|
||||||
RelationKey key = RelationKey.newKey(fromId, toId);
|
RelationKey key = RelationKey.newKey(fromId, toId);
|
||||||
if(!isSymmetric){
|
if(!isSymmetric){
|
||||||
if(times.containsKey(key)) return times.get(key);
|
if(times.containsKey(key)) return times.get(key);
|
||||||
|
|
@ -153,6 +204,7 @@ public class VehicleRoutingTransportCostsMatrix implements VehicleRoutingTranspo
|
||||||
|
|
||||||
private double getDistance(String fromId, String toId) {
|
private double getDistance(String fromId, String toId) {
|
||||||
if(fromId.equals(toId)) return 0.0;
|
if(fromId.equals(toId)) return 0.0;
|
||||||
|
if(!distancesSet) return 0.0;
|
||||||
RelationKey key = RelationKey.newKey(fromId, toId);
|
RelationKey key = RelationKey.newKey(fromId, toId);
|
||||||
if(!isSymmetric){
|
if(!isSymmetric){
|
||||||
if(distances.containsKey(key)) return distances.get(key);
|
if(distances.containsKey(key)) return distances.get(key);
|
||||||
|
|
|
||||||
|
|
@ -166,14 +166,16 @@
|
||||||
|
|
||||||
<xs:group name="gendreau_group">
|
<xs:group name="gendreau_group">
|
||||||
<xs:sequence>
|
<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="share" type="xs:double"/>
|
||||||
|
<xs:element name="ruin" type="ruinType"/>
|
||||||
|
<xs:element name="insertion" type="insertionType"/>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:group>
|
</xs:group>
|
||||||
|
|
||||||
<xs:complexType name="ruinType">
|
<xs:complexType name="ruinType">
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element name="share" minOccurs="1" maxOccurs="1">
|
<xs:element name="share" minOccurs="0" maxOccurs="1">
|
||||||
<xs:simpleType>
|
<xs:simpleType>
|
||||||
<xs:restriction base="xs:double">
|
<xs:restriction base="xs:double">
|
||||||
<xs:minInclusive value="0.0"/>
|
<xs:minInclusive value="0.0"/>
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ import algorithms.selectors.SelectRandomlyTest;
|
||||||
GendreauPostOptTest.class,
|
GendreauPostOptTest.class,
|
||||||
TestAlgorithmReader.class,
|
TestAlgorithmReader.class,
|
||||||
// TestAux.class,
|
// TestAux.class,
|
||||||
TestCalculatesActivityInsertion.class,
|
|
||||||
TestCalculatesServiceInsertion.class,
|
TestCalculatesServiceInsertion.class,
|
||||||
TestCalculatesServiceInsertionOnRouteLevel.class,
|
TestCalculatesServiceInsertionOnRouteLevel.class,
|
||||||
TestSchrimpf.class,
|
TestSchrimpf.class,
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -37,15 +37,16 @@ import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import basics.VehicleRoutingProblemSolution;
|
||||||
|
import basics.costs.VehicleRoutingActivityCosts;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
import basics.route.Driver;
|
import basics.route.Driver;
|
||||||
import basics.route.DriverImpl;
|
import basics.route.DriverImpl;
|
||||||
|
import basics.route.ServiceActivity;
|
||||||
import basics.route.TimeWindow;
|
import basics.route.TimeWindow;
|
||||||
import basics.route.TourActivities;
|
import basics.route.TourActivities;
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
import basics.route.VehicleImpl;
|
import basics.route.VehicleImpl;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
import basics.route.VehicleType;
|
|
||||||
import basics.route.VehicleTypeImpl;
|
import basics.route.VehicleTypeImpl;
|
||||||
|
|
||||||
public class GendreauPostOptTest {
|
public class GendreauPostOptTest {
|
||||||
|
|
@ -60,6 +61,8 @@ public class GendreauPostOptTest {
|
||||||
|
|
||||||
VehicleRoutingTransportCosts cost;
|
VehicleRoutingTransportCosts cost;
|
||||||
|
|
||||||
|
VehicleRoutingActivityCosts activityCosts;
|
||||||
|
|
||||||
VehicleRoutingProblem vrp;
|
VehicleRoutingProblem vrp;
|
||||||
|
|
||||||
Service job1;
|
Service job1;
|
||||||
|
|
@ -68,15 +71,13 @@ public class GendreauPostOptTest {
|
||||||
|
|
||||||
Service job3;
|
Service job3;
|
||||||
|
|
||||||
private RouteStates states;
|
private StateManagerImpl states;
|
||||||
|
|
||||||
private List<Vehicle> vehicles;
|
private List<Vehicle> vehicles;
|
||||||
|
|
||||||
private TourStateUpdater updater;
|
|
||||||
|
|
||||||
private VehicleFleetManagerImpl fleetManager;
|
private VehicleFleetManagerImpl fleetManager;
|
||||||
|
|
||||||
private RouteAlgorithmImpl routeAlgorithm;
|
private JobInsertionCalculator insertionCalc;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp(){
|
public void setUp(){
|
||||||
|
|
@ -146,32 +147,18 @@ public class GendreauPostOptTest {
|
||||||
|
|
||||||
// Collection<Vehicle> vehicles = Arrays.asList(lightVehicle1,lightVehicle2, heavyVehicle);
|
// Collection<Vehicle> vehicles = Arrays.asList(lightVehicle1,lightVehicle2, heavyVehicle);
|
||||||
fleetManager = new VehicleFleetManagerImpl(vehicles);
|
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);
|
CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(standardServiceInsertion, states);
|
||||||
withFixCost.setWeightOfFixCost(1.2);
|
withFixCost.setWeightOfFixCost(1.2);
|
||||||
|
|
||||||
final JobInsertionCalculator vehicleTypeDepInsertionCost = new CalculatesVehTypeDepServiceInsertion(fleetManager, withFixCost);
|
insertionCalc = new CalculatesVehTypeDepServiceInsertion(fleetManager, withFixCost);
|
||||||
updater = new TourStateUpdater(states, cost, activityCosts);
|
|
||||||
|
|
||||||
|
|
||||||
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(job1);
|
||||||
jobs.add(job2);
|
jobs.add(job2);
|
||||||
|
|
||||||
states.initialiseStateOfJobs(jobs);
|
|
||||||
vrp = VehicleRoutingProblem.Builder.newInstance().addAllJobs(jobs).addAllVehicles(vehicles).setRoutingCost(cost).build();
|
vrp = VehicleRoutingProblem.Builder.newInstance().addAllJobs(jobs).addAllVehicles(vehicles).setRoutingCost(cost).build();
|
||||||
|
|
||||||
TourActivities tour = new TourActivities();
|
TourActivities tour = new TourActivities();
|
||||||
tour.addActivity(states.getActivity(job1, true));
|
tour.addActivity(ServiceActivity.newInstance(job1));
|
||||||
tour.addActivity(states.getActivity(job2, true));
|
tour.addActivity(ServiceActivity.newInstance(job2));
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),heavyVehicle);
|
VehicleRoute route = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),heavyVehicle);
|
||||||
updater.updateRoute(route);
|
|
||||||
|
|
||||||
fleetManager.lock(heavyVehicle);
|
fleetManager.lock(heavyVehicle);
|
||||||
|
|
||||||
|
UpdateStates stateUpdater = new UpdateStates(states, vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||||
|
stateUpdater.update(route);
|
||||||
|
|
||||||
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
|
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
|
||||||
routes.add(route);
|
routes.add(route);
|
||||||
// routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle()));
|
// routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle()));
|
||||||
|
|
@ -202,10 +190,16 @@ public class GendreauPostOptTest {
|
||||||
|
|
||||||
assertEquals(110.0, sol.getCost(), 0.5);
|
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);
|
RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()));
|
||||||
GendreauPostOpt postOpt = new GendreauPostOpt(vrp, radialRuin, insertionStrategy);
|
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);
|
postOpt.setFleetManager(fleetManager);
|
||||||
|
|
||||||
VehicleRoutingProblemSolution newSolution = postOpt.runAndGetSolution(sol);
|
VehicleRoutingProblemSolution newSolution = postOpt.runAndGetSolution(sol);
|
||||||
|
|
||||||
assertEquals(2,RouteUtils.getNuOfActiveRoutes(newSolution.getRoutes()));
|
assertEquals(2,RouteUtils.getNuOfActiveRoutes(newSolution.getRoutes()));
|
||||||
|
|
@ -220,32 +214,32 @@ public class GendreauPostOptTest {
|
||||||
jobs.add(job2);
|
jobs.add(job2);
|
||||||
jobs.add(job3);
|
jobs.add(job3);
|
||||||
|
|
||||||
states.initialiseStateOfJobs(jobs);
|
|
||||||
vrp = VehicleRoutingProblem.Builder.newInstance().addAllJobs(jobs).addAllVehicles(vehicles).setRoutingCost(cost).build();
|
vrp = VehicleRoutingProblem.Builder.newInstance().addAllJobs(jobs).addAllVehicles(vehicles).setRoutingCost(cost).build();
|
||||||
|
|
||||||
TourActivities tour = new TourActivities();
|
TourActivities tour = new TourActivities();
|
||||||
tour.addActivity(states.getActivity(job1, true));
|
tour.addActivity(ServiceActivity.newInstance(job1));
|
||||||
tour.addActivity(states.getActivity(job2, true));
|
tour.addActivity(ServiceActivity.newInstance(job2));
|
||||||
tour.addActivity(states.getActivity(job3, true));
|
tour.addActivity(ServiceActivity.newInstance(job3));
|
||||||
|
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),heavyVehicle);
|
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);
|
fleetManager.lock(heavyVehicle);
|
||||||
|
|
||||||
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
|
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
|
||||||
routes.add(route);
|
routes.add(route);
|
||||||
// routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle()));
|
|
||||||
// routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle()));
|
|
||||||
|
|
||||||
VehicleRoutingProblemSolution sol = new VehicleRoutingProblemSolution(routes, route.getCost());
|
VehicleRoutingProblemSolution sol = new VehicleRoutingProblemSolution(routes, route.getCost());
|
||||||
|
|
||||||
assertEquals(110.0, sol.getCost(), 0.5);
|
assertEquals(110.0, sol.getCost(), 0.5);
|
||||||
|
|
||||||
RuinRadial radialRuin = RuinRadial.newInstance(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()), new JobRemoverImpl(), updater);
|
RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()));
|
||||||
AbstractInsertionStrategy insertionStrategy = new BestInsertion(routeAlgorithm);
|
InsertionStrategy insertionStrategy = new BestInsertion(insertionCalc);
|
||||||
GendreauPostOpt postOpt = new GendreauPostOpt(vrp, radialRuin, insertionStrategy);
|
insertionStrategy.addListener(stateUpdater);
|
||||||
|
insertionStrategy.addListener(new VehicleSwitched(fleetManager));
|
||||||
|
Gendreau postOpt = new Gendreau(vrp, radialRuin, insertionStrategy);
|
||||||
postOpt.setShareOfJobsToRuin(1.0);
|
postOpt.setShareOfJobsToRuin(1.0);
|
||||||
postOpt.setNuOfIterations(1);
|
postOpt.setNuOfIterations(1);
|
||||||
postOpt.setFleetManager(fleetManager);
|
postOpt.setFleetManager(fleetManager);
|
||||||
|
|
@ -257,18 +251,6 @@ public class GendreauPostOptTest {
|
||||||
assertEquals(80.0,newSolution.getCost(),0.5);
|
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) {
|
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();
|
Service s = Service.Builder.newInstance(to, 0).setLocationId(to).setServiceTime(serviceTime).setTimeWindow(TimeWindow.newInstance(0.0, 20.0)).build();
|
||||||
|
|
||||||
|
|
|
||||||
218
jsprit-core/src/test/java/algorithms/RefuseCollectionTest.java
Normal file
218
jsprit-core/src/test/java/algorithms/RefuseCollectionTest.java
Normal 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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -170,6 +170,24 @@ public class TestAlgorithmReader {
|
||||||
return null;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
StrategyModuleKey moduleKey = new StrategyModuleKey(key);
|
StrategyModuleKey moduleKey = new StrategyModuleKey(key);
|
||||||
|
|
@ -233,21 +251,21 @@ public class TestAlgorithmReader {
|
||||||
assertEquals(3, nOfModules);
|
assertEquals(3, nOfModules);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
// @Test
|
||||||
public void whenCreatingAlgorithm_regretInsertionIsReadCorrectly(){
|
// public void whenCreatingAlgorithm_regretInsertionIsReadCorrectly(){
|
||||||
VehicleRoutingAlgorithm algo = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "src/test/resources/configWithRegretInsertion.xml");
|
// VehicleRoutingAlgorithm algo = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "src/test/resources/configWithRegretInsertion.xml");
|
||||||
int nOfModules = 0;
|
// int nOfModules = 0;
|
||||||
for(SearchStrategy strat : algo.getSearchStrategyManager().getStrategies()){
|
// for(SearchStrategy strat : algo.getSearchStrategyManager().getStrategies()){
|
||||||
for(SearchStrategyModule module : strat.getSearchStrategyModules()){
|
// for(SearchStrategyModule module : strat.getSearchStrategyModules()){
|
||||||
if(module.getName().contains("ruin_and_recreate")){
|
// if(module.getName().contains("ruin_and_recreate")){
|
||||||
nOfModules++;
|
// nOfModules++;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
assertEquals(3, nOfModules);
|
// assertEquals(3, nOfModules);
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -36,6 +36,7 @@ import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
import basics.route.DriverImpl;
|
import basics.route.DriverImpl;
|
||||||
|
import basics.route.ServiceActivity;
|
||||||
import basics.route.TimeWindow;
|
import basics.route.TimeWindow;
|
||||||
import basics.route.TourActivities;
|
import basics.route.TourActivities;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
|
|
@ -61,12 +62,12 @@ public class TestCalculatesServiceInsertion {
|
||||||
|
|
||||||
private Service third;
|
private Service third;
|
||||||
|
|
||||||
private RouteStates states;
|
private StateManagerImpl states;
|
||||||
|
|
||||||
private TourStateUpdater tourStateUpdater;
|
|
||||||
|
|
||||||
private NoDriver driver;
|
private NoDriver driver;
|
||||||
|
|
||||||
|
private UpdateStates stateUpdater;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup(){
|
public void setup(){
|
||||||
Logger.getRootLogger().setLevel(Level.DEBUG);
|
Logger.getRootLogger().setLevel(Level.DEBUG);
|
||||||
|
|
@ -151,17 +152,13 @@ public class TestCalculatesServiceInsertion {
|
||||||
jobs.add(second);
|
jobs.add(second);
|
||||||
jobs.add(third);
|
jobs.add(third);
|
||||||
|
|
||||||
states = new RouteStates();
|
states = new StateManagerImpl();
|
||||||
states.initialiseStateOfJobs(jobs);
|
|
||||||
|
|
||||||
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
|
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
|
||||||
|
|
||||||
serviceInsertion = new CalculatesServiceInsertion(costs, activityCosts);
|
serviceInsertion = new CalculatesServiceInsertion(costs, new MarginalsCalculusTriangleInequality(costs, activityCosts, new HardConstraints.HardTimeWindowConstraint(states)), new HardConstraints.HardLoadConstraint(states));
|
||||||
serviceInsertion.setActivityStates(states);
|
|
||||||
|
|
||||||
tourStateUpdater = new TourStateUpdater(states, costs, activityCosts);
|
|
||||||
|
|
||||||
|
|
||||||
|
stateUpdater = new UpdateStates(states, costs, activityCosts);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,7 +173,7 @@ public class TestCalculatesServiceInsertion {
|
||||||
TourActivities tour = new TourActivities();
|
TourActivities tour = new TourActivities();
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
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);
|
InsertionData iData = serviceInsertion.calculate(route, first, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
||||||
assertEquals(20.0, iData.getInsertionCost(), 0.2);
|
assertEquals(20.0, iData.getInsertionCost(), 0.2);
|
||||||
|
|
@ -186,10 +183,10 @@ public class TestCalculatesServiceInsertion {
|
||||||
@Test
|
@Test
|
||||||
public void whenInsertingTheSecondJobInAnNonEmptyTourWithVehicle_itCalculatesMarginalCostChanges(){
|
public void whenInsertingTheSecondJobInAnNonEmptyTourWithVehicle_itCalculatesMarginalCostChanges(){
|
||||||
TourActivities tour = new TourActivities();
|
TourActivities tour = new TourActivities();
|
||||||
tour.addActivity(states.getActivity(first, true));
|
tour.addActivity(ServiceActivity.newInstance(first));
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
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);
|
InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
||||||
assertEquals(20.0, iData.getInsertionCost(), 0.2);
|
assertEquals(20.0, iData.getInsertionCost(), 0.2);
|
||||||
|
|
@ -199,12 +196,12 @@ public class TestCalculatesServiceInsertion {
|
||||||
@Test
|
@Test
|
||||||
public void whenInsertingThirdJobWithVehicle_itCalculatesMarginalCostChanges(){
|
public void whenInsertingThirdJobWithVehicle_itCalculatesMarginalCostChanges(){
|
||||||
TourActivities tour = new TourActivities();
|
TourActivities tour = new TourActivities();
|
||||||
tour.addActivity(states.getActivity(first,true));
|
tour.addActivity(ServiceActivity.newInstance(first));
|
||||||
tour.addActivity(states.getActivity(second,true));
|
tour.addActivity(ServiceActivity.newInstance(second));
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
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);
|
InsertionData iData = serviceInsertion.calculate(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
||||||
assertEquals(0.0, iData.getInsertionCost(), 0.2);
|
assertEquals(0.0, iData.getInsertionCost(), 0.2);
|
||||||
|
|
@ -214,12 +211,12 @@ public class TestCalculatesServiceInsertion {
|
||||||
@Test
|
@Test
|
||||||
public void whenInsertingThirdJobWithNewVehicle_itCalculatesMarginalCostChanges(){
|
public void whenInsertingThirdJobWithNewVehicle_itCalculatesMarginalCostChanges(){
|
||||||
TourActivities tour = new TourActivities();
|
TourActivities tour = new TourActivities();
|
||||||
tour.addActivity(states.getActivity(first,true));
|
tour.addActivity(ServiceActivity.newInstance(first));
|
||||||
tour.addActivity(states.getActivity(second,true));
|
tour.addActivity(ServiceActivity.newInstance(second));
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
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);
|
InsertionData iData = serviceInsertion.calculate(route, third, newVehicle, newVehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
||||||
assertEquals(20.0, iData.getInsertionCost(), 0.2);
|
assertEquals(20.0, iData.getInsertionCost(), 0.2);
|
||||||
|
|
@ -229,11 +226,11 @@ public class TestCalculatesServiceInsertion {
|
||||||
@Test
|
@Test
|
||||||
public void whenInsertingASecondJobWithAVehicle_itCalculatesLocalMarginalCostChanges(){
|
public void whenInsertingASecondJobWithAVehicle_itCalculatesLocalMarginalCostChanges(){
|
||||||
TourActivities tour = new TourActivities();
|
TourActivities tour = new TourActivities();
|
||||||
tour.addActivity(states.getActivity(first,true));
|
tour.addActivity(ServiceActivity.newInstance(first));
|
||||||
tour.addActivity(states.getActivity(third,true));
|
tour.addActivity(ServiceActivity.newInstance(third));
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
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);
|
InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
||||||
assertEquals(0.0, iData.getInsertionCost(), 0.2);
|
assertEquals(0.0, iData.getInsertionCost(), 0.2);
|
||||||
|
|
@ -243,13 +240,13 @@ public class TestCalculatesServiceInsertion {
|
||||||
@Test
|
@Test
|
||||||
public void whenInsertingASecondJobWithANewVehicle_itCalculatesLocalMarginalCostChanges(){
|
public void whenInsertingASecondJobWithANewVehicle_itCalculatesLocalMarginalCostChanges(){
|
||||||
TourActivities tour = new TourActivities();
|
TourActivities tour = new TourActivities();
|
||||||
tour.addActivity(states.getActivity(first,true));
|
tour.addActivity(ServiceActivity.newInstance(first));
|
||||||
tour.addActivity(states.getActivity(third,true));
|
tour.addActivity(ServiceActivity.newInstance(third));
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
||||||
// route.addActivity(states.getActivity(first,true));
|
// route.addActivity(states.getActivity(first,true));
|
||||||
// route.addActivity(states.getActivity(third,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);
|
InsertionData iData = serviceInsertion.calculate(route, second, newVehicle, newVehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
||||||
assertEquals(20.0, iData.getInsertionCost(), 0.2);
|
assertEquals(20.0, iData.getInsertionCost(), 0.2);
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import basics.Service;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
import basics.route.Driver;
|
import basics.route.Driver;
|
||||||
import basics.route.DriverImpl;
|
import basics.route.DriverImpl;
|
||||||
|
import basics.route.ServiceActivity;
|
||||||
import basics.route.TimeWindow;
|
import basics.route.TimeWindow;
|
||||||
import basics.route.TourActivities;
|
import basics.route.TourActivities;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
|
|
@ -64,12 +65,12 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
|
||||||
|
|
||||||
private Service third;
|
private Service third;
|
||||||
|
|
||||||
private RouteStates states;
|
private StateManagerImpl states;
|
||||||
|
|
||||||
private TourStateUpdater tourStateUpdater;
|
|
||||||
|
|
||||||
private NoDriver driver;
|
private NoDriver driver;
|
||||||
|
|
||||||
|
private UpdateStates updateStates;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup(){
|
public void setup(){
|
||||||
Logger.getRootLogger().setLevel(Level.DEBUG);
|
Logger.getRootLogger().setLevel(Level.DEBUG);
|
||||||
|
|
@ -142,15 +143,14 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
|
||||||
jobs.add(second);
|
jobs.add(second);
|
||||||
jobs.add(third);
|
jobs.add(third);
|
||||||
|
|
||||||
states = new RouteStates();
|
states = new StateManagerImpl();
|
||||||
states.initialiseStateOfJobs(jobs);
|
|
||||||
|
|
||||||
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
|
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
|
||||||
serviceInsertion = new CalculatesServiceInsertionOnRouteLevel(costs,activityCosts);
|
serviceInsertion = new CalculatesServiceInsertionOnRouteLevel(costs,activityCosts);
|
||||||
serviceInsertion.setNuOfActsForwardLooking(4);
|
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();
|
TourActivities tour = new TourActivities();
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
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);
|
InsertionData iData = serviceInsertion.calculate(route, first, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
||||||
assertEquals(20.0, iData.getInsertionCost(), 0.2);
|
assertEquals(20.0, iData.getInsertionCost(), 0.2);
|
||||||
assertEquals(0, iData.getDeliveryInsertionIndex());
|
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
|
@Test
|
||||||
public void whenInsertingThirdJobWithVehicle_itCalculatesMarginalCostChanges(){
|
public void whenInsertingThirdJobWithVehicle_itCalculatesMarginalCostChanges(){
|
||||||
TourActivities tour = new TourActivities();
|
TourActivities tour = new TourActivities();
|
||||||
tour.addActivity(states.getActivity(first,true));
|
tour.addActivity(ServiceActivity.newInstance(first));
|
||||||
tour.addActivity(states.getActivity(second,true));
|
tour.addActivity(ServiceActivity.newInstance(second));
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
||||||
|
updateStates.update(route);
|
||||||
tourStateUpdater.updateRoute(route);
|
|
||||||
|
|
||||||
InsertionData iData = serviceInsertion.calculate(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
InsertionData iData = serviceInsertion.calculate(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
||||||
assertEquals(0.0, iData.getInsertionCost(), 0.2);
|
assertEquals(0.0, iData.getInsertionCost(), 0.2);
|
||||||
|
|
@ -218,12 +191,11 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
|
||||||
@Test
|
@Test
|
||||||
public void whenInsertingThirdJobWithNewVehicle_itCalculatesMarginalCostChanges(){
|
public void whenInsertingThirdJobWithNewVehicle_itCalculatesMarginalCostChanges(){
|
||||||
TourActivities tour = new TourActivities();
|
TourActivities tour = new TourActivities();
|
||||||
tour.addActivity(states.getActivity(first,true));
|
tour.addActivity(ServiceActivity.newInstance(first));
|
||||||
tour.addActivity(states.getActivity(second,true));
|
tour.addActivity(ServiceActivity.newInstance(second));
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
||||||
|
updateStates.update(route);
|
||||||
tourStateUpdater.updateRoute(route);
|
|
||||||
|
|
||||||
InsertionData iData = serviceInsertion.calculate(route, third, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
InsertionData iData = serviceInsertion.calculate(route, third, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
||||||
assertEquals(40.0, iData.getInsertionCost(), 0.2);
|
assertEquals(40.0, iData.getInsertionCost(), 0.2);
|
||||||
|
|
@ -233,11 +205,11 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
|
||||||
@Test
|
@Test
|
||||||
public void whenInsertingASecondJobWithAVehicle_itCalculatesLocalMarginalCostChanges(){
|
public void whenInsertingASecondJobWithAVehicle_itCalculatesLocalMarginalCostChanges(){
|
||||||
TourActivities tour = new TourActivities();
|
TourActivities tour = new TourActivities();
|
||||||
tour.addActivity(states.getActivity(first,true));
|
tour.addActivity(ServiceActivity.newInstance(first));
|
||||||
tour.addActivity(states.getActivity(third,true));
|
tour.addActivity(ServiceActivity.newInstance(third));
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
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);
|
InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
||||||
assertEquals(0.0, iData.getInsertionCost(), 0.2);
|
assertEquals(0.0, iData.getInsertionCost(), 0.2);
|
||||||
|
|
@ -247,30 +219,15 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
|
||||||
@Test
|
@Test
|
||||||
public void whenInsertingASecondJobWithANewVehicle_itCalculatesLocalMarginalCostChanges(){
|
public void whenInsertingASecondJobWithANewVehicle_itCalculatesLocalMarginalCostChanges(){
|
||||||
TourActivities tour = new TourActivities();
|
TourActivities tour = new TourActivities();
|
||||||
tour.addActivity(states.getActivity(first,true));
|
tour.addActivity(ServiceActivity.newInstance(first));
|
||||||
tour.addActivity(states.getActivity(third,true));
|
tour.addActivity(ServiceActivity.newInstance(third));
|
||||||
|
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle);
|
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);
|
InsertionData iData = serviceInsertion.calculate(route, second, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE);
|
||||||
assertEquals(40.0, iData.getInsertionCost(), 0.2);
|
assertEquals(40.0, iData.getInsertionCost(), 0.2);
|
||||||
assertEquals(2, iData.getDeliveryInsertionIndex());
|
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());
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -32,6 +32,7 @@ import basics.Service;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
import basics.route.Driver;
|
import basics.route.Driver;
|
||||||
import basics.route.DriverImpl;
|
import basics.route.DriverImpl;
|
||||||
|
import basics.route.ServiceActivity;
|
||||||
import basics.route.TimeWindow;
|
import basics.route.TimeWindow;
|
||||||
import basics.route.TourActivities;
|
import basics.route.TourActivities;
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
|
|
@ -51,9 +52,9 @@ public class TestTourStateUpdaterWithService {
|
||||||
|
|
||||||
TourActivities anotherTour;
|
TourActivities anotherTour;
|
||||||
|
|
||||||
TourStateUpdater tdTourStatusProcessor;
|
UpdateStates updateStates;
|
||||||
|
|
||||||
RouteStates states;
|
StateManagerImpl states;
|
||||||
|
|
||||||
private VehicleRoute vehicleRoute;
|
private VehicleRoute vehicleRoute;
|
||||||
|
|
||||||
|
|
@ -100,33 +101,32 @@ public class TestTourStateUpdaterWithService {
|
||||||
services.add(firstService);
|
services.add(firstService);
|
||||||
services.add(secondService);
|
services.add(secondService);
|
||||||
|
|
||||||
states = new RouteStates();
|
states = new StateManagerImpl();
|
||||||
states.initialiseStateOfJobs(services);
|
|
||||||
|
|
||||||
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("test", 0).build();
|
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("test", 0).build();
|
||||||
vehicle = VehicleImpl.Builder.newInstance("testvehicle").setType(type).setLocationId("0,0")
|
vehicle = VehicleImpl.Builder.newInstance("testvehicle").setType(type).setLocationId("0,0")
|
||||||
.setEarliestStart(0.0).setLatestArrival(50.0).build();
|
.setEarliestStart(0.0).setLatestArrival(50.0).build();
|
||||||
|
|
||||||
tour = new TourActivities();
|
tour = new TourActivities();
|
||||||
tour.addActivity(states.getActivity(firstService,true));
|
tour.addActivity(ServiceActivity.newInstance(firstService));
|
||||||
tour.addActivity(states.getActivity(secondService,true));
|
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);
|
vehicleRoute = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),vehicle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCalculatedCost() {
|
public void testCalculatedCost() {
|
||||||
tdTourStatusProcessor.updateRoute(vehicleRoute);
|
updateStates.update(vehicleRoute);
|
||||||
assertEquals(40.0, states.getRouteState(vehicleRoute).getCosts(), 0.05);
|
assertEquals(40.0, states.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble(), 0.05);
|
||||||
assertEquals(10, states.getRouteState(vehicleRoute).getLoad());
|
assertEquals(10, states.getRouteState(vehicleRoute, StateTypes.LOAD).toDouble(), 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStatesOfAct0(){
|
public void testStatesOfAct0(){
|
||||||
tdTourStatusProcessor.updateRoute(vehicleRoute);
|
updateStates.update(vehicleRoute);
|
||||||
assertEquals(0.0, vehicleRoute.getStart().getEndTime(),0.05);
|
assertEquals(0.0, vehicleRoute.getStart().getEndTime(),0.05);
|
||||||
assertEquals(vehicleRoute.getVehicle().getLocationId(), vehicleRoute.getStart().getLocationId());
|
assertEquals(vehicleRoute.getVehicle().getLocationId(), vehicleRoute.getStart().getLocationId());
|
||||||
assertEquals(vehicleRoute.getVehicle().getEarliestDeparture(), vehicleRoute.getStart().getTheoreticalEarliestOperationStartTime(),0.05);
|
assertEquals(vehicleRoute.getVehicle().getEarliestDeparture(), vehicleRoute.getStart().getTheoreticalEarliestOperationStartTime(),0.05);
|
||||||
|
|
@ -136,112 +136,31 @@ public class TestTourStateUpdaterWithService {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStatesOfAct1(){
|
public void testStatesOfAct1(){
|
||||||
tdTourStatusProcessor.updateRoute(vehicleRoute);
|
updateStates.update(vehicleRoute);
|
||||||
assertEquals(10.0, states.getState(tour.getActivities().get(0)).getCurrentCost(),0.05);
|
assertEquals(10.0, states.getActivityState(tour.getActivities().get(0), StateTypes.COSTS).toDouble(),0.05);
|
||||||
assertEquals(5.0, states.getState(tour.getActivities().get(0)).getCurrentLoad(),0.05);
|
assertEquals(5.0, states.getActivityState(tour.getActivities().get(0), StateTypes.LOAD).toDouble(),0.05);
|
||||||
assertEquals(10.0, states.getState(tour.getActivities().get(0)).getEarliestOperationStart(),0.05);
|
// assertEquals(10.0, states.getActivityState(tour.getActivities().get(0), StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05);
|
||||||
assertEquals(20.0, states.getState(tour.getActivities().get(0)).getLatestOperationStart(),0.05);
|
assertEquals(20.0, states.getActivityState(tour.getActivities().get(0), StateTypes.LATEST_OPERATION_START_TIME).toDouble(),0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStatesOfAct2(){
|
public void testStatesOfAct2(){
|
||||||
tdTourStatusProcessor.updateRoute(vehicleRoute);
|
updateStates.update(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.getActivityState(tour.getActivities().get(1), StateTypes.COSTS).toDouble(),0.05);
|
||||||
assertEquals(30.0, states.getState(tour.getActivities().get(1)).getEarliestOperationStart(),0.05);
|
assertEquals(10.0, states.getActivityState(tour.getActivities().get(1), StateTypes.LOAD).toDouble(),0.05);
|
||||||
assertEquals(40.0, states.getState(tour.getActivities().get(1)).getLatestOperationStart(),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
|
@Test
|
||||||
public void testStatesOfAct3(){
|
public void testStatesOfAct3(){
|
||||||
tdTourStatusProcessor.updateRoute(vehicleRoute);
|
updateStates.update(vehicleRoute);
|
||||||
assertEquals(40.0, states.getRouteState(vehicleRoute).getCosts(), 0.05);
|
|
||||||
assertEquals(40.0, vehicleRoute.getEnd().getEndTime(),0.05);
|
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);
|
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());
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
node,quantity
|
||||||
|
2,4
|
||||||
|
3,6
|
||||||
|
4,5
|
||||||
|
5,4
|
||||||
|
6,7
|
||||||
|
7,3
|
||||||
|
8,5
|
||||||
|
9,4
|
||||||
|
10,4
|
||||||
635
jsprit-core/src/test/resources/vrpnc1-jsprit.xml
Normal file
635
jsprit-core/src/test/resources/vrpnc1-jsprit.xml
Normal 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>
|
||||||
|
|
@ -22,10 +22,12 @@
|
||||||
<algorithm xmlns="http://www.w3schools.com"
|
<algorithm xmlns="http://www.w3schools.com"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com algorithm_schema.xsd">
|
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>
|
<construction>
|
||||||
<insertion name="bestInsertion"/>
|
<insertion name="bestInsertion">
|
||||||
|
<level forwardLooking="2" memory="1">route</level>
|
||||||
|
</insertion>
|
||||||
</construction>
|
</construction>
|
||||||
|
|
||||||
<strategy>
|
<strategy>
|
||||||
|
|
@ -33,10 +35,8 @@
|
||||||
<searchStrategies>
|
<searchStrategies>
|
||||||
<searchStrategy name="radialRuinAndRecreate">
|
<searchStrategy name="radialRuinAndRecreate">
|
||||||
<selector name="selectBest"/>
|
<selector name="selectBest"/>
|
||||||
<acceptor name="schrimpfAcceptance">
|
<acceptor name="acceptNewRemoveWorst"/>
|
||||||
<alpha>0.1</alpha>
|
|
||||||
<warmup>100</warmup>
|
|
||||||
</acceptor>
|
|
||||||
<modules>
|
<modules>
|
||||||
<module name="ruin_and_recreate">
|
<module name="ruin_and_recreate">
|
||||||
<ruin name="randomRuin">
|
<ruin name="randomRuin">
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
|
|
||||||
<searchStrategy name="radialRuinAndRecreate">
|
<searchStrategy name="radialRuinAndRecreate">
|
||||||
<selector name="selectBest"/>
|
<selector name="selectBest"/>
|
||||||
<acceptor name="schrimpfAcceptance"/>
|
<acceptor name="acceptNewRemoveWorst"/>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module name="ruin_and_recreate">
|
<module name="ruin_and_recreate">
|
||||||
|
|
@ -67,7 +67,7 @@
|
||||||
|
|
||||||
<searchStrategy name="radialRuinAndRecreate">
|
<searchStrategy name="radialRuinAndRecreate">
|
||||||
<selector name="selectBest"/>
|
<selector name="selectBest"/>
|
||||||
<acceptor name="schrimpfAcceptance"/>
|
<acceptor name="acceptNewRemoveWorst"/>
|
||||||
<modules>
|
<modules>
|
||||||
<module name="ruin_and_recreate">
|
<module name="ruin_and_recreate">
|
||||||
<ruin id="2" name="radialRuin">
|
<ruin id="2" name="radialRuin">
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@
|
||||||
<iterations>2000</iterations>
|
<iterations>2000</iterations>
|
||||||
|
|
||||||
<construction>
|
<construction>
|
||||||
<insertion name="bestInsertion"/>
|
<insertion name="bestInsertion">
|
||||||
|
|
||||||
|
</insertion>
|
||||||
</construction>
|
</construction>
|
||||||
|
|
||||||
<strategy>
|
<strategy>
|
||||||
|
|
|
||||||
635
jsprit-examples/input/vrpnc1-jsprit.xml
Normal file
635
jsprit-examples/input/vrpnc1-jsprit.xml
Normal 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>
|
||||||
52
jsprit-examples/input/vrpnc1.txt
Normal file
52
jsprit-examples/input/vrpnc1.txt
Normal 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
|
||||||
16
jsprit-examples/src/main/java/examples/CVRPExample.java
Normal file
16
jsprit-examples/src/main/java/examples/CVRPExample.java
Normal 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,8 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package examples;
|
package examples;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
import readers.SolomonReader;
|
import readers.SolomonReader;
|
||||||
import algorithms.GreedySchrimpfFactory;
|
import algorithms.GreedySchrimpfFactory;
|
||||||
import algorithms.SchrimpfFactory;
|
import algorithms.SchrimpfFactory;
|
||||||
|
|
@ -35,7 +37,16 @@ public class CompareAlgorithmExample {
|
||||||
* @param args
|
* @param args
|
||||||
*/
|
*/
|
||||||
public static void main(String[] 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.
|
* Build the problem.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package examples;
|
package examples;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import util.Solutions;
|
import util.Solutions;
|
||||||
|
|
@ -32,7 +33,16 @@ public class CostMatrixExample {
|
||||||
* @param args
|
* @param args
|
||||||
*/
|
*/
|
||||||
public static void main(String[] 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();
|
VehicleType type = VehicleTypeImpl.Builder.newInstance("type", 2).setCostPerDistance(1).setCostPerTime(2).build();
|
||||||
Vehicle vehicle = VehicleImpl.Builder.newInstance("vehicle").setLocationId("0").setType(type).build();
|
Vehicle vehicle = VehicleImpl.Builder.newInstance("vehicle").setLocationId("0").setType(type).build();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package examples;
|
package examples;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
|
@ -18,7 +19,6 @@ import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
|
||||||
import basics.io.VrpXMLReader;
|
import basics.io.VrpXMLReader;
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
import basics.route.VehicleImpl;
|
import basics.route.VehicleImpl;
|
||||||
import basics.route.VehicleType;
|
|
||||||
import basics.route.VehicleTypeImpl;
|
import basics.route.VehicleTypeImpl;
|
||||||
|
|
||||||
public class MultipleDepotExample {
|
public class MultipleDepotExample {
|
||||||
|
|
@ -27,7 +27,16 @@ public class MultipleDepotExample {
|
||||||
* @param args
|
* @param args
|
||||||
*/
|
*/
|
||||||
public static void main(String[] 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();
|
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||||
/*
|
/*
|
||||||
* Read cordeau-instance p01, BUT only its services without any vehicles
|
* Read cordeau-instance p01, BUT only its services without any vehicles
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package examples;
|
package examples;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
|
@ -29,6 +30,16 @@ public class MultipleDepotExampleWithPenaltyVehicles {
|
||||||
* @param args
|
* @param args
|
||||||
*/
|
*/
|
||||||
public static void main(String[] 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();
|
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,16 @@ public class RefuseCollectionExample {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) 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
|
* create vehicle-type and vehicle
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package examples;
|
package examples;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import util.Coordinate;
|
import util.Coordinate;
|
||||||
|
|
@ -42,6 +43,16 @@ import basics.route.VehicleTypeImpl;
|
||||||
public class SimpleExample {
|
public class SimpleExample {
|
||||||
|
|
||||||
public static void main(String[] 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");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get a vehicle type-builder and build a type with the typeId "vehicleType" and a capacity of 2
|
* get a vehicle type-builder and build a type with the typeId "vehicleType" and a capacity of 2
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,12 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package examples;
|
package examples;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import readers.SolomonReader;
|
import readers.SolomonReader;
|
||||||
import algorithms.SchrimpfFactory;
|
import algorithms.VehicleRoutingAlgorithms;
|
||||||
import algorithms.selectors.SelectBest;
|
import algorithms.selectors.SelectBest;
|
||||||
import analysis.AlgorithmSearchProgressChartListener;
|
|
||||||
import analysis.SolutionPlotter;
|
import analysis.SolutionPlotter;
|
||||||
import analysis.SolutionPrinter;
|
import analysis.SolutionPrinter;
|
||||||
import analysis.SolutionPrinter.Print;
|
import analysis.SolutionPrinter.Print;
|
||||||
|
|
@ -36,7 +36,16 @@ import basics.VehicleRoutingProblemSolution;
|
||||||
public class SolomonExample {
|
public class SolomonExample {
|
||||||
|
|
||||||
public static void main(String[] 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.
|
* Build the problem.
|
||||||
|
|
@ -62,8 +71,10 @@ public class SolomonExample {
|
||||||
*
|
*
|
||||||
* The algorithm can be defined and configured in an xml-file.
|
* The algorithm can be defined and configured in an xml-file.
|
||||||
*/
|
*/
|
||||||
VehicleRoutingAlgorithm vra = new SchrimpfFactory().createAlgorithm(vrp);
|
// VehicleRoutingAlgorithm vra = new SchrimpfFactory().createAlgorithm(vrp);
|
||||||
vra.getAlgorithmListeners().addListener(new AlgorithmSearchProgressChartListener("output/sol_progress.png"));
|
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_solomon.xml");
|
||||||
|
vra.setPrematureBreak(100);
|
||||||
|
// vra.getAlgorithmListeners().addListener(new AlgorithmSearchProgressChartListener("output/sol_progress.png"));
|
||||||
/*
|
/*
|
||||||
* Solve the problem.
|
* Solve the problem.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
2
pom.xml
2
pom.xml
|
|
@ -42,7 +42,7 @@
|
||||||
<developers>
|
<developers>
|
||||||
<developer>
|
<developer>
|
||||||
<name>Stefan Schroeder</name>
|
<name>Stefan Schroeder</name>
|
||||||
<email>4sschroeder@gmail.com</email>
|
<email>jsprit.vehicle.routing@gmail.com</email>
|
||||||
</developer>
|
</developer>
|
||||||
</developers>
|
</developers>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue