VRP with Alternative Locations
Another Tour Planning feature allows getting even more advantageous tour optimization by setting the alternative locations for the jobs. This means that not only the specific time for the jobs’ execution will be considered when optimizing the tour, but also the different locations specified for the same jobs. Adding alternative locations helps to gain more flexibility for the customer in the terms of the places where they can get their orders to be done. It also improves the chances of better job assignments and efficient tours.
Let's say we have a customer that can receive his/her delivery on the specific time windows during the day. In the morning he/she can receive it at his/her home address, then during the day he/she will be available for delivery to his/her office address, and in the afternoon, he/she can be reached at his/her home address again or at some other venue of his/her choice. Using alternative locations allows considering all those constraints to visit the proper locations at the proper time.
Another situation when the alternative locations can be used is when a customer location is not reachable for some reason, or a customer cannot be reached there in the given time window. Then, the dispatcher may add a nearby pickup location for those jobs so that at least the delivery will still happen and the customer will be able to receive his/her items at any other suitable time, and the driver will not have to cancel or postpone those jobs.
In the simple example below we consider a problem when we have a vehicle with a specific shift time – from 8:00 to 21:00, and 2 jobs to execute – one pickup and one delivery. In our very case, we have 2 different time windows as well as 2 different locations for each of those jobs. The time windows for the jobs are specified in the usual way as we normally specify the time windows, but to consider the alternative locations, we additionally specify a different location for each of them.
Note that you can also use tags for your locations for more convenient reading of the solution. In our example, we specify “Home” and “Work” as alternative locations, but any other tags of your choice can be used.
The problem for our example 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-23T08:00:00Z",
"location": {
"lat": 52.5163527,
"lng": 13.3779290
}
},
"end": {
"time": "2021-10-23T21:00:00Z",
"location": {
"lat": 52.5163527,
"lng": 13.3779290
}
}
}
],
"capacity": [
10
],
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1",
"tasks": {
"pickups": [
{
"places": [
{
"times": [
[
"2021-10-23T08:30:00Z",
"2021-10-23T09:00:00Z"
]
],
"location": {
"lat": 52.5154509,
"lng": 13.4216700
},
"duration": 1150,
"tag": "Home"
},
{
"times": [
[
"2021-10-23T10:00:00Z",
"2021-10-23T19:00:00Z"
]
],
"location": {
"lat": 52.6834366,
"lng": 13.2781471
},
"duration": 1150,
"tag": "Work"
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_2",
"tasks": {
"deliveries": [
{
"places": [
{
"times": [
[
"2021-10-23T08:00:00Z",
"2021-10-23T10:30:00Z"
]
],
"location": {
"lat": 52.4583508,
"lng": 13.5787622
},
"duration": 1150,
"tag": "Home"
},
{
"times": [
[
"2021-10-23T11:10:00Z",
"2021-10-23T18:30:00Z"
]
],
"location": {
"lat": 52.4939523,
"lng": 13.5397955
},
"duration": 1150,
"tag": "Work"
}
],
"demand": [
1
]
}
]
}
}
]
}
}
The solution for such a problem will look as follows. From this simple example, along with all the statistics like total cost, distance, etc., we can see that the tour was optimized so that the first pickup job was executed on the "Home" location and the second delivery job - on the "Work" location due to the jobs time windows and locations and the vehicles shift time.
{
"statistic": {
"cost": 98.11200000000001,
"distance": 27697,
"duration": 10906,
"times": {
"driving": 3012,
"serving": 2300,
"waiting": 5594,
"break": 0
}
},
"tours": [
{
"vehicleId": "Vehicle_1_1",
"typeId": "Vehicle_1",
"stops": [
{
"location": {
"lat": 52.5163527,
"lng": 13.377929
},
"time": {
"arrival": "2021-10-23T08:00:00Z",
"departure": "2021-10-23T08:50:21Z"
},
"load": [
1
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
]
},
{
"location": {
"lat": 52.5154509,
"lng": 13.42167
},
"time": {
"arrival": "2021-10-23T09:00:00Z",
"departure": "2021-10-23T09:19:10Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_1",
"type": "pickup",
"jobTag": "Home"
}
]
},
{
"location": {
"lat": 52.4939523,
"lng": 13.5397955
},
"time": {
"arrival": "2021-10-23T09:36:46Z",
"departure": "2021-10-23T11:29:10Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_2",
"type": "delivery",
"jobTag": "Work"
}
]
},
{
"location": {
"lat": 52.5163527,
"lng": 13.377929
},
"time": {
"arrival": "2021-10-23T11:52:07Z",
"departure": "2021-10-23T11:52:07Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
]
}
],
"statistic": {
"cost": 98.11200000000001,
"distance": 27697,
"duration": 10906,
"times": {
"driving": 3012,
"serving": 2300,
"waiting": 5594,
"break": 0
}
},
"shiftIndex": 0
}
]
}