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
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)
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, 33825.03it/s]
All-or-Nothing - Traffic Class: car : 10%|█ | 1/10 [00:00<00:00, 6657.63it/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, 422.71it/s]
All-or-Nothing - Traffic Class: car : 20%|██ | 2/10 [00:00<00:00, 410.52it/s]
All-or-Nothing - Traffic Class: car : 20%|██ | 2/10 [00:00<00:00, 399.86it/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, 650.45it/s]
All-or-Nothing - Traffic Class: car : 30%|███ | 3/10 [00:00<00:00, 630.47it/s]
All-or-Nothing - Traffic Class: car : 30%|███ | 3/10 [00:00<00:00, 613.65it/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, 842.91it/s]
All-or-Nothing - Traffic Class: car : 40%|████ | 4/10 [00:00<00:00, 817.24it/s]
All-or-Nothing - Traffic Class: car : 40%|████ | 4/10 [00:00<00:00, 795.54it/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, 1078.45it/s]
All-or-Nothing - Traffic Class: car : 50%|█████ | 5/10 [00:00<00:00, 1047.79it/s]
All-or-Nothing - Traffic Class: car : 50%|█████ | 5/10 [00:00<00:00, 1020.46it/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 : 60%|██████ | 6/10 [00:00<00:00, 1250.04it/s]
All-or-Nothing - Traffic Class: car : 60%|██████ | 6/10 [00:00<00:00, 1216.03it/s]
All-or-Nothing - Traffic Class: car : 60%|██████ | 6/10 [00:00<00:00, 1184.33it/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.198095: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment : 70%|███████ | 7/10 [00:00<00:00, 1455.27it/s]
All-or-Nothing - Traffic Class: car : 70%|███████ | 7/10 [00:00<00:00, 1415.29it/s]
All-or-Nothing - Traffic Class: car : 70%|███████ | 7/10 [00:00<00:00, 1378.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: 7/10 - RGap: 0.0668172: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment : 80%|████████ | 8/10 [00:00<00:00, 1738.21it/s]
All-or-Nothing - Traffic Class: car : 80%|████████ | 8/10 [00:00<00:00, 1687.00it/s]
All-or-Nothing - Traffic Class: car : 80%|████████ | 8/10 [00:00<00:00, 1642.49it/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.0679212: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment : 90%|█████████ | 9/10 [00:00<00:00, 1896.06it/s]
All-or-Nothing - Traffic Class: car : 90%|█████████ | 9/10 [00:00<00:00, 1842.39it/s]
All-or-Nothing - Traffic Class: car : 90%|█████████ | 9/10 [00:00<00:00, 1795.42it/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.107056: 0%| | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment : 100%|██████████| 10/10 [00:00<00:00, 2031.63it/s]
All-or-Nothing - Traffic Class: car : 100%|██████████| 10/10 [00:00<00:00, 1977.05it/s]
All-or-Nothing - Traffic Class: car : 100%|██████████| 10/10 [00:00<00:00, 1928.50it/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.0403881: 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, 645.58it/s]
2/24 : 8%|▊ | 2/24 [00:00<00:00, 1130.39it/s]
3/24 : 12%|█▎ | 3/24 [00:00<00:00, 1522.62it/s]
4/24 : 17%|█▋ | 4/24 [00:00<00:00, 1856.30it/s]
5/24 : 21%|██ | 5/24 [00:00<00:00, 2140.82it/s]
6/24 : 25%|██▌ | 6/24 [00:00<00:00, 2348.65it/s]
7/24 : 29%|██▉ | 7/24 [00:00<00:00, 2557.95it/s]
8/24 : 33%|███▎ | 8/24 [00:00<00:00, 2746.09it/s]
9/24 : 38%|███▊ | 9/24 [00:00<00:00, 2902.41it/s]
10/24 : 42%|████▏ | 10/24 [00:00<00:00, 3051.29it/s]
11/24 : 46%|████▌ | 11/24 [00:00<00:00, 3170.30it/s]
12/24 : 50%|█████ | 12/24 [00:00<00:00, 3284.50it/s]
13/24 : 54%|█████▍ | 13/24 [00:00<00:00, 3397.68it/s]
14/24 : 58%|█████▊ | 14/24 [00:00<00:00, 3499.42it/s]
15/24 : 62%|██████▎ | 15/24 [00:00<00:00, 3587.74it/s]
16/24 : 67%|██████▋ | 16/24 [00:00<00:00, 3675.79it/s]
17/24 : 71%|███████ | 17/24 [00:00<00:00, 3721.65it/s]
18/24 : 75%|███████▌ | 18/24 [00:00<00:00, 3787.75it/s]
19/24 : 79%|███████▉ | 19/24 [00:00<00:00, 3855.43it/s]
20/24 : 83%|████████▎ | 20/24 [00:00<00:00, 3917.16it/s]
21/24 : 88%|████████▊ | 21/24 [00:00<00:00, 3970.27it/s]
22/24 : 92%|█████████▏| 22/24 [00:00<00:00, 4007.94it/s]
23/24 : 96%|█████████▌| 23/24 [00:00<00:00, 4060.14it/s]
24/24 : 100%|██████████| 24/24 [00:00<00:00, 4102.51it/s]
Saving Outputs : 100%|██████████| 24/24 [00:00<00:00, 3746.17it/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 0.654 seconds)