Google Maps Route Optimization API client library for assigning tasks and routes to vehicle fleets while optimizing against custom objectives and constraints.
—
Core single-request route optimization functionality for optimizing vehicle tours against custom objectives and constraints. This capability provides the primary API method for solving vehicle routing problems with shipments, vehicles, and optimization parameters.
Optimizes vehicle tours for a single ShipmentModel, returning optimized routes that minimize total cost while satisfying constraints.
def optimize_tours(
request: OptimizeToursRequest,
*,
retry: Optional[Retry] = gapic_v1.method.DEFAULT,
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
metadata: Sequence[Tuple[str, Union[str, bytes]]] = ()
) -> OptimizeToursResponse: ...Parameters:
request: OptimizeToursRequest - The optimization request containing the ShipmentModel and parametersretry: Optional retry configuration for the requesttimeout: Optional timeout for the request (float seconds or object)metadata: Optional metadata sequence for the requestReturns: OptimizeToursResponse containing optimized routes, metrics, and any validation errors
class OptimizeToursRequest:
parent: str # Required. Format: "projects/{project-id}" or "projects/{project-id}/locations/{location-id}"
timeout: Optional[duration_pb2.Duration] # Maximum computation time
model: Optional[ShipmentModel] # The shipment model to optimize
solving_mode: Optional[SolvingMode] # Optimization approach (DEFAULT_SOLVE, VALIDATE_ONLY, DETECT_SOME_INFEASIBLE_SHIPMENTS)
search_mode: Optional[SearchMode] # Search strategy (RETURN_FAST, CONSUME_ALL_AVAILABLE_TIME)
injected_first_solution_routes: Optional[Sequence[ShipmentRoute]] # Pre-assigned routes
injected_solution_constraint: Optional[InjectedSolutionConstraint] # Solution constraints
refresh_details_routes: Optional[Sequence[ShipmentRoute]] # Routes to refresh
interpret_injected_solutions_using_labels: Optional[bool] # Use labels for injected solutions
consider_road_traffic: Optional[bool] # Include traffic in routing
populate_polylines: Optional[bool] # Include route polylines in response
populate_transitions: Optional[bool] # Include transition details
allow_large_deadline_despite_interruption_risk: Optional[bool] # Allow long deadlines
use_geodesic_distances: Optional[bool] # Use geodesic distance calculations
geodesic_meters_per_second: Optional[float] # Speed for geodesic calculations
max_validation_errors: Optional[int] # Maximum validation errors to return
label: Optional[str] # Request label for trackingclass OptimizeToursResponse:
routes: Sequence[ShipmentRoute] # Optimized vehicle routes
request_label: str # Label from the request
skipped_shipments: Sequence[SkippedShipment] # Shipments that couldn't be assigned
validation_errors: Sequence[OptimizeToursValidationError] # Input validation errors
metrics: Optional[AggregatedMetrics] # Optimization statistics and costs
total_cost: float # Total cost of the solutionfrom google.maps import routeoptimization_v1
client = routeoptimization_v1.RouteOptimizationClient()
# Create optimization request
request = routeoptimization_v1.OptimizeToursRequest(
parent="projects/my-project",
model=routeoptimization_v1.ShipmentModel(
shipments=[
routeoptimization_v1.Shipment(
display_name="Delivery 1",
deliveries=[{
"location": {"lat_lng": {"latitude": 37.7749, "longitude": -122.4194}},
"time_windows": [{"start_time": {"seconds": 28800}, "end_time": {"seconds": 64800}}], # 8 AM - 6 PM
"duration": {"seconds": 300} # 5 minutes
}]
)
],
vehicles=[
routeoptimization_v1.Vehicle(
display_name="Truck 1",
start_location={"lat_lng": {"latitude": 37.7649, "longitude": -122.4294}},
end_location={"lat_lng": {"latitude": 37.7649, "longitude": -122.4294}},
start_time_windows=[{"start_time": {"seconds": 28800}, "end_time": {"seconds": 32400}}], # 8 AM - 9 AM
end_time_windows=[{"start_time": {"seconds": 57600}, "end_time": {"seconds": 64800}}], # 4 PM - 6 PM
cost_per_hour=25.0,
cost_per_kilometer=1.2
)
]
)
)
# Optimize tours
response = client.optimize_tours(request=request)
# Process results
print(f"Total cost: ${response.total_cost:.2f}")
for i, route in enumerate(response.routes):
print(f"Route {i}: {len(route.visits)} stops")
for visit in route.visits:
print(f" Stop: {visit.shipment_label} at {visit.start_time}")from google.maps import routeoptimization_v1
from google.protobuf import duration_pb2
client = routeoptimization_v1.RouteOptimizationClient()
# Create request with time constraints and vehicle capacities
request = routeoptimization_v1.OptimizeToursRequest(
parent="projects/my-project",
timeout=duration_pb2.Duration(seconds=300), # 5 minute timeout
model=routeoptimization_v1.ShipmentModel(
global_start_time={"seconds": 28800}, # 8 AM
global_end_time={"seconds": 64800}, # 6 PM
shipments=[
routeoptimization_v1.Shipment(
display_name="Heavy Package",
deliveries=[{
"location": {"lat_lng": {"latitude": 37.7749, "longitude": -122.4194}},
"duration": {"seconds": 600}, # 10 minutes
"load_demands": {"weight": {"amount": 50}} # 50 units of weight
}]
)
],
vehicles=[
routeoptimization_v1.Vehicle(
display_name="Small Truck",
start_location={"lat_lng": {"latitude": 37.7649, "longitude": -122.4294}},
load_limits={"weight": {"max_load": 100}}, # Max 100 units
break_rule=routeoptimization_v1.BreakRule(
break_requests=[{
"earliest_start_time": {"seconds": 43200}, # 12 PM
"latest_start_time": {"seconds": 46800}, # 1 PM
"min_duration": {"seconds": 1800} # 30 minutes
}]
)
)
]
),
consider_road_traffic=True,
populate_polylines=True
)
response = client.optimize_tours(request=request)
# Check for skipped shipments
if response.skipped_shipments:
print("Some shipments could not be assigned:")
for skipped in response.skipped_shipments:
print(f" {skipped.label}: {[r.name for r in skipped.reasons]}")from google.maps import routeoptimization_v1
client = routeoptimization_v1.RouteOptimizationClient()
# Validate model without optimization
request = routeoptimization_v1.OptimizeToursRequest(
parent="projects/my-project",
solving_mode=routeoptimization_v1.OptimizeToursRequest.SolvingMode.VALIDATE_ONLY,
model=your_shipment_model
)
response = client.optimize_tours(request=request)
# Check validation errors
if response.validation_errors:
print("Model validation errors:")
for error in response.validation_errors:
print(f" {error.error_message}")
else:
print("Model is valid")class SolvingMode(enum.Enum):
DEFAULT_SOLVE = 0 # Solve the model
VALIDATE_ONLY = 1 # Only validate, don't solve
DETECT_SOME_INFEASIBLE_SHIPMENTS = 2 # Detect infeasible shipmentsclass SearchMode(enum.Enum):
RETURN_FAST = 0 # Return quickly with good solution
CONSUME_ALL_AVAILABLE_TIME = 1 # Use all available time for best solutionclass AggregatedMetrics:
performed_shipment_count: int # Number of shipments performed
travel_duration: Optional[duration_pb2.Duration] # Total travel duration
wait_duration: Optional[duration_pb2.Duration] # Total wait duration
delay_duration: Optional[duration_pb2.Duration] # Total delay duration
break_duration: Optional[duration_pb2.Duration] # Total break duration
visit_duration: Optional[duration_pb2.Duration] # Total visit duration
total_duration: Optional[duration_pb2.Duration] # Total route duration
travel_distance_meters: float # Total travel distance
max_loads: Mapping[str, ShipmentRoute.VehicleLoad] # Maximum loads achievedclass SkippedShipment:
index: int # Shipment index in original request
label: str # Shipment label
reasons: Sequence[SkippedShipment.Reason] # Reasons for skipping
class Reason:
code: SkippedShipment.Reason.Code # Reason code
display_name: str # Human-readable reason
example_vehicle_index: int # Example vehicle that couldn't handle shipment
example_exceeded_capacity_type: str # Capacity type that was exceeded
class Code(enum.Enum):
CODE_UNSPECIFIED = 0
NO_VEHICLE = 1 # No vehicle can handle this shipment
DEMAND_EXCEEDS_VEHICLE_CAPACITY = 2 # Shipment demands exceed capacity
CANNOT_BE_PERFORMED_WITHIN_VEHICLE_DISTANCE_LIMIT = 3 # Distance limit exceeded
CANNOT_BE_PERFORMED_WITHIN_VEHICLE_DURATION_LIMIT = 4 # Duration limit exceeded
CANNOT_BE_PERFORMED_WITHIN_VEHICLE_TRAVEL_DURATION_LIMIT = 5 # Travel duration exceeded
CANNOT_BE_PERFORMED_WITHIN_VEHICLE_TIME_WINDOWS = 6 # Time window conflicts
VEHICLE_NOT_ALLOWED = 7 # Vehicle not allowed for this shipmentclass OptimizeToursValidationError:
code: int # Error code
display_name: str # Human-readable error name
fields: Sequence[OptimizeToursValidationError.FieldReference] # Fields with errors
error_message: str # Detailed error message
offset_index: int # Index of problematic element
class FieldReference:
name: str # Field name with error
index: int # Index if field is repeated
key: str # Key if field is a map
sub_field: Optional[OptimizeToursValidationError.FieldReference] # Nested field referenceclass ShipmentRoute:
vehicle_index: int # Index of vehicle performing this route
vehicle_label: str # Label of vehicle performing this route
vehicle_start_time: Optional[timestamp_pb2.Timestamp] # Route start time
vehicle_end_time: Optional[timestamp_pb2.Timestamp] # Route end time
visits: Sequence[ShipmentRoute.Visit] # Visits in order
transitions: Sequence[ShipmentRoute.Transition] # Transitions between visits
has_traffic_infeasibilities: bool # Whether route has traffic issues
route_polyline: Optional[ShipmentRoute.EncodedPolyline] # Encoded route polyline
breaks: Sequence[ShipmentRoute.Break] # Driver breaks
metrics: Optional[AggregatedMetrics] # Route metrics
route_costs: Mapping[str, float] # Cost breakdown by request fields
route_total_cost: float # Total cost for this route
class Visit:
shipment_index: int # Index of shipment being visited
is_pickup: bool # True if pickup, false if delivery
visit_request_index: int # Index of visit request within shipment
start_time: Optional[timestamp_pb2.Timestamp] # Visit start time
load_demands: Mapping[str, ShipmentRoute.VehicleLoad] # Load demands
detour: Optional[duration_pb2.Duration] # Detour caused by this visit
shipment_label: str # Label of visited shipment
visit_label: str # Label of this visit
class Transition:
travel_duration: Optional[duration_pb2.Duration] # Travel time
travel_distance_meters: float # Travel distance
traffic_info_unavailable: bool # Whether traffic info was available
delay_duration: Optional[duration_pb2.Duration] # Traffic delays
break_duration: Optional[duration_pb2.Duration] # Break time during transition
wait_duration: Optional[duration_pb2.Duration] # Wait time
total_duration: Optional[duration_pb2.Duration] # Total transition duration
start_time: Optional[timestamp_pb2.Timestamp] # Transition start time
vehicle_loads: Mapping[str, ShipmentRoute.VehicleLoad] # Vehicle loads
route_polyline: Optional[ShipmentRoute.EncodedPolyline] # Transition polyline
class VehicleLoad:
amount: int # Load amount
class EncodedPolyline:
value: str # Encoded polyline string
class Break:
start_time: Optional[timestamp_pb2.Timestamp] # Break start time
duration: Optional[duration_pb2.Duration] # Break durationclass InjectedSolutionConstraint:
routes: Sequence[ShipmentRoute] # Routes to inject as constraints
constraint_relaxations: Sequence[InjectedSolutionConstraint.ConstraintRelaxation] # Relaxation settings
class ConstraintRelaxation:
relaxations: Sequence[InjectedSolutionConstraint.ConstraintRelaxation.Relaxation] # Individual relaxations
vehicle_indices: Sequence[int] # Vehicles to apply relaxations to
class Relaxation:
level: InjectedSolutionConstraint.ConstraintRelaxation.Relaxation.Level # Relaxation level
threshold_time: Optional[timestamp_pb2.Timestamp] # Time threshold
threshold_visit_count: int # Visit count threshold
class Level(enum.Enum):
LEVEL_UNSPECIFIED = 0
RELAX_VISIT_TIMES_AFTER_THRESHOLD = 1 # Relax visit times
RELAX_VISIT_TIMES_AND_SEQUENCE_AFTER_THRESHOLD = 2 # Relax times and sequence
RELAX_ALL_AFTER_THRESHOLD = 3 # Relax all constraintsInstall with Tessl CLI
npx tessl i tessl/pypi-google-maps-routeoptimization