Summary
Creates a vehicle routing problem (VRP) network analysis layer and sets its analysis properties. A VRP analysis layer is useful for optimizing a set of routes using a fleet of vehicles. The layer can be created using a local network dataset or a service hosted online or in a portal.
Usage
After creating the analysis layer with this tool, you can add network analysis objects to it using the Add Locations tool, solve the analysis using the Solve tool, and save the results on disk using the Save To Layer File tool.
-
When using this tool in geoprocessing models, if the model is run as a tool, the output network analysis layer must be made a model parameter; otherwise, the output layer is not added to the contents of the map.
Syntax
arcpy.na.MakeVehicleRoutingProblemAnalysisLayer(network_data_source, {layer_name}, {travel_mode}, {time_units}, {distance_units}, {default_date}, {time_zone_for_time_fields}, {line_shape}, {time_window_factor}, {excess_transit_factor}, {generate_directions_on_solve}, {spatial_clustering})
Parameter | Explanation | Data Type |
network_data_source | The network dataset or service on which the network analysis will be performed. Use the portal URL for a service. | Network Dataset Layer; String |
layer_name (Optional) | The name of the VRP network analysis layer to create. | String |
travel_mode (Optional) | The name of the travel mode to use in the analysis. The travel mode represents a collection of network settings, such as travel restrictions and U-turn policies, that determine how a pedestrian, car, truck, or other medium of transportation moves through the network. Travel modes are defined on your network data source. An arcpy.na.TravelMode object and a string containing the valid JSON representation of a travel mode can also be used as input to the parameter. | String |
time_units (Optional) | Specifies the time units to be used by the temporal fields of the analysis layer's sublayers and tables (network analysis classes). This value does not need to match the units of the time cost attribute. Learn more about cost attributes
| String |
distance_units (Optional) | Specifies the distance units to be used by the distance fields of the analysis layer's sublayers and tables (network analysis classes). This value does not need to match the units of the optional distance cost attribute. Learn more about cost attributes
| String |
default_date (Optional) | The implied date for time field values that don't have a date specified with the time. If a time field for an order object, such as TimeWindowStart, has a time-only value, the date is assumed to be the default date. The default date has no effect on time field values that already have a date. | Date |
time_zone_for_time_fields (Optional) | Specifies the time zone to be used for the input date-time fields supported by the tool.
Specifying the date-time values in UTC is useful if you do not know the time zone in which the orders or depots are located or when you have orders and depots in multiple time zones and you want all the date-time values to start simultaneously. The UTC option is applicable only when your network dataset defines a time zone attribute. Otherwise, all the date-time values are always treated as the time zone corresponding with that location. | String |
line_shape (Optional) | Specifies the shape type for the route features that are output by the analysis.
No matter which output shape type is chosen, the best route is always determined by the network impedance, never Euclidean distance. This means that only the route shapes are different, not the underlying traversal of the network. | String |
time_window_factor (Optional) | Specifies the importance of honoring time windows without causing violations. A time window violation occurs when a route arrives at an order, depot, or break after a time window has closed. The violation is the interval between the end of the time window and the arrival time of a route.
| String |
excess_transit_factor (Optional) | Specifies the importance of reducing excess transit time. Excess transit time is the amount of time exceeding the time required to travel directly between paired orders. The excess time results from breaks or travel to other orders or depots between visits to the paired orders. This parameter is only relevant if you're using Order Pairs.
| String |
generate_directions_on_solve (Optional) | Specifies whether directions will be generated.
| Boolean |
spatial_clustering (Optional) | Specifies whether spatial clustering will be used.
| Boolean |
Derived Output
Name | Explanation | Data Type |
out_network_analysis_layer | The new network analysis layer. | Network Analyst Layer |
Code sample
Execute the tool using only the required parameters.
import arcpy
arcpy.env.workspace = "C:/Data/SanFrancisco.gdb"
arcpy.na.MakeVehicleRoutingProblemLayer("Transportation/Streets_ND")
Execute the tool using all parameters.
import arcpy
arcpy.env.workspace = "C:/Data/SanFrancisco.gdb"
arcpy.na.MakeVehicleRoutingProblemAnalysisLayer('Streets_ND', 'FridayRoutes',
'Driving Time', 'Minutes',
'Miles', '1/2/2020',
'LOCAL_TIME_AT_LOCATIONS',
'TRUE_LINES_WITHOUT_MEASURES',
'High', 'Medium', 'DIRECTIONS')
The following stand-alone Python script demonstrates how the MakeVehicleRoutingProblemAnalysisLayer tool can be used for servicing a set of orders with a fleet of vehicles.
# Name: MakeVRPAnalysisLayer_Ex3_Workflow.py
# Description: Find the best routes for a fleet of vehicles, which is operated
# by a distribution company, to deliver goods from a main
# distribution center to a set of grocery stores.
# Requirements: Network Analyst Extension
# Import system modules
import arcpy
import os
try:
# Check out the Network Analyst license if available.
# Fail if the Network Analyst
# license is not available.
if arcpy.CheckExtension("network") == "Available":
arcpy.CheckOutExtension("network")
else:
raise arcpy.ExecuteError("Network Analyst Extension license is not available.")
# Set environment settings
output_dir = r"C:\Data"
# The NA layer's data will be saved to the workspace specified here
arcpy.env.workspace = os.path.join(output_dir, "Output.gdb")
arcpy.env.overwriteOutput = True
# Set local variables
input_gdb = "C:/Data/SanFrancisco.gdb"
network = os.path.join(input_gdb, "Transportation", "Streets_ND")
layer_name = "StoreDeliveryRoute"
travel_mode = "Driving Time"
time_units = "Minutes"
distance_units = "Miles"
in_orders = os.path.join(input_gdb, "Analysis", "Stores")
in_depots = os.path.join(input_gdb, "Analysis", "DistributionCenter")
in_routes = os.path.join(input_gdb, "Analysis", "Routes")
output_layer_file = os.path.join(output_dir, layer_name + ".lyrx")
# Create a new Vehicle Routing Problem (VRP) layer. Since the time-based
# attributes such as ServiceTime on orders and CostPerUnitTime on routes is
# recorded in minutes, we use minutes for time_units parameter. As we are
# using cost per unit distance in routes, we have to specify a distance
# attribute. The values for CosterPerUnitDistance are in miles, so we
# specify miles for distance units parameter
result_object = arcpy.na.MakeVehicleRoutingProblemAnalysisLayer(
network, layer_name, travel_mode, time_units, distance_units,
line_shape="STRAIGHT_LINES")
# Get the layer object form the result object. The route layer can now be
# referenced using the layer object.
layer_object = result_object.getOutput(0)
# Get the names of all the sublayers within the VRP layer.
sub_layer_names = arcpy.na.GetNAClassNames(layer_object)
# Store the layer names that we will use later
orders_layer_name = sub_layer_names["Orders"]
depots_layer_name = sub_layer_names["Depots"]
routes_layer_name = sub_layer_names["Routes"]
# Load the store locations as orders. Using field mappings we map the
# TimeWindowStart1, TimeWindowEnd1, and DeliveryQuantities properties
# for Orders from the fields of store features and assign a value of
# 0 to MaxViolationTime1 property. The Name and ServiceTime properties
# have the correct mapped field names when using the candidate fields
# from store locations feature class.
candidate_fields = arcpy.ListFields(in_orders)
order_field_mappings = arcpy.na.NAClassFieldMappings(layer_object, orders_layer_name, False, candidate_fields)
order_field_mappings["TimeWindowStart"].mappedFieldName = "TimeStart1"
order_field_mappings["TimeWindowEnd"].mappedFieldName = "TimeEnd1"
order_field_mappings["DeliveryQuantity_1"].mappedFieldName = "Demand"
order_field_mappings["MaxViolationTime"].defaultValue = 0
arcpy.na.AddLocations(layer_object, orders_layer_name, in_orders, order_field_mappings, "")
# Load the depots from the distribution center features. Using field mappings
# we map the Name properties for Depots from the fields of distribution
# center features and assign a value of 8 AM for TimeWindowStart1 and a
# value of 5 PM for TimeWindowEnd1 properties
depot_field_mappings = arcpy.na.NAClassFieldMappings(layer_object, depots_layer_name)
depot_field_mappings["Name"].mappedFieldName = "Name"
depot_field_mappings["TimeWindowStart"].defaultValue = "8 AM"
depot_field_mappings["TimeWindowEnd"].defaultValue = "5 PM"
arcpy.na.AddLocations(layer_object, depots_layer_name, in_depots, depot_field_mappings, "")
# Load the routes from a table containing information about routes. In this
# case, since the fields on the routes table and property names for Routes
# are the same, we will just use the default field mappings
routes_field_mappings = arcpy.na.NAClassFieldMappings(layer_object, routes_layer_name)
routes_field_mappings["Name"].mappedFieldName = "Name"
routes_field_mappings["StartDepotName"].mappedFieldName = "StartDepotName"
routes_field_mappings["EndDepotName"].mappedFieldName = "EndDepotName"
routes_field_mappings["StartDepotServiceTime"].mappedFieldName = "StartDepotServiceTime"
routes_field_mappings["Capacity_1"].mappedFieldName = "Capacities"
routes_field_mappings["CostPerUnitTime"].mappedFieldName = "CostPerUnitTime"
routes_field_mappings["CostPerUnitDistance"].mappedFieldName = "CostPerUnitDistance"
routes_field_mappings["MaxOrderCount"].mappedFieldName = "MaxOrderCount"
routes_field_mappings["MaxTotalTime"].mappedFieldName = "MaxTotalTime"
routes_field_mappings["MaxTotalTravelTime"].mappedFieldName = "MaxTotalTravelTime"
routes_field_mappings["MaxTotalDistance"].mappedFieldName = "MaxTotalDistance"
arcpy.na.AddLocations(layer_object, routes_layer_name, in_routes, routes_field_mappings, "")
# Solve the VRP layer
arcpy.na.Solve(layer_object)
# Save the solved VRP layer as a layer file on disk with relative paths
arcpy.management.SaveToLayerFile(layer_object, output_layer_file, "RELATIVE")
print("Script Completed Successfully")
except Exception as e:
# If an error occurred, print line number and error message
import traceback
import sys
tb = sys.exc_info()[2]
print("An error occurred on line %i" % tb.tb_lineno)
print(str(e))
Environments
Licensing information
- Basic: Yes
- Standard: Yes
- Advanced: Yes