reinterpretcat / vrp

A Vehicle Routing Problem solver
https://reinterpretcat.github.io/vrp/
Apache License 2.0
331 stars 68 forks source link

Multi-location skills – one and only one should be selected #20

Open pierrethiriet opened 3 years ago

pierrethiriet commented 3 years ago

I have a specific use case that seems not possible to model with vrp-cli. But I may have missed something or thought about it in the wrong way.
Would it be possible to have a task, a job skill, assigned to a vehicle, that can be done in several places but only one should be selected at the end. It is similar to a location problem and thus somehow similar to dispatch or reloads, but without capacity question.

A current example of this problem is the integration of the refueling of the vehicles.
This task has to be done during the vehicle shift. It has to be done, but only once and only in few specific petrol stations (for accounting question). Therefore, the location/allocation of the petrol station should be done to a vehicle and integrated into its tours.

I thought first to loop over petrol stations, solve each problem and then keep the less costly one. But there may be a better option?

reinterpretcat commented 3 years ago

Regarding the refueling example. Would break with specified location after some period of time (or distance) work better for this purpose? Logically, you don't want to refuel your vehicle right after beginning, as it is still full, or in the end, risking to run out of fuel in the middle of tour.

Interval break which has to be taken after specific working time (can be extended for distance too) is supported as experimental (unstable) feature.

pierrethiriet commented 3 years ago

Thanks, I didn’t realize that location and even better several locations can be set for breaks.
In this case, I guess the location of the break is optimized regarding the rest of the tour. I’ll try this solution as it seems to fit quite well my needs. Thanks a lot.

pierrethiriet commented 3 years ago

Thanks to your advice, I am now using breaks to include actions related to the fleet (petrol station, etc.) that should happen during a tour but potentially in different alternative locations. It is working indeed very well.

This leads me to a side question. The solution return the following stop description

"jobId": "break",
"type": "break",

Would it be possible to add a specific jobId by passing an additional and optional property in break definition? Thanks.

reinterpretcat commented 3 years ago

I think it can be a tag property, similar one for a job. However, it would be one per break definition, not per break's location.

pierrethiriet commented 3 years ago

Yes, indeed, it could be one tag per break (like refueling). For locations, that can be hendle outside vrp-cli I guess.

reinterpretcat commented 3 years ago

I've added a tag property for break in the master branch. The plan is to make a new release this week, I just need to add some extra checks for solution checker

pierrethiriet commented 3 years ago

Thanks a lot.

pierrethiriet commented 3 years ago

The combination of breaks and tags provides an efficient solution for managing actions concerning vehicles: refueling, cleaning. However, several of these actions may happen in the same time window (TW), whatever the final order may be. It seems that the breaks option does not handle this specific case. Would it be possible to add an option to have several breaks in the same TW? Tanks a lot.

reinterpretcat commented 3 years ago

I think it should be possible: if I'm not mistaken, only problem validation prevents it at the moment:

https://github.com/reinterpretcat/vrp/blob/master/vrp-pragmatic/src/validation/vehicles.rs#L91

If you pass true for last parameter (skip_intersection_check), then it should not throw validation error for time window intersection. You can try it locally. For release, I would need to test it a bit

pierrethiriet commented 3 years ago

Thanks a lot. I am not 100% sure about how passing the parameter skip_intersection_check in javascript context, but I'll try.

reinterpretcat commented 3 years ago

I meant that you can checkout the source code, modify the line above, build binaries locally and test it

pierrethiriet commented 3 years ago

Ok. I'll get it. Thanks

pierrethiriet commented 3 years ago

Sorry for my late reply, I just comment the line check_e1303_vehicle_breaks_time_is_correct(ctx) :

pub fn validate_vehicles(ctx: &ValidationContext) -> Result<(), Vec<FormatError>> {
    combine_error_results(&[
        check_e1300_no_vehicle_types_with_duplicate_type_ids(ctx),
        check_e1301_no_vehicle_types_with_duplicate_ids(ctx),
        check_e1302_vehicle_shift_time(ctx),
        // check_e1303_vehicle_breaks_time_is_correct(ctx),
        check_e1304_vehicle_reload_time_is_correct(ctx),
        check_e1305_vehicle_limit_area_is_correct(ctx),
        check_e1306_vehicle_dispatch_is_correct(ctx),
        check_e1307_vehicle_has_no_zero_costs(ctx),
    ])
}

It indeed work as expected ! Thanks a lot.

pierrethiriet commented 2 years ago

I am currently updating my application with the latest version of _vrpcli (v.1.18.1), and it seems that the tag for vehicle shift breaks is not passed to the solution. In a previous version, the tag was available under jobTag. Is there some change in the pragmatic format? But looking at the doc, it seems not, but I may have missed something ? Thanks,

reinterpretcat commented 2 years ago

Hi,

no, there was no changes in api contract. I'll check it once I have time (just returned from vacation).

Update: actually, there is can_assign_break_between_jobs test which validates tag assignment in the solution for a break activity and it passes. Do you have a minimal reproducible example?

pierrethiriet commented 2 years ago

Sorry, it is my fault. In a previous version, breaks were slightly different. At that time, tag was just on the first level:

"breaks": [
  {
    "time": [
      "2019-07-04T12:00:00Z",
      "2019-07-04T14:00:00Z"
    ],
  "duration": 3600.0,
  "locations": [
    {}
  ],
  "tag": "testTag"
}

This is not the case anymore, as clearly stated in our docs...

"breaks": [
  {
    "time": [
      "2019-07-04T12:00:00Z",
      "2019-07-04T14:00:00Z"
    ],
    "places": [
      {
        "tag": "testTag",
        "duration": 3600.0
      }
    ]
  }
]

Sorry for the trouble, and thanks again