Skip to main content

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:

  1. first_in_trip: The dropoff node must be served first by the assigned vehicle.
  2. last_in_trip: The dropoff node must be served last by the assigned vehicle.
info

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_trip must be the first dropoff.
  • A node labeled last_in_trip must be the last dropoff.
  • Each vehicle can handle at most one first_in_trip node and at most one last_in_trip node.

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.

note

Groups are ignored in prebook (PDP mode) of the Stateless API.

Run In Postman

Please see example of prioritized dropoff below:

See JSON payload
Prioritize drop off in CVRPTW mode

{
"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:

  1. Nodes with groups in groups_order: These nodes are sorted by their priority values. Higher priority values appear earlier.
  2. Nodes without groups in groups_order: These nodes have the lowest priority and appear after all nodes in point 1.
  3. Nodes with groups in groups_order but with None priority: The order of these nodes is undefined and they may appear anywhere in the sequence.
warning

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.

warning

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
}
...
}
tip

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_trip Nodes: Assigned groups: ["high_priority"] and demand: { "high_priority": 1 }.
  • last_in_trip Nodes: Assigned groups: ["low_priority"] and demand: { "low_priority": 1 }.
  • Vehicle Configuration: Assigned capacity: { "high_priority": 1, "low_priority": 1 }.