Example settings for business cases

Planning the loading of your own couriers

What situations to use this in

When planning the loading of your own couriers, it's important to:

  • Involve all couriers.
  • Distribute work more or less evenly.

In this case, the algorithm must build a route in such a way that all resources are used evenly. Minimizing the amount of resources isn't a goal.

How to implement this scenario

In RouteQ, there are several parameters that you can use to involve all couriers and ensure uniform loading:

  1. cost.fixed reduces cost per use. The algorithm aims to reduce the total cost of the solution . If cost.fixed is specified, it also minimizes the number of couriers. For a scenario where all couriers must be involved, set this cost to 0 or the minimum. The choice of value depends on transport capacity:

    • If you use vehicles of the same capacity, cost.fixed = 0.

    • If you use vehicles with different carrying capacities, cost.fixed must be minimal, but proportional to the carrying capacity (see an example in Vehicle or courier carrying capacity). In this case, cost.fixed can't equal 0. Otherwise, there may be situations with a load mismatch for different vehicles (for example, a vehicle with a capacity of 0.8 tons will be loaded to 700 kg, while a vehicle with a capacity of 1.5 tons will be loaded to 100 kg).

  2. Sometimes, using cost.fixed = 0 isn't enough. Then you need to limit the minimum number of stops minimal_stops (for more information, see Limit the number of stops per shift). Set minimal_stops to 1 and set big penalties penalty.stop_lack.fixed (for making fewer stops than the minimum number) and penalty.stop_lack.per_stop (for each stop missing under the minimum number).

  3. For uniform distribution of orders among vehicles or couriers, use balancing settings (for more information, see Balanced loading option).

Alert

The cost per use is set to cost.fixed = 3000. That's why you must explicitly set 0 to specify a zero cost, instead of leaving an empty value.

Example 1

This example shows how the algorithm works without using uniform loading settings.

The task has 28 orders and 5 couriers. As a result of planning, only 4 couriers are used.

API request (JSON)API responseView on map

Example 2

We solve the same task in example 1, but using cost.fixed = 0. The result is that all 5 couriers are used.

API request (JSON)API responseView on map

Example 3

The task has 28 orders and 10 couriers. We use minimal_stops = 1 and penalties. As a result, the algorithm distributes orders among all 10 couriers.

API request (JSON)API responseView on map

Simultaneous planning for couriers who drive a vehicle and who use public transport

How to implement this scenario

