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"); + } + +}