Control job task position
The job task position feature allows you to directly set the serving order of jobs inside a tour. When using this feature, you can assign the desired position value to the tasks in the problem, and in this way, influence the order of serving them in the solution.
Consider a scenario where a logistics company needs to manage a fleet of delivery trucks. By determining the position of assignments, the company can ensure that the trucks complete all deliveries before any making any pickups. This prevents the trucks from carrying unnecessary load, improving fuel efficiency and reducing delivery times.
You have the option to specify the position of pickup or delivery assignments within the tour using the position object, which offers the values first, ordered, any, and last. This flexibility enables tailored prioritization based on factors such as urgency, proximity, and resource availability.
Note
The
orderproperty is now deprecated in favor of thepositionproperty. For more information, see the API Reference.
The following list provides an overview of how you can control the placement of specific tasks within a tour through the position option:
-
first: Assignments marked asfirstare addressed at the start of the tour, immediately after departure, and before tackling assignments with a specified position value, those without a defined position, or those with the position value set toanyorlast. In cases where multiple assignments are positioned asfirst, the API prioritizes them by determining the most efficient route between such assignments before moving on to subsequent tasks. -
ordered: Assignments labeled asorderedmust include an associated positionvalue, represented by an integer equal to or greater than1. Within the API, these assignments are prioritized lower than those marked asfirst, but higher than unordered tasks or those designated aslast. When multiple assignments are positioned as3, the API prioritizes them by determining the most efficient route between such assignments before moving on to subsequent tasks. You can also include thepriorityattribute to specify that some jobs are more desirable to be included in the tour than others. For more information, see Prioritize jobs. -
assignments without a position value: Assignments that do not have anypositionassigned are handled after the assignments labeled asfirstandorderedand before the assignments labeled aslast. -
any: This designation permits the API to position assignments within the tour anywhere betweenfirstandlastassignments. This flexibility allows assignments with thispositionvalue to be scattered amongposition.type: "ordered"and unordered assignments, optimizing the route for cost and time efficiency. -
last: If an assignment is labeled with thelastposition, the API prioritizes it as the final task to be handled after all other assignments, regardless of their position values. When multiple assignments are positioned aslast, the API prioritizes between them by determining the most efficient route.
Based on the previous overview, the following figure provides a visual representation of how the API positions tasks within the tour, depending on the task's position value:
The following comparison shows how to configure a job task within a problem depending whether the position.type is ordered or first/last/any:
ordered
{
"id": "Job_X",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
}first/last/any
{
"id": "Job_X",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "first"
}
}
]
}
}To illustrate how the position of tasks within a tour can vary based on different position settings, the following sections present a range of sample problem and solution files. The samples begin with a tour having no positioned tasks, then different position settings are progressively introduced, initially as hard constraints, and finally, the position is configured as a soft constraint. In addition, this tutorial provides additional scenarios that combine task position with other features like time windows and relations to further facilitate your understanding of the feature.
Problem: Tasks without a position
The following problem JSON serves as a starting point and does not contain positioned tasks:
Click to expand/collapse the sample JSON
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
100
],
"amount": 10
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_2",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_3",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_4",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_5",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_6",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_7",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_8",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_9",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_10",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_11",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_12",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_13",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
}
]
}
}Solution
As demonstrated in the following visualization, the optimization algorithm determined the most optimal solution for the tour based on no additional position constraint:
The following section contains the full solution JSON file:
Click to expand/collapse the sample JSON
{
"statistic": {
"cost": 91.16499999999999,
"distance": 60330,
"duration": 14233,
"times": {
"driving": 6433,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "small_8",
"typeId": "small",
"stops": [
{
"time": {
"arrival": "2023-05-28T08:00:00Z",
"departure": "2023-05-28T08:00:00Z"
},
"load": [
0
],
"activities": [
{
"jobId": "departure",
"type": "departure",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T08:00:00Z",
"end": "2023-05-28T08:00:00Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 0
},
{
"time": {
"arrival": "2023-05-28T08:19:39Z",
"departure": "2023-05-28T08:29:39Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_1",
"type": "pickup",
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"time": {
"start": "2023-05-28T08:19:39Z",
"end": "2023-05-28T08:29:39Z"
}
}
],
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"distance": 9971
},
{
"time": {
"arrival": "2023-05-28T08:36:16Z",
"departure": "2023-05-28T08:46:16Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_2",
"type": "pickup",
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"time": {
"start": "2023-05-28T08:36:16Z",
"end": "2023-05-28T08:46:16Z"
}
}
],
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"distance": 13720
},
{
"time": {
"arrival": "2023-05-28T09:00:18Z",
"departure": "2023-05-28T09:10:18Z"
},
"load": [
3
],
"activities": [
{
"jobId": "Job_3",
"type": "pickup",
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"time": {
"start": "2023-05-28T09:00:18Z",
"end": "2023-05-28T09:10:18Z"
}
}
],
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"distance": 22500
},
{
"time": {
"arrival": "2023-05-28T09:12:08Z",
"departure": "2023-05-28T09:22:08Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_4",
"type": "pickup",
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"time": {
"start": "2023-05-28T09:12:08Z",
"end": "2023-05-28T09:22:08Z"
}
}
],
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"distance": 23786
},
{
"time": {
"arrival": "2023-05-28T09:28:08Z",
"departure": "2023-05-28T09:38:08Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_5",
"type": "pickup",
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"time": {
"start": "2023-05-28T09:28:08Z",
"end": "2023-05-28T09:38:08Z"
}
}
],
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"distance": 26727
},
{
"time": {
"arrival": "2023-05-28T09:47:07Z",
"departure": "2023-05-28T09:57:07Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_6",
"type": "pickup",
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"time": {
"start": "2023-05-28T09:47:07Z",
"end": "2023-05-28T09:57:07Z"
}
}
],
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"distance": 32034
},
{
"time": {
"arrival": "2023-05-28T10:02:58Z",
"departure": "2023-05-28T10:12:58Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_7",
"type": "pickup",
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"time": {
"start": "2023-05-28T10:02:58Z",
"end": "2023-05-28T10:12:58Z"
}
}
],
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"distance": 35564
},
{
"time": {
"arrival": "2023-05-28T10:19:25Z",
"departure": "2023-05-28T10:29:25Z"
},
"load": [
8
],
"activities": [
{
"jobId": "Job_8",
"type": "pickup",
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"time": {
"start": "2023-05-28T10:19:25Z",
"end": "2023-05-28T10:29:25Z"
}
}
],
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"distance": 39588
},
{
"time": {
"arrival": "2023-05-28T10:34:40Z",
"departure": "2023-05-28T10:44:40Z"
},
"load": [
9
],
"activities": [
{
"jobId": "Job_9",
"type": "pickup",
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"time": {
"start": "2023-05-28T10:34:40Z",
"end": "2023-05-28T10:44:40Z"
}
}
],
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"distance": 42402
},
{
"time": {
"arrival": "2023-05-28T10:48:10Z",
"departure": "2023-05-28T10:58:10Z"
},
"load": [
10
],
"activities": [
{
"jobId": "Job_10",
"type": "pickup",
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"time": {
"start": "2023-05-28T10:48:10Z",
"end": "2023-05-28T10:58:10Z"
}
}
],
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"distance": 43986
},
{
"time": {
"arrival": "2023-05-28T11:01:31Z",
"departure": "2023-05-28T11:11:31Z"
},
"load": [
11
],
"activities": [
{
"jobId": "Job_11",
"type": "pickup",
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"time": {
"start": "2023-05-28T11:01:31Z",
"end": "2023-05-28T11:11:31Z"
}
}
],
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"distance": 45585
},
{
"time": {
"arrival": "2023-05-28T11:17:21Z",
"departure": "2023-05-28T11:27:21Z"
},
"load": [
12
],
"activities": [
{
"jobId": "Job_13",
"type": "pickup",
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"time": {
"start": "2023-05-28T11:17:21Z",
"end": "2023-05-28T11:27:21Z"
}
}
],
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"distance": 48285
},
{
"time": {
"arrival": "2023-05-28T11:29:52Z",
"departure": "2023-05-28T11:39:52Z"
},
"load": [
13
],
"activities": [
{
"jobId": "Job_12",
"type": "pickup",
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"time": {
"start": "2023-05-28T11:29:52Z",
"end": "2023-05-28T11:39:52Z"
}
}
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"distance": 49439
},
{
"time": {
"arrival": "2023-05-28T11:57:13Z",
"departure": "2023-05-28T11:57:13Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T11:57:13Z",
"end": "2023-05-28T11:57:13Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 60330
}
],
"statistic": {
"cost": 91.16499999999999,
"distance": 60330,
"duration": 14233,
"times": {
"driving": 6433,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}Problem: Positioned tasks
The following problem involves a tour plan similar to the previous example. However, in this instance, most tasks have a specific position designated by the position.type: "ordered" property and its corresponding value. The exceptions to this are Job_1, Job_2, and Job_13, which have no specified position.
To simplify identifying positioned tasks, the position is also reflected in the ID, such as Job_3_position-10.
Click to expand/collapse the sample JSON
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
20
],
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_2",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
},
{
"id": "Job_3_position-10",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 10
}
}
]
}
},
{
"id": "Job_4_position-9",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 9
}
}
]
}
},
{
"id": "Job_5_position-8",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 8
}
}
]
}
},
{
"id": "Job_6_position-7",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 7
}
}
]
}
},
{
"id": "Job_7_position-6",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 6
}
}
]
}
},
{
"id": "Job_8_position-5",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 5
}
}
]
}
},
{
"id": "Job_9_position-4",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 4
}
}
]
}
},
{
"id": "Job_10_position-3",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 3
}
}
]
}
},
{
"id": "Job_11_position-2",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_12_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_13",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
]
}
]
}
}
]
}
}Solution
In this case, the optimization algorithm assigns positioned tasks first, placing tasks without a position at the end of the tour. For positioned tasks, a lower value indicates a higher priority.
The following section contains the full solution JSON file:
Click to expand/collapse the sample JSON
{
"statistic": {
"cost": 102.16,
"distance": 84191,
"duration": 16432,
"times": {
"driving": 8632,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "small_1",
"typeId": "small",
"stops": [
{
"time": {
"arrival": "2023-05-28T08:00:00Z",
"departure": "2023-05-28T08:00:00Z"
},
"load": [
0
],
"activities": [
{
"jobId": "departure",
"type": "departure",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T08:00:00Z",
"end": "2023-05-28T08:00:00Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 0
},
{
"time": {
"arrival": "2023-05-28T08:18:22Z",
"departure": "2023-05-28T08:28:22Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_12_position-1",
"type": "pickup",
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"time": {
"start": "2023-05-28T08:18:22Z",
"end": "2023-05-28T08:28:22Z"
}
}
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"distance": 11325
},
{
"time": {
"arrival": "2023-05-28T08:32:24Z",
"departure": "2023-05-28T08:42:24Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_11_position-2",
"type": "pickup",
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"time": {
"start": "2023-05-28T08:32:24Z",
"end": "2023-05-28T08:42:24Z"
}
}
],
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"distance": 13451
},
{
"time": {
"arrival": "2023-05-28T08:45:55Z",
"departure": "2023-05-28T08:55:55Z"
},
"load": [
3
],
"activities": [
{
"jobId": "Job_10_position-3",
"type": "pickup",
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"time": {
"start": "2023-05-28T08:45:55Z",
"end": "2023-05-28T08:55:55Z"
}
}
],
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"distance": 15063
},
{
"time": {
"arrival": "2023-05-28T08:58:00Z",
"departure": "2023-05-28T09:08:00Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_9_position-4",
"type": "pickup",
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"time": {
"start": "2023-05-28T08:58:00Z",
"end": "2023-05-28T09:08:00Z"
}
}
],
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"distance": 16157
},
{
"time": {
"arrival": "2023-05-28T09:15:14Z",
"departure": "2023-05-28T09:25:14Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_8_position-5",
"type": "pickup",
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"time": {
"start": "2023-05-28T09:15:14Z",
"end": "2023-05-28T09:25:14Z"
}
}
],
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"distance": 19734
},
{
"time": {
"arrival": "2023-05-28T09:31:59Z",
"departure": "2023-05-28T09:41:59Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_7_position-6",
"type": "pickup",
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"time": {
"start": "2023-05-28T09:31:59Z",
"end": "2023-05-28T09:41:59Z"
}
}
],
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"distance": 23760
},
{
"time": {
"arrival": "2023-05-28T09:48:05Z",
"departure": "2023-05-28T09:58:05Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_6_position-7",
"type": "pickup",
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"time": {
"start": "2023-05-28T09:48:05Z",
"end": "2023-05-28T09:58:05Z"
}
}
],
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"distance": 27317
},
{
"time": {
"arrival": "2023-05-28T10:07:13Z",
"departure": "2023-05-28T10:17:13Z"
},
"load": [
8
],
"activities": [
{
"jobId": "Job_5_position-8",
"type": "pickup",
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"time": {
"start": "2023-05-28T10:07:13Z",
"end": "2023-05-28T10:17:13Z"
}
}
],
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"distance": 32635
},
{
"time": {
"arrival": "2023-05-28T10:23:53Z",
"departure": "2023-05-28T10:33:53Z"
},
"load": [
9
],
"activities": [
{
"jobId": "Job_4_position-9",
"type": "pickup",
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"time": {
"start": "2023-05-28T10:23:53Z",
"end": "2023-05-28T10:33:53Z"
}
}
],
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"distance": 35855
},
{
"time": {
"arrival": "2023-05-28T10:36:34Z",
"departure": "2023-05-28T10:46:34Z"
},
"load": [
10
],
"activities": [
{
"jobId": "Job_3_position-10",
"type": "pickup",
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"time": {
"start": "2023-05-28T10:36:34Z",
"end": "2023-05-28T10:46:34Z"
}
}
],
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"distance": 37299
},
{
"time": {
"arrival": "2023-05-28T11:00:08Z",
"departure": "2023-05-28T11:10:08Z"
},
"load": [
11
],
"activities": [
{
"jobId": "Job_2",
"type": "pickup",
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"time": {
"start": "2023-05-28T11:00:08Z",
"end": "2023-05-28T11:10:08Z"
}
}
],
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"distance": 46053
},
{
"time": {
"arrival": "2023-05-28T11:21:08Z",
"departure": "2023-05-28T11:31:08Z"
},
"load": [
12
],
"activities": [
{
"jobId": "Job_1",
"type": "pickup",
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"time": {
"start": "2023-05-28T11:21:08Z",
"end": "2023-05-28T11:31:08Z"
}
}
],
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"distance": 50696
},
{
"time": {
"arrival": "2023-05-28T12:05:09Z",
"departure": "2023-05-28T12:15:09Z"
},
"load": [
13
],
"activities": [
{
"jobId": "Job_13",
"type": "pickup",
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"time": {
"start": "2023-05-28T12:05:09Z",
"end": "2023-05-28T12:15:09Z"
}
}
],
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"distance": 71681
},
{
"time": {
"arrival": "2023-05-28T12:33:52Z",
"departure": "2023-05-28T12:33:52Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T12:33:52Z",
"end": "2023-05-28T12:33:52Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 84191
}
],
"statistic": {
"cost": 102.16,
"distance": 84191,
"duration": 16432,
"times": {
"driving": 8632,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}Problem: Ordered tasks with first, last, and any
In this scenario, the previously unpositioned tasks (Job_1, Job_2, and Job_13), are assigned the following positions:
Job_1is now assignedposition.type: "any"Job_2is now assignedposition.type: "last"Job_13is now assignedposition.type: "first"
Click to expand/collapse the sample JSON
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
20
],
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1_position-any",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "any"
}
}
]
}
},
{
"id": "Job_2_position-last",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "last"
}
}
]
}
},
{
"id": "Job_3_position-11",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 11
}
}
]
}
},
{
"id": "Job_4_position-10",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 10
}
}
]
}
},
{
"id": "Job_5_position-9",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 9
}
}
]
}
},
{
"id": "Job_6_position-8",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 8
}
}
]
}
},
{
"id": "Job_7_position-7",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 7
}
}
]
}
},
{
"id": "Job_8_position-6",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 6
}
}
]
}
},
{
"id": "Job_9_position-5",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 5
}
}
]
}
},
{
"id": "Job_10_position-4",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 4
}
}
]
}
},
{
"id": "Job_11_position-3",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 3
}
}
]
}
},
{
"id": "Job_12_position-2",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_13_position-first",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "first"
}
}
]
}
}
]
}
}Solution
With specific position type now applied to Job_1, Job_2, and Job_13, the optimization algorithm places these tasks within the tour corresponding to the position type of the task:
Job_1can be served anywhere between tasks whoseposition.typeisfirstandlast.Job_2is served after tasks whoseposition.typeisfirst,ordered, orany, as well as unpositioned tasks, and immediately before returning to the depot.Job_13is served as the first job, immediately after the vehicle departs from the depot, and before anyorderedjobs.
The following figure shows the updated tour and highlights the new positions of Job_1, Job_2, and Job_13:
The following section contains the full solution JSON file:
Click to expand/collapse the sample JSON
{
"statistic": {
"cost": 92.725,
"distance": 63720,
"duration": 14545,
"times": {
"driving": 6745,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "small_1",
"typeId": "small",
"stops": [
{
"time": {
"arrival": "2023-05-28T08:00:00Z",
"departure": "2023-05-28T08:00:00Z"
},
"load": [
0
],
"activities": [
{
"jobId": "departure",
"type": "departure",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T08:00:00Z",
"end": "2023-05-28T08:00:00Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 0
},
{
"time": {
"arrival": "2023-05-28T08:19:30Z",
"departure": "2023-05-28T08:29:30Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_13_position-first",
"type": "pickup",
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"time": {
"start": "2023-05-28T08:19:30Z",
"end": "2023-05-28T08:29:30Z"
}
}
],
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"distance": 12734
},
{
"time": {
"arrival": "2023-05-28T08:32:01Z",
"departure": "2023-05-28T08:42:01Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_12_position-2",
"type": "pickup",
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"time": {
"start": "2023-05-28T08:32:01Z",
"end": "2023-05-28T08:42:01Z"
}
}
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"distance": 13888
},
{
"time": {
"arrival": "2023-05-28T08:46:03Z",
"departure": "2023-05-28T08:56:03Z"
},
"load": [
3
],
"activities": [
{
"jobId": "Job_11_position-3",
"type": "pickup",
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"time": {
"start": "2023-05-28T08:46:03Z",
"end": "2023-05-28T08:56:03Z"
}
}
],
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"distance": 16014
},
{
"time": {
"arrival": "2023-05-28T08:59:34Z",
"departure": "2023-05-28T09:09:34Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_10_position-4",
"type": "pickup",
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"time": {
"start": "2023-05-28T08:59:34Z",
"end": "2023-05-28T09:09:34Z"
}
}
],
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"distance": 17626
},
{
"time": {
"arrival": "2023-05-28T09:11:39Z",
"departure": "2023-05-28T09:21:39Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_9_position-5",
"type": "pickup",
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"time": {
"start": "2023-05-28T09:11:39Z",
"end": "2023-05-28T09:21:39Z"
}
}
],
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"distance": 18720
},
{
"time": {
"arrival": "2023-05-28T09:28:53Z",
"departure": "2023-05-28T09:38:53Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_8_position-6",
"type": "pickup",
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"time": {
"start": "2023-05-28T09:28:53Z",
"end": "2023-05-28T09:38:53Z"
}
}
],
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"distance": 22297
},
{
"time": {
"arrival": "2023-05-28T09:45:38Z",
"departure": "2023-05-28T09:55:38Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_7_position-7",
"type": "pickup",
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"time": {
"start": "2023-05-28T09:45:38Z",
"end": "2023-05-28T09:55:38Z"
}
}
],
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"distance": 26323
},
{
"time": {
"arrival": "2023-05-28T10:01:44Z",
"departure": "2023-05-28T10:11:44Z"
},
"load": [
8
],
"activities": [
{
"jobId": "Job_6_position-8",
"type": "pickup",
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"time": {
"start": "2023-05-28T10:01:44Z",
"end": "2023-05-28T10:11:44Z"
}
}
],
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"distance": 29880
},
{
"time": {
"arrival": "2023-05-28T10:20:52Z",
"departure": "2023-05-28T10:30:52Z"
},
"load": [
9
],
"activities": [
{
"jobId": "Job_5_position-9",
"type": "pickup",
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"time": {
"start": "2023-05-28T10:20:52Z",
"end": "2023-05-28T10:30:52Z"
}
}
],
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"distance": 35198
},
{
"time": {
"arrival": "2023-05-28T10:37:32Z",
"departure": "2023-05-28T10:47:32Z"
},
"load": [
10
],
"activities": [
{
"jobId": "Job_4_position-10",
"type": "pickup",
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"time": {
"start": "2023-05-28T10:37:32Z",
"end": "2023-05-28T10:47:32Z"
}
}
],
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"distance": 38418
},
{
"time": {
"arrival": "2023-05-28T10:50:13Z",
"departure": "2023-05-28T11:00:13Z"
},
"load": [
11
],
"activities": [
{
"jobId": "Job_3_position-11",
"type": "pickup",
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"time": {
"start": "2023-05-28T10:50:13Z",
"end": "2023-05-28T11:00:13Z"
}
}
],
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"distance": 39862
},
{
"time": {
"arrival": "2023-05-28T11:20:47Z",
"departure": "2023-05-28T11:30:47Z"
},
"load": [
12
],
"activities": [
{
"jobId": "Job_1_position-any",
"type": "pickup",
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"time": {
"start": "2023-05-28T11:20:47Z",
"end": "2023-05-28T11:30:47Z"
}
}
],
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"distance": 51041
},
{
"time": {
"arrival": "2023-05-28T11:37:24Z",
"departure": "2023-05-28T11:47:24Z"
},
"load": [
13
],
"activities": [
{
"jobId": "Job_2_position-last",
"type": "pickup",
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"time": {
"start": "2023-05-28T11:37:24Z",
"end": "2023-05-28T11:47:24Z"
}
}
],
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"distance": 54790
},
{
"time": {
"arrival": "2023-05-28T12:02:25Z",
"departure": "2023-05-28T12:02:25Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T12:02:25Z",
"end": "2023-05-28T12:02:25Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 63720
}
],
"statistic": {
"cost": 92.725,
"distance": 63720,
"duration": 14545,
"times": {
"driving": 6745,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}Problem: Task position as soft constraint
When task positions are treated as hard constraints, the optimization algorithm must strictly follow the specified order, which can sometimes cause inefficient routes. However, by using the optimizeTaskPosition objective within the objectives array in the problem specification, you can allow the algorithm to consider task positions while still focusing on efficiency.
This means the algorithm can prioritize creating an efficient route, even if it needs to adjust the order of tasks. This approach leads to more efficient solutions because it introduces a balance between task positions and overall route optimization.
The following snippet provides a sample objectives array to optimize the efficiency of the tour, containing the optimizeTaskPosition objective at the recommended position:
{
"objectives": [
{
"type": "minimizeUnassigned"
},
{
"type": "optimizeTaskPosition"
},
{
"type": "minimizeCost"
}
]
}Note
The
minimizeUnassignedandminimizeCostobjectives are mandatory. For more information, see Use objective functions for specific optimization goals.
Consider the following sample problem that contains job tasks positioned as first, last, any, and ordered:
Click to expand/collapse the sample JSON
{
"fleet": {
"types": [
{
"id": "vehicle_1",
"profile": "vehicle",
"costs": {
"fixed": 22,
"distance": 0.0005,
"time": 0.0019444444444444444
},
"shifts": [
{
"start": {
"time": "2024-06-14T08:00:00+02:00",
"location": {
"lat": 52.531,
"lng": 13.38461
}
},
"end": {
"time": "2024-06-14T18:00:00+02:00",
"location": {
"lat": 52.531,
"lng": 13.38461
}
}
}
],
"capacity": [
30
],
"amount": 2
}
],
"profiles": [
{
"type": "car",
"name": "vehicle"
}
]
},
"plan": {
"jobs": [
{
"id": "job_0_position-first",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.53277,
"lng": 13.40199
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "first"
}
}
]
}
},
{
"id": "job_1_position-1",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.52777,
"lng": 13.40092
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "job_2_position-2",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.534,
"lng": 13.38847
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "job_3_position-3",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.52588,
"lng": 13.3899
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 3
}
}
]
}
},
{
"id": "job_4_position-4",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.53261,
"lng": 13.38863
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 4
}
}
]
}
},
{
"id": "job_5_position-5",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.5325,
"lng": 13.38878
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 5
}
}
]
}
},
{
"id": "job_6_position-6",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.53201,
"lng": 13.37802
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 6
}
}
]
}
},
{
"id": "job_7_position-7",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.52608,
"lng": 13.3892
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 7
}
}
]
}
},
{
"id": "job_8_position-8",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.524,
"lng": 13.3875
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 8
}
}
]
}
},
{
"id": "job_9_position-9",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.52872,
"lng": 13.37579
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 9
}
}
]
}
},
{
"id": "job_10_position-10",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.52373,
"lng": 13.38084
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 10
}
}
]
}
},
{
"id": "job_11_position-11",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.53627,
"lng": 13.37686
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 11
}
}
]
}
},
{
"id": "job_12_position-last",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.5311,
"lng": 13.3999
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "last"
}
}
]
}
},
{
"id": "job_13_position-any",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.53447,
"lng": 13.37006
},
"duration": 300
}
],
"demand": [
1
],
"position": {
"type": "any"
}
}
]
}
}
]
}
}Solution
The following sections compare the solutions for the preceding problem, considering both soft and hard constraints on the position.
To clearly illustrate the contrast between these solutions and effectively highlight the differences in tour order, the routes between stops are depicted as straight lines.
Position as hard constraint
The following figure visualizes the solution for the preceding problem, in which the position was configured as a hard constraint (the problem doesn't have the optimizeTaskPosition objective):
Because position is a hard constraint, the optimization algorithm must adhere to the specified task order rigidly, regardless of potential inefficiencies it might cause. As demonstrated in the previous figure, to maintain the position order, the vehicle is assigned to follow a long and convoluted route, even if better alternatives are available.
Position as soft constraint
By contrast, the following figure visualizes the solution for the preceding problem, but now position is a soft constraint (the problem has the optimizeTaskPosition objective):
In this case, the optimization algorithm treated the position order as a preference, rather than a strict constraint. This, for example, allowed it to serve a task with position.type set to last earlier than a task with position.type set to first—an outcome that would have been impossible with hard constraints. By doing so, the algorithm achieved greater tour efficiency by reducing the total tour distance as well as the overall tour cost.
Problem: Task position and multiple vehicles
Consider an example with more than one vehicle to serve jobs with various position constraints within the tour. In the following problem, the fleet consists of two vehicles belonging to a single vehicle type. The fleet is to perform 13 jobs, with varying position.type settings (ordered, first, last, and any).
Click to expand/collapse the sample JSON
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
7
],
"amount": 2
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1_position-any",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "any"
}
}
]
}
},
{
"id": "Job_2_position-last",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "last"
}
}
]
}
},
{
"id": "Job_3_position-11",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 11
}
}
]
}
},
{
"id": "Job_4_position-10",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 10
}
}
]
}
},
{
"id": "Job_5_position-9",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 9
}
}
]
}
},
{
"id": "Job_6_position-8",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 8
}
}
]
}
},
{
"id": "Job_7_position-7",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 7
}
}
]
}
},
{
"id": "Job_8_position-6",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 6
}
}
]
}
},
{
"id": "Job_9_position-5",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 5
}
}
]
}
},
{
"id": "Job_10_position-4",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 4
}
}
]
}
},
{
"id": "Job_11_position-3",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 3
}
}
]
}
},
{
"id": "Job_12_position-2",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_13_position-first",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "first"
}
}
]
}
}
]
}
}Solution
The solution demonstrates that each vehicle serves its assigned jobs according to its position: starting with tasks assigned to the first position, then moving on to ordered and any tasks, and finally finishing the tour with tasks assigned to the last position type.
The following figure shows the solution visualization for each vehicle, along with the corresponding tour position:
Note
For solutions involving multiple vehicles, jobs are positioned relative to each vehicle's route, rather than in absolute order. This means a task with position
7could be served before a job with position6if they are assigned to different vehicles, as demonstrated in the following figure:
The following section contains the full solution JSON file:
Click to expand/collapse the sample JSON
{
"statistic": {
"cost": 697.76,
"distance": 241984,
"duration": 26211,
"times": {
"driving": 21211,
"serving": 5000,
"waiting": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "6d1dc02e19d6_1",
"typeId": "6d1dc02e19d6",
"stops": [
{
"location": {
"lat": 52.530971,
"lng": 13.384915
},
"time": {
"arrival": "2021-08-27T06:03:00Z",
"departure": "2021-08-27T06:03:00Z"
},
"load": [
9
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
],
"distance": 0
},
{
"location": {
"lat": 52.90926602381726,
"lng": 13.781018586655174
},
"time": {
"arrival": "2021-08-27T06:56:53Z",
"departure": "2021-08-27T07:05:13Z"
},
"load": [
6
],
"activities": [
{
"jobId": "job_9",
"type": "delivery"
}
],
"distance": 11909
},
{
"location": {
"lat": 52.91900693527653,
"lng": 13.92574157985448
},
"time": {
"arrival": "2021-08-27T07:26:14Z",
"departure": "2021-08-27T07:34:34Z"
},
"load": [
3
],
"activities": [
{
"jobId": "job_8",
"type": "delivery"
}
],
"distance": 24698
},
{
"location": {
"lat": 52.73186486317331,
"lng": 13.59405790954721
},
"time": {
"arrival": "2021-08-27T08:19:56Z",
"departure": "2021-08-27T08:28:16Z"
},
"load": [
0
],
"activities": [
{
"jobId": "job_7",
"type": "delivery"
}
],
"distance": 35735
},
{
"location": {
"lat": 52.529953,
"lng": 13.314877
},
"time": {
"arrival": "2021-08-27T09:20:22Z",
"departure": "2021-08-27T09:20:22Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
],
"distance": 43438
}
],
"statistic": {
"cost": 441.36400000000003,
"distance": 163393,
"duration": 11842,
"times": {
"driving": 10342,
"serving": 1500,
"waiting": 0,
"break": 0
}
},
"shiftIndex": 0
},
{
"vehicleId": "b47bb0d26e4c_1",
"typeId": "b47bb0d26e4c",
"stops": [
{
"location": {
"lat": 52.530971,
"lng": 13.384915
},
"time": {
"arrival": "2021-08-27T14:03:00Z",
"departure": "2021-08-27T14:03:00Z"
},
"load": [
6
],
"activities": [
{
"jobId": "departure",
"type": "departure"
}
],
"distance": 0
},
{
"location": {
"lat": 52.469144533572845,
"lng": 13.497412369472364
},
"time": {
"arrival": "2021-08-27T14:35:54Z",
"departure": "2021-08-27T14:44:14Z"
},
"load": [
9
],
"activities": [
{
"jobId": "job_5",
"type": "pickup"
}
],
"distance": 3350
},
{
"location": {
"lat": 52.44927857909315,
"lng": 13.36502844360698
},
"time": {
"arrival": "2021-08-27T15:07:52Z",
"departure": "2021-08-27T15:16:12Z"
},
"load": [
12
],
"activities": [
{
"jobId": "job_3",
"type": "pickup"
}
],
"distance": 12036
},
{
"location": {
"lat": 52.48998701990294,
"lng": 13.286076137075746
},
"time": {
"arrival": "2021-08-27T15:36:17Z",
"departure": "2021-08-27T15:44:37Z"
},
"load": [
15
],
"activities": [
{
"jobId": "job_4",
"type": "pickup"
}
],
"distance": 18658
},
{
"location": {
"lat": 52.53315878386378,
"lng": 13.352999270430129
},
"time": {
"arrival": "2021-08-27T16:04:46Z",
"departure": "2021-08-27T16:13:06Z"
},
"load": [
18
],
"activities": [
{
"jobId": "job_2",
"type": "pickup"
}
],
"distance": 73933
},
{
"location": {
"lat": 52.58136440229602,
"lng": 13.423236627987324
},
"time": {
"arrival": "2021-08-27T16:37:27Z",
"departure": "2021-08-27T16:45:47Z"
},
"load": [
21
],
"activities": [
{
"jobId": "job_1",
"type": "pickup"
}
],
"distance": 91183
},
{
"location": {
"lat": 52.57604629377083,
"lng": 13.488619313215825
},
"time": {
"arrival": "2021-08-27T17:03:41Z",
"departure": "2021-08-27T17:12:01Z"
},
"load": [
18
],
"activities": [
{
"jobId": "job_6",
"type": "delivery"
}
],
"distance": 128474
},
{
"location": {
"lat": 52.55137844164478,
"lng": 13.509316000155945
},
"time": {
"arrival": "2021-08-27T17:25:49Z",
"departure": "2021-08-27T17:34:09Z"
},
"load": [
15
],
"activities": [
{
"jobId": "job_10",
"type": "delivery"
}
],
"distance": 157410
},
{
"location": {
"lat": 52.530971,
"lng": 13.384915
},
"time": {
"arrival": "2021-08-27T18:02:29Z",
"departure": "2021-08-27T18:02:29Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival"
}
],
"distance": 168272
}
],
"statistic": {
"cost": 256.39599999999996,
"distance": 78591,
"duration": 14369,
"times": {
"driving": 10869,
"serving": 3500,
"waiting": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}Problem: Task position and time windows
As the job task position is a hard constraint by default, it can conflict with some other job constraints that are considered as hard in Tour Planning, such as skills, territories, demand, or time windows.
Consider an example in which two jobs are configured with time windows and are assigned with a position:
Job_12:- Positioned as an ordered task within the tour (
position.type: "ordered") with the positionvalueset to2. - Configured with a time window for completion between
08:10:00and08:20:00
- Positioned as an ordered task within the tour (
Job_13:- Positioned as the first task in the tour (
position.type: "first") - Configured with a time window for completion between
08:30:00and08:40:00
- Positioned as the first task in the tour (
The following section contains this configuration within a context of a full problem JSON:
Click to expand/collapse the sample JSON
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
20
],
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1_position-any",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "any"
}
}
]
}
},
{
"id": "Job_2_position-last",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "last"
}
}
]
}
},
{
"id": "Job_3_position-11",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 11
}
}
]
}
},
{
"id": "Job_4_position-10",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 10
}
}
]
}
},
{
"id": "Job_5_position-9",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 9
}
}
]
}
},
{
"id": "Job_6_position-8",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 8
}
}
]
}
},
{
"id": "Job_7_position-7",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 7
}
}
]
}
},
{
"id": "Job_8_position-6",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 6
}
}
]
}
},
{
"id": "Job_9_position-5",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 5
}
}
]
}
},
{
"id": "Job_10_position-4",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 4
}
}
]
}
},
{
"id": "Job_11_position-3",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 3
}
}
]
}
},
{
"id": "Job_12_position-2",
"tasks": {
"pickups": [
{
"places": [
{
"times": [
[
"2023-05-28T08:10:00Z",
"2023-05-28T08:20:00Z"
]
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_13_position-first",
"tasks": {
"pickups": [
{
"places": [
{
"times": [
[
"2023-05-28T08:30:00Z",
"2023-05-28T08:40:00Z"
]
],
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "first"
}
}
]
}
}
]
}
}Solution
As demonstrated in the full solution JSON, the problem resulted in Job_13 being unassigned due to a violation of the time window constraint whose root cause was a misalignment of the job time windows with their required positions in the tour.
Based on the tour plan in the problem, Job_13 must be completed first, as it is positioned as the first task in the tour. Job_12 must be completed after the task that is in the first position, which, in this case, is Job_13. However, the time window for Job_13 is from 08:30:00 to 08:40:00, while the time window for Job_12 is from 08:10:00 to 08:20:00, which means that the time windows of the jobs do not allow for the required sequencing of the tasks based on their positions.
In this case, to avoid unassigned tasks in the tour, either extend their time windows or change the task positions.
The following section contains the full solution JSON file:
Click to expand/collapse the sample JSON
{
"statistic": {
"cost": 88.63,
"distance": 61157,
"duration": 13726,
"times": {
"driving": 6526,
"serving": 7200,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "small_1",
"typeId": "small",
"stops": [
{
"time": {
"arrival": "2023-05-28T08:00:00Z",
"departure": "2023-05-28T08:00:00Z"
},
"load": [
0
],
"activities": [
{
"jobId": "departure",
"type": "departure",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T08:00:00Z",
"end": "2023-05-28T08:00:00Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 0
},
{
"time": {
"arrival": "2023-05-28T08:18:22Z",
"departure": "2023-05-28T08:28:22Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_12_position-2",
"type": "pickup",
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"time": {
"start": "2023-05-28T08:18:22Z",
"end": "2023-05-28T08:28:22Z"
}
}
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"distance": 11325
},
{
"time": {
"arrival": "2023-05-28T08:32:24Z",
"departure": "2023-05-28T08:42:24Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_11_position-3",
"type": "pickup",
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"time": {
"start": "2023-05-28T08:32:24Z",
"end": "2023-05-28T08:42:24Z"
}
}
],
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"distance": 13451
},
{
"time": {
"arrival": "2023-05-28T08:45:55Z",
"departure": "2023-05-28T08:55:55Z"
},
"load": [
3
],
"activities": [
{
"jobId": "Job_10_position-4",
"type": "pickup",
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"time": {
"start": "2023-05-28T08:45:55Z",
"end": "2023-05-28T08:55:55Z"
}
}
],
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"distance": 15063
},
{
"time": {
"arrival": "2023-05-28T08:58:00Z",
"departure": "2023-05-28T09:08:00Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_9_position-5",
"type": "pickup",
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"time": {
"start": "2023-05-28T08:58:00Z",
"end": "2023-05-28T09:08:00Z"
}
}
],
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"distance": 16157
},
{
"time": {
"arrival": "2023-05-28T09:15:14Z",
"departure": "2023-05-28T09:25:14Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_8_position-6",
"type": "pickup",
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"time": {
"start": "2023-05-28T09:15:14Z",
"end": "2023-05-28T09:25:14Z"
}
}
],
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"distance": 19734
},
{
"time": {
"arrival": "2023-05-28T09:31:59Z",
"departure": "2023-05-28T09:41:59Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_7_position-7",
"type": "pickup",
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"time": {
"start": "2023-05-28T09:31:59Z",
"end": "2023-05-28T09:41:59Z"
}
}
],
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"distance": 23760
},
{
"time": {
"arrival": "2023-05-28T09:48:05Z",
"departure": "2023-05-28T09:58:05Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_6_position-8",
"type": "pickup",
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"time": {
"start": "2023-05-28T09:48:05Z",
"end": "2023-05-28T09:58:05Z"
}
}
],
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"distance": 27317
},
{
"time": {
"arrival": "2023-05-28T10:07:13Z",
"departure": "2023-05-28T10:17:13Z"
},
"load": [
8
],
"activities": [
{
"jobId": "Job_5_position-9",
"type": "pickup",
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"time": {
"start": "2023-05-28T10:07:13Z",
"end": "2023-05-28T10:17:13Z"
}
}
],
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"distance": 32635
},
{
"time": {
"arrival": "2023-05-28T10:23:53Z",
"departure": "2023-05-28T10:33:53Z"
},
"load": [
9
],
"activities": [
{
"jobId": "Job_4_position-10",
"type": "pickup",
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"time": {
"start": "2023-05-28T10:23:53Z",
"end": "2023-05-28T10:33:53Z"
}
}
],
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"distance": 35855
},
{
"time": {
"arrival": "2023-05-28T10:36:34Z",
"departure": "2023-05-28T10:46:34Z"
},
"load": [
10
],
"activities": [
{
"jobId": "Job_3_position-11",
"type": "pickup",
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"time": {
"start": "2023-05-28T10:36:34Z",
"end": "2023-05-28T10:46:34Z"
}
}
],
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"distance": 37299
},
{
"time": {
"arrival": "2023-05-28T11:07:08Z",
"departure": "2023-05-28T11:17:08Z"
},
"load": [
11
],
"activities": [
{
"jobId": "Job_1_position-any",
"type": "pickup",
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"time": {
"start": "2023-05-28T11:07:08Z",
"end": "2023-05-28T11:17:08Z"
}
}
],
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"distance": 48478
},
{
"time": {
"arrival": "2023-05-28T11:23:45Z",
"departure": "2023-05-28T11:33:45Z"
},
"load": [
12
],
"activities": [
{
"jobId": "Job_2_position-last",
"type": "pickup",
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"time": {
"start": "2023-05-28T11:23:45Z",
"end": "2023-05-28T11:33:45Z"
}
}
],
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"distance": 52227
},
{
"time": {
"arrival": "2023-05-28T11:48:46Z",
"departure": "2023-05-28T11:48:46Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T11:48:46Z",
"end": "2023-05-28T11:48:46Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 61157
}
],
"statistic": {
"cost": 88.63,
"distance": 61157,
"duration": 13726,
"times": {
"driving": 6526,
"serving": 7200,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"shiftIndex": 0
}
],
"unassigned": [
{
"jobId": "Job_13_position-first",
"reasons": [
{
"code": "TIME_WINDOW_CONSTRAINT",
"description": "cannot be assigned due to violation of time window",
"details": [
{
"vehicleId": "small_1",
"shiftIndex": 0
}
]
}
]
}
]
}Problem: Task position and relations
Some use cases require modeling a problem where tasks must be performed in a specific order, known as relations. To ensure these specific rules are followed in Tour Planning, relations always take precedence over the position setting.
For example, consider a sample sequence relation:
"relations": [
{
"type": "sequence",
"jobs": [
"Job_9_position-5",
"Job_10_position-4",
"Job_11_position-3",
"Job_13_position-first",
"Job_12_position-2"
],
"vehicleId": "small_1"
}
] This relation is particularly useful during tour replanning. When changes occur on the road, you can use the sequence relation to reinsert all locations as they were originally planned. The remaining part of the journey is then recalculated.
The following problem contains jobs with various position settings and a sequence relation from the previous example that ensures some tasks are performed in a specified order regardless of their position settings:
Note
While this sample problem shows how task position can interact with tour properties or constraints, combining
relationsandpositionfeatures is not recommended. When combined, these features might provide overlapping or conflicting information to the optimization algorithm, which can result in unassigned jobs or other unexpected results.
Click to expand/collapse the sample JSON
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
20
],
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1_position-any",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "any"
}
}
]
}
},
{
"id": "Job_2_position-last",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "last"
}
}
]
}
},
{
"id": "Job_3_position-11",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 11
}
}
]
}
},
{
"id": "Job_4_position-10",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 10
}
}
]
}
},
{
"id": "Job_5_position-9",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 9
}
}
]
}
},
{
"id": "Job_6_position-8",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 8
}
}
]
}
},
{
"id": "Job_7_position-7",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 7
}
}
]
}
},
{
"id": "Job_8_position-6",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 6
}
}
]
}
},
{
"id": "Job_9_position-5",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 5
}
}
]
}
},
{
"id": "Job_10_position-4",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 4
}
}
]
}
},
{
"id": "Job_11_position-3",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 3
}
}
]
}
},
{
"id": "Job_12_position-2",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_13_position-first",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "first"
}
}
]
}
}
],
"relations": [
{
"type": "sequence",
"jobs": [
"Job_9_position-5",
"Job_10_position-4",
"Job_11_position-3",
"Job_13_position-first",
"Job_12_position-2"
],
"vehicleId": "small_1"
}
]
}
}Solution
As the solution visualization demonstrates, the sequence relation takes precedence over the task position setting. In this specific solution, the tasks specified in the sequence relation are served at the beginning of the tour, while the remaining tasks are served according to their position type and value:
The following section provides the full solution JSON file:
Click to expand/collapse the sample JSON
{
"statistic": {
"cost": 93.515,
"distance": 62385,
"duration": 14703,
"times": {
"driving": 6903,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "small_1",
"typeId": "small",
"stops": [
{
"time": {
"arrival": "2023-05-28T08:00:00Z",
"departure": "2023-05-28T08:00:00Z"
},
"load": [
0
],
"activities": [
{
"jobId": "departure",
"type": "departure",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T08:00:00Z",
"end": "2023-05-28T08:00:00Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 0
},
{
"time": {
"arrival": "2023-05-28T08:19:04Z",
"departure": "2023-05-28T08:29:04Z"
},
"load": [
1
],
"activities": [
{
"jobId": "Job_9_position-5",
"type": "pickup",
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"time": {
"start": "2023-05-28T08:19:04Z",
"end": "2023-05-28T08:29:04Z"
}
}
],
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"distance": 9863
},
{
"time": {
"arrival": "2023-05-28T08:32:34Z",
"departure": "2023-05-28T08:42:34Z"
},
"load": [
2
],
"activities": [
{
"jobId": "Job_10_position-4",
"type": "pickup",
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"time": {
"start": "2023-05-28T08:32:34Z",
"end": "2023-05-28T08:42:34Z"
}
}
],
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"distance": 11447
},
{
"time": {
"arrival": "2023-05-28T08:45:55Z",
"departure": "2023-05-28T08:55:55Z"
},
"load": [
3
],
"activities": [
{
"jobId": "Job_11_position-3",
"type": "pickup",
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"time": {
"start": "2023-05-28T08:45:55Z",
"end": "2023-05-28T08:55:55Z"
}
}
],
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"distance": 13046
},
{
"time": {
"arrival": "2023-05-28T09:01:45Z",
"departure": "2023-05-28T09:11:45Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_13_position-first",
"type": "pickup",
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"time": {
"start": "2023-05-28T09:01:45Z",
"end": "2023-05-28T09:11:45Z"
}
}
],
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"distance": 15746
},
{
"time": {
"arrival": "2023-05-28T09:14:16Z",
"departure": "2023-05-28T09:24:16Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_12_position-2",
"type": "pickup",
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"time": {
"start": "2023-05-28T09:14:16Z",
"end": "2023-05-28T09:24:16Z"
}
}
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"distance": 16900
},
{
"time": {
"arrival": "2023-05-28T09:31:31Z",
"departure": "2023-05-28T09:41:31Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_8_position-6",
"type": "pickup",
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"time": {
"start": "2023-05-28T09:31:31Z",
"end": "2023-05-28T09:41:31Z"
}
}
],
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"distance": 20962
},
{
"time": {
"arrival": "2023-05-28T09:48:16Z",
"departure": "2023-05-28T09:58:16Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_7_position-7",
"type": "pickup",
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"time": {
"start": "2023-05-28T09:48:16Z",
"end": "2023-05-28T09:58:16Z"
}
}
],
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"distance": 24988
},
{
"time": {
"arrival": "2023-05-28T10:04:22Z",
"departure": "2023-05-28T10:14:22Z"
},
"load": [
8
],
"activities": [
{
"jobId": "Job_6_position-8",
"type": "pickup",
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"time": {
"start": "2023-05-28T10:04:22Z",
"end": "2023-05-28T10:14:22Z"
}
}
],
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"distance": 28545
},
{
"time": {
"arrival": "2023-05-28T10:23:30Z",
"departure": "2023-05-28T10:33:30Z"
},
"load": [
9
],
"activities": [
{
"jobId": "Job_5_position-9",
"type": "pickup",
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"time": {
"start": "2023-05-28T10:23:30Z",
"end": "2023-05-28T10:33:30Z"
}
}
],
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"distance": 33863
},
{
"time": {
"arrival": "2023-05-28T10:40:10Z",
"departure": "2023-05-28T10:50:10Z"
},
"load": [
10
],
"activities": [
{
"jobId": "Job_4_position-10",
"type": "pickup",
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"time": {
"start": "2023-05-28T10:40:10Z",
"end": "2023-05-28T10:50:10Z"
}
}
],
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"distance": 37083
},
{
"time": {
"arrival": "2023-05-28T10:52:51Z",
"departure": "2023-05-28T11:02:51Z"
},
"load": [
11
],
"activities": [
{
"jobId": "Job_3_position-11",
"type": "pickup",
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"time": {
"start": "2023-05-28T10:52:51Z",
"end": "2023-05-28T11:02:51Z"
}
}
],
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"distance": 38527
},
{
"time": {
"arrival": "2023-05-28T11:23:25Z",
"departure": "2023-05-28T11:33:25Z"
},
"load": [
12
],
"activities": [
{
"jobId": "Job_1_position-any",
"type": "pickup",
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"time": {
"start": "2023-05-28T11:23:25Z",
"end": "2023-05-28T11:33:25Z"
}
}
],
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"distance": 49706
},
{
"time": {
"arrival": "2023-05-28T11:40:02Z",
"departure": "2023-05-28T11:50:02Z"
},
"load": [
13
],
"activities": [
{
"jobId": "Job_2_position-last",
"type": "pickup",
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"time": {
"start": "2023-05-28T11:40:02Z",
"end": "2023-05-28T11:50:02Z"
}
}
],
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"distance": 53455
},
{
"time": {
"arrival": "2023-05-28T12:05:03Z",
"departure": "2023-05-28T12:05:03Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T12:05:03Z",
"end": "2023-05-28T12:05:03Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 62385
}
],
"statistic": {
"cost": 93.515,
"distance": 62385,
"duration": 14703,
"times": {
"driving": 6903,
"serving": 7800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"shiftIndex": 0
}
]
}Problem: Task position and multi-jobs
In tour planning, the concept of a multi-job encompasses scenarios where up to three pickup and delivery tasks are defined within a single job. In Tour Planning, the task position feature cannot be used to change the order of pickups and deliveries in multi-job assignments. The following scenario illustrates a potential conflict arising from differences in position settings between single-job tasks and those within a multi-job.
Consider the following snippet from a sample problem:
[
{
"id": "Job_X-delivery-2",
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_Y-pickup-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_Z-pickup-2-delivery-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"position": {
"type": "ordered",
"value": 2
},
"demand": [
1
]
}
],
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.457629,
"lng": 13.323742
},
"duration": 600
}
],
"position": {
"type": "ordered",
"value": 1
},
"demand": [
1
]
}
]
}
}
]In the preceding snippet, the position of the delivery/pickup tasks within Job_Z is reversed compared to the remaining jobs. The delivery task has a position of 1, indicating it should be executed before the pickup task, which has a position of 2.
As a result, the optimization algorithm left Job_Z unassigned, with the following message:
{
"unassigned": [
{
"jobId": "Job_Z-pickup-2-delivery-1",
"reasons": [
{
"code": "TOUR_ORDER_CONSTRAINT",
"description": "cannot be assigned due to tour order constraint"
}
]
}
]
}The job was not assigned to the tour because of a TOUR_ORDER_CONSTRAINT violation. This means that the order of jobs within the tour does not allow for Job_Z to be assigned due to pickup task needing to occur before the delivery task, which cannot be fulfilled within the existing tour sequence.
To avoid unassigned tours, adjust the order of pickup/delivery tasks in multi-job assignments to facilitate its assignment to tours and prevent unassigned tours.
Problem: Task position and priority
The position of a job defines its possible order but does not affect its priority within the tour, for example, in case of a lack of capacity. The following example demonstrates the difference between position and priority:
Click to expand/collapse the sample JSON
{
"fleet": {
"types": [
{
"id": "small",
"profile": "car",
"costs": {
"fixed": 20,
"distance": 0,
"time": 0.005
},
"shifts": [
{
"start": {
"time": "2023-05-28T08:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
},
"end": {
"time": "2023-05-28T16:00:00Z",
"location": {
"lat": 52.50935,
"lng": 13.41997
}
}
}
],
"capacity": [
8
],
"amount": 1
}
],
"profiles": [
{
"type": "car",
"name": "car"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1_D_position-2",
"priority":1,
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_2_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.534553,
"lng": 13.519429
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_3_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.482275,
"lng": 13.502456
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_4_D_position-2",
"priority":1,
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_5_P_position-1",
"priority":2,
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.463341,
"lng": 13.49061
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_6_D_position-2",
"priority":1,
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_7_D_position-2",
"priority":1,
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 2
}
}
]
}
},
{
"id": "Job_8_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_9_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.446407,
"lng": 13.36047
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_10_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_11_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"duration": 600
}
],
"demand": [
1
],
"position": {
"type": "ordered",
"value": 1
}
}
]
}
},
{
"id": "Job_12_P_position-1",
"tasks": {
"pickups": [
{
"places": [
{
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"duration": 600
}
],
"position": {
"type": "ordered",
"value": 1
},
"demand": [
1
]
}
]
}
}
]
}
}In the given scenario, delivery tasks are designated with a position.type: ordered value of 2, whereas pickup tasks hold a corresponding position value of 1. This hierarchy suggests that pickup tasks should be prioritized over deliveries in cases where insufficient capacity prevents the fleet from serving all jobs, as demonstrated in the preceding problem in which the capacity setting is limited to 8 while the number of jobs to serve is 12.
However, the problem JSON reveals that delivery tasks are additionally assigned a priority value of 1, superseding the positional arrangement.
Solution
In the following solution, the optimization algorithm left four jobs unassigned, as the following figure demonstrates:
All unassigned jobs were configured with a position value of 1. However, the algorithm prioritized the high-priority delivery jobs, despite their lower position value (2). This highlights the precedence of the priority setting over the position in use cases where there is insufficient capacity to serve all jobs.
The following section provides the full solution JSON file:
Click to expand/collapse the sample JSON
{
"statistic": {
"cost": 73.91,
"distance": 57009,
"duration": 10782,
"times": {
"driving": 5982,
"serving": 4800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"tours": [
{
"vehicleId": "small_1",
"typeId": "small",
"stops": [
{
"time": {
"arrival": "2023-05-28T08:00:00Z",
"departure": "2023-05-28T08:00:00Z"
},
"load": [
4
],
"activities": [
{
"jobId": "departure",
"type": "departure",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T08:00:00Z",
"end": "2023-05-28T08:00:00Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 0
},
{
"time": {
"arrival": "2023-05-28T08:18:12Z",
"departure": "2023-05-28T08:28:12Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_12_P_position-1",
"type": "pickup",
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"time": {
"start": "2023-05-28T08:18:12Z",
"end": "2023-05-28T08:28:12Z"
}
}
],
"location": {
"lat": 52.458232,
"lng": 13.338698
},
"distance": 11325
},
{
"time": {
"arrival": "2023-05-28T08:32:14Z",
"departure": "2023-05-28T08:42:14Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_11_P_position-1",
"type": "pickup",
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"time": {
"start": "2023-05-28T08:32:14Z",
"end": "2023-05-28T08:42:14Z"
}
}
],
"location": {
"lat": 52.441913,
"lng": 13.339028
},
"distance": 13451
},
{
"time": {
"arrival": "2023-05-28T08:45:45Z",
"departure": "2023-05-28T08:55:45Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_10_P_position-1",
"type": "pickup",
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"time": {
"start": "2023-05-28T08:45:45Z",
"end": "2023-05-28T08:55:45Z"
}
}
],
"location": {
"lat": 52.440807,
"lng": 13.351399
},
"distance": 15063
},
{
"time": {
"arrival": "2023-05-28T09:02:39Z",
"departure": "2023-05-28T09:12:39Z"
},
"load": [
8
],
"activities": [
{
"jobId": "Job_8_P_position-1",
"type": "pickup",
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"time": {
"start": "2023-05-28T09:02:39Z",
"end": "2023-05-28T09:12:39Z"
}
}
],
"location": {
"lat": 52.458414,
"lng": 13.392079
},
"distance": 18904
},
{
"time": {
"arrival": "2023-05-28T09:19:24Z",
"departure": "2023-05-28T09:29:24Z"
},
"load": [
7
],
"activities": [
{
"jobId": "Job_7_D_position-2",
"type": "delivery",
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"time": {
"start": "2023-05-28T09:19:24Z",
"end": "2023-05-28T09:29:24Z"
}
}
],
"location": {
"lat": 52.447476,
"lng": 13.433062
},
"distance": 22930
},
{
"time": {
"arrival": "2023-05-28T09:35:30Z",
"departure": "2023-05-28T09:45:30Z"
},
"load": [
6
],
"activities": [
{
"jobId": "Job_6_D_position-2",
"type": "delivery",
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"time": {
"start": "2023-05-28T09:35:30Z",
"end": "2023-05-28T09:45:30Z"
}
}
],
"location": {
"lat": 52.434003,
"lng": 13.466142
},
"distance": 26487
},
{
"time": {
"arrival": "2023-05-28T09:59:55Z",
"departure": "2023-05-28T10:09:55Z"
},
"load": [
5
],
"activities": [
{
"jobId": "Job_4_D_position-2",
"type": "delivery",
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"time": {
"start": "2023-05-28T09:59:55Z",
"end": "2023-05-28T10:09:55Z"
}
}
],
"location": {
"lat": 52.473537,
"lng": 13.505414
},
"distance": 34329
},
{
"time": {
"arrival": "2023-05-28T10:32:43Z",
"departure": "2023-05-28T10:42:43Z"
},
"load": [
4
],
"activities": [
{
"jobId": "Job_1_D_position-2",
"type": "delivery",
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"time": {
"start": "2023-05-28T10:32:43Z",
"end": "2023-05-28T10:42:43Z"
}
}
],
"location": {
"lat": 52.56182,
"lng": 13.497167
},
"distance": 47136
},
{
"time": {
"arrival": "2023-05-28T10:59:42Z",
"departure": "2023-05-28T10:59:42Z"
},
"load": [
0
],
"activities": [
{
"jobId": "arrival",
"type": "arrival",
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"time": {
"start": "2023-05-28T10:59:42Z",
"end": "2023-05-28T10:59:42Z"
}
}
],
"location": {
"lat": 52.50935,
"lng": 13.41997
},
"distance": 57009
}
],
"statistic": {
"cost": 73.91,
"distance": 57009,
"duration": 10782,
"times": {
"driving": 5982,
"serving": 4800,
"waiting": 0,
"stopping": 0,
"break": 0
}
},
"shiftIndex": 0
}
],
"unassigned": [
{
"jobId": "Job_2_P_position-1",
"reasons": [
{
"code": "TOUR_ORDER_CONSTRAINT",
"description": "cannot be assigned due to tour order constraint"
}
]
},
{
"jobId": "Job_5_P_position-1",
"reasons": [
{
"code": "TOUR_ORDER_CONSTRAINT",
"description": "cannot be assigned due to tour order constraint"
}
]
},
{
"jobId": "Job_9_P_position-1",
"reasons": [
{
"code": "TOUR_ORDER_CONSTRAINT",
"description": "cannot be assigned due to tour order constraint"
}
]
},
{
"jobId": "Job_3_P_position-1",
"reasons": [
{
"code": "TOUR_ORDER_CONSTRAINT",
"description": "cannot be assigned due to tour order constraint"
}
]
}
]
}Next steps
- For more information about formulating problems in the HERE Tour Planning API, see Problem.
- For an in-depth exploration of the HERE Tour Planning API methods, endpoints, and parameters, see the API Reference.
Updated 29 days ago
