Make Vehicle Routing Problem Analysis Layer (Network Analyst)

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})
ParameterExplanationData 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

  • MinutesThe time units will be minutes. This is the default.
  • SecondsThe time units will be seconds.
  • HoursThe time units will be hours.
  • DaysThe time units will be days.
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

  • MilesThe distance units will be miles. This is the default.
  • KilometersThe distance units will be kilometers.
  • FeetThe distance units will be feet.
  • YardsThe distance units will be yards.
  • MetersThe distance units will be meters.
  • InchesThe distance units will be inches.
  • CentimetersThe distance units will be centimeters.
  • MillimetersThe distance units will be millimeters.
  • DecimetersThe distance units will be decimeters.
  • NauticalMilesThe distance units will be nautical miles.
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.

  • LOCAL_TIME_AT_LOCATIONS The date-time values associated with the orders or depots will be in the time zone in which the orders and depots are located. For routes, the date-time values are based on the time zone in which the starting depot for the route is located. If a route does not have a starting depot, all orders and depots across all the routes must be in a single time zone. For breaks, the date-time values are based on the time zone of the routes. This is the default.
  • UTCThe date-time values associated with the orders or depots will be in coordinated universal time (UTC) and are not based on the time zone in which the orders or depots are located.

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.

  • ALONG_NETWORKThe output routes will have the exact shape of the underlying network sources. The output includes route measurements for linear referencing. The measurements increase from the first stop and record the cumulative impedance to reach a given position.
  • NO_LINESNo shape will be generated for the output routes.
  • STRAIGHT_LINESThe output route shape will be a single straight line between the stops.This option is not available if the selected network data source is a service.

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.

  • HighThe solver searches for a solution that minimizes time window violations at the expense of increasing the overall travel time. Choose this setting if arriving on time at orders is more important than minimizing the overall solution cost. This may be the case if you are meeting customers at your orders and you don't want to inconvenience them with late arrivals (another option is to use rigid time windows that cannot be violated).Given other constraints of a vehicle routing problem, it may be impossible to visit all the orders within their time windows. In this case, even a High setting might produce violations.
  • MediumThe solver searches for a balance between meeting time windows and reducing the overall solution cost. This is the default.
  • LowThe solver searches for a solution that minimizes overall travel time, regardless of time windows. Choose this setting if respecting time windows is less important than reducing the overall solution cost. You may want to use this setting if you have a growing backlog of service requests. For the purpose of servicing more orders in a day and reducing the backlog, you can choose this setting even though customers may be inconvenienced with your fleet's late arrivals.
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.

Learn more about Order Pairs

  • HighThe solver searches for a solution with less excess transit time between paired orders at the expense of increasing the overall travel costs. Use this setting if you are transporting people between paired orders and you want to shorten their ride time. This is characteristic of taxi services.
  • MediumThe solver searches for a balance between reducing excess transit time and reducing the overall solution cost. This is the default.
  • LowThe solver searches for a solution that minimizes overall solution cost, regardless of excess transit time. This setting is commonly used with courier services. Since couriers transport packages as opposed to people, ride time is not as important. Using this setting allows couriers to service paired orders in the proper sequence and minimize the overall solution cost.
String
generate_directions_on_solve
(Optional)

Specifies whether directions will be generated.

  • DIRECTIONSTurn-by-turn directions will be generated on solve. This is the default.
  • NO_DIRECTIONSTurn-by-turn directions will not be generated on solve.
Boolean
spatial_clustering
(Optional)

Specifies whether spatial clustering will be used.

  • CLUSTERThe orders assigned to an individual route will be spatially clustered. Clustering orders tends to keep routes in smaller areas and reduce how often route lines intersect one another; yet, clustering can increase overall travel times. This is the default.
  • NO_CLUSTERThe solver will not prioritize spatially clustering orders and the route lines may intersect. Use this option if route zones are specified.
Boolean

Derived Output

NameExplanationData Type
out_network_analysis_layer

The new network analysis layer.

Network Analyst Layer

Code sample

MakeVehicleRoutingProblemAnalysisLayer example 1 (Python window)

Execute the tool using only the required parameters.

import arcpy 
arcpy.env.workspace = "C:/Data/SanFrancisco.gdb" 
arcpy.na.MakeVehicleRoutingProblemLayer("Transportation/Streets_ND")
MakeVehicleRoutingProblemAnalysisLayer example 2 (Python window)

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')
MakeVehicleRoutingProblemAnalysisLayer example 3 (workflow)

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

Related topics