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()
name file_name cores procedure procedure_id timestamp description status
0 demand_omx demand.omx 1 None None 2020-11-24 08:47:18 Original data imported to OMX format
1 demand_mc demand_mc.omx 3 None None 2021-02-24 00:51:35 None
2 skims skims.omx 2 None None None Example skim
3 demand_aem demand.aem 1 None None 2020-11-24 08:46:42 Original data imported to AEM format


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)

Gallery generated by Sphinx-Gallery