# Determining optimum shared school bus route to a single destination from multiple origin points

Using ArcGIS Desktop and the Network Analyst extension, I want to determine the path of an optimized walking school bus route to school. a walking school bus is essentially a system by which adult volunteers chaperone elementary school children along a pre-set pedestrian path, to help keep them safe from traffic hazards and busy intersections. the idea would be that students would, starting from home, travel to their nearest walking bus "stop", then take the walking bus all the way to school.

I have a very detailed pedestrian network for my study area. scaled cost barriers include intersection controls, areas with high crime. the walking bus would bypass most of these barriers

Is there a workflow that could help determine the optimum location for the walking bus route itself? Right now my process is as follows:

Using closest facility analysis I determine the shortest path to the school for each house, then look at the density of routes along each segment of the network using a spatial join and the join count to find common "corridors". I would then digitize a route visually along this.

This is obviously fairly imprecise, and relies heavily on human judgement.

This looks like a Steiner tree problem. You'll need some programming to solve it. Picture below shows manually improved output of algorithm from networkX: and I think computing "flow" in this network will bring you even closer to near optimal solution: In this case SE student looks like a best candidate to start route.

What you are doing will give you blurry pattern like that: The script below assumes: - you have point layer - nodes at roads ends at least 2 of them (terminals) selected - polyline layer - edges, that have from and to INDICES of nodes populated - field TIMES in polylines stores a cost of travel through that edge (length?)

Script creates undirected graph first from all nodes (each has to be reachable from others) and computes much smaller new graph where nodes are terminals only and cost of travel between them is shortest distance. After that it computes minimum spanning tree of smaller graph and traces paths between terminals of original large graph. Remember, it is only approximation of optimal Steiner tree, see Wikipedia.

Script is tailored for my work environment (up to line 45) and not very tidy, so ask if any questions.

``````import arcpy, traceback, os, sys
import itertools
from itertools import tee,chain,combinations
scriptsPath=os.path.dirname(os.path.realpath(__file__))
os.chdir(scriptsPath)
import COMMON
import networkx as nx
import random, numpy, copy

try:
def showPyMessage():
arcpy.AddMessage(str(time.ctime()) + " - " + message)
def pairwise(iterable, cyclic=False):
"s -> (s0, s1), (s1, s2), (s2, s3), ..."
a, b = tee(iterable)
first = next(b, None)
if cyclic is True:
return zip(a, chain(b, (first,)))
return zip(a, b)

## FIND ENVIRONMENT TABLE
mxd = arcpy.mapping.MapDocument("CURRENT")
theT=COMMON.getTable(mxd)
##  FIND NODES LAYER
theNodesLayer = COMMON.getInfoFromTable(theT,1)
theNodesLayer = COMMON.isLayerExist(mxd,theNodesLayer)
##    GET NUMBER OF NODES AND NUMBER OF SELECTED
aBmNodes = theNodesLayer.getSelectionSet()
nSet=len(aBmNodes)
if nSet<2:
raise SystemExit('Missing input')
##  GET LINKS LAYER
G=nx.Graph()
for i,(f,t,c) in enumerate(cursor):
D=nx.Graph()
for f,t in combinations(aBmNodes, 2):
L=nx.dijkstra_path_length(G,f,t)
T=nx.minimum_spanning_tree(D)
del D
aList=[]
for F,T in T.edges():
nodes=nx.dijkstra_path(G,F,T)
for f,t in pairwise(nodes):
aList.append(G[f][t]['no'])
for f,t,c in cursor:
cursor.updateRow((f,t,0))