Multiple trips
These examples demonstrate how to use vehicle reload feature which is designed to overcome vehicle capacity limitation in order to perform multiple trips (tours).
Essentially, reload is a place where vehicle can unload static
pickups and load new static
deliveries. Here, static
correspond to static demand
concept which is defined via standalone pickup or delivery jobs, not by single pickup and
delivery job.
Same location reload
In this scenario, once some jobs are delivered, the vehicle returns to the original depot to load next goods.
Problem
{
"plan": {
"jobs": [
{
"id": "job1",
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.52599,
"lng": 13.45413
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job2",
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.5225,
"lng": 13.4095
},
"duration": 240.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job3",
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.5165,
"lng": 13.3808
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job4",
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.5145,
"lng": 13.3513
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
}
]
},
"fleet": {
"vehicles": [
{
"typeId": "vehicle",
"vehicleIds": [
"vehicle_1"
],
"profile": {
"matrix": "normal_car"
},
"costs": {
"fixed": 22.0,
"distance": 0.0002,
"time": 0.004806
},
"shifts": [
{
"start": {
"earliest": "2019-07-04T09:00:00Z",
"location": {
"lat": 52.5316,
"lng": 13.3884
}
},
"end": {
"latest": "2019-07-04T18:00:00Z",
"location": {
"lat": 52.5316,
"lng": 13.3884
}
},
"reloads": [
{
"location": {
"lat": 52.5316,
"lng": 13.3884
},
"duration": 600.0
}
]
}
],
"capacity": [
2
]
}
],
"profiles": [
{
"name": "normal_car"
}
]
}
}
Solution
{
"statistic": {
"cost": 52.651224000000006,
"distance": 20995,
"duration": 5504,
"times": {
"driving": 3764,
"serving": 1740,
"waiting": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "vehicle_1",
"typeId": "vehicle",
"shiftIndex": 0,
"stops": [
{
"location": {
"lat": 52.5316,
"lng": 13.3884
},
"time": {
"arrival": "2019-07-04T09:00:00Z",
"departure": "2019-07-04T09:00:00Z"
},
"distance": 0,
"load": [
2
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
]
},
{
"location": {
"lat": 52.52599,
"lng": 13.45413
},
"time": {
"arrival": "2019-07-04T09:14:49Z",
"departure": "2019-07-04T09:19:49Z"
},
"distance": 5090,
"load": [
1
],
"activities": [
{
"jobId": "job1",
"type": "delivery"
}
]
},
{
"location": {
"lat": 52.5225,
"lng": 13.4095
},
"time": {
"arrival": "2019-07-04T09:31:22Z",
"departure": "2019-07-04T09:35:22Z"
},
"distance": 8930,
"load": [
0
],
"activities": [
{
"jobId": "job2",
"type": "delivery"
}
]
},
{
"location": {
"lat": 52.5316,
"lng": 13.3884
},
"time": {
"arrival": "2019-07-04T09:45:02Z",
"departure": "2019-07-04T09:55:02Z"
},
"distance": 12156,
"load": [
2
],
"activities": [
{
"jobId": "reload",
"type": "reload"
}
]
},
{
"location": {
"lat": 52.5165,
"lng": 13.3808
},
"time": {
"arrival": "2019-07-04T10:02:31Z",
"departure": "2019-07-04T10:07:31Z"
},
"distance": 14308,
"load": [
1
],
"activities": [
{
"jobId": "job3",
"type": "delivery"
}
]
},
{
"location": {
"lat": 52.5145,
"lng": 13.3513
},
"time": {
"arrival": "2019-07-04T10:15:03Z",
"departure": "2019-07-04T10:20:03Z"
},
"distance": 17092,
"load": [
0
],
"activities": [
{
"jobId": "job4",
"type": "delivery"
}
]
},
{
"location": {
"lat": 52.5316,
"lng": 13.3884
},
"time": {
"arrival": "2019-07-04T10:31:44Z",
"departure": "2019-07-04T10:31:44Z"
},
"distance": 20995,
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
]
}
],
"statistic": {
"cost": 52.651224000000006,
"distance": 20995,
"duration": 5504,
"times": {
"driving": 3764,
"serving": 1740,
"waiting": 0,
"break": 0
}
}
}
],
"unassigned": []
}
Multiple reloads with different locations
In this scenario, vehicle picks goods and flushes them on two different locations during single tour. This can be used to model waste collection use case.
Problem
{
"plan": {
"jobs": [
{
"id": "job1",
"pickups": [
{
"places": [
{
"location": {
"lat": 52.52599,
"lng": 13.45413
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job2",
"pickups": [
{
"places": [
{
"location": {
"lat": 52.5225,
"lng": 13.4095
},
"duration": 240.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job3",
"pickups": [
{
"places": [
{
"location": {
"lat": 52.5165,
"lng": 13.3808
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job4",
"pickups": [
{
"places": [
{
"location": {
"lat": 52.5145,
"lng": 13.3513
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job5",
"pickups": [
{
"places": [
{
"location": {
"lat": 52.4922,
"lng": 13.4593
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job6",
"pickups": [
{
"places": [
{
"location": {
"lat": 52.4989,
"lng": 13.3917
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
}
]
},
"fleet": {
"vehicles": [
{
"typeId": "vehicle",
"vehicleIds": [
"vehicle_1"
],
"profile": {
"matrix": "normal_car"
},
"costs": {
"fixed": 22.0,
"distance": 0.0002,
"time": 0.004806
},
"shifts": [
{
"start": {
"earliest": "2019-07-04T09:00:00Z",
"location": {
"lat": 52.5316,
"lng": 13.3884
}
},
"end": {
"latest": "2019-07-04T18:00:00Z",
"location": {
"lat": 52.5316,
"lng": 13.3884
}
},
"reloads": [
{
"location": {
"lat": 52.5103,
"lng": 13.3898
},
"duration": 600.0
},
{
"location": {
"lat": 52.5043,
"lng": 13.4091
},
"duration": 600.0
}
]
}
],
"capacity": [
2
]
}
],
"profiles": [
{
"name": "normal_car"
}
]
}
}
Solution
{
"statistic": {
"cost": 52.38156800000001,
"distance": 23876,
"duration": 5328,
"times": {
"driving": 2388,
"serving": 2940,
"waiting": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "vehicle_1",
"typeId": "vehicle",
"shiftIndex": 0,
"stops": [
{
"location": {
"lat": 52.5316,
"lng": 13.3884
},
"time": {
"arrival": "2019-07-04T09:00:00Z",
"departure": "2019-07-04T09:00:00Z"
},
"distance": 0,
"load": [
0
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
]
},
{
"location": {
"lat": 52.5225,
"lng": 13.4095
},
"time": {
"arrival": "2019-07-04T09:02:55Z",
"departure": "2019-07-04T09:06:55Z"
},
"distance": 1752,
"load": [
1
],
"activities": [
{
"jobId": "job2",
"type": "pickup"
}
]
},
{
"location": {
"lat": 52.5165,
"lng": 13.3808
},
"time": {
"arrival": "2019-07-04T09:10:21Z",
"departure": "2019-07-04T09:15:21Z"
},
"distance": 3808,
"load": [
2
],
"activities": [
{
"jobId": "job3",
"type": "pickup"
}
]
},
{
"location": {
"lat": 52.5103,
"lng": 13.3898
},
"time": {
"arrival": "2019-07-04T09:16:53Z",
"departure": "2019-07-04T09:26:53Z"
},
"distance": 4729,
"load": [
0
],
"activities": [
{
"jobId": "reload",
"type": "reload"
}
]
},
{
"location": {
"lat": 52.5145,
"lng": 13.3513
},
"time": {
"arrival": "2019-07-04T09:31:18Z",
"departure": "2019-07-04T09:36:18Z"
},
"distance": 7379,
"load": [
1
],
"activities": [
{
"jobId": "job4",
"type": "pickup"
}
]
},
{
"location": {
"lat": 52.4989,
"lng": 13.3917
},
"time": {
"arrival": "2019-07-04T09:41:42Z",
"departure": "2019-07-04T09:46:42Z"
},
"distance": 10621,
"load": [
2
],
"activities": [
{
"jobId": "job6",
"type": "pickup"
}
]
},
{
"location": {
"lat": 52.5043,
"lng": 13.4091
},
"time": {
"arrival": "2019-07-04T09:48:54Z",
"departure": "2019-07-04T09:58:54Z"
},
"distance": 11944,
"load": [
0
],
"activities": [
{
"jobId": "reload",
"type": "reload"
}
]
},
{
"location": {
"lat": 52.4922,
"lng": 13.4593
},
"time": {
"arrival": "2019-07-04T10:05:00Z",
"departure": "2019-07-04T10:10:00Z"
},
"distance": 15603,
"load": [
1
],
"activities": [
{
"jobId": "job5",
"type": "pickup"
}
]
},
{
"location": {
"lat": 52.52599,
"lng": 13.45413
},
"time": {
"arrival": "2019-07-04T10:16:18Z",
"departure": "2019-07-04T10:21:18Z"
},
"distance": 19381,
"load": [
2
],
"activities": [
{
"jobId": "job1",
"type": "pickup"
}
]
},
{
"location": {
"lat": 52.5316,
"lng": 13.3884
},
"time": {
"arrival": "2019-07-04T10:28:48Z",
"departure": "2019-07-04T10:28:48Z"
},
"distance": 23876,
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
]
}
],
"statistic": {
"cost": 52.38156800000001,
"distance": 23876,
"duration": 5328,
"times": {
"driving": 2388,
"serving": 2940,
"waiting": 0,
"break": 0
}
}
}
],
"unassigned": []
}
Shared reload resource
In this scenario, there are two vehicles with limited capacity [2]
with reload which has shared resource constraint [1]
.
The problem has 6 delivery jobs in total.
Problem
{
"plan": {
"jobs": [
{
"id": "job1",
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.52599,
"lng": 13.45413
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job2",
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.5225,
"lng": 13.4095
},
"duration": 240.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job3",
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.5165,
"lng": 13.3808
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job4",
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.5145,
"lng": 13.3513
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job5",
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.4922,
"lng": 13.4593
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
},
{
"id": "job6",
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.4989,
"lng": 13.3917
},
"duration": 300.0
}
],
"demand": [
1
]
}
]
}
]
},
"fleet": {
"vehicles": [
{
"typeId": "vehicle",
"vehicleIds": [
"vehicle_1",
"vehicle_2"
],
"profile": {
"matrix": "normal_car"
},
"costs": {
"fixed": 22.0,
"distance": 0.0002,
"time": 0.004806
},
"shifts": [
{
"start": {
"earliest": "2019-07-04T09:00:00Z",
"location": {
"lat": 52.5316,
"lng": 13.3884
}
},
"end": {
"latest": "2019-07-04T18:00:00Z",
"location": {
"lat": 52.5316,
"lng": 13.3884
}
},
"reloads": [
{
"location": {
"lat": 52.5103,
"lng": 13.3898
},
"duration": 600.0,
"resourceId": "warehouse_a"
}
]
}
],
"capacity": [
2
]
}
],
"profiles": [
{
"name": "normal_car"
}
],
"resources": [
{
"type": "reload",
"id": "warehouse_a",
"capacity": [1]
}
]
}
}
As result, the solution has 5 jobs assigned and one is unassigned as there is not enough capacity and reload resource constraint doesn't allow to reload more than 1 delivery in total for all vehicles.
Solution
{
"statistic": {
"cost": 67.17683,
"distance": 19644,
"duration": 4005,
"times": {
"driving": 1965,
"serving": 2040,
"waiting": 0,
"break": 0,
"commuting": 0,
"parking": 0
}
},
"tours": [
{
"vehicleId": "vehicle_1",
"typeId": "vehicle",
"shiftIndex": 0,
"stops": [
{
"location": {
"lat": 52.5316,
"lng": 13.3884
},
"time": {
"arrival": "2019-07-04T09:00:00Z",
"departure": "2019-07-04T09:00:00Z"
},
"distance": 0,
"load": [
2
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
]
},
{
"location": {
"lat": 52.5145,
"lng": 13.3513
},
"time": {
"arrival": "2019-07-04T09:05:15Z",
"departure": "2019-07-04T09:10:15Z"
},
"distance": 3152,
"load": [
1
],
"activities": [
{
"jobId": "job4",
"type": "delivery"
}
]
},
{
"location": {
"lat": 52.4989,
"lng": 13.3917
},
"time": {
"arrival": "2019-07-04T09:15:39Z",
"departure": "2019-07-04T09:20:39Z"
},
"distance": 6394,
"load": [
0
],
"activities": [
{
"jobId": "job6",
"type": "delivery"
}
]
},
{
"location": {
"lat": 52.5103,
"lng": 13.3898
},
"time": {
"arrival": "2019-07-04T09:22:47Z",
"departure": "2019-07-04T09:32:47Z"
},
"distance": 7670,
"load": [
1
],
"activities": [
{
"jobId": "reload",
"type": "reload"
}
]
},
{
"location": {
"lat": 52.5165,
"lng": 13.3808
},
"time": {
"arrival": "2019-07-04T09:34:19Z",
"departure": "2019-07-04T09:39:19Z"
},
"distance": 8591,
"load": [
0
],
"activities": [
{
"jobId": "job3",
"type": "delivery"
}
]
},
{
"location": {
"lat": 52.5316,
"lng": 13.3884
},
"time": {
"arrival": "2019-07-04T09:42:15Z",
"departure": "2019-07-04T09:42:15Z"
},
"distance": 10349,
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
]
}
],
"statistic": {
"cost": 36.25301,
"distance": 10349,
"duration": 2535,
"times": {
"driving": 1035,
"serving": 1500,
"waiting": 0,
"break": 0,
"commuting": 0,
"parking": 0
}
}
},
{
"vehicleId": "vehicle_2",
"typeId": "vehicle",
"shiftIndex": 0,
"stops": [
{
"location": {
"lat": 52.5316,
"lng": 13.3884
},
"time": {
"arrival": "2019-07-04T09:00:00Z",
"departure": "2019-07-04T09:00:00Z"
},
"distance": 0,
"load": [
2
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
]
},
{
"location": {
"lat": 52.52599,
"lng": 13.45413
},
"time": {
"arrival": "2019-07-04T09:07:30Z",
"departure": "2019-07-04T09:12:30Z"
},
"distance": 4495,
"load": [
1
],
"activities": [
{
"jobId": "job1",
"type": "delivery"
}
]
},
{
"location": {
"lat": 52.5225,
"lng": 13.4095
},
"time": {
"arrival": "2019-07-04T09:17:35Z",
"departure": "2019-07-04T09:21:35Z"
},
"distance": 7543,
"load": [
0
],
"activities": [
{
"jobId": "job2",
"type": "delivery"
}
]
},
{
"location": {
"lat": 52.5316,
"lng": 13.3884
},
"time": {
"arrival": "2019-07-04T09:24:30Z",
"departure": "2019-07-04T09:24:30Z"
},
"distance": 9295,
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
]
}
],
"statistic": {
"cost": 30.92382,
"distance": 9295,
"duration": 1470,
"times": {
"driving": 930,
"serving": 540,
"waiting": 0,
"break": 0,
"commuting": 0,
"parking": 0
}
}
}
],
"unassigned": [
{
"jobId": "job5",
"reasons": [
{
"code": "RELOAD_RESOURCE_CONSTRAINT",
"description": "cannot be assigned due to reload resource constraint",
"details": [
{
"vehicleId": "vehicle_1",
"shiftIndex": 0
}
]
},
{
"code": "CAPACITY_CONSTRAINT",
"description": "does not fit into any vehicle due to capacity",
"details": [
{
"vehicleId": "vehicle_2",
"shiftIndex": 0
}
]
}
]
}
]
}