×

Welcome to Knowledge Base!

KB at your finger tips

This is one stop global knowledge base where you can learn about all the products, solutions and support features.

Categories
All
CRM-Salesforce
Salesforce Developers

Multiple Vehicles, Single Shift

Jimmy and Sally have been wildly successful and have new contracts with a few embassies in and around Washington, DC. Unfortunately, these embassies require native speakers of their respective languages, and so they also had to hire some new crew members. Luckily they were able to hire some linguistic geniuses that speak several languages. The examples below illustrate how the optimization engine can handle multiple vehicles on the same day and also match attributes so that the right vehicle services certain orders. This capability can be useful in a variety of "skill matching" use cases.

  • VEHICLES — The vehicles can have shifts that are completely independent of the other vehicles in terms of their start/end location and start/end times. Additionally, we can associate attributes with each vehicle and then force attribute matching with constraints. In this example, the vehicles will all be operating on the same day with the same shift times. Note that an individual vehicle cannot have shifts that overlap.
  • CONSTRAINTS — We will make use of the match_attributes constraint in this example to illustrate skill/vehicle matching with various orders.
  • ORDERS — We have some new orders in DC at various embassies. We associate attributes with each order using arbitrary strings.
Expand to view request sample

The fleet of three vehicles is able to visit all orders as we can see below. However, now that we are forcing attribute matching the routes inside the city appear inefficient as the green (Finnish speaking) vehicle comes into the "Embassy Row" area to service only a single order that is very near the routes of the other vehicles. However, since these vehicles don't match the attributes of the order at the Finnish assembly, they are not eligible to service the order.

img

The full 3 vehicle, single day solution where we enforce the attribute matching.

img A zoomed in view to show the travel inefficiencies that can result from enforcing the attribute matching. In this case, the green (Finnish speaking) vehicle services the green order #4 by going out of the way into the Embassy Row area. The orange and pink vehicles are nearby but do not match the attributes of the order at the Finnish Embassy, so they cannot service the order.

To illustrate the impact of this skill matching, we can simply remove the attributes and the match_attributes constraint to quickly find a new solution. In this case we service all the orders but now reduce the total travel time by about 30 minutes. Zooming in on the same area as in the above image, we can see that all six embassies in this area are serviced by the same vehicle.

img

Salesforce Developers

Pickup and Delivery Problems

The optimization engine provides the ability to solve complex logistical problems that involve pickups, deliveries, dropoffs, unloading, and replenishment of multiple item types. To be clear on exactly what these events are, we first clarify the specification of these problems and precisely define the event types that are supported.

An item is simply a physical object that is involved in the routing problem. The items are presented as top-level objects in the request that are then referenced elsewhere. An example of the JSON specification for two item types:

One can express the capacity of a vehicle in three ways:

One can express the capacity of vehicles in three ways: by quantity of each item type, by weight, or by volume. Note that any time that the optimization engine returns a solution, all routes will adhere to each dimension of the vehicle capacity. When specifying the capacity of a vehicle, volume_capacity and weight_capacity are optional and allow you to specify a capacity that involves multiple item_types that have different weights and volumes. However, if a vehicle is to carry a certain item_type, then that item type must be contained in the capacity_by_item array. Regarding the units for weight and volume, these are completely arbitrary and are just treated as numeric values by the optimization algorithm -- just make sure that you use consistent units for weight and volume when specifying your items and caapcities. The example below shows all of the different ways to express the capacity of a vehicle.

Demand for a pickup/delivery event is specified inside the orders. There are four different event types that can occur in our pickup/delivery problems

Delivery

In a delivery event, items are delivered to a customer location as part of the servicing of the order. It is important to note that the optimization determines the amount of each item that each route starts with - this is given in the start_items array in the response and is equal to the smallest amount of items necessary to fully satisfy all demand on the route. When servicing an order that involves a delivery, the item must be on the vehicle prior to servicing the order, and the amount carried on the vehicle will be decreased by the amount delivered upon completing the service. Also, if both a pickup and delivery or dropoff occur at the same order, then for the purposes of tracking the items carried on the vehicle, we assume that the delivery or dropoff always occurs before the pickup event. An example delivery demand is expressed as follows:

Pickup

Items are picked up at an order and placed in the vehicle. As mentioned previously, if a delivery or dropoff event also occurs at a stop, these events are assumed to occur before the pickup. The items picked up may be carried on the vehicle for the remainder of the route, or they may be dropped off at another location or order if a dropoff location is specified or if the route services another order that has a delivery demand for the same item type. Upon picking up the item, the vehicle’s amount carried will be increased appropriately and compared against the relevant capacity dimensions. In cases where items of the same general type are picked up and delivered, but one does not want to deliver the items picked up on the route, then a descriptive item_type can be used to guarantee this behavior. For example, if you are picking up portable toilets, it is highly recommended to use "dirty toilets" and "clean toilets" as separate item types to guarantee that a customer receives a toilet in the expected condition! A pickup demand is expressed as follows

