public static void main(String[] args) {

    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/stackoverflow/vrpnc1-jsprit.xml");

    /*
     * Finally, the problem can be built. By default, transportCosts are crowFlyDistances (as usually used for vrp-instances).
     */
    VehicleRoutingProblem vrp = vrpBuilder.build();

    final StateManager stateManager = new StateManager(vrp.getTransportCosts());

    ConstraintManager constraintManager = new ConstraintManager(vrp, stateManager);

    VehicleRoutingAlgorithmBuilder vraBuilder =
        new VehicleRoutingAlgorithmBuilder(vrp, "input/stackoverflow/rr_ta.xml");
    vraBuilder.setStateAndConstraintManager(stateManager, constraintManager);
    vraBuilder.addDefaultCostCalculators();
    VehicleRoutingAlgorithm vra = vraBuilder.build();

    vra.addListener(new AlgorithmSearchProgressChartListener("output/search"));

    //
    Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();

    SolutionPrinter.print(vrp, Solutions.bestOf(solutions), Print.VERBOSE);

    new Plotter(vrp, Solutions.bestOf(solutions))
        .setLabel(Label.ID)
        .plot("output/jsprit_vrpnc1_noConstraints", "jsprit: noConstraints");
  }
  public static void main(String[] args) {
    VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
    new SolomonReader(vrpBuilder).read("input/C101_solomon.txt");
    VehicleRoutingProblem vrp = vrpBuilder.build();

    // y >= 50 skill1 otherwise skill2
    // two vehicles: v1 - skill1 #5; v2 - skill2 #6
    Vehicle solomonVehicle = vrp.getVehicles().iterator().next();
    VehicleType newType = solomonVehicle.getType();
    VehicleRoutingProblem.Builder skillProblemBuilder = VehicleRoutingProblem.Builder.newInstance();
    for (int i = 0; i < 5; i++) {
      VehicleImpl skill1Vehicle =
          VehicleImpl.Builder.newInstance("skill1_vehicle_" + i)
              .addSkill("skill1")
              .setStartLocation(
                  Location.Builder.newInstance()
                      .setId(solomonVehicle.getStartLocation().getId())
                      .setCoordinate(solomonVehicle.getStartLocation().getCoordinate())
                      .build())
              .setEarliestStart(solomonVehicle.getEarliestDeparture())
              .setType(newType)
              .build();
      VehicleImpl skill2Vehicle =
          VehicleImpl.Builder.newInstance("skill2_vehicle_" + i)
              .addSkill("skill2")
              .setStartLocation(
                  Location.Builder.newInstance()
                      .setId(solomonVehicle.getStartLocation().getId())
                      .setCoordinate(solomonVehicle.getStartLocation().getCoordinate())
                      .build())
              .setEarliestStart(solomonVehicle.getEarliestDeparture())
              .setType(newType)
              .build();
      skillProblemBuilder.addVehicle(skill1Vehicle).addVehicle(skill2Vehicle);
    }
    for (Job job : vrp.getJobs().values()) {
      Service service = (Service) job;
      Service.Builder skillServiceBuilder;
      if (service.getLocation().getCoordinate().getY() < 50.) {
        skillServiceBuilder =
            Service.Builder.newInstance(service.getId() + "_skill2")
                .setServiceTime(service.getServiceDuration())
                .setLocation(
                    Location.Builder.newInstance()
                        .setId(service.getLocation().getId())
                        .setCoordinate(service.getLocation().getCoordinate())
                        .build())
                .setTimeWindow(service.getTimeWindow())
                .addSizeDimension(0, service.getSize().get(0));
        skillServiceBuilder.addRequiredSkill("skill2");
      } else {
        skillServiceBuilder =
            Service.Builder.newInstance(service.getId() + "_skill1")
                .setServiceTime(service.getServiceDuration())
                .setLocation(
                    Location.Builder.newInstance()
                        .setId(service.getLocation().getId())
                        .setCoordinate(service.getLocation().getCoordinate())
                        .build())
                .setTimeWindow(service.getTimeWindow())
                .addSizeDimension(0, service.getSize().get(0));
        skillServiceBuilder.addRequiredSkill("skill1");
      }
      skillProblemBuilder.addJob(skillServiceBuilder.build());
    }
    skillProblemBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE);
    VehicleRoutingProblem skillProblem = skillProblemBuilder.build();

    VehicleRoutingAlgorithmBuilder vraBuilder =
        new VehicleRoutingAlgorithmBuilder(skillProblem, "input/algorithmConfig_solomon.xml");
    vraBuilder.addCoreConstraints();
    vraBuilder.addDefaultCostCalculators();

    StateManager stateManager = new StateManager(skillProblem);
    stateManager.updateSkillStates();

    ConstraintManager constraintManager = new ConstraintManager(skillProblem, stateManager);
    constraintManager.addSkillsConstraint();

    VehicleRoutingAlgorithm vra =
        Jsprit.Builder.newInstance(skillProblem)
            .setStateAndConstraintManager(stateManager, constraintManager)
            .buildAlgorithm();

    Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
    VehicleRoutingProblemSolution solution = Solutions.bestOf(solutions);

    SolutionPrinter.print(skillProblem, solution, SolutionPrinter.Print.VERBOSE);

    new Plotter(skillProblem, solution).plot("output/skill_solution", "solomon_with_skills");

    new VrpXMLWriter(skillProblem, solutions).write("output/solomon_with_skills");
  }