Important concepts
The plan state¶
The Plotwise API plan has states. This means the plan has states and flows. It is really important the client is aware of it to make sure the requests sent are the ones allowed in a certain state.
You can find more state-related information in the flow section of the documentation and each entity state diagram in its reference page. E.g: Buckets state.
Tentative plan¶
A tentative plan is a valid plan available at every given time. It can be used to drive on, estimate the number of Routes for the final planning and makes it possible to check if specific deliveries can be delivered within a specific time slot.
It is however strongly recommended to take a look at the sequence diagram and the examples.
Non-Finalized Buckets¶
A regular cleanup task automatically cancels any non-finalized buckets (buckets in the open planning phase) whose due date is older than 2 days and newer than 7 days from the time of the cleanup.
Intermediate depots¶
Intermediate Depots are introduced in v2. The aim is to ensure that the maximum shift time is utilised and that resources are more efficiently used.
An intermediate depot is a dynamically inserted depot visit in the middle of a route. This additional depot visit breaks a single route down into multiple trips. A trip is a sequence of events where the first and last events are depot-like events (departure depot, arrival depot or intermediate depot), while all events between the first and last are deliveries. A route is therefore comprised of one or more trips (the number of trips in a route equals to 1 + the number of intermediate depots scheduled in it).
Trips exist so that the vehicle can reload and perform more deliveries within a given shift length. The following diagram illustrates the concept of Intermediate Depots:
To govern the addition of intermediary depots the following configuration parameters are set up at route creation.
- intermediate_depot_duration: The work time expended at that intermediate depot, i.e., its "stop time".
- capacity_threshold: This parameter is partially deprecated. It used to refer to the minimum used capacity ratio (used versus total) in a route for it to be considered for splitting (intermediary depot insertion). Currently, this value only needs to be filled with a value != 1.0 for the route to be considered for splitting.
- time_threshold: This parameter is partially deprecated. It used to refer to the maximum used capacity ratio (used versus total) of work time for a route to be considered for splitting (intermediary depot insertion). Currently, this value only needs to be filled with a value != 0.0 for the route to be considered for splitting.
- minimum_trip_length: This parameter is deprecated. It used to refer to the minimum work time duration a trip must have (in seconds) for it to be created (during an intermediate depot insertion) and continue to exist.
Intermediate depots are scheduled as needed in order to fit events into routes.
If adding a certain event to a route will cause its vehicle's capacity to be exceeded,
an intermediate depot (reload) stop will be planned in order to fit the event,
assuming that the route still has time to perform the intermediate depot (including the additional required drive time to/from the depot, and the extra intermediate_depot_duration
),
and assuming the driver_capacity
of the resource is not exceeded by the addition of the event.
Enable Intermediate Depots
To enable Intermediate Depots, it is mandatory to set intermediate_depot_duration
, capacity_threshold
and time_threshold
upon Route creation and vehicle_capacity
upon Resource creation.
Find more information about these entities in the Route, Resource and Event reference pages.
Intermediate depots examples¶
You can also find intermediate depots examples in here
Specifying Locations for Breaks¶
Routes can contain breaks to provide drivers with mandatory periods of rest at a defined interval. By default, the driver is assumed to be taking the breaks in their vehicle. This means that the location of the break will be the same as the location of the event preceding or succeeding the break. However, it is possible to specify a location for the break to be taken at. In this case, the planning will also take the time of travel to and from the break location into consideration when planning the break. To define a break, pass a geolocation when creating a route. You can read more about routes here.
Multiple Capacities¶
Originally only a single metric could be used to specify the capacity of an event and limit the capacity per trip (vehicle_capacity
) and route (driver_capacity
).
With multiple capacities, it is possible to specify up to 5 different metrics.
The interpretation of each metric is up to the customer but must be the same for every usage of capacities.
Examples of used interpretations are weight (in kilograms) and volume (in liters).
Assignment of resources to routes and prioritization of routes¶
Resources are assigned to routes based on vehicle_capacity
- bigger vehicles are assigned to longer routes (based on the time between the first and last timeslot_window
s of the route).
In the case of multiple capacities with a vehicle_capacity_vector
, the definition of "bigger" is based on the order capacity_1
-> capacity_2
-> ... -> capacity_5
.
For example, if a vehicle has a higher capacity_1
than another vehicle, it will be considered "bigger" regardless of the value of capacity_2
.
This behavior is respected when events are added to the planning, and maintained throughout the continuous planning, except when events are cancelled in a way that empties a long route.
This can be utilized to prioritize longer shifts in the planning - if there are as many large vehicles as there are long routes, the longer routes will be prioritized over shorter routes.
Resource route pairing¶
By default, any resource can be assigned to any route as long as capacity restrictions are respected. It is possible to explicitly pair one or more resources with one or more routes. This can, among others, be used to assign vehicles to routes starting from a specific depot.
When a resource has a resource_route_tag
, it is only assigned to a route with a matching resource_route_tag
. Resources and routes without tags are matched to each other. The prioritization rules explained in the section above are applicable within the set of matching resources and routes.
Tags are case-sensitive strings that cannot be longer than 32 characters and that can only contain letters (a-z), numbers, underscores, and hyphens. The field is optional, but if it is included in the request body, it cannot be left blank.
Resource-event and Route-event pairing¶
By default, events can be paired up with any resource and any route in the bucket. Tags can be assigned to events, routes and resources to change that behavior. When tagged, events will only be assigned to routes and resources that contain all of the tags present on an event. For maximum flexibility, route pairing and resource pairing are separate lists of tags.
Resource-event and route-event pairing can be used to indicate if certain deliveries can only be made for a specific subset either, such as requiring a driver with installation skills or a vehicle with a tailgate. Events with no matching resource or route will be returned as no-fits.
Tags are case-sensitive strings that cannot be longer than 32 characters and that can only contain letters (a-z), numbers, underscores, and hyphens. The field is optional, but if it is included in the request body, it cannot be left blank. There can be no more than 5 tags in each set of tags.
Freezing ETAs¶
Freezing ETAs guarantees that events stay within a given delivery window, even as the planning continues to be optimized and other events are being added. This mechanism could allow the user to freeze the bucket at a certain time in the evening and send emails to the end-customers containing the expected delivery window, while still allowing additional changes to the buckets and the planning
In order to make use of this functionality, one needs an initialized
bucket with some events planned in it. Such buckets can be transitioned into a frozen state by calling /buckets/{UUID}/action
endpoint with freeze
action along with two parameters seconds_before_eta
and seconds_after_eta
, see examples section for details.
This call creates, separately for every event, a restriction for the possible placement of events ETAs - a restriction that behaves similarly to approved suggestion windows.
This restriction is calculated to be [eta - seconds_before_eta, eta + seconds_before_eta] (where eta is the event ETA at the time of freezing the bucket), with some additional logic in edge cases where this window goes out of the range of the event min/max times or the selected timeslot.
The calculated window is stored in the frozen_window
field of events.
After triggering freeze
the bucket is moved into a frozen
state. Because of this new state, the initialized
state is no longer the only bucket state in which adding events is possible.
To make it easy to find buckets that can be modified, the bucket entity was extended with a new query param: mutable
(see examples section for usage).
Suggestions approved after freezing take precedence over the frozen window: such events will behave as if they were never frozen.
Freezing can be performed only on an initialized
bucket, a bucket that is already frozen
cannot be frozen again.
Planning profiles¶
The planning profiles is one of the attributes responsible for defining the behaviour of the bucket when processing and building the planning. In particular, planning profiles can be used to define a transport modality and/or specific parameters for a given depot area.
For instance, there can be one profile for bike and another for truck, but there can also be several profiles for bikes depending on different areas of service.
Profiles are customised to your needs, when getting access to the Plotwise service, you will be asked for information about your daily operations. This information will be used to generate a set of profiles that will fit your needs and make sure the plan is optimal.
You can find examples for planning profiles in here.
Feature flags¶
Feature flags are definitions within the planning profile, used to alter the behaviour of the bucket. By default, they are always false
.
The following feature flags are available for configuration:
allow_increased_reload_stops¶
By default, the maximum number of intermediate depots in a route is limited to be 2. This number can be increased to 3 by setting the allow_increased_reload_stops
feature flag to true
.
- When changing a profile's
false
into atrue
(i.e. to change a limit of 2 reload stops to 3 reload stops), all routes in the bucket will be able to use 3 reload stops. - When changing a profile's
true
into afalse
(i.e. to change a limit of 3 reload stops to 2 reload stops), only newly-added routes will have a limit of 2 reload stops. Older routes will still have a limit of 3.
special_ev_add_event¶
With the inclusion of the maximum_route_distance_meters
for resources, resources with an unlimited maximum route distance might get filled before ones that have a limited maximum route distance.
In that case, events that are far away from the depot might often become no-fits, as they cannot be reached by a resource with a limited driving distance.
This behavior can be altered by setting the special_ev_add_event
feature flag to true
.
When set to true
, before declaring a new event to be a no-fit, the planning will try to move some events from an unlimited-distance resource to a limited-distance resource in an attempt to provide enough room for the new event to fit in the planning.
If the new event still does not fit in the planning, it will be declared a no-fit.
Timeslots, min/max times, and suggestion timeslots¶
Tip
In this section, and in general in this documentation, "timeslot" and "window" mean the same thing, a min_time and a max_time. A time respects a timeslot/window if min_time <= time <= max_time.
The eta of an event determines when the event is expected to start. There are several data fields that limit the eta of events, especially deliveries and depots. The following behavior is guaranteed:
Depot etas will always be respect:
- The
min_time
andmax_time
from thedeparture_stop
(for the first depot) and thearrival_stop
(for the last depot) in the route'salgorithm_fields
. - The
min_time
andmax_time
from the route's firsttimeslot_window
(for the first depot) and the route's lasttimeslot_window
(for the last depot).
Delivery etas will always respect:
- The event
min_time
andmax_time
from the event itself. - The
min_time
andmax_time
from theselected_timeslot
within thealgorithm_fields
(if any). This field is filled when a suggestion has been picked and approved, based on the timeslot of that suggestion. - The
min_time
andmax_time
from thefrozen_window
within thealgorithm_fields
(if any). This field is filled when the bucket has been frozen. - In addition, when an event is assigned to a specific route, the etas will never be within the
min_time
andmax_time
of the first or the lasttimeslot_windows
of that route. This is because these two timeslots are reserved for vehicle loading/unloading and for driving.
There are several gotcha's that related to these limitations:
* The time limitations only apply to the eta itself. The end of the event (which is eta + stop_time) does not have to adhere to any of the rules described above.
* The middle timeslots within the route's timeslot_windows
are values that do not impact anything, they are validated for correctness and then ignored. (They used to have meaning, and an impact on performance, but do not anymore).
* If there is a gap between the max_time
of the departure_stop
and the min_time
of the arrival_stop
, this translates to "the driver is not allowed back at the depot until the arrival_stop's min_time, even if that driver is done with deliveries and waiting at the parking lot". Effectively, this means that optimization will struggle with finding better solutions, because there is no advantage to letting the driver arrive at the depot earlier in the day.
* To avoid confusion, timeslots whose min_time
and max_time
do not fully fit within the event's min_time
and max_time
are not considered to be valid for suggestions, and will never be given in the return values of the suggestion request.
That last gotcha deserves a practical example:
In theory, when an event has min/max_times and a selected timeslot, the eta of that event will adhere to the most restrictive limitation.
For example, an event with business hours limitations (min_time
= 9:00, max_time
= 17:00) and an afternoon selected timeslot (12:00-18:00) will be guaranteed by the code to have an eta between 12:00 and 17:00.
However, in reality, allowing such suggestions could create a lot of confusion - If a customer has the limitation of business hours and then gets a timeslot of 12:00-18:00, they might worry that they'll get their delivery at 17:30 (when the office is closed). To avoid this confusion, any timeslot that does not fit fully within the event's min/max_times is not considered valid and will not be returned as a possible suggestion.
This means that the afternoon timeslot of 12:00-18:00 will never be possible to be selected for a business-hour event. To work around this limitation, any timeslot sent in the suggestion request should be changed so that it's completely contained within the event's min/max_times. Namely, in this case, the morning timeslot should be 9:00-12:00 (instead of 7:30-12:00), and the afternoon timeslot should be 12:00-17:00 (instead of 12:00-18:00).