Replenishment

In problems that involve the delivery of the same item type(s) to multiple locations, it may be beneficial to replenish the supply of that item mid-route so as to service more orders over the course of the shift. There may be multiple replenishment sites available that are different from a central depot where the routes may start. A replenishment event involves re-supplying the vehicle with an amount of item(s) determined by the optimization. This is accomplished by adding a separate order that has a replenishment capacity as shown below. Note that replenishment orders are only visited if the optimization determines it is beneficial to do so, so that a default value of min_visits =0 is set for these orders. That way there is no penalty for the visit_range constraint if we do not visit these orders. An example replenishment order is provided below – as with standard orders, one can specify a duration and a maximum # of visits.

Unloading

In a case where items are picked up at customer locations, one can specify certain orders where a vehicle can unload its contents so that more items can be picked up. For example, a waste disposal company may have different dump sites so that the route optimization can select where to unload the contents. The vehicle can then continue to pick up more items at subsequent stops. As with replenishment orders, min_visits is forced to be 0 for these orders and they are only visited when it helps to improve the solution.

Dropoff

In our terminology, a dropoff is different from a delivery in that a specific item picked up during the course of a route can be dropped off at a specified stop along the way prior to the end of a route. For example, passengers may be picked up at the airport and be transported to a hotel with intermediate stops potentially on the way. In contrast, for an order that specifies a delivery event via delivery_item_quantities , one has no control over where a delivered item came from -- the items could be from the initial loading of the vehicle, a replenishment event, or items picked up at a different order. In general, when "point to point" shipment of an item is needed then an order should be specified with a dropoff_location_id to specify this behavior. More details on this distinction are available in the Pickup and Dropoff tutorial

Read article
Salesforce Developers

Pickup and Dropoff Problems

In our routing problems, items are loaded onto our vehicles in a variety of ways: they may be loaded onto the vehicle at the start of the route, items may be picked up at a customer order, or supply can be replenished at a specially designated "replenishment order". Once an item is onboard the vehicle, then it is eligible for a delivery event for orders that specify this item type in delivery_item_quantities . However, when these items are delivered, there is no way to specify that a specific item of that type should be delivered to a specific location. In other words, if the items are boxes, then with the typical usage of pickup_item_quantities and delivery_item_quantities there is no way to guarantee that a specific box is delivered to a specific location. However, this behavior can be guaranteed with the notion of a dropoff .

Given an order with items to be picked up, one can designate that these items are dropped off later in the route at a specific location by specifying a dropoff_location_id as part of the order object. An optional dropoff_deadline can be specified inside the order object to specify the latest time that the dropoff occurs. Adherence to this deadline is enforced via the dropoff_deadline constraint. Additionally, in cases where a deadline is less important than the amount of time an item spends on the vehicle (as in passenger pickup and dropoff or the transport of perishable goods), one can use the journey_time to limit the time between the pickup event and the eventual dropoff. The example order below demonstrates how to specify this sort of dropoff event.

For all problems involving the pickup of items that are then dropped off at a subsequent stop later in the same route, the optimization keeps track of the items on the vehicle and ensures that a vehicle's load never exceeds its capacity (specified in the vehicle object via capacity_by_item , weight_capacity , and/or volume_capacity ).

In the example request below, we have a fleet of three passenger vans that can each carry up to 6 people (this limit is set via the capacity_by_item for each vehicle). The vans start and end at different hotels in Atlanta, and the task is to pickup a variety of individuals and groups at locations throughout the city and drop them off later on at a different location. Many orders consist of multiple passengers and many orders also have a dropoff_deadline that is enforced with the dropoff_deadline constraint. In order to provide high quality service and to try to ensure that customers do not remain on the vehicle too long, we also provide a journey_time constraint that penalizes any route that has a customer on the vehicle for longer than 60 minutes.

Expand to view request sample
Read article
Salesforce Developers

Balanced Pickup and Unloading

In this example, we have a fictitious company that picks up various sizes of boxes and can unload them at a central facility when the vehicle is full. We have a fleet of heterogeneous vehicles that pick up the three item types as seen in the items array below

The vehicles are constrained in terms of how much of each item they can carry as well as by volume and weight. Each vehicle’s capacity is expressed separately as part of the vehicle object, and an example vehicle object now looks like this

Similar to delivery problems, we express the amount to be picked up at each order with pickup_item_quantities . In problems involving pickups, the vehicle may become full during the shift and be therefore unable to service any more orders. By specifying certain orders to have the ability to receive unloaded items , we can extend the shift since the vehicle can empty its contents at these orders. An example of such an order is below. Note that the amount that can be unloaded must be set – typically this should be a very large value to allow essentially unlimited unloading.

