Relations for Tour Replanning
Due to the Tour Planning concepts, using the optional relations
parameter, you can define the rules and the order of the execution of the jobs for the specific vehicles. By using relations, you can influence the behaviour of the algorithm for the re-planning process and the final solution. There are three types of relations:
-
sequence
- the jobs specified in this relation, must be served by this particular vehicle in the specified order. The order of execution may not be changed and no additional jobs may be inserted between the jobs specified in this relation.
"relations": [
{
"type": "sequence",
"jobs": [
"job_1",
"job_2"
"job_4"
],
"vehicleId": "Vehicle_1_1"
}
]
-
flexible
- the jobs specified in this relation, must be served by this particular vehicle in the specified order. The order of executing the jobs may not be changed, but the jobs that were not specified in this or another relation can be inserted anywhere in this vehicle's tour even between the jobs defined in this relation.
"relations": [
{
"type": "flexible",
"jobs": [
"job_1",
"job_2"
"job_4"
],
"vehicleId": "Vehicle_1_1"
}
]
-
tour
- the jobs specified in this relation, must be served by this particular vehicle, but the order of the jobs may be changed.
"relations": [
{
"type": "tour",
"jobs": [
"job_1",
"job_2"
"job_4"
],
"vehicleId": "Vehicle_1_1"
}
]
Unlike the sequence
and flexible
relations, the tour
relation doesn't guarantee that all the jobs will be assigned in the tour. Some jobs in the tour
relation can be unassigned due to some other constraint reasons, e.g. capacity, time, etc. If those jobs still need to be assigned, then you should use the higher priority for them, or use another type of relation which guarantees assignment.
Please note that jobs added into a sequence
or a flexible
relation are not checked for constraint violations, e.g. time windows, skill requirements, capacity violations, pickup/delivery assignment, routing availability, etc. This might lead to infeasible or undesired solutions. Also, a relation cannot be used in multi-jobs.
There is no restriction on the number of jobs set in the relations for a vehicle, as well as in combining several relations for different vehicles in the fleet on the same tour.
Also, note that the vehicleId
is the vehicle type
id
+ _index. In our case, the vehicle type
id
is Vehicle_1
, and the amount of vehicles is 3, so the vehicleId
s in our examples will be Vehicle_1_1
, Vehicle_1_2
and Vehicle_1_3
.
To check how the `relations' can influence the problem solutions while replanning the tour, let's try some simple examples.
Sequence
Let's assume we have a vehicle with enough capacity and respective shift time to execute 4 jobs. Two of those four jobs are needed to be executed one after another because deliveries or pickups are somehow connected, even though their locations are not very close to each other. Typically, those jobs would be optimized in a tour more advantageously, but as we set the relation type sequence
to them, they only can be executed one after another. The simple problem example would look as follows:
{
"fleet": {
"types": [
{
"id": "Vehicle_1",
"profile": "car_1",
"costs": {
"fixed": 9.0,
"distance": 0.004,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2021-08-27T08:03:00Z",
"location": {
"lat": 52.530971,
"lng": 13.384915
}
},
"end": {
"time": "2021-08-27T18:03:00Z",
"location": {
"lat": 52.530971,
"lng": 13.384915
}
}
}
],
"capacity": [
10
],
"limits": {
"maxDistance": 300000,
"shiftTime": 43200
},
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car_1"
}
]
},
"plan": {
"jobs": [
{
"id": "job_1",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-08-27T09:03:00Z",
"2021-08-27T18:03:00Z"
]
],
"location": {
"lat": 52.59175589353722,
"lng": 13.350747750372257
},
"duration": 360
}
],
"demand": [
1
]
}
]
}
},
{
"id": "job_2",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-08-27T11:03:00Z",
"2021-08-27T20:03:00Z"
]
],
"location": {
"lat": 52.43363386232821,
"lng": 13.403232562191313
},
"duration": 540
}
],
"demand": [
1
]
}
]
}
},
{
"id": "job_3",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-08-27T10:03:00Z",
"2021-08-27T16:03:00Z"
]
],
"location": {
"lat": 52.473321658918245,
"lng": 13.28972099097991
},
"duration": 660
}
],
"demand": [
1
]
}
]
}
},
{
"id": "job_4",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-08-27T09:03:00Z",
"2021-08-27T17:03:00Z"
]
],
"location": {
"lat": 52.54165532725351,
"lng": 13.365047170290309
},
"duration": 1140
}
],
"demand": [
1
]
}
]
}
}
],
"relations": [
{
"type": "sequence",
"jobs": [
"job_1",
"job_4"
],
"vehicleId": "Vehicle_1_1"
}
]
}
}
Analyzing the initial solution for this problem, we may notice that the vehicle will first execute job_2
and job_3
, and afterwards job_1
and job_4
that were specified in the relations. In this way, you should note that if any of the constraints during the tour will change and the tour is recalculated, the jobs with sequence relation will be executed in the specified order anyway.
{
"statistic": {
"cost": 269.051,
"distance": 55254,
"duration": 7807,
"times": {
"driving": 5107,
"serving": 2700,
"waiting": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "Vehicle_1_1",
"typeId": "Vehicle_1",
"stops": [
{
"location": {
"lat": 52.530971,
"lng": 13.384915
},
"time": {
"arrival": "2021-08-27T08:03:00Z",
"departure": "2021-08-27T10:38:23Z"
},
"load": [
4
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
],
"distance": 0
},
{
"location": {
"lat": 52.43363386232821,
"lng": 13.403232562191311
},
"time": {
"arrival": "2021-08-27T11:03:00Z",
"departure": "2021-08-27T11:12:00Z"
},
"load": [
3
],
"activities": [
{
"jobId": "job_2",
"type": "delivery"
}
],
"distance": 14847
},
{
"location": {
"lat": 52.473321658918245,
"lng": 13.28972099097991
},
"time": {
"arrival": "2021-08-27T11:30:55Z",
"departure": "2021-08-27T11:41:55Z"
},
"load": [
2
],
"activities": [
{
"jobId": "job_3",
"type": "delivery"
}
],
"distance": 28933
},
{
"location": {
"lat": 52.59175589353722,
"lng": 13.350747750372255
},
"time": {
"arrival": "2021-08-27T12:03:55Z",
"departure": "2021-08-27T12:09:55Z"
},
"load": [
1
],
"activities": [
{
"jobId": "job_1",
"type": "delivery"
}
],
"distance": 45708
},
{
"location": {
"lat": 52.54165532725351,
"lng": 13.365047170290309
},
"time": {
"arrival": "2021-08-27T12:24:34Z",
"departure": "2021-08-27T12:43:34Z"
},
"load": [
0
],
"activities": [
{
"jobId": "job_4",
"type": "delivery"
}
],
"distance": 53145
},
{
"location": {
"lat": 52.530971,
"lng": 13.384915
},
"time": {
"arrival": "2021-08-27T12:48:30Z",
"departure": "2021-08-27T12:48:30Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
],
"distance": 55249
}
],
"statistic": {
"cost": 269.051,
"distance": 55254,
"duration": 7807,
"times": {
"driving": 5107,
"serving": 2700,
"waiting": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}
Let's assume that after executing job_3
, one more job was added to the tour in the nearby location. Normally, job_5
would be executed after job_1
, but considering the sequence
relation, no jobs can be added between job_1
and job_4
, that's why after replanning, job_5
will be performed before the two jobs from the relations, and job_1
and job_4
will be executed in sequence after that.
{
"statistic": {
"cost": 147.98,
"distance": 28900,
"duration": 4676,
"times": {
"driving": 2816,
"serving": 1860,
"waiting": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "Vehicle_1_1",
"typeId": "Vehicle_1",
"stops": [
{
"location": {
"lat": 52.473321658918245,
"lng": 13.28972099097991
},
"time": {
"arrival": "2021-08-27T11:41:55Z",
"departure": "2021-08-27T11:41:55Z"
},
"load": [
3
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
],
"distance": 0
},
{
"location": {
"lat": 52.57175589353722,
"lng": 13.360747750372257
},
"time": {
"arrival": "2021-08-27T12:02:47Z",
"departure": "2021-08-27T12:08:47Z"
},
"load": [
2
],
"activities": [
{
"jobId": "job_5",
"type": "delivery"
}
],
"distance": 14847
},
{
"location": {
"lat": 52.59175589353722,
"lng": 13.350747750372255
},
"time": {
"arrival": "2021-08-27T12:15:16Z",
"departure": "2021-08-27T12:21:16Z"
},
"load": [
1
],
"activities": [
{
"jobId": "job_1",
"type": "delivery"
}
],
"distance": 28933
},
{
"location": {
"lat": 52.54165532725351,
"lng": 13.365047170290309
},
"time": {
"arrival": "2021-08-27T12:35:55Z",
"departure": "2021-08-27T12:54:55Z"
},
"load": [
0
],
"activities": [
{
"jobId": "job_4",
"type": "delivery"
}
],
"distance": 45708
},
{
"location": {
"lat": 52.530971,
"lng": 13.384915
},
"time": {
"arrival": "2021-08-27T12:59:51Z",
"departure": "2021-08-27T12:59:51Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
],
"distance": 53145
}
],
"statistic": {
"cost": 147.98,
"distance": 28900,
"duration": 4676,
"times": {
"driving": 2816,
"serving": 1860,
"waiting": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}
Flexible
Let's model a situation where we have a vehicle with enough capacity and respective shift time to execute 4 jobs. Two of those four jobs (job_1
and job_4
) are needed to be executed one after another because deliveries or pickups are somehow connected, even though logically the algorithm would settle them in a different order. Also, we need to consider that some new jobs may appear during the tour in the area of those 2 jobs, so that vehicle should be allowed to execute them as well.
In this situation, we need to set the flexible
relation for those jobs, so when executing the jobs from relation, the other jobs may be added to the tour. The simple problem example for such constraints would look as follows:
{
"fleet": {
"types": [
{
"id": "Vehicle_1",
"profile": "car_1",
"costs": {
"fixed": 9.0,
"distance": 0.004,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2021-08-27T08:03:00Z",
"location": {
"lat": 52.530971,
"lng": 13.384915
}
},
"end": {
"time": "2021-08-27T18:03:00Z",
"location": {
"lat": 52.530971,
"lng": 13.384915
}
}
}
],
"capacity": [
10
],
"limits": {
"maxDistance": 300000,
"shiftTime": 43200
},
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car_1"
}
]
},
"plan": {
"jobs": [
{
"id": "job_1",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-08-27T09:03:00Z",
"2021-08-27T18:03:00Z"
]
],
"location": {
"lat": 52.59175589353722,
"lng": 13.350747750372257
},
"duration": 360
}
],
"demand": [
1
]
}
]
}
},
{
"id": "job_2",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-08-27T11:03:00Z",
"2021-08-27T20:03:00Z"
]
],
"location": {
"lat": 52.43363386232821,
"lng": 13.403232562191313
},
"duration": 540
}
],
"demand": [
1
]
}
]
}
},
{
"id": "job_3",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-08-27T10:03:00Z",
"2021-08-27T16:03:00Z"
]
],
"location": {
"lat": 52.473321658918245,
"lng": 13.28972099097991
},
"duration": 660
}
],
"demand": [
1
]
}
]
}
},
{
"id": "job_4",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-08-27T09:03:00Z",
"2021-08-27T17:03:00Z"
]
],
"location": {
"lat": 52.54165532725351,
"lng": 13.365047170290309
},
"duration": 1140
}
],
"demand": [
1
]
}
]
}
}
],
"relations": [
{
"type": "flexible",
"jobs": [
"job_1",
"job_4"
],
"vehicleId": "Vehicle_1_1"
}
]
}
}
As we can see from the initial solution, job_4
was settled after job_1
in the tour, and the tour was optimized in the way that those two jobs were settled after the jobs outside the relations.
{
"statistic": {
"cost": 269.116,
"distance": 55254,
"duration": 7820,
"times": {
"driving": 5120,
"serving": 2700,
"waiting": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "Vehicle_1_1",
"typeId": "Vehicle_1",
"stops": [
{
"location": {
"lat": 52.530971,
"lng": 13.384915
},
"time": {
"arrival": "2021-08-27T08:03:00Z",
"departure": "2021-08-27T10:38:23Z"
},
"load": [
4
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
],
"distance": 0
},
{
"location": {
"lat": 52.43363386232821,
"lng": 13.403232562191311
},
"time": {
"arrival": "2021-08-27T11:03:00Z",
"departure": "2021-08-27T11:12:00Z"
},
"load": [
3
],
"activities": [
{
"jobId": "job_2",
"type": "delivery"
}
],
"distance": 14847
},
{
"location": {
"lat": 52.473321658918245,
"lng": 13.28972099097991
},
"time": {
"arrival": "2021-08-27T11:30:55Z",
"departure": "2021-08-27T11:41:55Z"
},
"load": [
2
],
"activities": [
{
"jobId": "job_3",
"type": "delivery"
}
],
"distance": 28933
},
{
"location": {
"lat": 52.59175589353722,
"lng": 13.350747750372255
},
"time": {
"arrival": "2021-08-27T12:04:08Z",
"departure": "2021-08-27T12:10:08Z"
},
"load": [
1
],
"activities": [
{
"jobId": "job_1",
"type": "delivery"
}
],
"distance": 45708
},
{
"location": {
"lat": 52.54165532725351,
"lng": 13.365047170290309
},
"time": {
"arrival": "2021-08-27T12:24:47Z",
"departure": "2021-08-27T12:43:47Z"
},
"load": [
0
],
"activities": [
{
"jobId": "job_4",
"type": "delivery"
}
],
"distance": 53145
},
{
"location": {
"lat": 52.530971,
"lng": 13.384915
},
"time": {
"arrival": "2021-08-27T12:48:43Z",
"departure": "2021-08-27T12:48:43Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
],
"distance": 55249
}
],
"statistic": {
"cost": 269.116,
"distance": 55254,
"duration": 7820,
"times": {
"driving": 5120,
"serving": 2700,
"waiting": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}
Let's assume that after executing job_3
, two more jobs were added to the tour in the nearby location - job_5
and job_6
. Normally, if we use the sequence
relations, the newly added job_5
and job_6
would be executed after job_4
. But because in the flexible
relation the jobs can be added between job_1
and job_4
, the tour will be optimized so that job_6
will be executed before job_1
, and job_5
will be inserted between job_1
and job_4
that will still be settled one after another in the tour.
{
"statistic": {
"cost": 158.063,
"distance": 29782,
"duration": 5987,
"times": {
"driving": 3767,
"serving": 2220,
"waiting": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "Vehicle_1_1",
"typeId": "Vehicle_1",
"stops": [
{
"location": {
"lat": 52.473321658918245,
"lng": 13.28972099097991
},
"time": {
"arrival": "2021-08-27T11:41:55Z",
"departure": "2021-08-27T11:41:55Z"
},
"load": [
4
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
],
"distance": 0
},
{
"location": {
"lat": 52.52175589353722,
"lng": 13.357747750372257
},
"time": {
"arrival": "2021-08-27T12:00:23Z",
"departure": "2021-08-27T12:06:23Z"
},
"load": [
3
],
"activities": [
{
"jobId": "job_6",
"type": "delivery"
}
],
"distance": 14847
},
{
"location": {
"lat": 52.59175589353722,
"lng": 13.350747750372255
},
"time": {
"arrival": "2021-08-27T12:28:05Z",
"departure": "2021-08-27T12:34:05Z"
},
"load": [
2
],
"activities": [
{
"jobId": "job_1",
"type": "delivery"
}
],
"distance": 28933
},
{
"location": {
"lat": 52.55175589353722,
"lng": 13.357747750372257
},
"time": {
"arrival": "2021-08-27T12:46:57Z",
"departure": "2021-08-27T12:52:57Z"
},
"load": [
1
],
"activities": [
{
"jobId": "job_5",
"type": "delivery"
}
],
"distance": 45708
},
{
"location": {
"lat": 52.54165532725351,
"lng": 13.365047170290309
},
"time": {
"arrival": "2021-08-27T12:57:46Z",
"departure": "2021-08-27T13:16:46Z"
},
"load": [
0
],
"activities": [
{
"jobId": "job_4",
"type": "delivery"
}
],
"distance": 53145
},
{
"location": {
"lat": 52.530971,
"lng": 13.384915
},
"time": {
"arrival": "2021-08-27T13:21:42Z",
"departure": "2021-08-27T13:21:42Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
],
"distance": 55249
}
],
"statistic": {
"cost": 158.063,
"distance": 29782,
"duration": 5987,
"times": {
"driving": 3767,
"serving": 2220,
"waiting": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}
Tour
When we have several vehicles in our fleet and we want some of the jobs to be executed by the specific vehicle, and the order of the execution is not critical, then we should use the tour
relation. For example, we have a fleet of 2 vehicles and 6 jobs to execute. According to our plan, we need one of the vehicles to operate with the specific jobs from this list. Which of the vehicles will execute the other 3 jobs is not critical. So, in our example, we set the tour
relation with job_1
, job_2
, and job_3
to the Vehicle_1_1
. Note that it doesn't mean that the Vehicle_1_1
will only execute those jobs and will be restricted to executing the others, but it means that only Vehicle_1_1
can execute them, and Vehicle_1_2
can not. The problem for such constraints will look as follows:
{
"fleet": {
"types": [
{
"id": "Vehicle_1",
"profile": "car",
"costs": {
"fixed": 10.0,
"distance": 0.002,
"time": 0.003
},
"shifts": [
{
"start": {
"time": "2021-10-23T10:16:40Z",
"location": {
"lat": 51.08511,
"lng": 13.76875
}
},
"end": {
"time": "2021-10-23T17:00:00Z",
"location": {
"lat": 51.059188,
"lng": 13.540317
}
}
}
],
"capacity": [
5
],
"amount": 1
},
{
"id": "Vehicle_2",
"profile": "car",
"costs": {
"fixed": 12.0,
"distance": 0.002,
"time": 0.002
},
"shifts": [
{
"start": {
"time": "2021-10-23T08:00:00Z",
"location": {
"lat": 51.059188,
"lng": 13.540317
}
},
"end": {
"time": "2021-10-23T19:00:00Z",
"location": {
"lat": 51.059188,
"lng": 13.540317
}
}
}
],
"capacity": [
5
],
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-10-23T12:30:00Z",
"2021-10-23T14:00:00Z"
]
],
"location": {
"lat": 51.05238,
"lng": 13.74114
},
"duration": 1800
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_2",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-10-23T12:05:00Z",
"2021-10-23T17:30:00Z"
]
],
"location": {
"lat": 51.06099,
"lng": 13.75245
},
"duration": 2000
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_3",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-10-23T13:35:00Z",
"2021-10-23T17:00:00Z"
]
],
"location": {
"lat": 51.08511,
"lng": 13.76875
},
"duration": 1800
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_4",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-10-23T10:05:00Z",
"2021-10-23T10:30:00Z"
]
],
"location": {
"lat": 51.1323847,
"lng": 13.7779515
},
"duration": 2000
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_5",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-10-23T16:35:00Z",
"2021-10-23T17:00:00Z"
]
],
"location": {
"lat": 51.11716,
"lng": 13.73054
},
"duration": 1800
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_6",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-10-23T11:05:00Z",
"2021-10-23T11:30:00Z"
]
],
"location": {
"lat": 51.12308,
"lng": 13.76406
},
"duration": 2000
}
],
"demand": [
1
]
}
]
}
}
],
"relations": [
{
"type": "tour",
"jobs": [
"Job_1",
"Job_2",
"Job_3"
],
"vehicleId": "Vehicle_1_1"
}
]
}
}
As we can see from the initial solution, Vehicle_1_1
will perform not only job_1
, job_2
, and job_3
that were specified in its tour
relation, but also job_4
and job_6
. Furthermore, the order of execution will not keep the sequence of the jobs in the relation - job_2
, job_1
and after that job_3
. Vehicle_2_1
in its turn will only execute job_5
.
{
"statistic": {
"cost": 251.099,
"distance": 88444,
"duration": 18630,
"times": {
"driving": 6068,
"serving": 11400,
"waiting": 1162,
"break": 0
}
},
"tours": [
{
"vehicleId": "Vehicle_1_1",
"typeId": "Vehicle_1",
"stops": [
{
"location": {
"lat": 51.08511,
"lng": 13.76875
},
"time": {
"arrival": "2021-10-23T10:16:40Z",
"departure": "2021-10-23T10:19:10Z"
},
"load": [
5
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
],
"distance": 0
},
{
"location": {
"lat": 51.1323847,
"lng": 13.7779515
},
"time": {
"arrival": "2021-10-23T10:30:00Z",
"departure": "2021-10-23T11:03:20Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_4",
"type": "delivery"
}
],
"distance": 6555
},
{
"location": {
"lat": 51.12308,
"lng": 13.76406
},
"time": {
"arrival": "2021-10-23T11:07:30Z",
"departure": "2021-10-23T11:40:50Z"
},
"load": [
3
],
"activities": [
{
"jobId": "Job_6",
"type": "delivery"
}
],
"distance": 8361
},
{
"location": {
"lat": 51.06099,
"lng": 13.75245
},
"time": {
"arrival": "2021-10-23T11:54:33Z",
"departure": "2021-10-23T12:38:20Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_2",
"type": "delivery"
}
],
"distance": 16515
},
{
"location": {
"lat": 51.05238,
"lng": 13.74114
},
"time": {
"arrival": "2021-10-23T12:44:20Z",
"departure": "2021-10-23T13:14:20Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_1",
"type": "delivery"
}
],
"distance": 18811
},
{
"location": {
"lat": 51.08511,
"lng": 13.76875
},
"time": {
"arrival": "2021-10-23T13:26:05Z",
"departure": "2021-10-23T14:05:00Z"
},
"load": [
0
],
"activities": [
{
"jobId": "Job_3",
"type": "delivery"
}
],
"distance": 24558
},
{
"location": {
"lat": 51.059188,
"lng": 13.540317
},
"time": {
"arrival": "2021-10-23T14:28:21Z",
"departure": "2021-10-23T14:28:21Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
],
"distance": 48802
}
],
"statistic": {
"cost": 152.46499999999997,
"distance": 48806,
"duration": 14951,
"times": {
"driving": 4189,
"serving": 9600,
"waiting": 1162,
"break": 0
}
},
"shiftIndex": 0
},
{
"vehicleId": "Vehicle_2_1",
"typeId": "Vehicle_2",
"stops": [
{
"location": {
"lat": 51.059188,
"lng": 13.540317
},
"time": {
"arrival": "2021-10-23T08:00:00Z",
"departure": "2021-10-23T16:18:57Z"
},
"load": [
1
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
],
"distance": 0
},
{
"location": {
"lat": 51.11716,
"lng": 13.73054
},
"time": {
"arrival": "2021-10-23T16:35:00Z",
"departure": "2021-10-23T17:05:00Z"
},
"load": [
0
],
"activities": [
{
"jobId": "Job_5",
"type": "delivery"
}
],
"distance": 19957
},
{
"location": {
"lat": 51.059188,
"lng": 13.540317
},
"time": {
"arrival": "2021-10-23T17:20:16Z",
"departure": "2021-10-23T17:20:16Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
],
"distance": 39636
}
],
"statistic": {
"cost": 98.63400000000001,
"distance": 39638,
"duration": 3679,
"times": {
"driving": 1879,
"serving": 1800,
"waiting": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}
Let's assume that after Vehicle_1_1
has executed the first 2 jobs - job_4
and job_6
, another 3 jobs were added to the tour - job_7
, job_8
, and job_9
. After the replanning, the solution has changed, but still, the jobs in the tour
relations are left for execution by Vehicle_1_1
. Now, Vehicle_1_1
will continue the tour executing job_1
, job_3
, job_2
, and job_7
. Vehicle_1_2
in its turn will proceed with job_9
, job_5
, and job_8
.
{
"statistic": {
"cost": 288.165,
"distance": 106927,
"duration": 20372,
"times": {
"driving": 6972,
"serving": 13400,
"waiting": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "Vehicle_1_1",
"typeId": "Vehicle_1",
"stops": [
{
"location": {
"lat": 51.08511,
"lng": 13.76875
},
"time": {
"arrival": "2021-10-23T12:38:20Z",
"departure": "2021-10-23T12:41:08Z"
},
"load": [
4
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
],
"distance": 0
},
{
"location": {
"lat": 51.05238,
"lng": 13.74114
},
"time": {
"arrival": "2021-10-23T12:53:15Z",
"departure": "2021-10-23T13:23:15Z"
},
"load": [
3
],
"activities": [
{
"jobId": "Job_1",
"type": "delivery"
}
],
"distance": 6555
},
{
"location": {
"lat": 51.08511,
"lng": 13.76875
},
"time": {
"arrival": "2021-10-23T13:35:00Z",
"departure": "2021-10-23T14:05:00Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_3",
"type": "delivery"
}
],
"distance": 8361
},
{
"location": {
"lat": 51.06099,
"lng": 13.75245
},
"time": {
"arrival": "2021-10-23T14:13:04Z",
"departure": "2021-10-23T14:46:24Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_2",
"type": "delivery"
}
],
"distance": 16515
},
{
"location": {
"lat": 51.09099,
"lng": 13.65245
},
"time": {
"arrival": "2021-10-23T15:04:39Z",
"departure": "2021-10-23T15:37:59Z"
},
"load": [
0
],
"activities": [
{
"jobId": "Job_7",
"type": "delivery"
}
],
"distance": 18811
},
{
"location": {
"lat": 51.059188,
"lng": 13.540317
},
"time": {
"arrival": "2021-10-23T15:53:55Z",
"departure": "2021-10-23T15:53:55Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
],
"distance": 24558
}
],
"statistic": {
"cost": 126.51100000000001,
"distance": 40905,
"duration": 11567,
"times": {
"driving": 3967,
"serving": 7600,
"waiting": 0,
"break": 0
}
},
"shiftIndex": 0
},
{
"vehicleId": "Vehicle_2_1",
"typeId": "Vehicle_2",
"stops": [
{
"location": {
"lat": 51.059188,
"lng": 13.540317
},
"time": {
"arrival": "2021-10-23T08:00:00Z",
"departure": "2021-10-23T15:41:33Z"
},
"load": [
3
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
],
"distance": 0
},
{
"location": {
"lat": 51.16099,
"lng": 13.75245
},
"time": {
"arrival": "2021-10-23T15:58:41Z",
"departure": "2021-10-23T16:32:01Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_9",
"type": "delivery"
}
],
"distance": 19957
},
{
"location": {
"lat": 51.11716,
"lng": 13.73054
},
"time": {
"arrival": "2021-10-23T16:45:55Z",
"departure": "2021-10-23T17:15:55Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_5",
"type": "delivery"
}
],
"distance": 24558
},
{
"location": {
"lat": 51.11099,
"lng": 13.70245
},
"time": {
"arrival": "2021-10-23T17:20:46Z",
"departure": "2021-10-23T17:54:06Z"
},
"load": [
0
],
"activities": [
{
"jobId": "Job_8",
"type": "delivery"
}
],
"distance": 39636
},
{
"location": {
"lat": 51.059188,
"lng": 13.540317
},
"time": {
"arrival": "2021-10-23T18:08:18Z",
"departure": "2021-10-23T18:08:18Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
],
"distance": 48802
}
],
"statistic": {
"cost": 161.654,
"distance": 66022,
"duration": 8805,
"times": {
"driving": 3005,
"serving": 5800,
"waiting": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}
Note If you got some unassigned jobs in the solution when using the tour
relation, and you still need those jobs to be assigned, then you should use the higher priority for them, or use sequence
or flexible
type of relations which guarantees assignment.