Note
Go to the end to download the full example code.
Assigning sparse matrices#
Modern Activity-Based models (and even some trip-based and tour-based ones) result on incredibly sparse demand matrices, which opens up a significant opportunity to save time during assignment by using early-exiting during the path-computation phase of assignment.
To take advantage of this, while still computing assignment skims, AequilibraE has a built-in method to skim the last iteration after the assignment is done.
Technical references
See also
Several functions, methods, classes and modules are used in this example:
# Imports
from os.path import join
from tempfile import gettempdir
from uuid import uuid4
from aequilibrae.utils.create_example import create_example
from aequilibrae.paths import TrafficAssignment, TrafficClass
# We create the example project inside our temp folder
fldr = join(gettempdir(), uuid4().hex)
project = create_example(fldr)
logger = project.logger
Environment variable 'AEQ_SPATIALITE_DIR' was provided (C:\path\to\existing\download), but mod_spatialite could not be loaded from this directory. Trying system path
Environment variable 'AEQ_SPATIALITE_DIR' was provided (C:\path\to\existing\download), but mod_spatialite could not be loaded from this directory. Trying system path
Environment variable 'AEQ_SPATIALITE_DIR' was provided (C:\path\to\existing\download), but mod_spatialite could not be loaded from this directory. Trying system path
Environment variable 'AEQ_SPATIALITE_DIR' was provided (C:\path\to\existing\download), but mod_spatialite could not be loaded from this directory. Trying system path
Traffic assignment#
We build all graphs
project.network.build_graphs()
# We get warnings that several fields in the project are filled with NaNs.
# This is true, but we won't use those fields.
# We grab the graph for cars
graph = project.network.graphs["c"]
# Let's say we want to minimize the free_flow_time
graph.set_graph("free_flow_time")
# And we will allow paths to be computed going through other centroids/centroid connectors
# required for the Sioux Falls network, as all nodes are centroids
graph.set_blocked_centroid_flows(False)
Environment variable 'AEQ_SPATIALITE_DIR' was provided (C:\path\to\existing\download), but mod_spatialite could not be loaded from this directory. Trying system path
Let’s get the demand matrix directly from the project record, and inspect what matrices we have in the project.
proj_matrices = project.matrices
proj_matrices.list()
We get the demand matrix, and prepare it for computation
demand = proj_matrices.get_matrix("demand_omx")
demand.computational_view(["matrix"])
Let’s perform the traffic assignment
# Create the assignment class
assigclass = TrafficClass(name="car", graph=graph, matrix=demand)
assig = TrafficAssignment()
# We start by adding the list of traffic classes to be assigned
assig.add_class(assigclass)
# Then we set these parameters, which an only be configured after adding one class to the assignment
assig.set_vdf("BPR") # This is not case-sensitive
# Then we set the volume delay function and its parameters
assig.set_vdf_parameters({"alpha": "b", "beta": "power"})
# The capacity and free flow travel times as they exist in the graph
assig.set_capacity_field("capacity")
assig.set_time_field("free_flow_time")
# And the algorithm we want to use to assign
assig.set_algorithm("bfw")
# Let's set parameters that make this example run very fast
assig.max_iter = 10
assig.rgap_target = 0.01
# we then execute the assignment
assig.execute()
car : 0%| | 0/24 [00:00<?, ?it/s]
Equilibrium Assignment : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car : 10%|█ | 1/10 [00:00<00:00, 20068.44it/s]
All-or-Nothing - Traffic Class: car : 10%|█ | 1/10 [00:00<00:00, 7073.03it/s]
All-or-Nothing - Traffic Class: car : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 0/24 : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 10/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 20/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 24/24: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment - Iteration: 1/10 - RGap: inf: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment : 20%|██ | 2/10 [00:00<00:00, 35.47it/s]
All-or-Nothing - Traffic Class: car : 20%|██ | 2/10 [00:00<00:00, 35.39it/s]
All-or-Nothing - Traffic Class: car : 20%|██ | 2/10 [00:00<00:00, 35.32it/s]
All-or-Nothing - Traffic Class: car : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 0/24 : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 10/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 20/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 24/24: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment - Iteration: 2/10 - RGap: 0.855075: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment : 30%|███ | 3/10 [00:00<00:00, 43.71it/s]
All-or-Nothing - Traffic Class: car : 30%|███ | 3/10 [00:00<00:00, 43.65it/s]
All-or-Nothing - Traffic Class: car : 30%|███ | 3/10 [00:00<00:00, 43.60it/s]
All-or-Nothing - Traffic Class: car : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 0/24 : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 10/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 20/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 24/24: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment - Iteration: 3/10 - RGap: 0.476346: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment : 40%|████ | 4/10 [00:00<00:00, 83.79it/s]
All-or-Nothing - Traffic Class: car : 40%|████ | 4/10 [00:00<00:00, 83.64it/s]
All-or-Nothing - Traffic Class: car : 40%|████ | 4/10 [00:00<00:00, 83.51it/s]
All-or-Nothing - Traffic Class: car : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 0/24 : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 10/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 20/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 24/24: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment - Iteration: 4/10 - RGap: 0.235513: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment : 50%|█████ | 5/10 [00:00<00:00, 79.63it/s]
All-or-Nothing - Traffic Class: car : 50%|█████ | 5/10 [00:00<00:00, 79.53it/s]
All-or-Nothing - Traffic Class: car : 50%|█████ | 5/10 [00:00<00:00, 79.43it/s]
All-or-Nothing - Traffic Class: car : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 0/24 : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 10/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 20/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 24/24: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment - Iteration: 5/10 - RGap: 0.109241: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment - Iteration: 5/10 - RGap: 0.109241: 60%|██████ | 6/10 [00:00<00:00, 52.92it/s]
Equilibrium Assignment : 60%|██████ | 6/10 [00:00<00:00, 52.92it/s]
All-or-Nothing - Traffic Class: car : 60%|██████ | 6/10 [00:00<00:00, 52.92it/s]
All-or-Nothing - Traffic Class: car : 60%|██████ | 6/10 [00:00<00:00, 52.92it/s]
All-or-Nothing - Traffic Class: car : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 0/24 : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 10/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 20/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 24/24: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment - Iteration: 6/10 - RGap: 0.109241: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment : 70%|███████ | 7/10 [00:00<00:00, 72.09it/s]
All-or-Nothing - Traffic Class: car : 70%|███████ | 7/10 [00:00<00:00, 72.03it/s]
All-or-Nothing - Traffic Class: car : 70%|███████ | 7/10 [00:00<00:00, 71.98it/s]
All-or-Nothing - Traffic Class: car : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 0/24 : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 10/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 20/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 24/24: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment - Iteration: 7/10 - RGap: 0.146818: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment : 80%|████████ | 8/10 [00:00<00:00, 157.46it/s]
All-or-Nothing - Traffic Class: car : 80%|████████ | 8/10 [00:00<00:00, 157.21it/s]
All-or-Nothing - Traffic Class: car : 80%|████████ | 8/10 [00:00<00:00, 156.99it/s]
All-or-Nothing - Traffic Class: car : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 0/24 : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 10/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 20/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 24/24: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment - Iteration: 8/10 - RGap: 0.0676479: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment : 90%|█████████ | 9/10 [00:00<00:00, 136.62it/s]
All-or-Nothing - Traffic Class: car : 90%|█████████ | 9/10 [00:00<00:00, 136.46it/s]
All-or-Nothing - Traffic Class: car : 90%|█████████ | 9/10 [00:00<00:00, 136.30it/s]
All-or-Nothing - Traffic Class: car : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 0/24 : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 10/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 20/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 24/24: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment - Iteration: 9/10 - RGap: 0.0556948: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment : 100%|██████████| 10/10 [00:00<00:00, 137.38it/s]
All-or-Nothing - Traffic Class: car : 100%|██████████| 10/10 [00:00<00:00, 137.22it/s]
All-or-Nothing - Traffic Class: car : 100%|██████████| 10/10 [00:00<00:00, 137.08it/s]
All-or-Nothing - Traffic Class: car : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 0/24 : 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 10/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 20/24: 0%| | 0/10 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: car - Zones: 24/24: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment - Iteration: 10/10 - RGap: 0.0556948: 0%| | 0/10 [00:00<?, ?it/s]
After finishing the assignment, we can skim the last iteration
skims = assig.skim_congested(["distance"], return_matrices=True)
# Skims are returned as a dictionary, with the class names as keys
# Let's see all skims we have inside it:
print(skims["car"].names)
: 0%| | 0/24 [00:00<?, ?it/s]
1/24 : 4%|▍ | 1/24 [00:00<00:00, 171.01it/s]
2/24 : 8%|▊ | 2/24 [00:00<00:00, 327.11it/s]
3/24 : 12%|█▎ | 3/24 [00:00<00:00, 473.33it/s]
4/24 : 17%|█▋ | 4/24 [00:00<00:00, 525.37it/s]
5/24 : 21%|██ | 5/24 [00:00<00:00, 637.51it/s]
6/24 : 25%|██▌ | 6/24 [00:00<00:00, 744.60it/s]
7/24 : 29%|██▉ | 7/24 [00:00<00:00, 846.53it/s]
8/24 : 33%|███▎ | 8/24 [00:00<00:00, 879.36it/s]
9/24 : 38%|███▊ | 9/24 [00:00<00:00, 965.17it/s]
10/24 : 42%|████▏ | 10/24 [00:00<00:00, 1045.60it/s]
11/24 : 46%|████▌ | 11/24 [00:00<00:00, 1124.94it/s]
12/24 : 50%|█████ | 12/24 [00:00<00:00, 1201.43it/s]
13/24 : 54%|█████▍ | 13/24 [00:00<00:00, 1274.45it/s]
14/24 : 58%|█████▊ | 14/24 [00:00<00:00, 1345.07it/s]
15/24 : 62%|██████▎ | 15/24 [00:00<00:00, 1408.90it/s]
16/24 : 67%|██████▋ | 16/24 [00:00<00:00, 1473.79it/s]
17/24 : 71%|███████ | 17/24 [00:00<00:00, 1536.84it/s]
18/24 : 75%|███████▌ | 18/24 [00:00<00:00, 1597.53it/s]
19/24 : 79%|███████▉ | 19/24 [00:00<00:00, 1056.61it/s]
20/24 : 83%|████████▎ | 20/24 [00:00<00:00, 1093.35it/s]
21/24 : 88%|████████▊ | 21/24 [00:00<00:00, 1127.28it/s]
22/24 : 92%|█████████▏| 22/24 [00:00<00:00, 1059.09it/s]
23/24 : 96%|█████████▌| 23/24 [00:00<00:00, 1093.72it/s]
24/24 : 100%|██████████| 24/24 [00:00<00:00, 1133.85it/s]
Saving Outputs : 100%|██████████| 24/24 [00:00<00:00, 1066.59it/s]
['distance', '__assignment_cost__', '__congested_time__']
We can save the skims, but we need to choose to only save the final ones, as the blended were not generated
assig.save_skims("base_year_assignment_skims", which_ones="final", format="omx")
Close the project
project.close()
Total running time of the script: (0 minutes 1.794 seconds)