From 4e25d894b63846018370485e3623c4deb43b1ce8 Mon Sep 17 00:00:00 2001
From: Stefan Schroeder <4sschroeder@gmail.com>
Date: Wed, 27 Nov 2013 17:22:42 +0100
Subject: [PATCH] modify insertion to incorporate open-routes
---
.../core/algorithm/recreate/Inserter.java | 20 +++
...LocalActivityInsertionCostsCalculator.java | 8 ++
.../jsprit/core/problem/vehicle/Vehicle.java | 2 +
.../core/problem/vehicle/VehicleImpl.java | 21 +++
.../core/algorithm/recreate/TestInserter.java | 7 +
...utePickupAndDeliveryOpenRoutesExample.java | 132 ++++++++++++++++++
.../examples/SimpleExampleOpenRoutes.java | 109 +++++++++++++++
7 files changed, 299 insertions(+)
create mode 100644 jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestInserter.java
create mode 100644 jsprit-examples/src/main/java/jsprit/examples/SimpleEnRoutePickupAndDeliveryOpenRoutesExample.java
create mode 100644 jsprit-examples/src/main/java/jsprit/examples/SimpleExampleOpenRoutes.java
diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/Inserter.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/Inserter.java
index 6e73e670..aed0becb 100644
--- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/Inserter.java
+++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/Inserter.java
@@ -62,10 +62,20 @@ class Inserter {
if(job instanceof Service){
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), this.activityFactory.createActivity((Service)job));
route.setDepartureTime(iData.getVehicleDepartureTime());
+ if(!iData.getSelectedVehicle().isReturnToDepot()){
+ if(iData.getDeliveryInsertionIndex()>=route.getTourActivities().getActivities().size()){
+ setEndLocation(route,(Service)job);
+ }
+ }
}
else delegator.handleJobInsertion(job, iData, route);
}
+ private void setEndLocation(VehicleRoute route, Service service) {
+ route.getEnd().setCoordinate(service.getCoord());
+ route.getEnd().setLocationId(service.getLocationId());
+ }
+
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
this.delegator = jobInsertionHandler;
}
@@ -86,10 +96,20 @@ class Inserter {
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), deliverShipment);
route.getTourActivities().addActivity(iData.getPickupInsertionIndex(), pickupShipment);
route.setDepartureTime(iData.getVehicleDepartureTime());
+ if(!iData.getSelectedVehicle().isReturnToDepot()){
+ if(iData.getDeliveryInsertionIndex()>=route.getTourActivities().getActivities().size()){
+ setEndLocation(route,(Shipment)job);
+ }
+ }
}
else delegator.handleJobInsertion(job, iData, route);
}
+ private void setEndLocation(VehicleRoute route, Shipment shipment) {
+ route.getEnd().setCoordinate(shipment.getDeliveryCoord());
+ route.getEnd().setLocationId(shipment.getDeliveryLocation());
+ }
+
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
this.delegator = jobInsertionHandler;
}
diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/LocalActivityInsertionCostsCalculator.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/LocalActivityInsertionCostsCalculator.java
index 92dacfb9..56b755f0 100644
--- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/LocalActivityInsertionCostsCalculator.java
+++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/LocalActivityInsertionCostsCalculator.java
@@ -23,6 +23,7 @@ package jsprit.core.algorithm.recreate;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
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.util.CalculationUtils;
@@ -61,6 +62,13 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
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_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
diff --git a/jsprit-core/src/main/java/jsprit/core/problem/vehicle/Vehicle.java b/jsprit-core/src/main/java/jsprit/core/problem/vehicle/Vehicle.java
index 0d178938..f846e201 100644
--- a/jsprit-core/src/main/java/jsprit/core/problem/vehicle/Vehicle.java
+++ b/jsprit-core/src/main/java/jsprit/core/problem/vehicle/Vehicle.java
@@ -35,5 +35,7 @@ public interface Vehicle {
public abstract String getId();
public abstract int getCapacity();
+
+ public abstract boolean isReturnToDepot();
}
diff --git a/jsprit-core/src/main/java/jsprit/core/problem/vehicle/VehicleImpl.java b/jsprit-core/src/main/java/jsprit/core/problem/vehicle/VehicleImpl.java
index b7d53c1a..3be48623 100644
--- a/jsprit-core/src/main/java/jsprit/core/problem/vehicle/VehicleImpl.java
+++ b/jsprit-core/src/main/java/jsprit/core/problem/vehicle/VehicleImpl.java
@@ -54,6 +54,8 @@ public class VehicleImpl implements Vehicle {
private double earliestStart = 0.0;
private double latestArrival = Double.MAX_VALUE;
+ private boolean returnToDepot = true;
+
private VehicleType type = VehicleTypeImpl.Builder.newInstance("default", 0).build();
private Builder(String id) {
@@ -66,6 +68,11 @@ public class VehicleImpl implements Vehicle {
return this;
}
+ public Builder setReturnToDepot(boolean returnToDepot){
+ this.returnToDepot = returnToDepot;
+ return this;
+ }
+
public Builder setLocationId(String id){
this.locationId = id;
return this;
@@ -113,6 +120,8 @@ public class VehicleImpl implements Vehicle {
private final double earliestDeparture;
private final double latestArrival;
+
+ private boolean returnToDepot;
private VehicleImpl(Builder builder){
id = builder.id;
@@ -121,6 +130,7 @@ public class VehicleImpl implements Vehicle {
locationId = builder.locationId;
earliestDeparture = builder.earliestStart;
latestArrival = builder.latestArrival;
+ returnToDepot = builder.returnToDepot;
}
@@ -193,5 +203,16 @@ public class VehicleImpl implements Vehicle {
public int getCapacity() {
return type.getCapacity();
}
+
+
+
+ /**
+ * @return the returnToDepot
+ */
+ public boolean isReturnToDepot() {
+ return returnToDepot;
+ }
+
+
}
diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestInserter.java b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestInserter.java
new file mode 100644
index 00000000..20e28113
--- /dev/null
+++ b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestInserter.java
@@ -0,0 +1,7 @@
+package jsprit.core.algorithm.recreate;
+
+public class TestInserter {
+
+
+
+}
diff --git a/jsprit-examples/src/main/java/jsprit/examples/SimpleEnRoutePickupAndDeliveryOpenRoutesExample.java b/jsprit-examples/src/main/java/jsprit/examples/SimpleEnRoutePickupAndDeliveryOpenRoutesExample.java
new file mode 100644
index 00000000..4203e4aa
--- /dev/null
+++ b/jsprit-examples/src/main/java/jsprit/examples/SimpleEnRoutePickupAndDeliveryOpenRoutesExample.java
@@ -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 .
+ ******************************************************************************/
+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 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");
+
+ }
+
+}
diff --git a/jsprit-examples/src/main/java/jsprit/examples/SimpleExampleOpenRoutes.java b/jsprit-examples/src/main/java/jsprit/examples/SimpleExampleOpenRoutes.java
new file mode 100644
index 00000000..1bc409b7
--- /dev/null
+++ b/jsprit-examples/src/main/java/jsprit/examples/SimpleExampleOpenRoutes.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * 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 .
+ ******************************************************************************/
+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.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);
+ 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 = new SchrimpfFactory().createAlgorithm(problem);
+
+ /*
+ * and search a solution
+ */
+ Collection 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");
+ }
+
+}