mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
Merge branch 'open-vehicle-routes'
This commit is contained in:
commit
126538ef1f
28 changed files with 4800 additions and 51 deletions
|
|
@ -22,6 +22,7 @@ import java.util.List;
|
||||||
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||||
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
import jsprit.core.problem.driver.Driver;
|
import jsprit.core.problem.driver.Driver;
|
||||||
|
import jsprit.core.problem.solution.route.activity.End;
|
||||||
import jsprit.core.problem.solution.route.activity.TourActivity;
|
import jsprit.core.problem.solution.route.activity.TourActivity;
|
||||||
import jsprit.core.problem.vehicle.Vehicle;
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
|
||||||
|
|
@ -33,10 +34,10 @@ final class AuxilliaryCostCalculator {
|
||||||
|
|
||||||
private final VehicleRoutingActivityCosts activityCosts;
|
private final VehicleRoutingActivityCosts activityCosts;
|
||||||
|
|
||||||
public AuxilliaryCostCalculator(final VehicleRoutingTransportCosts routingCosts, final VehicleRoutingActivityCosts costFunction) {
|
public AuxilliaryCostCalculator(final VehicleRoutingTransportCosts routingCosts, final VehicleRoutingActivityCosts actCosts) {
|
||||||
super();
|
super();
|
||||||
this.routingCosts = routingCosts;
|
this.routingCosts = routingCosts;
|
||||||
this.activityCosts = costFunction;
|
this.activityCosts = actCosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -59,6 +60,11 @@ final class AuxilliaryCostCalculator {
|
||||||
double departureTimePrevAct = depTime;
|
double departureTimePrevAct = depTime;
|
||||||
while(actIter.hasNext()){
|
while(actIter.hasNext()){
|
||||||
TourActivity act = actIter.next();
|
TourActivity act = actIter.next();
|
||||||
|
if(act instanceof End){
|
||||||
|
if(!vehicle.isReturnToDepot()){
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
}
|
||||||
double transportCost = routingCosts.getTransportCost(prevAct.getLocationId(), act.getLocationId(), departureTimePrevAct, driver, vehicle);
|
double transportCost = routingCosts.getTransportCost(prevAct.getLocationId(), act.getLocationId(), departureTimePrevAct, driver, vehicle);
|
||||||
double transportTime = routingCosts.getTransportTime(prevAct.getLocationId(), act.getLocationId(), departureTimePrevAct, driver, vehicle);
|
double transportTime = routingCosts.getTransportTime(prevAct.getLocationId(), act.getLocationId(), departureTimePrevAct, driver, vehicle);
|
||||||
cost += transportCost;
|
cost += transportCost;
|
||||||
|
|
@ -72,37 +78,5 @@ final class AuxilliaryCostCalculator {
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double costOfPath(String startLocationId, final double startTime, final List<TourActivity> path, String endLocationId, final Driver driver, final Vehicle vehicle){
|
|
||||||
if(path.isEmpty()){
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
double cost = 0.0;
|
|
||||||
// Iterator<TourActivity> actIter = path.iterator();
|
|
||||||
String prevActLocation = startLocationId;
|
|
||||||
// TourActivity prevAct = actIter.next();
|
|
||||||
double startCost = 0.0;
|
|
||||||
cost += startCost;
|
|
||||||
double departureTimePrevAct = startTime;
|
|
||||||
for(TourActivity act : path){
|
|
||||||
// TourActivity act = actIter.next();
|
|
||||||
double transportCost = routingCosts.getTransportCost(prevActLocation, act.getLocationId(), departureTimePrevAct, driver, vehicle);
|
|
||||||
double transportTime = routingCosts.getTransportTime(prevActLocation, act.getLocationId(), departureTimePrevAct, driver, vehicle);
|
|
||||||
cost += transportCost;
|
|
||||||
double actStartTime = departureTimePrevAct + transportTime;
|
|
||||||
double earliestOperationStartTime = Math.max(actStartTime, act.getTheoreticalEarliestOperationStartTime());
|
|
||||||
double actEndTime = earliestOperationStartTime + act.getOperationTime();
|
|
||||||
departureTimePrevAct = actEndTime;
|
|
||||||
cost += activityCosts.getActivityCost(act, actStartTime, driver, vehicle);
|
|
||||||
prevActLocation = act.getLocationId();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
*!!! ENDLOCATION
|
|
||||||
=> Start u. End können primitiv sein.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
return cost;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,12 +60,21 @@ class Inserter {
|
||||||
@Override
|
@Override
|
||||||
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
|
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
|
||||||
if(job instanceof Service){
|
if(job instanceof Service){
|
||||||
|
if(!iData.getSelectedVehicle().isReturnToDepot()){
|
||||||
|
if(iData.getDeliveryInsertionIndex()>=route.getTourActivities().getActivities().size()){
|
||||||
|
setEndLocation(route,(Service)job);
|
||||||
|
}
|
||||||
|
}
|
||||||
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), this.activityFactory.createActivity((Service)job));
|
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), this.activityFactory.createActivity((Service)job));
|
||||||
route.setDepartureTime(iData.getVehicleDepartureTime());
|
route.setDepartureTime(iData.getVehicleDepartureTime());
|
||||||
}
|
}
|
||||||
else delegator.handleJobInsertion(job, iData, route);
|
else delegator.handleJobInsertion(job, iData, route);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setEndLocation(VehicleRoute route, Service service) {
|
||||||
|
route.getEnd().setLocationId(service.getLocationId());
|
||||||
|
}
|
||||||
|
|
||||||
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
|
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
|
||||||
this.delegator = jobInsertionHandler;
|
this.delegator = jobInsertionHandler;
|
||||||
}
|
}
|
||||||
|
|
@ -83,6 +92,11 @@ class Inserter {
|
||||||
if(job instanceof Shipment){
|
if(job instanceof Shipment){
|
||||||
TourActivity pickupShipment = this.activityFactory.createPickup((Shipment)job);
|
TourActivity pickupShipment = this.activityFactory.createPickup((Shipment)job);
|
||||||
TourActivity deliverShipment = this.activityFactory.createDelivery((Shipment)job);
|
TourActivity deliverShipment = this.activityFactory.createDelivery((Shipment)job);
|
||||||
|
if(!iData.getSelectedVehicle().isReturnToDepot()){
|
||||||
|
if(iData.getDeliveryInsertionIndex()>=route.getTourActivities().getActivities().size()){
|
||||||
|
setEndLocation(route,(Shipment)job);
|
||||||
|
}
|
||||||
|
}
|
||||||
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), deliverShipment);
|
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), deliverShipment);
|
||||||
route.getTourActivities().addActivity(iData.getPickupInsertionIndex(), pickupShipment);
|
route.getTourActivities().addActivity(iData.getPickupInsertionIndex(), pickupShipment);
|
||||||
route.setDepartureTime(iData.getVehicleDepartureTime());
|
route.setDepartureTime(iData.getVehicleDepartureTime());
|
||||||
|
|
@ -90,6 +104,10 @@ class Inserter {
|
||||||
else delegator.handleJobInsertion(job, iData, route);
|
else delegator.handleJobInsertion(job, iData, route);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setEndLocation(VehicleRoute route, Shipment shipment) {
|
||||||
|
route.getEnd().setLocationId(shipment.getDeliveryLocation());
|
||||||
|
}
|
||||||
|
|
||||||
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
|
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
|
||||||
this.delegator = jobInsertionHandler;
|
this.delegator = jobInsertionHandler;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ package jsprit.core.algorithm.recreate;
|
||||||
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||||
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
import jsprit.core.problem.misc.JobInsertionContext;
|
import jsprit.core.problem.misc.JobInsertionContext;
|
||||||
|
import jsprit.core.problem.solution.route.activity.End;
|
||||||
import jsprit.core.problem.solution.route.activity.TourActivity;
|
import jsprit.core.problem.solution.route.activity.TourActivity;
|
||||||
import jsprit.core.util.CalculationUtils;
|
import jsprit.core.util.CalculationUtils;
|
||||||
|
|
||||||
|
|
@ -61,6 +62,13 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
|
||||||
|
|
||||||
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||||
|
|
||||||
|
//open routes
|
||||||
|
if(nextAct instanceof End){
|
||||||
|
if(!iFacts.getNewVehicle().isReturnToDepot()){
|
||||||
|
return new ActivityInsertionCosts(tp_costs_prevAct_newAct, tp_time_prevAct_newAct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, 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 tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -230,14 +230,19 @@ public class VrpXMLReader{
|
||||||
if(vehicle == null) throw new IllegalStateException("vehicle is missing.");
|
if(vehicle == null) throw new IllegalStateException("vehicle is missing.");
|
||||||
String start = routeConfig.getString("start");
|
String start = routeConfig.getString("start");
|
||||||
if(start == null) throw new IllegalStateException("route start-time is missing.");
|
if(start == null) throw new IllegalStateException("route start-time is missing.");
|
||||||
|
double departureTime = Double.parseDouble(start);
|
||||||
|
|
||||||
String end = routeConfig.getString("end");
|
String end = routeConfig.getString("end");
|
||||||
if(end == null) throw new IllegalStateException("route end-time is missing.");
|
if(end == null) throw new IllegalStateException("route end-time is missing.");
|
||||||
Start startAct = Start.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
|
|
||||||
startAct.setEndTime(Double.parseDouble(start));
|
// Start startAct = Start.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
|
||||||
|
// startAct.setEndTime(Double.parseDouble(start));
|
||||||
End endAct = End.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
|
End endAct = End.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
|
||||||
endAct.setArrTime(Double.parseDouble(end));
|
endAct.setArrTime(Double.parseDouble(end));
|
||||||
|
|
||||||
VehicleRoute.Builder routeBuilder = VehicleRoute.Builder.newInstance(vehicle, driver);
|
VehicleRoute.Builder routeBuilder = VehicleRoute.Builder.newInstance(vehicle, driver);
|
||||||
|
routeBuilder.setDepartureTime(departureTime);
|
||||||
|
routeBuilder.setRouteEndArrivalTime(Double.parseDouble(end));
|
||||||
List<HierarchicalConfiguration> actConfigs = routeConfig.configurationsAt("act");
|
List<HierarchicalConfiguration> actConfigs = routeConfig.configurationsAt("act");
|
||||||
for(HierarchicalConfiguration actConfig : actConfigs){
|
for(HierarchicalConfiguration actConfig : actConfigs){
|
||||||
String type = actConfig.getString("[@type]");
|
String type = actConfig.getString("[@type]");
|
||||||
|
|
@ -466,6 +471,10 @@ public class VrpXMLReader{
|
||||||
String end = vehicleConfig.getString("timeSchedule.end");
|
String end = vehicleConfig.getString("timeSchedule.end");
|
||||||
if(start != null) builder.setEarliestStart(Double.parseDouble(start));
|
if(start != null) builder.setEarliestStart(Double.parseDouble(start));
|
||||||
if(end != null) builder.setLatestArrival(Double.parseDouble(end));
|
if(end != null) builder.setLatestArrival(Double.parseDouble(end));
|
||||||
|
String returnToDepot = vehicleConfig.getString("returnToDepot");
|
||||||
|
if(returnToDepot != null){
|
||||||
|
builder.setReturnToDepot(vehicleConfig.getBoolean("returnToDepot"));
|
||||||
|
}
|
||||||
VehicleImpl vehicle = builder.build();
|
VehicleImpl vehicle = builder.build();
|
||||||
vrpBuilder.addVehicle(vehicle);
|
vrpBuilder.addVehicle(vehicle);
|
||||||
vehicleMap.put(vehicleId, vehicle);
|
vehicleMap.put(vehicleId, vehicle);
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,7 @@ public class VrpXMLWriter {
|
||||||
xmlConfig.setProperty(vehiclePathString + "("+counter+").timeSchedule.start", vehicle.getEarliestDeparture());
|
xmlConfig.setProperty(vehiclePathString + "("+counter+").timeSchedule.start", vehicle.getEarliestDeparture());
|
||||||
xmlConfig.setProperty(vehiclePathString + "("+counter+").timeSchedule.end", vehicle.getLatestArrival());
|
xmlConfig.setProperty(vehiclePathString + "("+counter+").timeSchedule.end", vehicle.getLatestArrival());
|
||||||
|
|
||||||
|
xmlConfig.setProperty(vehiclePathString + "("+counter+").returnToDepot", vehicle.isReturnToDepot());
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,8 @@ public class VehicleRoute {
|
||||||
|
|
||||||
private Start start;
|
private Start start;
|
||||||
|
|
||||||
|
private End end;
|
||||||
|
|
||||||
private TourActivities tourActivities = new TourActivities();
|
private TourActivities tourActivities = new TourActivities();
|
||||||
|
|
||||||
private TourActivityFactory serviceActivityFactory = new DefaultTourActivityFactory();
|
private TourActivityFactory serviceActivityFactory = new DefaultTourActivityFactory();
|
||||||
|
|
@ -79,6 +81,10 @@ public class VehicleRoute {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the route-builder.
|
* Constructs the route-builder.
|
||||||
|
*
|
||||||
|
* <p>Default startLocation is vehicle.getLocationId()<br>
|
||||||
|
* Default departureTime is vehicle.getEarliestDeparture()<br>
|
||||||
|
* Default endLocation is either vehicle.getLocationId() or (if !vehicle.isReturnToDepot()) last specified activityLocation
|
||||||
* @param vehicle
|
* @param vehicle
|
||||||
* @param driver
|
* @param driver
|
||||||
*/
|
*/
|
||||||
|
|
@ -88,7 +94,7 @@ public class VehicleRoute {
|
||||||
this.driver = driver;
|
this.driver = driver;
|
||||||
start = Start.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
|
start = Start.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
|
||||||
start.setEndTime(vehicle.getEarliestDeparture());
|
start.setEndTime(vehicle.getEarliestDeparture());
|
||||||
End.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
|
end = End.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -102,6 +108,11 @@ public class VehicleRoute {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setRouteEndArrivalTime(double endTime){
|
||||||
|
end.setArrTime(endTime);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Builder addService(Service service){
|
public Builder addService(Service service){
|
||||||
addService(service,0.0,0.0);
|
addService(service,0.0,0.0);
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -185,7 +196,12 @@ public class VehicleRoute {
|
||||||
if(!openShipments.isEmpty()){
|
if(!openShipments.isEmpty()){
|
||||||
throw new IllegalStateException("there are still shipments that have not been delivered yet.");
|
throw new IllegalStateException("there are still shipments that have not been delivered yet.");
|
||||||
}
|
}
|
||||||
VehicleRoute route = VehicleRoute.newInstance(tourActivities, driver, vehicle);
|
if(!vehicle.isReturnToDepot()){
|
||||||
|
if(!tourActivities.isEmpty()){
|
||||||
|
end.setLocationId(tourActivities.getActivities().get(tourActivities.getActivities().size()-1).getLocationId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VehicleRoute route = new VehicleRoute(this);
|
||||||
return route;
|
return route;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,13 +234,14 @@ public class VehicleRoute {
|
||||||
setStartAndEnd(vehicle, vehicle.getEarliestDeparture());
|
setStartAndEnd(vehicle, vehicle.getEarliestDeparture());
|
||||||
}
|
}
|
||||||
|
|
||||||
// private VehicleRoute(Builder builder){
|
|
||||||
// this.tourActivities = builder.tour;
|
private VehicleRoute(Builder builder){
|
||||||
// this.vehicle = builder.vehicle;
|
this.tourActivities = builder.tourActivities;
|
||||||
// this.driver = builder.driver;
|
this.vehicle = builder.vehicle;
|
||||||
// this.start = builder.start;
|
this.driver = builder.driver;
|
||||||
// this.end = builder.end;
|
this.start = builder.start;
|
||||||
// }
|
this.end = builder.end;
|
||||||
|
}
|
||||||
|
|
||||||
private void verify(TourActivities tour, Driver driver, Vehicle vehicle) {
|
private void verify(TourActivities tour, Driver driver, Vehicle vehicle) {
|
||||||
if(tour == null || driver == null || vehicle == null) throw new IllegalStateException("null is not allowed for tour, driver or vehicle. use emptyRoute. use Tour.emptyTour, DriverImpl.noDriver() and VehicleImpl.noVehicle() instead." +
|
if(tour == null || driver == null || vehicle == null) throw new IllegalStateException("null is not allowed for tour, driver or vehicle. use emptyRoute. use Tour.emptyTour, DriverImpl.noDriver() and VehicleImpl.noVehicle() instead." +
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,11 @@ public final class End implements TourActivity {
|
||||||
|
|
||||||
private Coordinate coordinate;
|
private Coordinate coordinate;
|
||||||
|
|
||||||
public Coordinate getCoordinate() {
|
Coordinate getCoordinate() {
|
||||||
return coordinate;
|
return coordinate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCoordinate(Coordinate coordinate) {
|
void setCoordinate(Coordinate coordinate) {
|
||||||
this.coordinate = coordinate;
|
this.coordinate = coordinate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,11 +65,11 @@ public final class Start implements TourActivity {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Coordinate getCoordinate() {
|
Coordinate getCoordinate() {
|
||||||
return coordinate;
|
return coordinate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCoordinate(Coordinate coordinate) {
|
void setCoordinate(Coordinate coordinate) {
|
||||||
this.coordinate = coordinate;
|
this.coordinate = coordinate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,4 +36,6 @@ public interface Vehicle {
|
||||||
|
|
||||||
public abstract int getCapacity();
|
public abstract int getCapacity();
|
||||||
|
|
||||||
|
public abstract boolean isReturnToDepot();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,8 @@ public class VehicleImpl implements Vehicle {
|
||||||
private double earliestStart = 0.0;
|
private double earliestStart = 0.0;
|
||||||
private double latestArrival = Double.MAX_VALUE;
|
private double latestArrival = Double.MAX_VALUE;
|
||||||
|
|
||||||
|
private boolean returnToDepot = true;
|
||||||
|
|
||||||
private VehicleType type = VehicleTypeImpl.Builder.newInstance("default", 0).build();
|
private VehicleType type = VehicleTypeImpl.Builder.newInstance("default", 0).build();
|
||||||
|
|
||||||
private Builder(String id) {
|
private Builder(String id) {
|
||||||
|
|
@ -66,6 +68,11 @@ public class VehicleImpl implements Vehicle {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setReturnToDepot(boolean returnToDepot){
|
||||||
|
this.returnToDepot = returnToDepot;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Builder setLocationId(String id){
|
public Builder setLocationId(String id){
|
||||||
this.locationId = id;
|
this.locationId = id;
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -114,6 +121,8 @@ public class VehicleImpl implements Vehicle {
|
||||||
|
|
||||||
private final double latestArrival;
|
private final double latestArrival;
|
||||||
|
|
||||||
|
private boolean returnToDepot;
|
||||||
|
|
||||||
private VehicleImpl(Builder builder){
|
private VehicleImpl(Builder builder){
|
||||||
id = builder.id;
|
id = builder.id;
|
||||||
type = builder.type;
|
type = builder.type;
|
||||||
|
|
@ -121,6 +130,7 @@ public class VehicleImpl implements Vehicle {
|
||||||
locationId = builder.locationId;
|
locationId = builder.locationId;
|
||||||
earliestDeparture = builder.earliestStart;
|
earliestDeparture = builder.earliestStart;
|
||||||
latestArrival = builder.latestArrival;
|
latestArrival = builder.latestArrival;
|
||||||
|
returnToDepot = builder.returnToDepot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -194,4 +204,15 @@ public class VehicleImpl implements Vehicle {
|
||||||
return type.getCapacity();
|
return type.getCapacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the returnToDepot
|
||||||
|
*/
|
||||||
|
public boolean isReturnToDepot() {
|
||||||
|
return returnToDepot;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="typeId" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
<xs:element name="typeId" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||||
<xs:element name="timeSchedule" type="timeWindowType"/>
|
<xs:element name="timeSchedule" type="timeWindowType"/>
|
||||||
|
<xs:element name="returnToDepot" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||||
</xs:all>
|
</xs:all>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
package jsprit.core.algorithm.recreate;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||||
|
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
|
import jsprit.core.problem.solution.route.activity.End;
|
||||||
|
import jsprit.core.problem.solution.route.activity.TourActivity;
|
||||||
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestAuxilliaryCostCalculator {
|
||||||
|
|
||||||
|
private VehicleRoutingTransportCosts routingCosts;
|
||||||
|
|
||||||
|
private VehicleRoutingActivityCosts actCosts;
|
||||||
|
|
||||||
|
private Vehicle vehicle;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void doBefore(){
|
||||||
|
vehicle = mock(Vehicle.class);
|
||||||
|
|
||||||
|
routingCosts = mock(VehicleRoutingTransportCosts.class);
|
||||||
|
actCosts = mock(VehicleRoutingActivityCosts.class);
|
||||||
|
|
||||||
|
when(routingCosts.getTransportCost("i", "j", 0.0, null, vehicle)).thenReturn(2.0);
|
||||||
|
when(routingCosts.getTransportTime("i", "j", 0.0, null, vehicle)).thenReturn(0.0);
|
||||||
|
when(routingCosts.getTransportCost("i", "k", 0.0, null, vehicle)).thenReturn(3.0);
|
||||||
|
when(routingCosts.getTransportTime("i", "k", 0.0, null, vehicle)).thenReturn(0.0);
|
||||||
|
when(routingCosts.getTransportCost("k", "j", 0.0, null, vehicle)).thenReturn(3.0);
|
||||||
|
when(routingCosts.getTransportTime("k", "j", 0.0, null, vehicle)).thenReturn(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRouteIsClosed_itCalculatesCostUpToEnd_v1(){
|
||||||
|
TourActivity prevAct = mock(TourActivity.class);
|
||||||
|
when(prevAct.getLocationId()).thenReturn("i");
|
||||||
|
TourActivity nextAct = mock(TourActivity.class);
|
||||||
|
when(nextAct.getLocationId()).thenReturn("j");
|
||||||
|
TourActivity newAct = mock(TourActivity.class);
|
||||||
|
when(newAct.getLocationId()).thenReturn("k");
|
||||||
|
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(true);
|
||||||
|
|
||||||
|
AuxilliaryCostCalculator aCalc = new AuxilliaryCostCalculator(routingCosts, actCosts);
|
||||||
|
double costs = aCalc.costOfPath(Arrays.asList(prevAct,newAct,nextAct), 0.0, null, vehicle);
|
||||||
|
assertEquals(6.0,costs,0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRouteIsClosed_itCalculatesCostUpToEnd_v2(){
|
||||||
|
TourActivity prevAct = mock(TourActivity.class);
|
||||||
|
when(prevAct.getLocationId()).thenReturn("i");
|
||||||
|
End nextAct = End.newInstance("j", 0.0, 0.0);
|
||||||
|
TourActivity newAct = mock(TourActivity.class);
|
||||||
|
when(newAct.getLocationId()).thenReturn("k");
|
||||||
|
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(true);
|
||||||
|
|
||||||
|
AuxilliaryCostCalculator aCalc = new AuxilliaryCostCalculator(routingCosts, actCosts);
|
||||||
|
double costs = aCalc.costOfPath(Arrays.asList(prevAct,newAct,nextAct), 0.0, null, vehicle);
|
||||||
|
assertEquals(6.0,costs,0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRouteIsOpen_itCalculatesCostUpToEnd_v1(){
|
||||||
|
TourActivity prevAct = mock(TourActivity.class);
|
||||||
|
when(prevAct.getLocationId()).thenReturn("i");
|
||||||
|
TourActivity nextAct = mock(TourActivity.class);
|
||||||
|
when(nextAct.getLocationId()).thenReturn("j");
|
||||||
|
TourActivity newAct = mock(TourActivity.class);
|
||||||
|
when(newAct.getLocationId()).thenReturn("k");
|
||||||
|
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(false);
|
||||||
|
|
||||||
|
AuxilliaryCostCalculator aCalc = new AuxilliaryCostCalculator(routingCosts, actCosts);
|
||||||
|
double costs = aCalc.costOfPath(Arrays.asList(prevAct,newAct,nextAct), 0.0, null, vehicle);
|
||||||
|
assertEquals(6.0,costs,0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRouteIsOpen_itCalculatesCostUpToEnd_v2(){
|
||||||
|
TourActivity prevAct = mock(TourActivity.class);
|
||||||
|
when(prevAct.getLocationId()).thenReturn("i");
|
||||||
|
End nextAct = End.newInstance("j", 0.0, 0.0);
|
||||||
|
TourActivity newAct = mock(TourActivity.class);
|
||||||
|
when(newAct.getLocationId()).thenReturn("k");
|
||||||
|
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(false);
|
||||||
|
|
||||||
|
AuxilliaryCostCalculator aCalc = new AuxilliaryCostCalculator(routingCosts, actCosts);
|
||||||
|
double costs = aCalc.costOfPath(Arrays.asList(prevAct,newAct,nextAct), 0.0, null, vehicle);
|
||||||
|
assertEquals(3.0,costs,0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package jsprit.core.algorithm.recreate;
|
package jsprit.core.algorithm.recreate;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
@ -80,12 +81,14 @@ public class TestCalculatesServiceInsertion {
|
||||||
when(vehicle.getLocationId()).thenReturn("depot");
|
when(vehicle.getLocationId()).thenReturn("depot");
|
||||||
when(vehicle.getEarliestDeparture()).thenReturn(0.0);
|
when(vehicle.getEarliestDeparture()).thenReturn(0.0);
|
||||||
when(vehicle.getLatestArrival()).thenReturn(100.0);
|
when(vehicle.getLatestArrival()).thenReturn(100.0);
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(true);
|
||||||
|
|
||||||
newVehicle = mock(Vehicle.class);
|
newVehicle = mock(Vehicle.class);
|
||||||
when(newVehicle.getCapacity()).thenReturn(1000);
|
when(newVehicle.getCapacity()).thenReturn(1000);
|
||||||
when(newVehicle.getLocationId()).thenReturn("depot");
|
when(newVehicle.getLocationId()).thenReturn("depot");
|
||||||
when(newVehicle.getEarliestDeparture()).thenReturn(0.0);
|
when(newVehicle.getEarliestDeparture()).thenReturn(0.0);
|
||||||
when(newVehicle.getLatestArrival()).thenReturn(100.0);
|
when(newVehicle.getLatestArrival()).thenReturn(100.0);
|
||||||
|
when(newVehicle.isReturnToDepot()).thenReturn(true);
|
||||||
|
|
||||||
driver = DriverImpl.noDriver();
|
driver = DriverImpl.noDriver();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package jsprit.core.algorithm.recreate;
|
package jsprit.core.algorithm.recreate;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
|
@ -82,12 +83,14 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
|
||||||
when(vehicle.getLocationId()).thenReturn("0,0");
|
when(vehicle.getLocationId()).thenReturn("0,0");
|
||||||
when(vehicle.getEarliestDeparture()).thenReturn(0.0);
|
when(vehicle.getEarliestDeparture()).thenReturn(0.0);
|
||||||
when(vehicle.getLatestArrival()).thenReturn(100.0);
|
when(vehicle.getLatestArrival()).thenReturn(100.0);
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(true);
|
||||||
|
|
||||||
newVehicle = mock(Vehicle.class);
|
newVehicle = mock(Vehicle.class);
|
||||||
when(newVehicle.getCapacity()).thenReturn(1000);
|
when(newVehicle.getCapacity()).thenReturn(1000);
|
||||||
when(newVehicle.getLocationId()).thenReturn("0,0");
|
when(newVehicle.getLocationId()).thenReturn("0,0");
|
||||||
when(newVehicle.getEarliestDeparture()).thenReturn(0.0);
|
when(newVehicle.getEarliestDeparture()).thenReturn(0.0);
|
||||||
when(newVehicle.getLatestArrival()).thenReturn(100.0);
|
when(newVehicle.getLatestArrival()).thenReturn(100.0);
|
||||||
|
when(newVehicle.isReturnToDepot()).thenReturn(true);
|
||||||
|
|
||||||
driver = DriverImpl.noDriver();
|
driver = DriverImpl.noDriver();
|
||||||
|
|
||||||
|
|
@ -239,4 +242,5 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
|
||||||
assertEquals(2, iData.getDeliveryInsertionIndex());
|
assertEquals(2, iData.getDeliveryInsertionIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
package jsprit.core.algorithm.recreate;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import jsprit.core.algorithm.recreate.listener.InsertionListeners;
|
||||||
|
import jsprit.core.problem.driver.Driver;
|
||||||
|
import jsprit.core.problem.job.Service;
|
||||||
|
import jsprit.core.problem.job.Shipment;
|
||||||
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestInserter {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInsertingServiceAndRouteIsClosed_itInsertsCorrectly(){
|
||||||
|
Service service = mock(Service.class);
|
||||||
|
Vehicle vehicle = mock(Vehicle.class);
|
||||||
|
when(vehicle.getLocationId()).thenReturn("vehLoc");
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(true);
|
||||||
|
when(vehicle.getId()).thenReturn("vehId");
|
||||||
|
|
||||||
|
VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addService(service).build();
|
||||||
|
//start - pick(shipment) - del(shipment) - end
|
||||||
|
Service serviceToInsert = mock(Service.class);
|
||||||
|
when(serviceToInsert.getLocationId()).thenReturn("delLoc");
|
||||||
|
|
||||||
|
InsertionData iData = mock(InsertionData.class);
|
||||||
|
when(iData.getDeliveryInsertionIndex()).thenReturn(1);
|
||||||
|
when(iData.getSelectedVehicle()).thenReturn(vehicle);
|
||||||
|
|
||||||
|
Inserter inserter = new Inserter(mock(InsertionListeners.class));
|
||||||
|
inserter.insertJob(serviceToInsert, iData, route);
|
||||||
|
|
||||||
|
assertEquals(2,route.getTourActivities().getActivities().size());
|
||||||
|
assertEquals(route.getTourActivities().getActivities().get(1).getLocationId(),serviceToInsert.getLocationId());
|
||||||
|
assertEquals(route.getEnd().getLocationId(),vehicle.getLocationId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInsertingServiceAndRouteIsOpen_itInsertsCorrectlyAndSwitchesEndLocation(){
|
||||||
|
Service service = mock(Service.class);
|
||||||
|
Vehicle vehicle = mock(Vehicle.class);
|
||||||
|
when(vehicle.getLocationId()).thenReturn("vehLoc");
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(false);
|
||||||
|
when(vehicle.getId()).thenReturn("vehId");
|
||||||
|
|
||||||
|
VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addService(service).build();
|
||||||
|
Service serviceToInsert = mock(Service.class);
|
||||||
|
when(serviceToInsert.getLocationId()).thenReturn("delLoc");
|
||||||
|
|
||||||
|
InsertionData iData = mock(InsertionData.class);
|
||||||
|
when(iData.getDeliveryInsertionIndex()).thenReturn(1);
|
||||||
|
when(iData.getSelectedVehicle()).thenReturn(vehicle);
|
||||||
|
|
||||||
|
Inserter inserter = new Inserter(mock(InsertionListeners.class));
|
||||||
|
inserter.insertJob(serviceToInsert, iData, route);
|
||||||
|
|
||||||
|
assertEquals(2,route.getTourActivities().getActivities().size());
|
||||||
|
assertEquals(route.getTourActivities().getActivities().get(1).getLocationId(),serviceToInsert.getLocationId());
|
||||||
|
assertEquals(route.getEnd().getLocationId(),serviceToInsert.getLocationId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInsertingShipmentAndRouteIsClosed_itInsertsCorrectly(){
|
||||||
|
Shipment shipment = mock(Shipment.class);
|
||||||
|
Vehicle vehicle = mock(Vehicle.class);
|
||||||
|
when(vehicle.getLocationId()).thenReturn("vehLoc");
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(true);
|
||||||
|
when(vehicle.getId()).thenReturn("vehId");
|
||||||
|
|
||||||
|
VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addPickup(shipment).addDelivery(shipment).build();
|
||||||
|
//start - pick(shipment) - del(shipment) - end
|
||||||
|
Shipment shipmentToInsert = mock(Shipment.class);
|
||||||
|
when(shipmentToInsert.getDeliveryLocation()).thenReturn("delLoc");
|
||||||
|
when(shipmentToInsert.getPickupLocation()).thenReturn("pickLoc");
|
||||||
|
InsertionData iData = mock(InsertionData.class);
|
||||||
|
when(iData.getPickupInsertionIndex()).thenReturn(2);
|
||||||
|
when(iData.getDeliveryInsertionIndex()).thenReturn(2);
|
||||||
|
when(iData.getSelectedVehicle()).thenReturn(vehicle);
|
||||||
|
|
||||||
|
Inserter inserter = new Inserter(mock(InsertionListeners.class));
|
||||||
|
inserter.insertJob(shipmentToInsert, iData, route);
|
||||||
|
|
||||||
|
assertEquals(4,route.getTourActivities().getActivities().size());
|
||||||
|
assertEquals(route.getTourActivities().getActivities().get(2).getLocationId(),shipmentToInsert.getPickupLocation());
|
||||||
|
assertEquals(route.getTourActivities().getActivities().get(3).getLocationId(),shipmentToInsert.getDeliveryLocation());
|
||||||
|
assertEquals(route.getEnd().getLocationId(),vehicle.getLocationId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInsertingShipmentAndRouteIsOpen_itInsertsCorrectlyAndSwitchesEndLocation(){
|
||||||
|
Shipment shipment = mock(Shipment.class);
|
||||||
|
Vehicle vehicle = mock(Vehicle.class);
|
||||||
|
when(vehicle.getLocationId()).thenReturn("vehLoc");
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(false);
|
||||||
|
when(vehicle.getId()).thenReturn("vehId");
|
||||||
|
|
||||||
|
VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addPickup(shipment).addDelivery(shipment).build();
|
||||||
|
//start - pick(shipment) - del(shipment) - end
|
||||||
|
Shipment shipmentToInsert = mock(Shipment.class);
|
||||||
|
when(shipmentToInsert.getDeliveryLocation()).thenReturn("delLoc");
|
||||||
|
when(shipmentToInsert.getPickupLocation()).thenReturn("pickLoc");
|
||||||
|
InsertionData iData = mock(InsertionData.class);
|
||||||
|
when(iData.getPickupInsertionIndex()).thenReturn(2);
|
||||||
|
when(iData.getDeliveryInsertionIndex()).thenReturn(2);
|
||||||
|
when(iData.getSelectedVehicle()).thenReturn(vehicle);
|
||||||
|
|
||||||
|
Inserter inserter = new Inserter(mock(InsertionListeners.class));
|
||||||
|
inserter.insertJob(shipmentToInsert, iData, route);
|
||||||
|
|
||||||
|
assertEquals(4,route.getTourActivities().getActivities().size());
|
||||||
|
assertEquals(route.getTourActivities().getActivities().get(2).getLocationId(),shipmentToInsert.getPickupLocation());
|
||||||
|
assertEquals(route.getTourActivities().getActivities().get(3).getLocationId(),shipmentToInsert.getDeliveryLocation());
|
||||||
|
assertEquals(route.getEnd().getLocationId(),shipmentToInsert.getDeliveryLocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
package jsprit.core.algorithm.recreate;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import jsprit.core.algorithm.recreate.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
|
||||||
|
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||||
|
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
|
import jsprit.core.problem.misc.JobInsertionContext;
|
||||||
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
|
import jsprit.core.problem.solution.route.activity.End;
|
||||||
|
import jsprit.core.problem.solution.route.activity.TourActivity;
|
||||||
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestLocalActivityInsertionCostsCalculator {
|
||||||
|
|
||||||
|
VehicleRoutingTransportCosts tpCosts;
|
||||||
|
|
||||||
|
VehicleRoutingActivityCosts actCosts;
|
||||||
|
|
||||||
|
LocalActivityInsertionCostsCalculator calc;
|
||||||
|
|
||||||
|
Vehicle vehicle;
|
||||||
|
|
||||||
|
VehicleRoute route;
|
||||||
|
|
||||||
|
JobInsertionContext jic;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void doBefore(){
|
||||||
|
|
||||||
|
vehicle = mock(Vehicle.class);
|
||||||
|
route = mock(VehicleRoute.class);
|
||||||
|
when(route.isEmpty()).thenReturn(false);
|
||||||
|
when(route.getVehicle()).thenReturn(vehicle);
|
||||||
|
|
||||||
|
jic = mock(JobInsertionContext.class);
|
||||||
|
when(jic.getRoute()).thenReturn(route);
|
||||||
|
when(jic.getNewVehicle()).thenReturn(vehicle);
|
||||||
|
|
||||||
|
tpCosts = mock(VehicleRoutingTransportCosts.class);
|
||||||
|
when(tpCosts.getTransportCost("i", "j", 0.0, null, vehicle)).thenReturn(2.0);
|
||||||
|
when(tpCosts.getTransportTime("i", "j", 0.0, null, vehicle)).thenReturn(0.0);
|
||||||
|
when(tpCosts.getTransportCost("i", "k", 0.0, null, vehicle)).thenReturn(3.0);
|
||||||
|
when(tpCosts.getTransportTime("i", "k", 0.0, null, vehicle)).thenReturn(0.0);
|
||||||
|
when(tpCosts.getTransportCost("k", "j", 0.0, null, vehicle)).thenReturn(3.0);
|
||||||
|
when(tpCosts.getTransportTime("k", "j", 0.0, null, vehicle)).thenReturn(0.0);
|
||||||
|
|
||||||
|
actCosts = mock(VehicleRoutingActivityCosts.class);
|
||||||
|
calc = new LocalActivityInsertionCostsCalculator(tpCosts, actCosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInsertingActBetweenTwoRouteActs_itCalcsMarginalTpCosts(){
|
||||||
|
TourActivity prevAct = mock(TourActivity.class);
|
||||||
|
when(prevAct.getLocationId()).thenReturn("i");
|
||||||
|
TourActivity nextAct = mock(TourActivity.class);
|
||||||
|
when(nextAct.getLocationId()).thenReturn("j");
|
||||||
|
TourActivity newAct = mock(TourActivity.class);
|
||||||
|
when(newAct.getLocationId()).thenReturn("k");
|
||||||
|
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(true);
|
||||||
|
|
||||||
|
ActivityInsertionCosts costs = calc.getCosts(jic, prevAct, nextAct, newAct, 0.0);
|
||||||
|
assertEquals(4.0,costs.getAdditionalCosts(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInsertingActBetweenLastActAndEnd_itCalcsMarginalTpCosts(){
|
||||||
|
TourActivity prevAct = mock(TourActivity.class);
|
||||||
|
when(prevAct.getLocationId()).thenReturn("i");
|
||||||
|
End nextAct = End.newInstance("j", 0.0, 0.0);
|
||||||
|
TourActivity newAct = mock(TourActivity.class);
|
||||||
|
when(newAct.getLocationId()).thenReturn("k");
|
||||||
|
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(true);
|
||||||
|
|
||||||
|
ActivityInsertionCosts costs = calc.getCosts(jic, prevAct, nextAct, newAct, 0.0);
|
||||||
|
assertEquals(4.0,costs.getAdditionalCosts(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInsertingActBetweenTwoRouteActsAndRouteIsOpen_itCalcsMarginalTpCosts(){
|
||||||
|
TourActivity prevAct = mock(TourActivity.class);
|
||||||
|
when(prevAct.getLocationId()).thenReturn("i");
|
||||||
|
TourActivity nextAct = mock(TourActivity.class);
|
||||||
|
when(nextAct.getLocationId()).thenReturn("j");
|
||||||
|
TourActivity newAct = mock(TourActivity.class);
|
||||||
|
when(newAct.getLocationId()).thenReturn("k");
|
||||||
|
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(false);
|
||||||
|
|
||||||
|
ActivityInsertionCosts costs = calc.getCosts(jic, prevAct, nextAct, newAct, 0.0);
|
||||||
|
assertEquals(4.0,costs.getAdditionalCosts(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInsertingActBetweenLastActAndEndAndRouteIsOpen_itCalculatesTpCostsFromPrevToNewAct(){
|
||||||
|
TourActivity prevAct = mock(TourActivity.class);
|
||||||
|
when(prevAct.getLocationId()).thenReturn("i");
|
||||||
|
End nextAct = End.newInstance("j", 0.0, 0.0);
|
||||||
|
TourActivity newAct = mock(TourActivity.class);
|
||||||
|
when(newAct.getLocationId()).thenReturn("k");
|
||||||
|
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(false);
|
||||||
|
|
||||||
|
ActivityInsertionCosts costs = calc.getCosts(jic, prevAct, nextAct, newAct, 0.0);
|
||||||
|
assertEquals(3.0,costs.getAdditionalCosts(),0.01);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ package jsprit.core.problem.solution.route;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
import jsprit.core.problem.driver.Driver;
|
import jsprit.core.problem.driver.Driver;
|
||||||
import jsprit.core.problem.job.Shipment;
|
import jsprit.core.problem.job.Shipment;
|
||||||
import jsprit.core.problem.vehicle.Vehicle;
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
|
@ -58,4 +59,74 @@ public class VehicleRouteBuilderTest {
|
||||||
assertEquals(4,route.getTourActivities().getActivities().size());
|
assertEquals(4,route.getTourActivities().getActivities().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenBuildingClosedRoute_routeEndShouldHaveLocationOfVehicle(){
|
||||||
|
Shipment s = mock(Shipment.class);
|
||||||
|
Shipment s2 = mock(Shipment.class);
|
||||||
|
Vehicle vehicle = mock(Vehicle.class);
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(true);
|
||||||
|
when(vehicle.getLocationId()).thenReturn("vehLoc");
|
||||||
|
VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class));
|
||||||
|
builder.addPickup(s);
|
||||||
|
builder.addPickup(s2);
|
||||||
|
builder.addDelivery(s);
|
||||||
|
builder.addDelivery(s2);
|
||||||
|
VehicleRoute route = builder.build();
|
||||||
|
assertEquals(route.getEnd().getLocationId(), vehicle.getLocationId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenBuildingOpenRoute_routeEndShouldHaveLocationOfLastActivity(){
|
||||||
|
Shipment s = mock(Shipment.class);
|
||||||
|
Shipment s2 = mock(Shipment.class);
|
||||||
|
when(s2.getDeliveryLocation()).thenReturn("delLoc");
|
||||||
|
Vehicle vehicle = mock(Vehicle.class);
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(false);
|
||||||
|
when(vehicle.getLocationId()).thenReturn("vehLoc");
|
||||||
|
VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class));
|
||||||
|
builder.addPickup(s);
|
||||||
|
builder.addPickup(s2);
|
||||||
|
builder.addDelivery(s);
|
||||||
|
builder.addDelivery(s2);
|
||||||
|
VehicleRoute route = builder.build();
|
||||||
|
assertEquals(route.getEnd().getLocationId(), s2.getDeliveryLocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSettingDepartureTime(){
|
||||||
|
Shipment s = mock(Shipment.class);
|
||||||
|
Shipment s2 = mock(Shipment.class);
|
||||||
|
when(s2.getDeliveryLocation()).thenReturn("delLoc");
|
||||||
|
Vehicle vehicle = mock(Vehicle.class);
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(false);
|
||||||
|
when(vehicle.getLocationId()).thenReturn("vehLoc");
|
||||||
|
VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class));
|
||||||
|
builder.addPickup(s);
|
||||||
|
builder.addPickup(s2);
|
||||||
|
builder.addDelivery(s);
|
||||||
|
builder.addDelivery(s2);
|
||||||
|
builder.setDepartureTime(100);
|
||||||
|
VehicleRoute route = builder.build();
|
||||||
|
assertEquals(100.0,route.getDepartureTime(),0.01);
|
||||||
|
assertEquals(100.0,route.getStart().getEndTime(),0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSettingEndTime(){
|
||||||
|
Shipment s = mock(Shipment.class);
|
||||||
|
Shipment s2 = mock(Shipment.class);
|
||||||
|
when(s2.getDeliveryLocation()).thenReturn("delLoc");
|
||||||
|
Vehicle vehicle = mock(Vehicle.class);
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(false);
|
||||||
|
when(vehicle.getLocationId()).thenReturn("vehLoc");
|
||||||
|
VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class));
|
||||||
|
builder.addPickup(s);
|
||||||
|
builder.addPickup(s2);
|
||||||
|
builder.addDelivery(s);
|
||||||
|
builder.addDelivery(s2);
|
||||||
|
builder.setRouteEndArrivalTime(100.0);
|
||||||
|
VehicleRoute route = builder.build();
|
||||||
|
assertEquals(100.0,route.getEnd().getArrTime(),0.01);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
<start>0.0</start>
|
<start>0.0</start>
|
||||||
<end>1.7976931348623157E308</end>
|
<end>1.7976931348623157E308</end>
|
||||||
</timeSchedule>
|
</timeSchedule>
|
||||||
|
<returnToDepot>true</returnToDepot>
|
||||||
</vehicle>
|
</vehicle>
|
||||||
<vehicle>
|
<vehicle>
|
||||||
<id>v2</id>
|
<id>v2</id>
|
||||||
|
|
@ -27,6 +28,7 @@
|
||||||
<start>0.0</start>
|
<start>0.0</start>
|
||||||
<end>1.7976931348623157E308</end>
|
<end>1.7976931348623157E308</end>
|
||||||
</timeSchedule>
|
</timeSchedule>
|
||||||
|
<returnToDepot>true</returnToDepot>
|
||||||
</vehicle>
|
</vehicle>
|
||||||
</vehicles>
|
</vehicles>
|
||||||
<vehicleTypes>
|
<vehicleTypes>
|
||||||
|
|
|
||||||
49
jsprit-examples/input/algorithmConfig_fix.xml
Executable file
49
jsprit-examples/input/algorithmConfig_fix.xml
Executable file
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
|
<algorithm xmlns="http://www.w3schools.com"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com algorithm_schema.xsd">
|
||||||
|
|
||||||
|
<iterations>2000</iterations>
|
||||||
|
|
||||||
|
<construction>
|
||||||
|
<insertion name="bestInsertion">
|
||||||
|
<considerFixedCosts>1.0</considerFixedCosts>
|
||||||
|
</insertion>
|
||||||
|
</construction>
|
||||||
|
|
||||||
|
<strategy>
|
||||||
|
<memory>1</memory>
|
||||||
|
<searchStrategies>
|
||||||
|
|
||||||
|
<searchStrategy name="randomRuinAndRecreate">
|
||||||
|
<selector name="selectBest"/>
|
||||||
|
<acceptor name="acceptNewRemoveWorst"/>
|
||||||
|
<modules>
|
||||||
|
<module name="ruin_and_recreate">
|
||||||
|
<ruin name="randomRuin">
|
||||||
|
<share>0.5</share>
|
||||||
|
</ruin>
|
||||||
|
<insertion name="bestInsertion"/>
|
||||||
|
</module>
|
||||||
|
</modules>
|
||||||
|
<probability>0.5</probability>
|
||||||
|
</searchStrategy>
|
||||||
|
|
||||||
|
<searchStrategy name="radialRuinAndRecreate">
|
||||||
|
<selector name="selectBest"/>
|
||||||
|
<acceptor name="acceptNewRemoveWorst"/>
|
||||||
|
<modules>
|
||||||
|
<module name="ruin_and_recreate">
|
||||||
|
<ruin name="radialRuin">
|
||||||
|
<share>0.3</share>
|
||||||
|
</ruin>
|
||||||
|
<insertion name="bestInsertion"/>
|
||||||
|
</module>
|
||||||
|
</modules>
|
||||||
|
<probability>0.5</probability>
|
||||||
|
</searchStrategy>
|
||||||
|
</searchStrategies>
|
||||||
|
</strategy>
|
||||||
|
|
||||||
|
|
||||||
|
</algorithm>
|
||||||
71
jsprit-examples/input/algorithmConfig_open.xml
Executable file
71
jsprit-examples/input/algorithmConfig_open.xml
Executable file
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
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
|
||||||
|
-->
|
||||||
|
<algorithm xmlns="http://www.w3schools.com"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com algorithm_schema.xsd">
|
||||||
|
|
||||||
|
<iterations>2000</iterations>
|
||||||
|
|
||||||
|
<construction>
|
||||||
|
<insertion name="bestInsertion">
|
||||||
|
|
||||||
|
</insertion>
|
||||||
|
</construction>
|
||||||
|
|
||||||
|
<strategy>
|
||||||
|
<memory>1</memory>
|
||||||
|
<searchStrategies>
|
||||||
|
<searchStrategy name="radialRuinAndRecreate">
|
||||||
|
<selector name="selectBest"/>
|
||||||
|
<acceptor name="acceptNewRemoveWorst"/>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module name="ruin_and_recreate">
|
||||||
|
<ruin name="randomRuin">
|
||||||
|
<share>0.5</share>
|
||||||
|
</ruin>
|
||||||
|
<insertion name="bestInsertion"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
</modules>
|
||||||
|
<probability>0.5</probability>
|
||||||
|
</searchStrategy>
|
||||||
|
|
||||||
|
<searchStrategy name="radialRuinAndRecreate">
|
||||||
|
<selector name="selectBest"/>
|
||||||
|
<acceptor name="acceptNewRemoveWorst"/>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module name="ruin_and_recreate">
|
||||||
|
<ruin id="1" name="radialRuin">
|
||||||
|
<share>0.3</share>
|
||||||
|
</ruin>
|
||||||
|
<insertion name="bestInsertion"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
</modules>
|
||||||
|
<probability>0.5</probability>
|
||||||
|
</searchStrategy>
|
||||||
|
</searchStrategies>
|
||||||
|
</strategy>
|
||||||
|
|
||||||
|
|
||||||
|
</algorithm>
|
||||||
1236
jsprit-examples/input/deliveries_solomon_open_c101.xml
Normal file
1236
jsprit-examples/input/deliveries_solomon_open_c101.xml
Normal file
File diff suppressed because it is too large
Load diff
1236
jsprit-examples/input/pickups_and_deliveries_solomon_r101_open.xml
Normal file
1236
jsprit-examples/input/pickups_and_deliveries_solomon_r101_open.xml
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -57,7 +57,7 @@ public class PickupAndDeliveryExample {
|
||||||
/*
|
/*
|
||||||
* A solomonReader reads solomon-instance files, and stores the required information in the builder.
|
* A solomonReader reads solomon-instance files, and stores the required information in the builder.
|
||||||
*/
|
*/
|
||||||
new VrpXMLReader(vrpBuilder).read("input/pickups_and_deliveries_solomon_r101.xml");
|
new VrpXMLReader(vrpBuilder).read("input/pickups_and_deliveries_solomon_r101_withoutTWs.xml");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finally, the problem can be built. By default, transportCosts are crowFlyDistances (as usually used for vrp-instances).
|
* Finally, the problem can be built. By default, transportCosts are crowFlyDistances (as usually used for vrp-instances).
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2013 Stefan Schroeder
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3.0 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
package jsprit.examples;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import jsprit.analysis.toolbox.AlgorithmSearchProgressChartListener;
|
||||||
|
import jsprit.analysis.toolbox.Plotter;
|
||||||
|
import jsprit.analysis.toolbox.Plotter.Label;
|
||||||
|
import jsprit.analysis.toolbox.SolutionPlotter;
|
||||||
|
import jsprit.analysis.toolbox.SolutionPrinter;
|
||||||
|
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||||
|
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
|
||||||
|
import jsprit.core.algorithm.selector.SelectBest;
|
||||||
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
|
import jsprit.core.problem.io.VrpXMLReader;
|
||||||
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
|
|
||||||
|
public class PickupAndDeliveryOpenExample {
|
||||||
|
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* But define a problem-builder first.
|
||||||
|
*/
|
||||||
|
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A solomonReader reads solomon-instance files, and stores the required information in the builder.
|
||||||
|
*/
|
||||||
|
new VrpXMLReader(vrpBuilder).read("input/pickups_and_deliveries_solomon_r101_withoutTWs_open.xml");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finally, the problem can be built. By default, transportCosts are crowFlyDistances (as usually used for vrp-instances).
|
||||||
|
*/
|
||||||
|
|
||||||
|
VehicleRoutingProblem vrp = vrpBuilder.build();
|
||||||
|
|
||||||
|
// SolutionPlotter.plotVrpAsPNG(vrp, "output/pd_solomon_r101_o.png", "pd_r101");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the required vehicle-routing algorithms to solve the above problem.
|
||||||
|
*
|
||||||
|
* The algorithm can be defined and configured in an xml-file.
|
||||||
|
*/
|
||||||
|
// VehicleRoutingAlgorithm vra = new SchrimpfFactory().createAlgorithm(vrp);
|
||||||
|
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_open.xml");
|
||||||
|
vra.getAlgorithmListeners().addListener(new AlgorithmSearchProgressChartListener("output/sol_progress.png"));
|
||||||
|
/*
|
||||||
|
* Solve the problem.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve best solution.
|
||||||
|
*/
|
||||||
|
VehicleRoutingProblemSolution solution = new SelectBest().selectSolution(solutions);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print solution
|
||||||
|
*/
|
||||||
|
SolutionPrinter.print(solution);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Plot solution.
|
||||||
|
*/
|
||||||
|
// SolutionPlotter.plotSolutionAsPNG(vrp, solution, "output/pd_solomon_r101_solution.png","pd_r101");
|
||||||
|
Plotter plotter = new Plotter(vrp, solution);
|
||||||
|
plotter.setLabel(Label.SIZE);
|
||||||
|
plotter.setShowFirstActivity(true);
|
||||||
|
plotter.plot("output/pd_solomon_r101_solution_open.png","pd_r101");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2013 Stefan Schroeder
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3.0 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
package jsprit.examples;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import jsprit.analysis.toolbox.Plotter;
|
||||||
|
import jsprit.analysis.toolbox.SolutionPrinter;
|
||||||
|
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||||
|
import jsprit.core.algorithm.box.SchrimpfFactory;
|
||||||
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
|
import jsprit.core.problem.io.VrpXMLWriter;
|
||||||
|
import jsprit.core.problem.job.Shipment;
|
||||||
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleImpl;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleImpl.Builder;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleType;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleTypeImpl;
|
||||||
|
import jsprit.core.util.Coordinate;
|
||||||
|
import jsprit.core.util.Solutions;
|
||||||
|
|
||||||
|
|
||||||
|
public class SimpleEnRoutePickupAndDeliveryOpenRoutesExample {
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
VehicleTypeImpl.Builder vehicleTypeBuilder = VehicleTypeImpl.Builder.newInstance("vehicleType", 2);
|
||||||
|
VehicleType vehicleType = vehicleTypeBuilder.build();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get a vehicle-builder and build a vehicle located at (10,10) with type "vehicleType"
|
||||||
|
*/
|
||||||
|
Builder vehicleBuilder = VehicleImpl.Builder.newInstance("vehicle");
|
||||||
|
vehicleBuilder.setLocationCoord(Coordinate.newInstance(10, 10));
|
||||||
|
vehicleBuilder.setType(vehicleType);
|
||||||
|
vehicleBuilder.setReturnToDepot(false);
|
||||||
|
Vehicle vehicle = vehicleBuilder.build();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* build shipments at the required locations, each with a capacity-demand of 1.
|
||||||
|
* 4 shipments
|
||||||
|
* 1: (5,7)->(6,9)
|
||||||
|
* 2: (5,13)->(6,11)
|
||||||
|
* 3: (15,7)->(14,9)
|
||||||
|
* 4: (15,13)->(14,11)
|
||||||
|
*/
|
||||||
|
|
||||||
|
Shipment shipment1 = Shipment.Builder.newInstance("1", 1).setPickupCoord(Coordinate.newInstance(5, 7)).setDeliveryCoord(Coordinate.newInstance(6, 9)).build();
|
||||||
|
Shipment shipment2 = Shipment.Builder.newInstance("2", 1).setPickupCoord(Coordinate.newInstance(5, 13)).setDeliveryCoord(Coordinate.newInstance(6, 11)).build();
|
||||||
|
|
||||||
|
Shipment shipment3 = Shipment.Builder.newInstance("3", 1).setPickupCoord(Coordinate.newInstance(15, 7)).setDeliveryCoord(Coordinate.newInstance(14, 9)).build();
|
||||||
|
Shipment shipment4 = Shipment.Builder.newInstance("4", 1).setPickupCoord(Coordinate.newInstance(15, 13)).setDeliveryCoord(Coordinate.newInstance(14, 11)).build();
|
||||||
|
|
||||||
|
|
||||||
|
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||||
|
vrpBuilder.addVehicle(vehicle);
|
||||||
|
vrpBuilder.addJob(shipment1).addJob(shipment2).addJob(shipment3).addJob(shipment4);
|
||||||
|
|
||||||
|
VehicleRoutingProblem problem = vrpBuilder.build();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get the algorithm out-of-the-box.
|
||||||
|
*/
|
||||||
|
VehicleRoutingAlgorithm algorithm = new SchrimpfFactory().createAlgorithm(problem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* and search a solution
|
||||||
|
*/
|
||||||
|
Collection<VehicleRoutingProblemSolution> solutions = algorithm.searchSolutions();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get the best
|
||||||
|
*/
|
||||||
|
VehicleRoutingProblemSolution bestSolution = Solutions.bestOf(solutions);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* write out problem and solution to xml-file
|
||||||
|
*/
|
||||||
|
new VrpXMLWriter(problem, solutions).write("output/shipment-problem-with-solution.xml");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print nRoutes and totalCosts of bestSolution
|
||||||
|
*/
|
||||||
|
SolutionPrinter.print(bestSolution);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* plot problem without solution
|
||||||
|
*/
|
||||||
|
Plotter problemPlotter = new Plotter(problem);
|
||||||
|
problemPlotter.plotShipments(true);
|
||||||
|
problemPlotter.plot("output/simpleEnRoutePickupAndDeliveryExample_problem.png", "en-route pickup and delivery");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* plot problem with solution
|
||||||
|
*/
|
||||||
|
Plotter solutionPlotter = new Plotter(problem,Solutions.bestOf(solutions).getRoutes());
|
||||||
|
solutionPlotter.plotShipments(true);
|
||||||
|
solutionPlotter.plot("output/simpleEnRoutePickupAndDeliveryExample_solution.png", "en-route pickup and delivery");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2013 Stefan Schroeder
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3.0 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
package jsprit.examples;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import jsprit.analysis.toolbox.SolutionPlotter;
|
||||||
|
import jsprit.analysis.toolbox.SolutionPrinter;
|
||||||
|
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||||
|
import jsprit.core.algorithm.box.SchrimpfFactory;
|
||||||
|
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
|
||||||
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
|
import jsprit.core.problem.io.VrpXMLWriter;
|
||||||
|
import jsprit.core.problem.job.Service;
|
||||||
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleImpl;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleImpl.Builder;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleType;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleTypeImpl;
|
||||||
|
import jsprit.core.util.Coordinate;
|
||||||
|
import jsprit.core.util.Solutions;
|
||||||
|
|
||||||
|
|
||||||
|
public class SimpleExampleOpenRoutes {
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
VehicleTypeImpl.Builder vehicleTypeBuilder = VehicleTypeImpl.Builder.newInstance("vehicleType", 2);
|
||||||
|
vehicleTypeBuilder.setFixedCost(100);
|
||||||
|
VehicleType vehicleType = vehicleTypeBuilder.build();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get a vehicle-builder and build a vehicle located at (10,10) with type "vehicleType"
|
||||||
|
*/
|
||||||
|
Builder vehicleBuilder = VehicleImpl.Builder.newInstance("vehicle");
|
||||||
|
vehicleBuilder.setLocationCoord(Coordinate.newInstance(10, 10));
|
||||||
|
vehicleBuilder.setType(vehicleType);
|
||||||
|
vehicleBuilder.setReturnToDepot(false);
|
||||||
|
|
||||||
|
Vehicle vehicle = vehicleBuilder.build();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* build services at the required locations, each with a capacity-demand of 1.
|
||||||
|
*/
|
||||||
|
Service service1 = Service.Builder.newInstance("1", 1).setCoord(Coordinate.newInstance(5, 7)).build();
|
||||||
|
Service service2 = Service.Builder.newInstance("2", 1).setCoord(Coordinate.newInstance(5, 13)).build();
|
||||||
|
|
||||||
|
Service service3 = Service.Builder.newInstance("3", 1).setCoord(Coordinate.newInstance(15, 7)).build();
|
||||||
|
Service service4 = Service.Builder.newInstance("4", 1).setCoord(Coordinate.newInstance(15, 13)).build();
|
||||||
|
|
||||||
|
|
||||||
|
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||||
|
vrpBuilder.addVehicle(vehicle);
|
||||||
|
vrpBuilder.addJob(service1).addJob(service2).addJob(service3).addJob(service4);
|
||||||
|
|
||||||
|
VehicleRoutingProblem problem = vrpBuilder.build();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get the algorithm out-of-the-box.
|
||||||
|
*/
|
||||||
|
VehicleRoutingAlgorithm algorithm = VehicleRoutingAlgorithms.readAndCreateAlgorithm(problem, "input/algorithmConfig_fix.xml");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* and search a solution
|
||||||
|
*/
|
||||||
|
Collection<VehicleRoutingProblemSolution> solutions = algorithm.searchSolutions();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get the best
|
||||||
|
*/
|
||||||
|
VehicleRoutingProblemSolution bestSolution = Solutions.bestOf(solutions);
|
||||||
|
|
||||||
|
new VrpXMLWriter(problem, solutions).write("output/problem-with-solution.xml");
|
||||||
|
|
||||||
|
SolutionPrinter.print(bestSolution);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* plot
|
||||||
|
*/
|
||||||
|
SolutionPlotter.plotSolutionAsPNG(problem, bestSolution, "output/solution.png", "solution");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2013 Stefan Schroeder
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3.0 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
package jsprit.examples;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import jsprit.analysis.toolbox.SolutionPlotter;
|
||||||
|
import jsprit.analysis.toolbox.SolutionPrinter;
|
||||||
|
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||||
|
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
|
||||||
|
import jsprit.core.algorithm.selector.SelectBest;
|
||||||
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
|
import jsprit.core.problem.io.VrpXMLReader;
|
||||||
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
import jsprit.instance.reader.SolomonReader;
|
||||||
|
|
||||||
|
|
||||||
|
public class SolomonOpenExample {
|
||||||
|
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* But define a problem-builder first.
|
||||||
|
*/
|
||||||
|
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A solomonReader reads solomon-instance files, and stores the required information in the builder.
|
||||||
|
*/
|
||||||
|
new VrpXMLReader(vrpBuilder).read("input/deliveries_solomon_open_c101.xml");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finally, the problem can be built. By default, transportCosts are crowFlyDistances (as usually used for vrp-instances).
|
||||||
|
*/
|
||||||
|
VehicleRoutingProblem vrp = vrpBuilder.build();
|
||||||
|
|
||||||
|
SolutionPlotter.plotVrpAsPNG(vrp, "output/solomon_C101_open.png", "C101");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the required vehicle-routing algorithms to solve the above problem.
|
||||||
|
*
|
||||||
|
* The algorithm can be defined and configured in an xml-file.
|
||||||
|
*/
|
||||||
|
// VehicleRoutingAlgorithm vra = new SchrimpfFactory().createAlgorithm(vrp);
|
||||||
|
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_fix.xml");
|
||||||
|
// vra.setPrematureBreak(100);
|
||||||
|
// vra.getAlgorithmListeners().addListener(new AlgorithmSearchProgressChartListener("output/sol_progress.png"));
|
||||||
|
/*
|
||||||
|
* Solve the problem.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve best solution.
|
||||||
|
*/
|
||||||
|
VehicleRoutingProblemSolution solution = new SelectBest().selectSolution(solutions);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print solution
|
||||||
|
*/
|
||||||
|
SolutionPrinter.print(solution);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Plot solution.
|
||||||
|
*/
|
||||||
|
SolutionPlotter.plotSolutionAsPNG(vrp, solution, "output/solomon_C101_open_solution.png","C101");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue