The OptimizeToursRequest
message (REST, gRPC) contains a number of
properties related to
costs. Together, these cost parameters represent the request's
cost model. The cost model captures many of the request's high-level
optimization objectives, such as:
- Prioritizing faster
Vehicle
routes over shorter routes or the other way around - Deciding whether the cost to deliver a
Shipment
is worth the value of theShipment
's completion - Performing pickups and deliveries within time windows only when doing so is cost effective
See an example request with costs
{ "model": { "globalStartTime": "2023-01-13T16:00:00-08:00", "globalEndTime": "2023-01-14T16:00:00-08:00", "shipments": [ { "deliveries": [ { "arrivalLocation": { "latitude": 37.789456, "longitude": -122.390192 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 100.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 5.0 }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 50.0 } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0 } ] } }
Vehicle
cost properties
The Vehicle
message (REST, gRPC) has several cost properties:
Vehicle.cost_per_hour
: represents the cost of operating a vehicle per hour inclusive of transit, wait, visit, and break times..Vehicle.cost_per_kilometer
: represents the cost per kilometer traveled by the vehicle.Vehicle.cost_per_traveled_hour
: represents the cost of operating a vehicle only while in transit, excluding wait, visit, and break times.
These cost parameters allow the optimizer to make time-versus-traveled-distance
tradeoffs. The costs incurred by the optimized route appear in the response
message as metrics.costs
:
As costPerHour
increases, the optimizer attempts to find faster routes
that may not be the shortest routes. In this example the fastest route happens
to be the shortest, so changes to the cost parameters have little effect.
Shipment
cost properties
The Shipment
message (REST, gRPC) also has several cost
parameters:
Shipment.penalty_cost
represents the cost incurred by skipping the shipment.Shipment.VisitRequest.cost
represents the cost of a specific pickup or delivery, used primarily to enable cost tradeoffs between multiple pickup or delivery options for a single shipment.
Shipment
cost parameters use the same dimensionless units as Vehicle
cost
parameters. Cost incurred complete a Shipment
exceeds its penalty cost, the
Shipment
is not included on any Vehicle
's route and instead appears in the
skipped_shipments
list in the response message.
ShipmentModel
cost properties
The ShipmentModel
message (REST, gRPC) includes a single cost
property, globalDurationCostPerHour
. This cost is incurred based on the total
time required for all vehicles to complete their ShipmentRoute
s. Increasing
globalDurationCostPerHour
prioritizes earlier completion of all shipments.
Route Optimization response cost properties
The OptimizeToursResponse
message (REST, gRPC) has cost properties
that represent the costs incurred in the process of completing ShipmentRoute
s.
The metrics.costs
and metrics.totalCost
properties represent the number of
cost units incurred across all routes in the response. Each routes
entry has
routeCosts
and routeTotalCosts
properties that represent costs for that
specific route.
See a response to the example request with costs
{ "routes": [ { "vehicleStartTime": "2023-01-14T00:00:00Z", "vehicleEndTime": "2023-01-14T00:28:22Z", "visits": [ { "isPickup": true, "startTime": "2023-01-14T00:00:00Z", "detour": "0s" }, { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-14T00:02:30Z", "detour": "150s" }, { "startTime": "2023-01-14T00:08:55Z", "detour": "150s" }, { "shipmentIndex": 2, "startTime": "2023-01-14T00:21:21Z", "detour": "572s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:00:00Z" }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:02:30Z" }, { "travelDuration": "235s", "travelDistanceMeters": 795, "waitDuration": "0s", "totalDuration": "235s", "startTime": "2023-01-14T00:05:00Z" }, { "travelDuration": "496s", "travelDistanceMeters": 1893, "waitDuration": "0s", "totalDuration": "496s", "startTime": "2023-01-14T00:13:05Z" }, { "travelDuration": "171s", "travelDistanceMeters": 665, "waitDuration": "0s", "totalDuration": "171s", "startTime": "2023-01-14T00:25:31Z" } ], "metrics": { "performedShipmentCount": 2, "travelDuration": "902s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "800s", "totalDuration": "1702s", "travelDistanceMeters": 3353 }, "routeCosts": { "model.vehicles.cost_per_kilometer": 33.53, "model.vehicles.cost_per_hour": 18.911111111111111 }, "routeTotalCost": 52.441111111111113 } ], "skippedShipments": [ { "index": 1 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 2, "travelDuration": "902s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "800s", "totalDuration": "1702s", "travelDistanceMeters": 3353 }, "usedVehicleCount": 1, "earliestVehicleStartTime": "2023-01-14T00:00:00Z", "latestVehicleEndTime": "2023-01-14T00:28:22Z", "totalCost": 57.441111111111113, "costs": { "model.vehicles.cost_per_kilometer": 33.53, "model.vehicles.cost_per_hour": 18.911111111111111, "model.shipments.penalty_cost": 5 } } }
In the example response, the top-level metrics.costs
are:
{
"metrics": {
...
"costs": {
"model.vehicles.cost_per_hour": 18.911111111111111,
"model.vehicles.cost_per_kilometer": 33.53,
"model.shipments.penalty_cost": 5
}
}
}
The model.shipments.penalty_cost
value represents the cost incurred due to
skipped shipments. The skippedShipments
property lists which shipments were
skipped.
In this example, only model.shipments[1]
in the example request is skipped.
model.shipments[1]
has a penalty cost of 5 units, which matches the total
model.shipments.penalty_cost
key in the example response. The shipment's low
penaltyCost
compared to the Vehicle
's 40.0 costPerHour
and 10.0
costPerKilometer
make it more cost-effective to skip the shipment than to
complete it.
Advanced topic: costs and soft constraints
Several OptimizeToursRequest
message (REST, gRPC) properties
represent soft constraints, which are constraints that incur a cost when they
cannot be satisfied.
For example, vehicle LoadLimit
(REST, gRPC) constraints have
softMaxLoad
and costPerUnitAboveSoftMax
properties. Together, these incur a
cost proportional to the load units that exceed softMaxLoad
, allowing the
limit to be exceeded only if doing so makes sense from a cost standpoint.
Similarly, TimeWindow
constraints (REST, gRPC) has
soft_start_time
and soft_end_time
properties, with corresponding
cost_per_hour_before_soft_start_time
and cost_per_hour_after_soft_end_time
that are incurred based on how early or late the constrained event occurs with
respect to the TimeWindow
.
As with all cost model parameters, soft constraint costs are expressed in the same dimensionless units as other cost parameters.
LoadLimit
constraints are addressed in detail in
Load Demands and Limits. TimeWindow
constraints are addressed in detail
in Pickup and Delivery Time Window Constraints.