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 } ] } ] } ] }