Hi,
i am currently trying some of the functionalities of jsprit. I have made a test case with 2 vehicles and two shipments. Both shipments can only be performed by one vehicle. The first shipment has a skill-constraint, which is not fulfilled by both vehicles, the second shipment has timewindow constraint, which is not fulfilled by one of the vehicles, because of a break.
I am wondering why the correct solution depends on the number of iterations. In the following code, if I set algorithm.setMaxIterations(20); I receive the expected solution:
±-------------------------------------------------------------------------------------------------------------------------------+
| detailed solution |
±--------±---------------------±----------------------±----------------±----------------±----------------±----------------+
| route | vehicle | activity | job | arrTime | endTime | costs |
±--------±---------------------±----------------------±----------------±----------------±----------------±----------------+
| 1 | v1, s2 | start | - | undef | 0 | 0 |
| 1 | v1, s2 | pickupShipment | b → a (s2) | 28 | 105 | 105 |
| 1 | v1, s2 | deliverShipment | b → a (s2) | 119 | 119 | 119 |
| 1 | v1, s2 | end | - | 133 | undef | 133 |
±--------±---------------------±----------------------±----------------±----------------±----------------±----------------+
| 2 | v2, s1,s2 | start | - | undef | 0 | 0 |
| 2 | v2, s1,s2 | pickupShipment | a → b (s1) | 14 | 14 | 14 |
| 2 | v2, s1,s2 | deliverShipment | a → b (s1) | 28 | 28 | 28 |
| 2 | v2, s1,s2 | end | - | 57 | undef | 57 |
±-------------------------------------------------------------------------------------------------------------------------------+
However, if I set algorithm.maxIterations(10); the break of vehicle2 is completely ignored and I get a wrong solution, where vehicle2 can performs shipment2, while vehicle2 actually would have to make a break, in the timewindow, when shipment2 can be performed.
±-------------------------------------------------------------------------------------------------------------------------------+
| detailed solution |
±--------±---------------------±----------------------±----------------±----------------±----------------±----------------+
| route | vehicle | activity | job | arrTime | endTime | costs |
±--------±---------------------±----------------------±----------------±----------------±----------------±----------------+
| 1 | v2, s1,s2 | start | - | undef | 0 | 0 |
| 1 | v2, s1,s2 | pickupShipment | a → b (s1) | 14 | 14 | 14 |
| 1 | v2, s1,s2 | deliverShipment | a → b (s1) | 28 | 28 | 28 |
| 1 | v2, s1,s2 | pickupShipment | b → a (s2) | 28 | 105 | 105 |
| 1 | v2, s1,s2 | deliverShipment | b → a (s2) | 119 | 119 | 119 |
| 1 | v2, s1,s2 | end | - | 133 | undef | 133 |
±-------------------------------------------------------------------------------------------------------------------------------+
Is there any explanation how this can be avoided? How could I know how much iterations are enough so that such things cannot happen?
I tried with the following code:
/*
*
*/
package com.graphhopper.jsprit.examples;
import java.util.Collection;
import com.graphhopper.jsprit.analysis.toolbox.Plotter;
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm;
import com.graphhopper.jsprit.core.algorithm.box.Jsprit;
import com.graphhopper.jsprit.core.problem.Location;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.job.Break;
import com.graphhopper.jsprit.core.problem.job.Shipment;
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleType;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeImpl;
import com.graphhopper.jsprit.core.reporting.SolutionPrinter;
import com.graphhopper.jsprit.core.util.Solutions;
public class MyBreakExample2
{
public static void main(String[] args)
{
/*
* get a vehicle type-builder and build a type with the typeId "vehicleType" and one capacity dimension, i.e. weight, and capacity dimension value of 2
*/
final int WEIGHT_INDEX = 0;
VehicleTypeImpl.Builder vehicleTypeBuilder = VehicleTypeImpl.Builder
.newInstance("vehicleType")
.addCapacityDimension(WEIGHT_INDEX, 1)
.setCostPerWaitingTime(1.0)
.setCostPerServiceTime(1.0)
.setCostPerTransportTime(1.0);
VehicleType vehicleType = vehicleTypeBuilder.build();
/*
* get a vehicle-builder and build a vehicle located at (10,10) with type "vehicleType"
*/
VehicleImpl vehicle1 = VehicleImpl.Builder.newInstance("v1, s2")
.setStartLocation(Location.newInstance(0, 0))
.setType(vehicleType)
.addSkill("s2")
.setEarliestStart(0)
.setLatestArrival(200)
.build();
VehicleImpl vehicle2 = VehicleImpl.Builder.newInstance("v2, s1,s2")
.setStartLocation(Location.newInstance(0, 0))
.setType(vehicleType)
.addSkill("s1")
.addSkill("s2")
.setEarliestStart(0)
.setLatestArrival(200)
.setBreak(Break.Builder.newInstance("myBreak")
.setTimeWindow(TimeWindow.newInstance(100, 100))
.setServiceTime(50)
.build())
.build();
/*
* build shipments at the required locations, each with a capacity-demand of 1.
*/
// shipment1
Shipment shipment1 = Shipment.Builder.newInstance("a -> b (s1)")
.addSizeDimension(0, 1)
.addRequiredSkill("s1")
.setPickupLocation(Location.newInstance(10, 10))
.setDeliveryLocation(Location.newInstance(20, 20))
.setDeliveryTimeWindow(TimeWindow.newInstance(10, 40))
.build();
// shipment2
Shipment shipment2 = Shipment.Builder.newInstance("b -> a (s2)")
.addSizeDimension(0, 1)
.addRequiredSkill("s2")
.setPickupLocation(Location.newInstance(20, 20))
.setPickupTimeWindow(TimeWindow.newInstance(105, 130))
.setDeliveryLocation(Location.newInstance(10, 10))
.build();
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
vrpBuilder.addVehicle(vehicle1).addVehicle(vehicle2).addJob(shipment1).addJob(shipment2);
vrpBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE);
VehicleRoutingProblem problem = vrpBuilder.build();
/*
* get the algorithm out-of-the-box.
*/
VehicleRoutingAlgorithm algorithm = Jsprit.Builder.newInstance(problem)
.buildAlgorithm();
algorithm.setMaxIterations(20);
/*
* and search a solution
*/
Collection<VehicleRoutingProblemSolution> solutions = algorithm.searchSolutions();
/*
* get the best
*/
VehicleRoutingProblemSolution bestSolution = Solutions.bestOf(solutions);
SolutionPrinter.print(problem, bestSolution, SolutionPrinter.Print.VERBOSE);
/*
* plot
*/
new Plotter(problem, bestSolution).plot("output/plot", "breaks");
}
}
Best Regards,
Stefan.