Note
Go to the end to download the full example code.
Static Traffic Assignment#
We can also perform static traffic assignment using Open-Source libraries for back-of-the-envelop analysis during debugging efforts
Exporting matrices#
sphinx_gallery_thumbnail_path = ‘../../examples/modelling_like_the_old_days/sta_results.png’
from pathlib import Path
from polaris.analyze.trip_metrics import TripMetrics
from polaris.runs.convergence.convergence_iteration import ConvergenceIteration
from polaris.runs.static_skimmer.static_assign import static_assignment
from polaris.runs.static_skimmer.static_graph import build_graph
Matrix#
We get the demand matrices for the AM peak for one iteration
project_dir = Path("/tmp/Bloomington")
supply_pth = project_dir / "Bloomington-Supply.sqlite"
iteration_3 = ConvergenceIteration.from_dir(project_dir / "Bloomington_iteration_3")
tm3 = TripMetrics(supply_pth, iteration_3.files.demand_db)
# Let's say that one afternoon peak hour is from 16:45AM to 17:45AM, so we egt trips starting during that time
matrix = tm3.vehicle_trip_matrix(from_start_time=16.75 * 3600, to_start_time=17.75 * 3600)
# This matrix has multiple vehicle types, and we could separate them to make sure we observe
# link type constraints, but that shouldn't be needed in a back-of-the-envelope exercise
# Instead, we will just multiply the PCEs for each matrix to the matrices themselves
pces = {"SOV_0": 1.0, "TAXI_9": 1.0, "MD_TRUCK_17": 2.5, "HD_TRUCK_18": 4.0, "BPLATE_19": 2.0, "LD_TRUCK_20": 1.8}
for i, mat in enumerate(matrix.names):
matrix.matrices[:, :, i] *= pces[mat]
Graph#
We build an AequilibraE graph using the underlying Polaris supply model
This procedure asserts some things about the links so we can get everything we need for a static traffic assignment Assumptions are made about (HOURLY) capacities and centroid connector placements
graph = build_graph(supply_pth)
One can see the results of these assumptions in the graph object
graph.network.head()
Assignment#
We perform traffic assignment and skimming using the AequilibraE library
We can load the assignment parameters from the default values and change them
from polaris.runs.static_skimmer.static_skimmer_inputs import STAInputs
sta_pars = STAInputs()
# Not sure why somewhat would want msa over bi-conjugate Frank-Wolfe, but...
sta_pars.assignment_algorithm = "msa"
sta_pars.max_iterations = 10
sta_pars.rgap = 0.01
# By default assignment uses BPR, but we can change the parameters
sta_pars.bpr_alpha = 0.14
sta_pars.bpr_beta = 3.9
No turning constraints are observed in this assignment
assig = static_assignment(graph, matrix, sta_pars)
Then we can see the results
link_loads = assig.results()
link_loads.head()
And get the skims
assig_class = assig.classes[0]
skim = assig_class.results.skims
# And show some elements
skim.time[:10, :10]
array([[ 0. , 10.7245319 , 11.03757707, 3.0547657 , 9.5243757 ,
12.05866538, 7.44881255, 8.53107085, 18.94485772, 17.17150986],
[ 9.90031742, 0. , 6.82824537, 7.99503446, 9.46120217,
4.3716889 , 3.95376437, 2.60070847, 10.99242506, 8.77731033],
[ 6.12517001, 5.90071241, 0. , 4.21988705, 5.3453872 ,
8.01130538, 5.20016304, 6.24032495, 12.61901381, 10.40389908],
[ 3.0793165 , 8.84379975, 9.17209323, 0. , 7.65889186,
10.17793322, 5.56808039, 6.65033869, 17.06412556, 15.2907777 ],
[14.96063516, 13.62288499, 15.69405372, 13.0553522 , 0. ,
15.73347797, 14.03562819, 13.96249753, 20.34118639, 18.12607166],
[ 9.00961813, 6.63165065, 3.45976844, 7.10433517, 8.22983532,
0. , 8.08461116, 6.97126318, 13.34995205, 11.13483732],
[ 7.47363374, 4.80182722, 8.38240729, 5.56835078, 7.11728046,
6.13596069, 0. , 2.47300759, 13.46391991, 11.24880518],
[ 8.55091741, 3.44939017, 7.24008011, 6.64563445, 8.19456413,
4.78352364, 2.47362645, 0. , 12.11148286, 9.89636813],
[12.66570298, 6.00655976, 8.48766128, 10.76042002, 12.22658773,
6.03110481, 6.71914993, 5.36609402, 0. , 7.86636255],
[18.73423764, 12.59770372, 15.07880523, 16.82895468, 15.02139944,
12.62224877, 13.31029388, 11.95723798, 10.08545046, 0. ]])
Total running time of the script: (0 minutes 1.116 seconds)