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()
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 NaN
2 skims skims.omx 2 None None NaN 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, 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)

Gallery generated by Sphinx-Gallery