Break is not part of the solution

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.

Powered by Discourse