A full request involving pickups, unloading events, and a num_stops constraint to balance the routes is given below.

Expand to view request sample

img

All orders are visited and the routes are very balanced in terms of number of stops (either 10 or 11 orders serviced in each route). The unloading facility (boxed in red) is visited a total of 8 times to allow the vehicles to empty their contents and continue the route.

In the routes returned in the API response, any stop where items are picked up will have details of what is picked up, and how much of each item is in the vehicle at that time

In the API response, the orders array contains the details of all the visits to the order. Of interest is the Unload at trash facility order :

Additionally, for every stop at the unloading facility, an items_unloaded array is included to describe the activity at the stop.

Other features of the pickup/delivery aspects of the route are also included in the route object, such as max_volume_in_vehicle , max_num_items_in_vehicle , and max_weight_in_vehicle . Since vehicle capacity constraints are never violated, the optimization engine ensures that no vehicle will ever be carrying more than its capacity at any point during the route (in terms of weight/volume/number of items). The unloading stops are strategically inserted by the algorithm in order to satisfy as many orders as possible while still respecting the vehicle capacities.

Read article
Salesforce Developers

Delivery Only Problem

In this example, we have a fleet of heterogeneous vehicles that deliver two item types, box (volume of 1 unit) and big_box (volume of 2 units) as seen in the items array below

The vehicles are constrained both in terms of how much of each item they can carry as well as by maximum volume carried. Each vehicle’s capacity is expressed separately allowing for a truly heterogeneous fleet. Our vehicle object now looks like this

The orders also have a demand for some number of items of these types – this is expressed in their delivery_item_quantities as seen in the full request below. Note that there are no pickup_item_quantities at any of the orders so that this is a pure delivery problem where the optimization engine will determine how much of each item type each vehicle must start the route with.

Expand to view request sample

img

In this case we use all 4 vehicles but are unable to visit 4 of the orders due to the capacity constraints on the vehicles. Below, we see the impact of doubling each vehicle’s capacity – we are now able to visit all the orders and actually only need 3 of the 4 vehicles to do so.

img

The impact of doubling vehicle capacity. In the API response, the items_delivered at each stop is given in an array

The optimization engine also determines how many items the vehicle must have on board when the shift begins. This is recorded in the start_items object of the route. By loading the vehicle with these items at the start of the route, all orders in the route will have their delivery demand satisfied.

Other features of the delivery aspect of the route are also included in the route object, such as max_volume_in_vehicle , max_num_items_in_vehicle .

Read article
Salesforce Developers

Single Vehicle

Jimmy and Sally have just started a lighting company to service a number of commercial addresses. Lucky for them, their first major assignment is a government contract. They start and end their day at the White House, and here are the places they were assigned to service.

  • The Washington Monument: 38.889484, -77.035278
  • Ford’s Theatre: 38.8967, -77.0257
  • Abe Lincoln Memorial: 38.8893, -77.0502
  • The Vietnam Memorial: 38.8913, -77.0477
  • The Thomas Jefferson Memorial: 38.8814, -77.0365

We begin by building out a JSON payload and add the locations of the job sites as a simple array of locations objects:

Jimmy and Sally also think about the time they want to start and end their day. They estimate the amount of time (in seconds) required to service each order and add this as the duration. They also prioritize the orders since there is a chance they may not be able to service all the orders in a single day (shift). Note that an order is directly related to a location. Conceptually, orders represent a request for service (such as delivering goods to a store), and a higher priority indicates that if it is not possible to visit all orders, then the higher priority orders should be favored.

With the locations and orders specified, the next step is to define constraints. the Optimization API has an extensive library of constraints that allows you to very precisely define what a “good” solution looks like. In this case, the objective is simple: visit as many orders as possible, minimize travel time, and make sure that if we can’t visit all the orders, we at least visit the highest priority orders. Each constraint has a penalty which determines how important it is to satisfy. For many constraints, the degree of the constraint violation can also be included in the penalty via the violation_increment . We do this below with the travel_time constraint so that each second that a vehicle travels is assessed a penalty of 1. This gives us a standard way of thinking about penalties and is recommended in all use cases. The visit_range constraint tells the Optimization API that we want to visit as many orders as possible. Since the penalty for this constraint is 10,000, if we miss an order then the solution is assessed a penalty of 10,000. The order_priority constraint indicates that orders with higher priority should be favored if all orders cannot be serviced (see the documentationof this constraint for additional details).

Sally and Jimmy also need to specify a vehicle and their shift. The shift is how the Optimization API knows when the vehicle and associated workers are allowed to operate. In this case, Sally and Jimmy define the shift as being from 8:30am to 5:00pm, and they also specify where the shift must start and end (the White House). Note that a shift can start and end at somewhere other than an order, for example a worker’s home address. Also, they specify vehicle type “car”. If routes for trucks and other restricted vehicles are desired, then the vehicle type can be set to “truck” with other parameters in order to ensure that the routes returned by the Optimization API are compliant.

