Iterate different stops for different routes

4184
6
09-27-2015 09:31 AM
HazelAng1
New Contributor

Hi all

Is there any way that I can build a model to iterate for different routes based on different combinations of stops?

For example, I have 6 stops A,B,C,D,E and F. The fixed sequencing is F-->A--> .......-->F.

After the first 2 stops, whatever combinations of B,C,D,E are possible before the route ends at F.

I need the list of total distance travelled based on the different combinations. Does anyone knows how I may go about doing it? Thanks!

Tags (2)
0 Kudos
6 Replies
FreddieGibson
Occasional Contributor III

Out of the box modelbuilder wouldn't allow you to do this without manually setting up all of your permutations for your routes. I would think that what you'd want to do is develop a script tool that can return a list of all of your different route permutations and then use a submodel with an iterator to solve for each of these permutations.

RamB
by
Occasional Contributor III

Hi,

You can generate random sequences between FA...F using excel, save them to a notepad file and then use the route builder to build routes. I think this should work.

regards,

Srirama

0 Kudos
HazelAng1
New Contributor

Hi Srirama

I have a notepad with all the permutations available. However, I am not too

sure how to go about from here. I have my network layer with me as well.

I'm only stuck with how to fit that list of permutations into an iterator

to generate different routes.

Regards

Hazel

On Tue, Sep 29, 2015 at 1:41 AM, Srirama Bhamidipati <geonet@esri.com>

0 Kudos
FreddieGibson
Occasional Contributor III

Hi Hazel,

Are you by any chance familiar with python? You could use excel to create the permutations or even have them written down in notepad, but taking these approaches is going to result in you having to manually input this information into your model.

I would highly suggest using python to accomplish this task. Within python creating the permutations is a one line call. For example,

2015-09-30_1630.png

I'm not sure how well you understand python, but I have included code below that I was able to utilize to create the results you're seeking. You can review this if you want to utilize this workflow to accomplish your task. I pulled the example from the page listed below and modified it.

Make Route Layer

http://desktop.arcgis.com/en/desktop/latest/tools/network-analyst-toolbox/make-route-layer.htm

