Prioritization of drop off or pickup
Significance for Planners
In logistics and route planning, certain stops often have strict sequencing requirements irrespective of the geographical efficiency. For example:
- First-in-trip: Urgent deliveries or pickups that must be handled immediately upon the vehicle's departure.
- Last-in-trip: Returns, waste collection, or items that need to be brought back to the depot at the end of the run.
By enforcing these priorities, planners can ensure operational compliance, such as loading logic (Last-In-First-Out) or service level agreements (SLAs) for VIP customers.
Order Prioritization in Integration API
This section explains how the Integration API (Logistics) automatically manages order prioritization concepts like first_in_trip and last_in_trip by leveraging the underlying stateless solver capabilities.
Overview
Bookings in the Integration API may specify an order_position:
first_in_trip: The dropoff node must be served first by the assigned vehicle.last_in_trip: The dropoff node must be served last by the assigned vehicle.
This prioritization logic applies to both CVRPTW and PDP modes. For more information on the differences between these modes, please refer to the Scheduling Modes documentation.
Configuration
This feature is controlled by the booking_order_prioritization parameter in the logistics_api_settings.
disabled(Default): Prioritization logic is turned off.strict: Enforces strict ordering and limits.non_strict: Enables prioritization but may allow soft constraints.
Strict Mode Behavior
In strict mode, the system enforces the following constraints:
- A node labeled
first_in_tripmust be the first dropoff. - A node labeled
last_in_tripmust be the last dropoff. - Each vehicle can handle at most one
first_in_tripnode and at most onelast_in_tripnode.
Technical Implementation (Stateless API)
The Stateless API supports prioritization of drop off or pickup deliveries in prebook_cvrptw mode.
Prioritization of drop off or pickup points is achieved by using groups ordering with each pair of drop off and pickups belonging to that group.
The Integration API uses these underlying mechanisms to achieve the behavior described above.
Groups are ignored in prebook (PDP mode) of the Stateless API.
Please see example of prioritized dropoff below:
See JSON payload
{
"current_time": "2024-07-10T08:00:00+00:00",
"engine_settings": {
"calculation_parameters": {
"calculations_mode": "sync",
"scheduling_mode": "prebook_cvrptw"
},
"model_parameters": {
"mixed_fleet": false,
"optimize_quantity": "total_time",
"groups_order": {
// Create group for priority nodes
"high_priority": 0
}
},
"routing_engine": {
"batch_matrix_size": 250,
"continue_straight": true,
"curb": false,
"key": "<routing_key>",
"make_depot_zero": true,
"road_network": "van",
"routing_engine_name": "osrme",
"speed": null,
"time_factor": 1,
"url": "http://mapbox-osrm-proxy",
"use_speed_in_routing": false
},
"solver_parameters": {}
},
"nodes": [
{
"booking_uid": "b00c0000-2024-0421-0616-000000000001",
"close_time_ts": "2026-01-03T09:00:00+00:00",
"close_time_ts_dynamic": "2026-01-03T09:00:00+00:00",
"demand": {
"units": 10
},
"end_of_trip": false,
"geofence_ids": [],
// Assign this node to a prioritized group
"groups": ["high_priority"],
"lat": 1.280097,
"lon": 103.889129,
"lifo_order_check": false,
"lifo_order_penalty": null,
"location_name": "Dropoff location 1",
"matrix_timestamp": "2024-07-10T08:00:00+00:00",
"max_slack": null,
"node_type": "dropoff",
"open_time_ts": "2026-01-01T00:00:00+00:00",
"service_time": 360.0,
"trip_cost": 0.0,
"uid": "f0de0001-2024-0731-88ad-05ddd46ce72d",
"vehicle_characteristics": {}
},
{
"booking_uid": "b00c0000-2024-0421-0616-000000000002",
"close_time_ts": "2026-01-03T09:00:00+00:00",
"close_time_ts_dynamic": "2026-01-03T09:00:00+00:00",
"demand": {
"units": 10
},
"end_of_trip": false,
"geofence_ids": [],
"groups": [],
"lat": 1.290097,
"lon": 103.989129,
"lifo_order_check": false,
"lifo_order_penalty": null,
"location_name": "Dropoff location 2",
"matrix_timestamp": "2024-07-10T08:00:00+00:00",
"max_slack": null,
"node_type": "dropoff",
"open_time_ts": "2026-01-01T00:00:00+00:00",
"service_time": 360.0,
"trip_cost": 0.0,
"uid": "f0de0001-2024-0731-88ad-05ddd46ce74d",
"vehicle_characteristics": {}
},
{
"close_time_ts": "2026-01-05T00:35:00+00:00",
"close_time_ts_dynamic": "2026-01-05T00:35:00+00:00",
"demand": {
"units": 0
},
"lat": 1.290662,
"lon": 103.943407,
"location_name": "Office",
"max_trip_duration": 0,
"node_type": "point",
"open_time_ts": "2026-01-01T00:00:00+00:00",
"end_of_trip": true,
"service_time": 0.0,
"trip_cost": 0,
"weight": 0.0,
"uid": "dc1e0000-2024-0731-b23d-5206f1c21d09"
}
],
"vehicles": [
{
"agent_id": "dc1e0000-2024-0731-aaaa-5206f1c21d09",
"capacity": {
"units": 999
},
"characteristics": {},
"partial_route": ["dc1e0000-2024-0731-b23d-5206f1c21d09"],
"completed_nodes": [],
"end_time": "2026-01-10T14:59:59+00:00",
"lat": 1.290662,
"lon": 103.943407,
"routing_engine": {
"batch_matrix_size": 250,
"curb": false,
"key": "routing_key",
"make_depot_zero": true,
"road_network": "van",
"routing_engine_name": "osrme",
"speed": null,
"time_factor": 1,
"url": "http://mapbox-osrm-proxy",
"use_speed_in_routing": false
},
"service_number": "Van 2 - instance",
"start_time": "2024-01-01T00:00:00+00:00",
"vehicle_cost": 1000.0
}
]
}
Rules for applying priorities for the nodes
Node ordering depends on their assigned groups and the groups_order configuration:
- Nodes with groups in
groups_order: These nodes are sorted by their priority values. Higher priority values appear earlier. - Nodes without groups in
groups_order: These nodes have the lowest priority and appear after all nodes in point 1. - Nodes with groups in
groups_orderbut withNonepriority: The order of these nodes is undefined and they may appear anywhere in the sequence.
Prioritization logic does not affect point nodes; they are ignored.
Technical details for the order priority implementation
Given this configuration
"model_parameters": {
"mixed_fleet": false,
"optimize_quantity": "total_time",
"groups_order": {
// Create group for priority nodes
"high_priority": 0,
"mid_priority": 1,
"low_priority": 2
}
}
In a given vehicle, nodes are sequenced in ascending order based on their priority number. This means nodes with lower priority numbers appear earlier in the sequence.
A single vehicle can contain multiple high-priority nodes.
Nodes without a priority number are not subject to this ordering rule and can be placed anywhere in the vehicle's sequence.
For prebook_cvrptw mode to function correctly, each vehicle must have a partial_route defined that starts with the depot node's uid. If this is not set, the vehicle may not start at the depot, which can lead to unexpected routing and prioritization results.
Modelling only one high priotity or low priority stop per vehicle
Using groups in the example might assign multiple orders of the same priority to the same vehicle, which may not be desirable in certain situations. To ensure a vehicle receives only a single high or low priority order, you can adjust the demand field.
To specify demand types and their values for nodes, and corresponding capacity types and values for vehicles, use the demand field for nodes and the capacity field for vehicles. For example, a node definition might include:
{
"uid": "1318f77b-b424-421f-83ff-54fe4b315b22",
...
"demand": {
"CBCM": 1771100,
"WEIGHT": 645,
"lowest_priority": 1
},
...
And a vehicle definition might include:
{
"agent_id": "Truck_10W",
"capacity": {
"CBCM": 7000000,
"WEIGHT": 33,
"lowest_priority": 1
}
...
}
By adjusting the capacity value for a specific priority type, it is possible to assign multiple (no more than the value of capacity value) orders of that same priority to a vehicle.
Underlying Implementation Details
The Integration API achieves priority behavior by automatically generating a Stateless API payload that uses the group prioritization and capacity constraints.
The default prioritization rule corresponds to:
DEFAULT_BOOKING_ORDER_PRIORITIZATION_RULE = dict(
high_priority=0, # Corresponds to first_in_trip
no_priority=1, # Corresponds to standard bookings
low_priority=2, # Corresponds to last_in_trip
)
To enforce the strict "one per vehicle" limit, the API modifies the demand and capacity attributes as follows:
first_in_tripNodes: Assignedgroups: ["high_priority"]anddemand: { "high_priority": 1 }.last_in_tripNodes: Assignedgroups: ["low_priority"]anddemand: { "low_priority": 1 }.- Vehicle Configuration: Assigned
capacity: { "high_priority": 1, "low_priority": 1 }.