You’ll notice that the vehicles parameter is actually an array. This is because the Optimization API can support multiple vehicles for a given problem. Additionally, each vehicle can operate for multiple shifts so that the Optimization API is able to solve problem involving many disjoint shifts. We will return to this more advanced functionality in later examples. Putting it all together, the payload looks like this.

Expand to view request sample

img

Four of the five orders are visited. The lowest priority Vietnam Memorial (red pin) is missed, but otherwise the route is efficient in terms of travel and meets our objectives.

The urgencyconstraint is different from Order Priority in that it tries to satisfy visiting more urgent orders earlier during the planning period (represented by a vehicle’s shift object). In the original solution, we visited the Lincoln Memorial as the last order. Now suppose we need to visit the Lincoln Memorial and Ford’s Theater earlier in the planning horizon. We could either add time windows for these orders or use the urgency constraint to encourage visiting them earlier in the day. First we will demonstrate this capability by adding urgency values for these two orders and then adding a new constraint of type urgency. The new request is below (only change to first request is addition of urgency constraint).

Expand to view request sample

img

img

The high urgency orders at Ford’s Theater and the Lincoln Memorial are now visited earlier in the day. The route is less efficient from a travel perspective but the sequence better meets our objectives. The Vietnam memorial is still not visited since we still have the order_priority constraint in place.

Sally and Jimmy received some changes – they will also have to service the Ravens football stadium in Baltimore. They reflected on how they might change their trip around. Some of the job sites are more complex than others and require more time. Instead of spending one quick day in DC, they need to spread their trip over two days. As such, they reserve a night or two at a hotel north of DC. Sally appends this location (39.064295, -76.965838) to their list. They will start each day at the hotel, plan on ending at the White House on day 1 to do some sightseeing, and will also plan on celebrating the end of the DC work by going to a sushi restaurant in Annapolis – this will be the end_location of their shift on the second day.

Let’s summarize how these stipulations change the the Optimization API payload.

  • LOCATIONS — Not much changes here. Sally just adds the latitude and longitude of the stadium, hotel and restaurant to the array.

  • SHIFTS — Sally adds another shift to the shift array to account for the extra day. Additionally, with all this new work they will be hungry so lunch breaks are now added each day from noon to 1pm.

  • ORDERS — The amount of work changes at each order, so the durations change, we add an appointment at the Lincoln Memorial and Vietnam Memorial, and also add a new long job at the Ravens stadium. Note that adding the appointment to the order doesn’t guarantee that we will visit it – we need a constraint to enforce that.

  • CONSTRAINTS — Sally now specifies a scheduled_appointment constraint with a high penalty to ensure the appointments are met.

Expand to view request sample

Luckily it is still possible for the pair to complete all the work, do some sightseeing and finish with a celebration in Annapolis. Since the Optimization API accounts for predicted traffic in its routing calculations, the pair takes paths between locations that minimize the estimated travel time. Nevertheless, the pair expect their total travel time to be about 39 minutes longer due to traffic over the two day period (total_traffic_time in the response).

img

The first day in purple, the second day is in green. Note that the shifts are for the same vehicle but the Optimization API allows you to have different start or end locations for individual shifts.

Sally and Jimmy have now received word that some of the locations they are servicing have other events planned, and they must arrive at the orders only during certain times. These are referred to as time windows and the Optimization API allows us to ensure that service at an order only begins during a time window. We remove the appointments from the existing orders and now update each order with a time window. This will lead to a less efficient route from a travel perspective, but they will now be starting service at each order only during the allowed window.

  • Orders : Each order now receives a time window.
  • Constraints : The scheduled_appointment constraint is removed in favor of a time_window constraint. Note that we use a violation_increment of 3600 in this constraint which makes the penalty depend on by how much we violate a time window. For example, if we are 3 hours late for a time window, then we will be hit with a penalty of 5000 for the initial violation plus another 3*5000 = 15,000 to penalize the fact that we are 3 hours late. The total penalty in this case is then 20,000 – equivalent to about 6 hours of travel.
Expand to view request sample

Luckily it is still possible to service all the orders where the pair arrives during a time window, eat lunch, and start/end each day at the desired location. Now the workload is more spread out across each day with 3 orders serviced on each day.

img

The Full solution for the two-day situation where all time windows are honored.

img Zoomed in view of the 5 orders visited in the city. Note that time windows often force us to visit orders in a less efficient sequence than we would do otherwise.

Read article

Still Thinking?
Give us a try!

We embrace agility in everything we do.
Our onboarding process is both simple and meaningful.
We can't wait to welcome you on AiDOOS!