# Name: MakeRouteLayer_Workflow.py
# Description: Find a best route to visit the stop locations and save the 
#              route to a layer file. The stop locations are geocoded from a 
#              text file containing the addresses.
# Requirements: Network Analyst Extension 
# Import system modules
import arcpy
import itertools
import os
from arcpy import env
try:    
    dataPath = os.path.join(os.path.dirname(__file__), "data")
    
    # Check out the Network Analyst extension license
    arcpy.CheckOutExtension("Network")
    # Set environment settings
    env.workspace = os.path.join(dataPath, "SanFrancisco.gdb")
    env.overwriteOutput = True
    
    # Set local variables
    inNetworkDataset = "Transportation/Streets_ND"
    outNALayerName = "BestRoute"
    impedanceAttribute = "TravelTime"
    outStops = "Analysis/Stores"
    outLayerFile = os.path.join(dataPath, "output", outNALayerName + ".lyr")
    
    if arcpy.Exists(os.path.dirname(outLayerFile)):
        arcpy.management.Delete(os.path.dirname(outLayerFile))
    os.makedirs(os.path.dirname(outLayerFile))    
    
    # Create a new Route layer. For this scenario, the default value for all the
    # remaining parameters statisfies the analysis requirements
    outNALayer = arcpy.na.MakeRouteLayer(inNetworkDataset, outNALayerName, impedanceAttribute)
    
    # Get the layer object from the result object. The route layer can now be
    # referenced using the layer object.
    outNALayer = outNALayer.getOutput(0)
    
    # Get the names of all the sublayers within the route layer.
    subLayerNames = arcpy.na.GetNAClassNames(outNALayer)
    # Stores the layer names that we will use later
    stopsLayerName = subLayerNames["Stops"]
    
    # Load the geocoded address locations as stops mapping the address field from
    # geocoded stop features as Name property using field mappings.
    fieldMappings = arcpy.na.NAClassFieldMappings(outNALayer, stopsLayerName)
    fieldMappings["Name"].mappedFieldName = "NAME"
    
    # Get a list of all of the OIDs for the stops we need to create a route against
    oidfieldname = arcpy.Describe(outStops).oidfieldname    
    with arcpy.da.SearchCursor(outStops, ["OID@"], "{} < {}".format(*[oidfieldname, 6])) as cursor:
        oids = [row[0] for row in cursor]
        
    # Get all of the permutations for all of the stops except the start/end
    permutations = list(itertools.permutations(oids[1:-1], len(oids)-2))
    
    stopsLayer = arcpy.management.MakeFeatureLayer(outStops, "LoadOrder")        
    for n,stops in enumerate(permutations):
        # Add the start stop
        arcpy.management.SelectLayerByAttribute(stopsLayer, "NEW_SELECTION", "{} = {}".format(*[oidfieldname, oids[0]]))
        arcpy.na.AddLocations(outNALayer, stopsLayerName, stopsLayer, fieldMappings, "", exclude_restricted_elements="EXCLUDE",
                                  append="CLEAR") 
        
        # Add the in-between stops in the permutation order
        for i, stop in enumerate(stops):
            arcpy.management.SelectLayerByAttribute(stopsLayer, "NEW_SELECTION", "{} = {}".format(*[oidfieldname, stop]))
            arcpy.na.AddLocations(outNALayer, stopsLayerName, stopsLayer, fieldMappings, "", exclude_restricted_elements="EXCLUDE",
                                  append="APPEND")   
        
        # Add the end stop
        arcpy.management.SelectLayerByAttribute(stopsLayer, "NEW_SELECTION", "{} = {}".format(*[oidfieldname, oids[-1]]))
        arcpy.na.AddLocations(outNALayer, stopsLayerName, stopsLayer, fieldMappings, "", exclude_restricted_elements="EXCLUDE",
                                  append="APPEND") 
                
        # Solve the route layer, ignore any invalid locations such as those that
        # can not be geocoded
        arcpy.na.Solve(outNALayer,"SKIP")
        
        # Save the solved route layer as a layer file on disk with relative paths
        arcpy.management.SaveToLayerFile(outNALayer,outLayerFile.replace(".lyr", "_{0}.lyr".format(str(n+1).zfill(len(
                                                                permutations)))),"RELATIVE")
    print("Script completed successfully")
except Exception as e:
    # If an error occurred, print line number and error message
    import traceback, sys
    tb = sys.exc_info()[2]
    print("An error occured on line %i" % tb.tb_lineno)
    print(str(e))

As a side note, if you wanted you could take lines 52-83 from my code, convert it into a script tool and then use this within a Model to implement the advanced logic needed here to execute the task. This iteration logic would not be natively possible to implement within ModelBuilder.

RamB
by
Occasional Contributor III

Hallo,

Python is good way to solve. But if you don't understand it, you tend to force your data to fit into the requirements of the code instead of your own way of solving. If you understand python, you can go by above solution.

If you do not understand python, read carefully the following page. It is in 9.3 version, but I am sure it exists in 10.2 version also. Basically you will need two columns with your stops. One column tells arcgis which route a stops belongs to. Second column tell the order or sequence number of that stop within a route. So if you can load a table in this format and ask to generate a route/ path. You will have your solution. I used to do this 10 years ago and it works perfect. I am sure it has only gotten better.

So, read very carefully and understand this page: ArcGIS Desktop Help 9.3 - finding the best route

Specifically focus on "Stop Properties" section and within this section, understand parts on- RouteName and sequence. 

best wishes,

Srirama Bhamidipati

Transport Planner

Delft - South Africa

HazelAng1
New Contributor

Hi Freddie and Srirama

Thanks so much for the help. I will try them out. Hopefully they work! Thanks so much once again!

Regards

Hazel

0 Kudos