Multiple Zone Systems Design - ActivitySim/activitysim GitHub Wiki

Overview

The SANDAG CT-RAMP model has three zone systems: MAZs (microzones), TAZs, and TAPs (transit access points). ActivitySim currently supports only one zone system, typically TAZs. In addition, the skims object supports only TAZ to TAZ skims. In order to support multiple zone systems, the skims object will be re-imagined as something more like a NetworkLOS object. The NetworkLOS object will allow the user to read multiple types of network level-of-service data and then query it in vectorized form.

Input Data

NetworkLOS will support two types of inputs: pandas DataFrames in an HDF5 file and skim matrices in OMX files.

The inputs to the NetworkLOS object will be:

  • NetworkData.HDF5
Table Primary Key(s) Foreign Key(s) Notes
TAZ TAZ All TAZs with additional optional attributes
MAZ MAZ TAZ All MAZs with additional optional attributes; nest within TAZs
TAP TAP MAZ All TAPs with additional optional attributes; point within an MAZ
MAZtoMAZ (OMAZ, DMAZ) MAZ to nearby MAZs network cost data; additional optional attributes
MAZtoTAP (MAZ, TAP) MAZ to nearby TAPs network cost data; additional optional attributes
  • OMX skim matrix files
Files Primary Key(s) Foreign Key(s) Notes
*.omx (OTAZ, DTAZ, TIMEPERIOD) multiple TAZ to TAZ skims per file and multiple files possible
*.omx (OTAP, DTAP, TIMEPERIOD) multiple TAP to TAP skims per file and multiple files possible; a different file for each skim set is typical, such as local_bus or premium

NetworkLOS Queries

All NetworkLOS queries are vectorized, i.e. they take vector arguments and return vectors. The NetworkLOS query interface will be revised to support expressions such as:

Query Example Arguments Notes
Attributes
Get TAZ for TAPs nLOS.get_tap(TAP,"TAZ") tap vector, "TAZ" attribute returns a vector of TAZ for the TAP vector
Get MAZ for TAPs nLOS.get_tap(TAP,"MAZ") tap vector, "MAZ" attribute returns a vector of MAZ for the TAP vector
Get TAZ for MAZs nLOS.get_maz(MAZ,"TAZ") maz vector, "TAZ" attribute returns a vector of TAZ for the MAZ vector
Get an optional attribute of TAPs nLOS.get_tap(TAP, "CANPNR") tap vector, "CANPNR" attribute returns a vector of can park and ride for the TAP vector
Get an optional attribute of MAZs nLOS.get_maz(MAZ, "HASTRANSIT") maz vector, "HASTRANSIT" attribute returns a vector of MAZ has transit access for the MAZ vector
Get an optional attribute of TAZs nLOS.get_taz(TAZ, "HASTAPS") taz vector, "HASTAPS" attribute returns a vector of HASTAPS for the TAZ vector
OD data
Travel time between TAZ pairs nLOS.get_tazpairs(OTAZ,DTAZ, "TIME") otaz vector, dtaz vector, "TIME" measure returns a vector of travel times for taz pairs
Travel time between TAZ pairs nLOS.get_tazpairs3d(OTAZ,DTAZ, TIMEPERIOD,"TIME") otaz vector, dtaz vector, time
period vector, "TIME" measure returns a vector of travel times for taz pairs
Walk travel distance between MAZ pairs nLOS.get_mazpairs(OMAZ,DMAZ, "WALK_DISTANCE") omaz vector, dmaz vector, "WALK_DISTANCE" measure returns a vector of walk travel distances for maz pairs
Bike travel distance between MAZ-TAP pairs nLOS.get_maztappairs(OMAZ,DTAP, "BIKE_DISTANCE") omaz vector, dtap vector, "BIKE_DISTANCE" measure returns a vector of bike travel distances for maz-tap pairs
Travel times between TAP pairs nLOS.get_tappairs(OTAP,DTAP, "TIME") otap vector, dtap vector, "TIME" measure returns a vector of travel times for tap pairs
Travel times between TAP pairs nLOS.get_tappairs3d(OTAP,DTAP, TIMEPERIOD, "TIME") otap vector, dtap vector, time period vector, "TIME" measure returns a vector of travel times for tap pairs
Ragged Arrays
Nearby TAPs for MAZs nLOS.get_taps_mazs(OMAZ, "DISTANCE") omaz vector, optional "DISTANCE" measure returns a table of (maz, tap, distance) for all mazs to all nearby taps; should be sorted by distance if desired
Transit Virtual Path Building
Best TAP pairs for MAZ pairs nLOS.get_tappairs_mazpairs(OMAZ,DMAZ, TIMEPERIOD,"BEST") omaz vector, dmaz vector, time period vector, "BEST" criteria returns a tuple of tap pairs (boarding tap, alighting tap) for maz pairs
Best TAP pairs for MAZ pairs for skim set 1 nLOS.get_tappairs_mazpairs(OMAZ,DMAZ, TIMEPERIOD,"SKIMSET1", "BEST") omaz vector, dmaz vector, time period vector, skim set 1, "BEST" criteria returns a tuple of tap pairs (boarding tap, alighting tap) for maz pairs for skim set 1

