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.72528472, 11.23800313, 3.05524142, 9.64934026,
12.05939302, 7.44948445, 8.53459384, 18.97354925, 17.17276722],
[ 9.90386744, 0. , 6.90357459, 7.99508391, 9.5964571 ,
4.37169228, 3.9532718 , 2.60182148, 10.99290116, 8.77783759],
[ 6.12958091, 5.90080079, 0. , 4.22079737, 5.46588849,
8.01137404, 5.20123395, 6.24150323, 12.61954346, 10.40447989],
[ 3.08281707, 8.84407684, 9.35679524, 0. , 7.76813238,
10.17818514, 5.56827657, 6.65338596, 17.09234137, 15.29155933],
[14.96419668, 13.62299272, 15.88916714, 13.05541315, 0. ,
15.73356596, 14.03584973, 13.96369516, 20.34173538, 18.12667181],
[ 9.08935487, 6.63267069, 3.53509429, 7.18057134, 8.42566246,
0. , 8.16100792, 6.97337313, 13.35141335, 11.13634978],
[ 7.47719183, 4.80197622, 8.4860492 , 5.5684083 , 7.22649885,
6.13608451, 0. , 2.47397262, 13.46452228, 11.24945871],
[ 8.55348777, 3.44934368, 7.31533429, 6.64470424, 8.30279478,
4.78345198, 2.4727904 , 0. , 12.11188974, 9.89682617],
[12.6696452 , 6.00669722, 8.56309946, 10.76086167, 12.36223486,
6.03121715, 6.71904956, 5.36759924, 0. , 7.86697607],
[18.75619251, 12.59835899, 15.15476124, 16.84740898, 15.06965504,
12.62287893, 13.31071134, 11.95926101, 10.08605734, 0. ]])
Total running time of the script: (0 minutes 1.210 seconds)