Balanced loading
The main priority of route planning is often to get a relatively uniform distribution of orders across vehicles or couriers.
Use balanced_groups
to ensure balanced loading based on a certain attribute.
How it works
Balanced loading can be based on one or more parameters at the same time:
custom_value
: Sum of the orders' custom unit values.hour
: Route time.km
: Mileage kilometers.served_order
: Number of orders handled.stop
: Number of stops.unit
: Number of units.weight_kg
: Total weight of orders (in kg).
The solution building process only includes the balancing parameters specified during planning.
You can create several balanced groups, with each vehicle or courier group to be balanced separately (for more information, see Balancing groups). The balanced group ID is specified for the shift in the shifts.N.balanced_group_id
field of the Vehicles sheet.
Balanced group settings can be changed on the Options sheet in one row, as follows: the settings of the first balanced group in fields with the balanced_groups.0
index, the settings of the second balanced group in fields with the balanced_groups.1
index, and so on. For each group , the following is specified:
-
balanced_groups.N.id
— group ID. This is a required parameter (it is also specified for vehicles in theshifts.N.balanced_group_id
field). -
Amount of penalties for routes that are unbalanced relative to each other (
balanced_groups.N.penalty.hour
,balanced_groups.N.penalty.stop
,balanced_groups.N.penalty.custom_value
,balanced_groups.N.penalty.km
,balanced_groups.N.penalty.served_order
,balanced_groups.N.penalty.unit
,balanced_groups.N.penalty.weight_kg
). You can set up balancing using one or more parameters. Note that these parameters have default values. -
The
balanced_groups.N.penalty.ignore_unused_vehicles
parameter determines how load is blanced: if set tofalse
(default value), the algorithm evenly distributes the load to all the vehicles in the shift that have the same balancing. This may result in more vehicles being used in a solution than necessary. If the parameter's value istrue
, then vehicles that are not used in the solution are not taken into account during load balancing. This yields a more optimal solution.
We do not recommend using load balancing on initial planning runs. If you need routes with a more even distribution, you can fill in the balanced groups using the default values: balanced_groups.N.penalty.hour
= 200, balanced_groups.N.penalty.stop
= 100. Then adjust these settings based on the results.
Note
For large penalty values, use sequence post-optimization.
Balancing groups
We recommend that you balance the loading of couriers that originally have similar conditions. This may apply to various task parameters: duration and window of courier shift, order density per specific group of couriers, load capacity, tags, and so on. For couriers with different conditions, we recommend that you create different balanced groups. For example:
- Couriers might have different shift durations: for some, it is 8 hours, for others, it is 12 hours. You may need to balance such couriers separately (for example, based on the number of stops), because their route times will differ, and they will be able to complete different numbers of orders.
- Couriers work morning and evening shifts (of the same duration) and are routed within the same request. Let's assume that the number of orders in the morning and evening shifts is unevenly distributed. Then you either need to separately balance between the morning and evening couriers, or only balance them by route time, because the average number of orders (and, accordingly, stops on the route), would most likely be different for the morning and evening shifts.
- The same vehicles are used, but there are many orders in the city and a few orders in the surrounding area in different directions. You can only balance such a task by route time. This is because the vehicles that drive a long distance will, most likely, complete fewer orders.
- Vehicles of different load capacity (cars and trucks) are used. They usually carry orders that have different weights. That's why you need to either set different balanced groups for different load capacities, or balance vehicles by route time only (we recommend the second option).
- Couriers use different transportation methods: some travel by vehicle, others walk. In this case, you need to set different balanced groups for different transportation methods (for example, based on orders).
Note
When you use balanced groups, it usually results in less optimal routes in terms of general solution metrics (by "Total mileage"/"Total route time"). If you increase the penalties for unbalanced distribution, you get a more uniform solution achieved at the expense of optimal routes. If there is only one vehicle or courier in a balanced group, the balancing process will not work correctly and will produce uneven routes.
The balanced loading option helps you to balance routes inside a specific planning. If your task is to balance the load on your resources over an extended period of time (for example, a month), you need to implement it outside RouteQ in a separate process. In this process, couriers are assigned to routes based on the accumulated value you balance the solution against. For example, let couriers accumulate a total number of working hours. After the routes are planned for a given day, the courier who has the minimum accumulated value (of the total working hours) is assigned the longest route, and vice versa. Therefore, this balancing will be achieved not for a specific day, but over a period of time. However, on a given day, the routes might still be optimal, even if they are unevenly distributed.
Example 1
The task includes 52 orders and 3 couriers. Solve the task without balancing.
Planning result:
Courier | Number of stops in the route | Mileage, km | Route time |
---|---|---|---|
Courier 1 | 19 | 50 | 10:49 |
Courier 2 | 17 | 47.4 | 09:50 |
Courier 3 | 16 | 35.8 | 09:04 |
Total | 52 | 133.1 | 29:43 |
API request (JSON) ⋅ API response ⋅ View on map
Example 2
The same task as in example 1, but with the following additions:
-
Enable the balanced group option.
-
Create one balanced group.
-
Use the default penalties for unbalanced routes.
Planning result:
Courier | Number of stops in the route | Mileage, km | Route time |
---|---|---|---|
Courier 1 | 17 | 54.1 | 09:56 |
Courier 2 | 17 | 41.9 | 09:48 |
Courier 3 | 18 | 48.7 | 10:05 |
Total | 52 | 144.7 | 29:49 |
Routes are now more balanced relative to the indicator "Number of stops on the route"/"Route time", but the overall metrics of the solution ("Total mileage"/"Total route time") have degraded compared to example 1.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
The same task as in example 1, but with the following additions:
-
Enable the balanced group option.
-
Balance the routes by the route time only.
-
Increase the penalties for unbalanced routes relative to default.
Planning result:
Courier | Number of stops in the route | Mileage, km | Route time |
---|---|---|---|
Courier 1 | 17 | 47.5 | 10:09 |
Courier 2 | 18 | 50 | 10:09 |
Courier 3 | 17 | 52.5 | 10:09 |
Total | 52 | 150 | 30:27 |
Now the couriers work the same hours, but the overall solution metrics have degraded even more. This is because the algorithm with increased penalties for unbalanced routes tries to find a solution that would be more balanced than optimal.
API request (JSON) ⋅ API response ⋅ View on map
Example 4.1
The same task as in example 3, but only the first 30 orders are delivered. Two couriers are enough, but the task specifies three. The balanced_groups.penalty.ignore_unused_vehicles
parameter is set to false
(default value), so the load is distributed evenly among all the couriers:
Courier | Number of stops in the route | Mileage, km | Route time |
---|---|---|---|
Courier 1 | 10 | 40.5 | 06:49 |
Courier 2 | 10 | 41.9 | 06:47 |
Courier 3 | 10 | 43.8 | 06:48 |
Total | 30 | 126.3 | 20:25 |
API request (JSON) ⋅ API response ⋅ View on map
Example 4.2
The same as in example 4.1, but the balanced_groups.penalty.ignore_unused_vehicles
parameter is set to true
, so load balancing ignores unused vehicles. Only two of three couriers are used in the solution, with the load balanced between them:
Courier | Number of stops in the route | Mileage, km | Route time |
---|---|---|---|
Courier 1 | 15 | 53.2 | 09:11 |
Courier 3 | 15 | 51.8 | 09:11 |
Total | 30 | 105 | 18:23 |
API request (JSON) ⋅ API response ⋅ View on map