Grouping locations and multi-orders

To reduce the time to complete the route, you can combine some orders. You can combine them manually by grouping locations. If orders are located at the same address (for example, a shopping mall or an apartment building), they can be automatically combined into one multi-order. If there are several closely located orders on a route, you can set requirements for them to be visited by the same courier or within the same route.

Order grouping

When you build routes, you often need to deliver multiple orders by one courier. It might be important that all orders are completed by one vehicle. For example, if you have a chain of delivery, where your courier needs to take an order to a point, get the delivery documents there, and then bring them to the office.

You can group orders in RouteQ using the location_groups option. Orders are added to the group by their IDs. The order sequence that's set in the group doesn't matter: when planning, the algorithm can arrange the orders in any sequence.

You can specify a name for each order group. This does not affect routing, but allows you to assign convenient names to groups.

Group properties for setting up planning:

  • options.location_groups.solid: The true value specifies that the group can't be broken up: orders in it must be delivered without other orders between them. Order sequence within the group isn't fixed. For example, this property is often used if a cargo taxi has to deliver cargo from one point to another, and a new order can't be added to the vehicle before unloading. Default value: false.

  • options.location_groups.dependent: The true value specifies that the group is indivisible: all orders must either be completed or (if at least one order can't be delivered) set to unassigned. Default value: false.

Example 1

In this sample, two vehicles carry orders across 8 points. Since the location_groups option is not used, RouteQ builds the optimal route.

API request (JSON)API responseView on map

Example 2

This example uses the same input data as Example 1, but orders 7 and 8 are combined into one group. RouteQ assigns these orders to one vehicle. The resulting route is less optimal in terms of metrics, but meets the delivery requirements.

API request (JSON)API responseView on map

Example 3

8 orders are divided into 3 groups, each of which includes orders from a single customer. It's specified that the groups can't be broken up: the options.location_groups.solid property is set to true. The route doesn't mix the locations of different clients: first, client 1's orders are delivered, then client 2's, and finally, client 3's.

API request (JSON)API responseView on map

Example 4

8 orders are divided into 2 groups. The value options.location_groups.dependent = true. This means that if at least one order from the group can't be fulfilled, the entire group is set to unassigned.

The total weight of the first group of orders is 250 kg, and the total weight of the second group is 450 kg. Because of the 600 kg load capacity limit, the courier can't deliver two indivisible groups of orders in one route. So, the algorithm sets one of the groups to unassigned.

API request (JSON)API responseView on map

Multi-orders

Orders located at the same address can be automatically combined into one multi-order. The combining algorithm takes into account geographical proximity and the possibility to deliver the orders at the same time and with one vehicle or courier, as well as tags, carrying capacity, and delivery priority.

To ensure that orders located at the same address are combined into one multi-order (taking into account other restrictions), set the option merge_multiorders = true. In this case, orders can be combined into one multi-order even if there is a waiting time between them (by default, the option wait_in_multiorders is true).

To make it so the multi-order can't be divided, set options.force_merge_multiorders = true. In this case, all orders to the same address will be delivered by the same vehicle, and if that's not possible, the entire multi-order will be moved to unassigned. Default value: false.

By default, orders that are delivered to different clients (with different client_id's) at the same address are counted as a single stop. To make them count as separate stops, set options.merge_multiorders_of_different_clients = false. The number of stops can be used to calculate the route cost. The option doesn't affect the handling time calculation: the location.shared_service_duration_s time for document handover or parking is calculated based on the longest time among all of the orders within the multi-order.

The proximity of the orders is determined by the multiorder_radius_m option (1 m by default). The value should not be too high so that orders located in neighboring buildings do not get combined into a multi-order. In such cases, it is better to use the Delivery with vehicle parking before the walking part of the route scenario for planning.

By default, time for parking or delivering documents shared_service_duration_s is tracked once for the entire multi-order. However, if there is a waiting time between orders (orders have different time windows and the courier completes the handover of one order before starting the next one), the handling time shared_service_duration_s can be tracked separately for each order. To do this, disable the waiting option options.wait_in_multiorders = false. To take into account the time shared_service_duration_s separately for a specific order, disable the option location.can_be_merged = false for that order. Learn more about order time tracking in Handover time.

During planning, the algorithm will try to reduce the number of return visits to multi-order addresses. The API response includes the following metrics:

  • multiorders_extra_points: The number of multi-order addresses which couriers visited more than once.
  • multiorders_extra_visits: The number of return visits to multi-order addresses.
  • multiorders_extra_vehicles: The number of couriers who revisited multi-order addresses.

You can apply the following penalties for return visits:

  • options.penalty.multiorders.per_extra_point: For each multi-order address which had to be visited again.
  • options.penalty.multiorders.per_extra_visit: For each return visit to a multi-order address.
  • options.penalty.multiorders.per_extra_vehicle: For each courier who returns to a multi-order address.

Example 1

The vehicle delivers three orders. Orders 1 and 2 are delivered to the same address and combined in a multi-order.

API request (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/c493eed8-42754094-af37202e-e88a8faa) ⋅ API responseVie on map

Example 2.1

The vehicle delivers three orders. Orders 1 and 2 are delivered to the same address and combined in a multi-order. By default, wait_in_multiorders = true, and the handling time is tracked once. There is a waiting time due to the difference in time windows between these orders, and orders 1 and 2 aren't visually combined into one multi-order, but order 2 has the parameter multi_order = true in the API response.

API request (JSON)API responseView on map

Example 2.2

The same orders are delivered as in example 2.1, but the option wait_in_multiorders = false. Orders 1 and 2 weren't combined into one multi-order (multi_order = false for order 2), and the service time is tracked separately for each order.

API request (JSON)API responseView on map

Example 3

Orders 1, 2, and 3 have to to be delivered to the same address. Order 4 has to be delivered to a different address. Every order weighs 500 kg. The carrying capacity of the vehicle is only 1200 kg, so it makes two runs. It first delivers orders 1 and 2, and then delivers orders 3 and 4.

The algorithm combined orders 1 and 2 into a multi-order, despite the fact that merge_multiorders = false (by default). Since it took 2 runs to deliver order 3, the penalty is the following: 10 units for the address that had to be revisited, and 1000 units for the return visit to the multi-order address.

API request (JSON)API responseView on map

Closely located orders

If you want to limit the number of couriers or routes that go to closely located orders, combine such orders into groups. To do this, go to the Options sheet and set the following parameters:

  • close_location_groups_radius_m: Maximum distance at which orders are considered close to each other, in meters. The default is 0.
  • penalty.close_location_groups.per_extra_point: Penalty for each point the courier visits more than once.
  • penalty.close_location_groups.per_extra_vehicle: Penalty for each additional courier who visits a group of closely located orders.
  • penalty.close_location_groups.per_extra_visit: Penalty for each additional visit to a group of closely located orders.

If the parameter close_location_groups_radius_m > 0, we recommend grouping closely located orders only at the sequence post-optimization stage. To do this, set options.post_optimization = true and options.close_locations_during_post_optimization_only = true (the default is false).

To set restrictions for a courier on visiting closely located orders, go to the Vehicles sheet and set the following parameters:

  • close_locations.routing_mode: Transportation method for determining the proximity of orders (the same for all orders in the solution).
  • close_locations.search_radius_m: Distance between two orders for the selected transportation method (the orders are considered closely located and are subject to the restrictions).
  • close_locations.soft_search_radius_m: If the value of this parameter exceeds the value of the corresponding close_locations.search_radius_m, orders at a distance from search_radius_m to soft_search_radius_m are also subject to penalties, but their size decreases linearly depending on the distance. For example, at the distance (search_radius_m + soft_search_radius_m) / 2, a penalty with a weight of 0.5 applies.
  • close_locations.duration_till_service_s.value and close_locations.duration_till_service_s.penalty: The maximum time (in seconds) between handling two closely located orders and the penalty for violating the restriction.
  • close_locations.distance_till_service_m.value and close_locations.distance_till_service_m.penalty: The maximum distance (in meters) between handling two closely located orders and the penalty for violating the restriction.
Example of using the settings of closely located orders
 {
 ...
     "vehicles": [{
         ...
         "close_locations": [
             {
                 "routing_mode": "driving",
                 "search_radius_m": 400,
                 "soft_search_radius_m": 500,
                 "distance_till_service_m": {
                     "penalty": 0.02,
                     "value": 1500
                 }
             },
             {
                 "routing_mode": "driving",
                 "search_radius_m": 100,
                 "soft_search_radius_m": 160,
                 "duration_till_service_s": {
                     "penalty": 0.02,
                     "value": 1500
                 }
             }
         ],
         ...
     },
     ...
     ],
 ...
 }

Alert

If the walking_courier parameter is not specified for the courier on the Vehicle sheet, then you can't set the transportation method in close_locations.routing_mode. Instead, the courier's transportation method is used by default. If the walking_courier parameter is set, then you can specify the value of close_locations.routing_mode as walking or as the courier's transportation method.

Contact support