Transit Virtual Path Building

The transit virtual path builder (TVPB) selects the best tap pairs for a given OMAZ and DMAZ given a user specified transit path utility that combines five elements:

  • OMAZ to BTAP attributes (such as travel time)
  • BTAP attributes (such as station quality (in the form of equivalent minutes))
  • BTAP to ATAP attributes (such as travel time)
  • ATAP attributes (such as station quality (in the form of equivalent minutes))
  • ATAP to DMAZ attributes (such as travel time)

This process is repeated for each skim set - such as local_bus versus premium or set1, set2, set3, etc. - and then the best path across sets is selected. In reality the usage of the TVPB is more complicated than this, but this is sufficient behavior for now. For the prototype, a simple vectorized algorithm for selecting the best tap pair might look something like:

# Step 1 - get nearby boarding TAPs to origin
omaz_btap_table = nLOS.get_taps_mazs(OMAZ)

# Step 2 - get nearby alighting TAPs to destination
dmaz_atap_table = nLOS.get_taps_mazs(DMAZ)

# Step 3 - merge into one big pandas table with all boarding and alighting combinations
omaz_btap_atap_dmaz_table = ...

# Step 4 - get data for each path leg for this skim set
omaz_btap_atap_dmaz_table.omaz_btap_cost = nLOS.get_maztappairs(OMAZ,BTAP,MODE,"TIME")
omaz_btap_atap_dmaz_table.btap_cost = nLOS.get_tap(BTAP,"QUALITY")
omaz_btap_atap_dmaz_table.btap_atap_cost = nLOS.get_tappairs(BTAP,ATAP,TIME,"TIME")
omaz_btap_atap_dmaz_table.atap_cost = nLOS.get_tap(ATAP,"QUALITY")
omaz_btap_atap_dmaz_table.dmaz_atap_cost = nLOS.get_maztappairs(DMAZ,ATAP,MODE,"TIME")

# Step 5 - calculate total utility
omaz_btap_atap_dmaz_table.totalcost = omaz_btap_cost + btap_cost + 
  btap_atap_cost + atap_cost + dmaz_atap_cost

# Step 6 - select best and return (btap,atap) tuple for each MAZ pair for this skim set
grouped = omaz_btap_atap_dmaz_table.grouby([omaz,dmaz])
grouped['totalcost'].idxmin()

Another option for implementation is to build a small network of the path combinations and solve the problem using a shortest path algorithm. This may need to be implemented in Cython for performance reasons, since the operation is not easily vectorized.

SANDAG Specific File Conversions

The SANDAG input files are converted via this Python script into the formats expected by NetworkLOS as follows:

  • NetworkData.HDF5:
    • bikeMgraLogsum.csv (bike logsums for OD pairs < 2mi) -> MAZtoMAZ
    • walkMgraTapEquivMinutes.csv -> MAZtoTAP
    • walkMgraEquivMinutes.csv -> MAZtoMAZ
    • mgra_based_input2012.csv -> MAZ
    • Accessam.csv -> MAZtoTAP
    • Tap_ptye.csv -> TAP
    • Zone_term.csv -> TAZ
    • Zone_park.csv -> TAZ
    • Taps.csv (this is a new file with every TAP and its MAZ and (parking) LOTMAZ) -> TAP
  • taz_skims.omx - TAZ to TAZ skims:
    • bikeTazLogsum.csv (bike logsums for OD pairs > 2 mi) -> bike_logum, bike_time skims
    • impdan_AM.omx -> various AM time period drive alone no toll skims for testing
    • impdan_PM.omx -> various PM time period drive alone no toll skims for testing
  • tap_skims_locl.omx - TAP to TAP skims for LOCAL BUS set:
    • implocl_AMo.omx -> various AM time period local bus skims for testing
    • implocl_PMo.omx -> various PM time period local bus skims for testing
  • tap_skims_prem.omx - TAP to TAP skims for PREM BUS set:
    • impprem_AMo.omx -> various AM time period premium service skims for testing
    • impprem_PMo.omx -> various PM time period premium service skims for testing
⚠️ **GitHub.com Fallback** ⚠️