In case of simultaneous planning for couriers who travel by public transport and who drive, note that it's necessary to specify a different cost per kilometer and per hour for them. This is for the following reasons:

  • The cost of traveling by public transport

    For couriers traveling by public transport, mileage in the service is counted only for the part of the route where the courier travels on foot.

    For couriers who travel by public transport, set the cost per kilometer of mileage cost.km higher than for couriers who drive. This is necessary so that the algorithm considers the route where couriers have to walk a lot (for example, if delivery points are far from public transport stops) to be more expensive than the route where delivery points are located near public transport stops. The algorithm will try to reduce the cost of the solution, so it'll tend to build routes with short walking sections.

  • Order distribution

    Couriers on vehicles must carry out longer-distance orders, and couriers on public transport must carry out orders in the city center.

    You can only strictly distribute orders using tags (for more information, see Vehicle tags), but this can be achieved indirectly by setting a different cost per hour of work cost.hour (you can't use cost per kilometer of mileage, because only the walking mileage is taken into account for couriers on public transport). This means that cost.hour must be higher for couriers on public transport so that the algorithm builds short routes for them.

Example

There are 4 couriers in the task: 2 couriers using public transport, 2 drivers, and 40 orders. For couriers using public transport, cost.km = 30 and cost.hour = 300. For couriers who drive, cost.km = 8 and cost.hour = 100.

As a result, 3 out of 4 couriers are used, 2 of them drive, and only 1 uses public transport. The total travel time for a courier using public transport is 3 hours 12 minutes. For couriers who drive, the time is 5 hours 53 minutes and 7 hours 5 minutes.

API request (JSON)API responseView on map

Simultaneous planning of current and next-day orders

What situations to use this in

The shipment period may sometimes take more than a day. For example, it may happen under the following conditions:

  1. Planning is done in the daytime.
  2. Shipment is carried out in the evening or at night of the same day and on the next morning.

How to implement this scenario

The scenario is implemented using the relative format of time windows. In the order, shift, and depot windows, use the shift relative to the planning date.

In the interface, set the planning date when you start the task. In the API request, do it in the options.date field.

It's important to specify the shift correctly for order windows, courier shift windows, and depot windows. Example of an order with an evening window of 21:00–23:00:

  • The morning window for the next day is set to 1.07:00–1.09:00.

  • Vehicles that deliver orders in the evening and at night have a 20:00–1.04:00 shift.

  • Vehicles that deliver in the morning have a 1.05:00–1.18:00 shift.

  • The specified depot window covers the entire delivery period: 20:00–1.20:00 (the return of the vehicle to the depot must also fall within the depot's operation window).

Example

In this example, there are orders that need to be delivered this evening and the next day. One courier works the night shift, and the other one works the morning and afternoon shift. The depot's operation window is set to cover the entire delivery period. As a result, current-day orders are delivered by the first courier, and next-day orders are delivered by the second one.

API request (JSON)API responseView on map

Planning orders that can be rescheduled / Planning part of the orders

What situations to use this in

Use this scenario in situations when, as a result of planning, some orders may be unassigned, for example:

  • There's a lot of orders

    Planning involves more orders than can be shipped by the couriers available. The algorithm needs to plan routes in such a way that a maximum number of orders is carried out.

  • The possible delivery period is defined

    Planning involves orders that can be delivered during a certain time period, not necessarily today. They can be delivered today, if this is the best option, or rescheduled for tomorrow.

How to implement this scenario

Change the non-delivery penalty for orders in the penalty.drop parameter. By default, it's set to 1,000,000. Such a large value is used because when planning, in the normal course of events, it's assumed that all orders must be delivered.

Also note the following:

  • Set a penalty.drop penalty taking into account the number of orders at one point.

    In the data structure, the penalty.drop penalty is set per order (location), not per point. If there are multiple orders to the same point, the penalty for non-delivery to this point is several times higher than to other points. This may lead to situations where points with multiple orders will be included in routes, even if this is suboptimal in terms of mileage. When you have few multi-orders, the effect may be very slight, but for frequent multi-orders, set penalty.drop as a penalty for a single point, divided by the number of orders in it. For example, if penalty.drop is 10,000 for all orders, set penalty.drop or a point with four orders to 10 000 / 4 = 2500.

  • Range orders by priority.

    If it makes sense to deliver particular orders today or at a later date, implement it by setting different penalty.drop penalty values for high- and low-priority orders. Set a higher penalty.drop value for a high-priority order. If you make penalty.drop values the same, then when everything else is equal, long-distance orders that are far from the rest won't be delivered. To prevent long-distance orders from being included in unassigned orders, use the max_drop_penalty_percentage parameter (for more information, see Allowable share of unassigned orders).

  • Set the cost.

    Don't use the default penalty.drop value in this scenario, because the ratio of costs and penalties is very important for the algorithm when it builds routes. For example, if cost per km is 10, cost per hour is 100, and penalty.drop = 1000, then an order that's 2 hours and 81 km away will be unassigned. This will happen because the cost of delivery is 2 * 100 + 10 * 81. That's more than the penalty for an unassigned order, which is 1000.

Example 1

Example with a small penalty.drop value for all orders. Some orders are close, some are far away. As a result, long-distance orders are unassigned.

API request (JSON)API responseView on map

Example 2

An example of corporate client orders that can't be rescheduled, and individual orders that can be rescheduled for tomorrow.

For orders from corporate clients, penalty.drop = 1,000,000, and for individuals, penalty.drop is small. As a result, the algorithm plans all corporate orders, even if they're far away, as well as some individual orders.

API request (JSON)API responseView on map

Example 3

  1. In this example, there are several orders and one long-distance multi-order. The same penalty.drop is specified for all of them. As a result, the algorithm plans the long-distance multi-order, despite the fact that this looks suboptimal on the map.

    API request (JSON)API responseView on map

  2. In this example, there are several orders and one long-distance multi-order. They have different penalty.drop values. As a result, the algorithm plans the nearby orders and doesn't allocate the long-distance multi-order.

    API request (JSON)API responseView on map

Planning with uniform shift time violation for drivers

What situations to use this in

In some cases, the order time window is wider than the time window for changing drivers. When planning, this causes a significant shift window violation for one driver, and no violation at all or a slight violation for the rest of the drivers.

If it's impossible to fulfill all orders without violating drivers' shifts, you need to ensure that the violation of working hours is fairly distributed among drivers (so that everyone has a violation, but it's a small one).

How to implement this scenario

For a more uniform shift violation, change the default value of penalties for a shift time window violation (for more information, see Vehicle or courier work shifts).

Change the penalties:

  1. Set a small or zero value for shifts.penalty.out_of_time.fixed.
  2. Set a significantly larger value for shifts.penalty.out_of_time.minute (it can be based on the cost per km), for example, 3–10 times more than the cost per km.

Another way to implement a uniform shift violation for drivers is to set a hard window around a soft one.

Example 1

In this example, there are several drivers and several dozen orders. Drivers have flexible shifts, penalty values are set by default, and orders have hard time windows. The shift window is 10:00–17:00, and the order window is 10:00–21:00. The service time and location of orders make it impossible to fulfill all orders without shift time violations. As a result, one driver has a significant shift time violation, but the rest of the drivers have no violation.

API request (JSON)API responseView on map

Example 2

The same example, but with a uniform shift violation. These are the penalty values for a shift window violation: shifts.penalty.out_of_time.fixed = 0 and shifts.penalty.out_of_time.minute = 800.

API request (JSON)API responseView on map

Example 3

The same example, but now the order windows are 10:00–17:00 and soft. The shift violation is also uniform, because the algorithm now takes into account a limit on order windows: the drivers who work after 17:00 violate both shift and order windows.

API request (JSON)API responseView on map

Example 4

The same as in example 1, but now in addition to the main time window time_window, couriers also have an external hard time window hard_time_window. It limits the allowed time of the main window violation from 09:45 to 19:00. As a result, all orders will be completed within the set limits.

API request (JSON)API responseView on map

Transport with different load capacities

How to implement this scenario

It's more expensive to use a large truck with a trailer than a small courier vehicle. That's why it's best to specify cost per use (cost.fixed) based on the load capacity (weight_kg): the bigger the tonnage, the higher the cost. This is usually a linear relationship like: cost.fixed = X + weight_kg * Y .

In most cases, we recommend setting the same cost per kilometer, per hour, and per ton-kilometer (cost.km, cost.hour, cost.tonne_km) for vehicles with different tonnage.

To calculate cost.fixed, we'll use the coefficient values X = 2000 and Y = 0.5. For these coefficients, the answers are as follows:

  • What's cheaper: to use 2 vehicles with a load capacity of 1500 kg or 1 vehicle with a load capacity of 3000 kg?

    • 2 lightweight vehicles: 2 × (2000 + 1500 × 0.5) = 5500.
    • 1 heavyweight vehicle: 2000 + 3000 × 0.5 = 3500.
    • 5500 > 3500, so it's cheaper to use 1 heavyweight vehicle.
  • What's cheaper: to use 4 vehicles with a load capacity of 3000 kg or 3 vehicles with a load capacity of 5000 kg?

    • 4 lightweight vehicles: 4 × (2000 + 3000 × 0.5) = 14,000.
    • 3 heavyweight vehicles: 3 × (2000 + 5000 × 0.5) = 13,500.
    • 14,000 > 13,500, so it's cheaper to use 3 heavyweight vehicles.

Alert

In your case, the coefficients may differ.

For this case, it is often necessary to limit minimum the order weight for delivery to a single destination for large-capacity vehicles. You can also limit the maximum number of stops on the route for such vehicles.

In some situations, use the weighted_drop_penalty parameter, which sets penalties for failure to deliver in proportion to the order weight/volume. For more information, see Proportional penalty for not delivering an order.

Example 1

Planning involves 3 vehicles with a load capacity of 1.5 t, 3 t, and 5 t. The cost per use is the same. All orders can be fulfilled by at least two couriers in one shift. As a result, the most heavyweight vehicles are loaded: 5 t and 3 t.

API request (JSON)API responseView on map

Example 2

The same example, but cost per use is calculated using a formula. We get the values 2750, 3500, and 4500. As a result, the algorithm plans the most profitable vehicle combination: 5 t and 1.5 t.

API request (JSON)API responseView on map

Experienced and novice couriers

What situations to use this in

In most cases, experienced couriers complete tasks faster than novices. Experienced couriers can travel faster, spend less time on operations, and fulfill more orders. You can take this into account when planning to get more realistic results.

How to implement this scenario

There are two ways to implement this scenario:

Adjusting the vehicle's moving time takes into account deviations that depend on vehicle type and the courier's driving style.

Adjusting the handling time takes into account the time needed to park the vehicle and hand over the order.

Limiting the number of stops regulates the maximum load on a courier per day and allows you to put a courier on a route with a particular number of stops. This helps to limit the load on a novice courier and use an experienced courier on a long route, which they can complete faster.

Priority couriers

What situations to use this in

It's sometimes necessary to distribute orders between couriers unevenly. For example:

  1. Some couriers need to be loaded as much as possible, so that the others only ship orders that are left over. For example, when some couriers are full-time workers and the rest are part-time workers.
  2. All the couriers need to be loaded, but some must get more orders than others. For example, on peak days, the main staff can't cope and additional couriers come, but you need to minimize their load. Also, if couriers are paid by the piece, more loaded routes must be given to experienced couriers whom should the company wishes to retain.

How to implement this scenario

In the first situation, specify a lower cost.fixed value for higher-priority couriers. Then, where everything else is equal, they will be given preference (for more information, see using your own and hired transport at the same time).

In the latter case, use the ability to limit the number of stops per shift to specify a higher maximal_stops value for priority couriers.

Example 1

There are 40 orders and 4 couriers, of which 2 are priority and 2 are additional. Dofferent cost.fixed values are specified: 2500 for priority couriers and 3500 for additional couriers. As a result, all orders are distributed among priority couriers.

API request (JSON)API responseView on map

Example 2

The data is the same as in example 1, but maximal_stops is set to 15 for priority couriers and 10 for additional couriers. Penalties for excessive stops are also specified. These penalties are mandatory when using the maximal_stops parameter. As a result, priority couriers get 15 orders each, and an additional courier gets 10 orders.

API request (JSON)API responseView on map

Restriction on arriving at the location early

How to implement this scenario

In situations where it's impossible to plan routes without planned order window violations, use soft time windows. In this case, the algorithm may schedule the arrival both earlier and later than the time window. To allow delays but prohibit early arrivals, use different order penalties:

  • Use larger values for penalties that regulate early arrival: penalty.early.fixed and penalty.early.minute.

  • Set the penalty for late arrival penalty.late.fixed to 0.

  • For the penalty per minute of late arrival penalty.late.minute, specify a value that's comparable to the cost of use per hour or kilometer (for example, if 1 km costs 10, the recommended penalty value is between 20–100).

You can also set a hard window around a soft one using the hard_time_window parameter. To prohibit early arrivals and allow delays, the left limit of the hard window must match the soft one, and the right limit must exceed the soft one.

Example 1

Order windows are soft and short, and penalties for early and late arrivals are the same. The courier doesn't always arrive on time.

API request (JSON)API responseView on map

Example 2

The same as example 1, but penalties for early arrival are significantly higher, and the penalty for late arrival is set to zero. As a result, the average time window violation is smaller, but the mileage, route time, driving time, and waiting time metrics deteriorate.

API request (JSON)API responseView on map

Example 3

The same as in example 1, but hard windows are set around soft windows for orders. As a result, the average waiting time will increase, and the travel and route time will decrease.

API request (JSON)API responseView on map

Using your own and hired transport at the same time

What situations to use this in

For a situation where you use your own and hired transport at the same time, the following requirements are typical:

  1. Prioritize using your own transport and do it as efficiently as possible, while minimizing the use of hired transport.
  2. Your own transport must return to the depot, and hired transport mustn't.

How to implement this scenario

To prioritize the use of your own vehicles, use the recommendations given in Planning the loading of your own couriers.

  • For your own vehicles, it is a good idea to reduce the utilization cost in cost.fixed (for more information, see Transport with different load capacities).

    Vehicle cost must increase proportionally to load capacity, and the cost of your own vehicle must be lower than the cost of a hired one with the same load capacity.

  • If lowering cost.fixed doesn't help, set a limit on the minimum number of stops.

    Specify minimal_stops = 1 and heavy penalties for violations (penalty.stop_lack.fixed and penalty.stop_lack.per_stop).

  • If your own vehicles must return to the depot at the end of the shift, and hired vehicles don't have to do that, we recommend lowering the cost per hour and/or per km for your own vehicles (cost.km and cost.hour). The values of these parameters for your own transport must be approximately 10–80% of the values for hired transport.

Example 1

There are 3 orders weighing 1.5 t and 3 of your own and hired vehicles with a load capacity of 1.5 t, 3 t, and 5 t. Each order takes up one place, and there's one place available in each vehicle. The cost per use is lower for your own vehicles and increases with tonnage. The cost per 1 km is lower for your own vehicles. As a result, your own vehicle with a load capacity of 5 t stays in the garage, and a hired vehicle with a load capacity of 1.5 t does the run, because this costs less.

API request (JSON)API responseView on map

Example 2

The same example, but with the added condition minimal_stops = 1 for your own vehicles and penalties for violating the minimum number of stops. As a result, all of your own cars do the run, and all hired ones stay in the garage.

API request (JSON)API responseView on map

Minimizing waiting time for couriers

What situations to use this in

When you plan many orders that have narrow time windows, there may be some waiting times for the courier on the route. Waiting means that the courier arrived at the location earlier than the time window and has to wait for it to start.

  • If time windows are soft (hard_window = false) and there are waiting times, the algorithm has a choice that depends on the courier's cost per hour of work (cost.hour) and the penalties for violating the order time window:

    • To violate the time window: to start service before the time window starts.

    • To create downtime for the courier: to wait for the time window to start.

  • If time windows are hard (hard_window = true), there's no choice, so the courier waits for the window to start.

For example, consider a situation where a courier arrives 10 minutes before the start of the order time window. Given that:

  • The cost per hour of work cost.hour = 300.

  • The fixed penalty for window violation penalty.out_of_time.fixed (or penalty.early.fixed ) = 100.

  • The penalty per minute of time window violation penalty.out_of_time.minute (or penalty.early.minute) = 20.

The algorithm will choose to wait, because the cost of additional courier downtime is 300 * 10 / 60 = 50, which is less than the cost of violating the time window by  10 minutes, which is 100 + 10 * 20 = 300.

Note

In real-life planning, the situation may not be so clear: sometimes, a time window violation for one order lets you avoid violating several more time windows in the next part of the route.

How to implement this scenario

You can reduce your couriers' waiting time in two ways (which can be used separately or in combination):

  • Increase the courier's cost per hour of work.

  • Set up soft time windows and reduce penalties for their violation.

Note that many route characteristics depend on one another, and improving one indicator is often achieved at the cost of others. The interdependent characteristics are:

  • The number and total time of window violations.

  • Total waiting time.

  • Total mileage.

  • The grouping of routes.

Example 1

There are a lot of orders with narrow time windows, and the courier's cost per hour of work is cost.hour = 100 . As a result, the total waiting time is 4 hours 27 minutes.

API request (JSON)API responseView on map

Example 2

Let's increase the courier's cost per hour of work to 300. The waiting time is significantly reduced and is now 1 hour 2 minutes. At the same time, the total mileage increased.

API request (JSON)API responseView on map

Example 3

We set the courier's cost per hour of work to the default cost.hour = 100. We reduce the penalties for violation of the time window. Now, location.penalty.early.fixed = 0 and location.penalty.late.fixed = 0, location.penalty.early.minute = 10 and location.penalty.late.minute = 10. There are now 2 violations of time windows in the route, but the couriers' waiting time is only 8 minutes.

API request (JSON)API responseView on map

Minimizing the number of couriers

What situations to use this in

A common task when building routes is to minimize the amount of resources used. The main setting for regulating the number of couriers is a fixed cost cost.fixed (for more information, see Vehicle or courier cost). The higher the value, the more expensive it is for the algorithm to use another courier, which is why fewer couriers will be involved as a result.

Alert

The ratio of costs and penalties used is important for the algorithm. That's why you can reduce the number of couriers if you leave cost.fixed unchanged, but lower the values of all other costs and penalties.

How to implement this scenario

As a rule, you can reduce the number of couriers by changing other route characteristics:

  • Working hours (10 couriers work for 8 hours each. If you want to use 9 couriers, they must all work 8.5 hours).

  • Order window violations (10 couriers can fulfill all orders without delays. If you use 9 couriers, they'll have to arrive half an hour late to 10 clients).

  • The grouping of routes.

Settings that may increase the number of couriers in the solution too much:

Example 1

In this example, there are 150 orders with  5 -hour time windows. Parameter settings:

  • For windows:

    • Order windows are soft (hard_window = false).

    • Couriers' shift windows are soft (shifts.0.hard_window = false).

  • For penalties:

    • No penalty for a window violation (locations.penalty.out_of_time.fixed = 0).

    • The penalty per minute of violation is 30 (location.penalty.out_of_time.minute = 30).

    • No penalty for a window violation (vehicles.shifts.penalty.out_of_time.fixed = 0).

    • The penalty per minute of violation is 100 (vehicles.shifts.penalty.out_of_time.minute = 100).

  • For the grouping of routes:

    • Routes must be grouped, so proximity_factor = 1.
  • For costs:

    • The cost per kilometer of mileage cost.km = 16.

    • The fixed cost per use of vehicle cost.fixed = 3000 (default value).

The algorithm distributed the orders in such a way that there are 7 well-grouped routes in the solution. There are no time window violations.

API request (JSON)API responseView on map

Example 2

The same as in example 1, but the cost per use of the vehicle is different. Now, cost.fixed = 5000.

As a result, the number of couriers is smaller: now there are 6 of them, but time windows are violated twice. The total mileage and moving time increased.

Note

Such reallocation of orders among a smaller number of couriers is possible if other restrictions don't interfere:

API request (JSON)API responseView on map

Example 3

The same as in example 1, but the fixed cost per use is even higher. In this example, cost.fixed = 30,000.

The number of couriers is even smaller: now there are 5 of them, but the number of time window violations has increased to 3. The total mileage and driving time increased even more.

API request (JSON)API responseView on map

Priority orders

How to implement this scenario

Depending on what is meant by order priority, different recommended settings are used. Possible options:

  1. Fulfill a priority order in the specified time window, without delay

    Set a hard time window for the priority order. Sometimes, you need to use additional parameters: penalty for service outside of the time window and minimizing the risk of late arrivals.

  2. Fulfill the priority order in any case, and fulfill the rest of the orders if possible

    For more information, see Planning orders that can be rescheduled / Planning part of the orders.

You can also use the sequence_order parameter to set a sequence order within a specific route. The sequence order is set end-to-end for all of the vehicle's runs. As part of overall planning for different routes, there may be a situation when an order with a greater sequence_order parameter value in one route will be delivered earlier than an order with a lower parameter value in another route. Orders with identical sequence_order values are completed out of sequence. If no sequence is set, orders can be placed in any order and anywhere on the route.

Example 1

The route is built for one vehicle that fulfills 7 orders. The order windows partially overlap. Four orders are high priority, and a hard time window is set for them. As a result of planning, the routes for orders with a hard time window contain no violations, but two orders with a soft time window are delayed.

API request (JSON)API responseView on map

Example 2

The route is built for two vehicles that must complete 7 orders. There are two orders that must be delivered early in the morning to remote locations. Their sequence is set using the sequence_order parameter (Orders 1 and 4). Drivers need to go to these locations first, although while they're on their way, they may fulfill other orders to optimize the route.

API request (JSON)API responseView on map

Grouped routes

What situations to use this in

Routes usually need to be grouped in the following cases:

  • The time of order pickup from the client is highly likely to change.
  • There's a large margin of error in determining the planned handling time.
  • Convenience of work for couriers in familiar areas and when delivering to regular clients.

How to implement this scenario

Option 1

Use the following options:

In some cases, you can separately increase the cost per kilometer cost.km.

For individual couriers, you can plan routes that are geographically grouped around "hotspots" (see Route grouping).

Option 2

Use the cost calculation formula (vehicles.cost) with the max_edge_duration_h and max_edge_distance_m parameters. These parameters set clear restrictions on the proximity of adjacent consecutive points on routes.

The proximity_factor and global_proximity_factor parameters affect the average length of individual route segments between orders, while the max_edge_distance_m and max_edge_duration_h parameters limit the maximum length or maximum time for each of the consecutive route segments between orders.

Example 1

cost.km = 8 (the default value), and the proximity_factor and global_proximity_factor values are set to zero.

API request (JSON)API responseView on map

Example 2

The same as example 1, but the proximity_factor and global_proximity_factor values are set to 0.5. Routes have become more grouped, the distance between all the points decreased.

API request (JSON)API responseView on map

Example 3

The same as example 1, but proximity_factor = 0.5, and global_proximity_factor = 0. Routes are less grouped geographically, but the distance between neighboring consecutive points decreased.

API request (JSON)API responseView on map

Example 4

The same as example 1, but advanced cost settings vehicles.cost.run are used for the run:

  • 3000 for starting a route.
  • 8 for every kilometer traveled.
  • 1000 penalty if the maximum length of segments between orders (max_edge_distance_m) exceeds 3 km.

Calculation formula:

vehicles.cost.run = 3000 + distance_km * 8 + (max_edge_distance_m > 3000) * 1000

As a result of planning, the distance between neighboring consecutive points on the route decreased.

API request (JSON)API responseView on map

Reducing the number of delays

How to implement this scenario

If you use soft time windows, the algorithm can plan a route that violates these windows. To reduce the number of window violations, you can change the penalty.out_of_time penalty group or the penalty.late and penalty.early penalty groups separately (see also the Restriction on arriving at the location early scenario — in some cases, you need to make these penalties different).

We recommend the following scenario for changing settings:

  • Penalty for violation: Set to 0 or a small value.

  • Penalty per minute of violation: Set a value greater than the default value. The higher the value, the fewer window violations you'll have.

Another way to reduce the number of window violations is to set a hard window around a soft one using the hard_time_window parameter.

All route characteristics are interconnected. In most cases, window violations result from building more grouped routes, building routes that are more optimal in terms of mileage, or using fewer couriers. That's why decreasing the number of window violations is likely to lead to a deterioration of other route characteristics.

Example 1

11 couriers serve 149 orders, and delivery windows are soft. The penalties are set by default: 1000 for a window violation and 17 per minute of violation. This results in 6 delays, over 5 hours in total. There are 4 big delays, each of which lasts over an hour.

API request (JSON)API responseView on map

Example 2

The same as in example 1, but now there's no penalty for a window violation, and the penalty per minute of violation is set to 100. As a result, there are more window violations (19 delays), but the total violation time is reduced to 2 hours. In this example, we managed to get rid of long delays : most delays last less than 10 minutes now.

API request (JSON)API responseView on map

Example 3

The same as in example 1, but now orders have a hard window around a soft one — hard_time_window. The left limit of the hard window matches the soft one, and the right limit is 1 hour later than the soft window. As a result, the average delay and waiting time decreased, and mileage increased.

API request (JSON)API responseView on map

Planning routes by geofence

What situations to use this in

When planning, it may be necessary to distribute routes so that specific vehicles or couriers work only in certain territories, or so that certain territories don't overlap within the same route. To do this , use geofences.

Advantages of using geofences:

  • It's easier to mark up geofences, since visualization on the map is used for this.
  • Geofences can overlap.

At the same time, geofences set a hard restriction that the algorithm can't violate.

We recommend the following:

  1. Don't make your zones too small. In practice, the best are enlarged geofences, where several couriers can travel. The algorithm will thus be able to smooth out possible unevennesses in orders on a specific day. You can use the Grouped routes function along with the zones.
  2. Don't leave delivery areas between zones where the order can theoretically fit.

In addition to hard geofencing restrictions for order distribution, you can use:

Alert

If you use order incompatibility, order and vehicle compatibility, or optional tags, perform the initial mapping between an order and a zone outside of the service.

How to implement this scenario

Geofences can be used both when planning via the RouteQ interface and when working via the API. For more information, see Geofences.

The zones that the courier or the vehicle can deliver orders to are set by the vehicles.allowed_zones parameter. The zones forbidden for this vehicle or courier are set by the vehicle.forbidden_zones parameter.

Example 1

Saint Petersburg is divided into 7 geofences. For each vehicle, a delivery zone is set in the allowed_zones field. Coordinates automatically determine how orders pertain to geofences. As a result, each courier delivers orders only in one zone and doesn't go to the adjacent ones.

API request (JSON)API responseView on map

Example 2

The example describes 2 couriers — staff and third-party. 2 geofences are set: "north" and "south". The staff courier must deliver only in the northern part of the Moscow region.

API request (JSON)API responseView on map

Note

To reproduce the examples described in Excel, add the used geofences to the geofence master data.

Example 3

St. Petersburg is divided into 7 zones, and each zone corresponds to 1 type (load_type). For each order, a type is specified and its incompatibility with other types is described. As a result, each courier delivers orders only in one zone and doesn't go to the adjacent ones.

API request (JSON)API responseView on map

Priority areas for couriers

How to implement this scenario

To set up priority areas for couriers, we recommend using optional tags or geofences.

Planning orders for multiple days

What situations to use this in

In in some tasks, planning covers several days. For example, when an order is expected over the next few days but at a specific time.

How to implement this scenario

Use an order with multiple time windows to define the days and times for your order delivery. Specify the time windows:

  • For the orders, specify several windows, a single window for each delivery day, such as 08:00 – 16:00 and 1.08:00 – 1.16:00, respectively. For more information, see Relative format of time windows.

  • For the couriers, also specify several shifts, such as 07:00–18:00 for the first day, 1.07:00–1.18:00 for the second day, and so on.

  • For the depot, specify one large window to cover the entire delivery period, such as 08:00 - 22:00.

Example

In the following three days, many orders need to be delivered between 08:00 and 16:00. This is why three time windows are specified for each order, three shifts for the couriers (one per day), and the depot's total business hours from the first to the third day for the depot.

API request (JSON)API responseView on map

Multi-day routes

How to implement this scenario

To plan a multi-day route, you need to specify:

Example

There are 8 orders in the planning task that need to be delivered in 3 days. This is why three time windows are specified for each order, three shifts for the couriers, and the depot's total working hours from the first to the third day for the depot. The schedule for breaks is set. After the shift, one of the two couriers returns to the depot.

API request (JSON)API responseView on map

Vehicle with multiple compartments

Alert

This business case implies that this type of cargo can only be placed in a certain compartment. There is no variability that this type of cargo can be placed in one of several compartments to choose from.

It's also assumed that the compartments are set initially (the scenario with dynamic movement of the partition to change the size of the compartments isn't supported).

What situations to use this in

Apply the scenario when the fleet has vehicles with several compartments where different types of cargo can be transported. For example, vehicles that can transport frozen and ordinary products at the same time. At the same time, each compartment has its own capacity that must be taken into account when planning.

How to implement this scenario

To describe such a vehicle in the planning task, you can use:

Both options must be applied simultaneously.

Example

A vehicle with a body divided into 2 compartments is used in the planning:

  • A cold compartment for products requiring low temperature.

  • A standard compartment for products that don't require special transportation conditions.

The capacity is set for each compartment using paired parameters:

Parameters

What is set

capacity.custom.0.name capacity.custom.0.size

Weight capacity for the cold compartment, kg

capacity.custom.1.name capacity.custom.1.size

Volume capacity for the cold compartment, m3

capacity.custom.2.name capacity.custom.2.size

Weight capacity for the standard compartment, kg

capacity.custom.3.name capacity.custom.3.size

Volume capacity for the standard compartment, m3

Order 1 must be placed only in the cold compartment, order 2 only in the standard one, and order 3 must be divided into two parts in different compartments. Orders are described using custom capacity parameters:

Parameters

What is set

shipment_size.custom.0.name shipment_size.custom.0.size

Cargo weight for the cold compartment, kg

shipment_size.custom.1.name shipment_size.custom.1.size

Cargo volume for the cold compartment, m3

shipment_size.custom.2.name shipment_size.custom.2.size

Cargo weight for the standard compartment, kg

shipment_size.custom.3.name shipment_size.custom.3.size

Cargo volume for the standard compartment, m3

All orders in the solution are distributed to the necessary compartments to fully load them.

API request (JSON)API responseView on map

Depot departure time

What situations to use this in

To build an optimal route, it's important to select the optimal time for the courier to leave the depot. Depending on the settings, the departure time can be determined by the depot's and courier's work schedule or automatically selected by an algorithm during planning.

How to implement this scenario

If the value of the depot.flexible_start_time (flexible start time) parameter is false, the departure time is determined by the courier's work schedule and number of shifts. For example, the depot is open from 7:00 to 22:00, and the courier works from 8:00 to 20:00. The loading time at the depot is 30 minutes. In this case, the courier leaves the depot at 8:30. This is the latest possible start of the window (from the depot and shift windows), taking into account the loading time at the depot. If the courier has two shifts from 8:00 to 20:00 and from 10:00 to 22:00, they leave the depot at either 8:30 or 10:30. In this case, the departure time is selected from two options by an algorithm, taking into account the loading time at the depot.

The depot departure time depends on the following settings:

When determining the depot departure time, all the handling times set for the depot, orders, and courier are added together.

If depot.flexible_start_time=false and the time when the order is ready at the depot is set, the departure time is also affected by the options.load_when_ready (load when ready) option.

If depot.flexible_start_time=true, the departure time is determined by the algorithm. At the same time, the loading window sets the timeframe when items can be unloaded at the depot. Note that the departure time is affected by external factors (such as traffic), order location, time windows, and planning settings:

To move the depot departure time to the beginning of the time window, use the Prompt delivery function.

Diagram

Example 1

Two couriers deliver 30 orders. The depot's and couriers' working hours are from 8:00 to 20:00. All orders must be delivered between 11:00 and 19:00. The couriers arrive at the depot at 8:00 and load the orders. Order loading time is the combination of the depot handling time depot.service_duration_s, the time to load each order location.depot_duration_s, and the time to load orders into the vehiclevehicle.depot_extra_service_duration_s. Because flexible_start_time=false, every courier has additional waiting time.

API request (JSON)API responseView on map

Example 2

The same as in example 1, but flexible_start_time=true. The algorithm calculates the departure time to eliminate any unnecessary waiting. The following parameters are also set:

  • penalize_late_service=true: Penalty for order handling outside the time window.

  • minimize_lateness_risk=true: Minimize the risk of delay.

  • penalty.arrival_after_start:

    • average_h = 2000: Penalty for arriving after the start of the time window.
    • as_soon_as_possible=true: Ability to promptly start the route.

The start time is now later, and the routes don't have any long waits.

API request (JSON)API responseView on map

Pricing by geofences

What situations to use this in

Use this scenario if the delivery cost depends on the geofence.

How to implement this scenario

Set the vehicle or courier cost using the formula with advanced cost settings. To determine the order geofence, use the in_zone option.

This scenario has some restrictions:

  • The ignore_zones option needs to be disabled.
  • You can use public geofences when planning via the API only.
  • You need to specify geofences for couriers in the formula and in one or more of the parameters: allowed_zones, forbidden_zones, or incompatible_zones.

Example

In the example, 4 couriers deliver 18 orders. Four of the orders have the optional vip tag. There are four geofences in the delivery zone: North-West, South-West, North-East, and South-East.

The following pricing plan is used:

  • Basic route cost: 5 units per 1 kilometer.

  • Delivery cost by zone (regardless of the number of orders):

    • South-West: 150 units.
    • North-West: 100 units.
    • South-East: 100 units.
    • North-East: 50 units.
  • For orders with the optional vip tag, 70 units are added to the basic route cost.

The price is expressed by the following formula:

5 * distance_km + 150 * has_location(is_delivery() & in_zone('South-West')) +
100 * has_location(is_delivery() & in_zone('South-East') | in_zone('North-West')) +
50 * has_location(is_delivery() & in_zone('North-East')) + 70 * order_count(has_tag('vip'))

The planning results in an optimized route where each courier visits one geofence only. The route cost is:

  • For courier 1: 5*49,506 + 100 + 70*1 = 417,53 units.
  • For courier 2: 5*39,03 + 50 + 70*1 = 315,15 units.
  • For courier 3: 5*39,405 + 150 = 347,025 units.
  • For courier 4: 5*34,047 + 100 + 70*2 = 410,235 units.

API request (JSON)API responseView on map

Contact support