Project Scenarios#

In this example, we show how to use AequilibraE’s scenario system to manage multiple model variants within a single project, using different example networks to demonstrate scenario isolation and management.

See also

Several functions, methods, classes and modules are used in this example:

  • aequilibrae.Project.list_scenarios()

  • aequilibrae.Project.use_scenario()

  • aequilibrae.Project.create_empty_scenario()

  • aequilibrae.Project.clone_scenario()

# Imports
from uuid import uuid4
from tempfile import gettempdir
from pathlib import Path
from os.path import join
import pandas as pd

from aequilibrae.utils.create_example import create_example
from aequilibrae import TrafficAssignment, TrafficClass
No pre-existing parameter file exists for this project. Will use default
# We create the example project inside our temp folder.
fldr = Path(gettempdir()) / uuid4().hex
project = create_example(fldr, "sioux_falls")

Working with scenarios#

Let’s first see what scenarios exist in our project

project.list_scenarios()
scenario_name description
0 root The default, and root, scenario for an Aequilb...


The root scenario is always present and represents the base model. Let’s examine the current scenario’s network

print(f"Current scenario network has {len(project.network.links.data)} links")
print(f"Current scenario network has {len(project.network.nodes.data)} nodes")
Current scenario network has 76 links
Current scenario network has 24 nodes

Creating new scenarios#

We can create empty scenarios or clone existing ones

# Create an empty scenario to manually populate with a future/different network
project.create_empty_scenario("test_modifications", "Scenario for testing network modifications")

# Clone the root scenario to preserve the original network
project.clone_scenario("limited_capacity", "Testing different assignment parameters")
No pre-existing parameter file exists for this project. Will use default

Let’s see our updated scenario list

project.list_scenarios()
scenario_name description
0 root The default, and root, scenario for an Aequilb...
1 test_modifications Scenario for testing network modifications
2 limited_capacity Testing different assignment parameters


Switching between scenarios#

Each scenario operates independently with its own data

# Switch to the cloned scenario
project.use_scenario("limited_capacity")
print(f"This scenario has {len(project.network.links.data)} links")

# Modify the network
with project.db_connection as conn:
    conn.execute("UPDATE links SET capacity_ab=capacity_ab/2, capacity_ba=capacity_ba/2 WHERE link_id > 20 AND link_id < 50")
This scenario has 76 links

Let’s perform a traffic assignment in this scenario with lowered capacity

# Build the network graph
project.network.build_graphs(fields=["distance", "capacity_ab", "capacity_ba"], modes=["c"])
graph = project.network.graphs["c"]
graph.set_graph("distance")
graph.set_blocked_centroid_flows(False)

# Get the demand matrix
mat = project.matrices.get_matrix("demand_omx")
mat.computational_view()

# Create traffic assignment with alternative parameters
assigclass = TrafficClass("car", graph, mat)
assignment = TrafficAssignment(project)
assignment.add_class(assigclass)
assignment.set_vdf("BPR")

assignment.set_vdf_parameters({"alpha": 0.15, "beta": 4.0})
assignment.set_capacity_field("capacity")
assignment.set_time_field("distance")
assignment.max_iter = 10
assignment.set_algorithm("msa")

assignment.execute()

# Save results specific to this scenario
assignment.save_results("alternative_assignment")

print(f"Assignment completed. Total flow: {assigclass.results.total_link_loads.sum():.2f}")
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, 30393.51it/s]
All-or-Nothing - Traffic Class: car               :  10%|█         | 1/10 [00:00<00:00, 7681.88it/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, 378.97it/s]
All-or-Nothing - Traffic Class: car               :  20%|██        | 2/10 [00:00<00:00, 370.64it/s]
All-or-Nothing - Traffic Class: car               :  20%|██        | 2/10 [00:00<00:00, 364.77it/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.717655:   0%|          | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment                            :  30%|███       | 3/10 [00:00<00:00, 654.95it/s]
All-or-Nothing - Traffic Class: car               :  30%|███       | 3/10 [00:00<00:00, 641.85it/s]
All-or-Nothing - Traffic Class: car               :  30%|███       | 3/10 [00:00<00:00, 630.72it/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.943093:   0%|          | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment                            :  40%|████      | 4/10 [00:00<00:00, 808.38it/s]
All-or-Nothing - Traffic Class: car               :  40%|████      | 4/10 [00:00<00:00, 792.84it/s]
All-or-Nothing - Traffic Class: car               :  40%|████      | 4/10 [00:00<00:00, 779.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: 4/10 - RGap: 0.750474:   0%|          | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment                            :  50%|█████     | 5/10 [00:00<00:00, 1136.61it/s]
All-or-Nothing - Traffic Class: car               :  50%|█████     | 5/10 [00:00<00:00, 1113.55it/s]
All-or-Nothing - Traffic Class: car               :  50%|█████     | 5/10 [00:00<00:00, 1093.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.688544:   0%|          | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment                            :  60%|██████    | 6/10 [00:00<00:00, 1348.29it/s]
All-or-Nothing - Traffic Class: car               :  60%|██████    | 6/10 [00:00<00:00, 1321.04it/s]
All-or-Nothing - Traffic Class: car               :  60%|██████    | 6/10 [00:00<00:00, 1297.47it/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.556378:   0%|          | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment                            :  70%|███████   | 7/10 [00:00<00:00, 1514.81it/s]
All-or-Nothing - Traffic Class: car               :  70%|███████   | 7/10 [00:00<00:00, 1484.63it/s]
All-or-Nothing - Traffic Class: car               :  70%|███████   | 7/10 [00:00<00:00, 1458.53it/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.418738:   0%|          | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment                            :  80%|████████  | 8/10 [00:00<00:00, 1829.28it/s]
All-or-Nothing - Traffic Class: car               :  80%|████████  | 8/10 [00:00<00:00, 1791.96it/s]
All-or-Nothing - Traffic Class: car               :  80%|████████  | 8/10 [00:00<00:00, 1728.90it/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.262796:   0%|          | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment                            :  90%|█████████ | 9/10 [00:00<00:00, 2039.92it/s]
All-or-Nothing - Traffic Class: car               :  90%|█████████ | 9/10 [00:00<00:00, 1999.30it/s]
All-or-Nothing - Traffic Class: car               :  90%|█████████ | 9/10 [00:00<00:00, 1963.73it/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.199138:   0%|          | 0/10 [00:00<?, ?it/s]
Equilibrium Assignment                            : 100%|██████████| 10/10 [00:00<00:00, 2170.85it/s]
All-or-Nothing - Traffic Class: car               : 100%|██████████| 10/10 [00:00<00:00, 2129.74it/s]
All-or-Nothing - Traffic Class: car               : 100%|██████████| 10/10 [00:00<00:00, 2093.38it/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.174405:   0%|          | 0/10 [00:00<?, ?it/s]

Assignment completed. Total flow: 1136690.00

Switch to empty scenario for modifications

project.use_scenario("test_modifications")
print(f"Empty scenario has {len(project.network.links.data)} links")

# This scenario starts with an empty network, suitable for building from scratch
# or testing specific network configurations
Empty scenario has 0 links

Scenario isolation demonstration#

Let’s switch back to root and show that scenarios are isolated

project.use_scenario("root")
print(f"Back to root scenario with {len(project.network.links.data)} links")

# Check results - only root scenario results should be visible
root_results = project.results.list()
print(f"Root scenario has {len(root_results)} result tables")

# Switch to alternative scenario and check its results
project.use_scenario("limited_capacity")
alt_results = project.results.list()
print(f"Alternative scenario has {len(alt_results)} result tables")

# Each scenario maintains its own results database
alternative_assignment_exists = "alternative_assignment" in alt_results["table_name"].values
print(f"Alternative assignment result exists in this scenario: {alternative_assignment_exists}")
Back to root scenario with 76 links
Root scenario has 0 result tables
Alternative scenario has 1 result tables
Alternative assignment result exists in this scenario: True

Best practices for scenario management#

# Always return to root when doing project-wide operations
project.use_scenario("root")

# List scenarios for reference
final_scenarios = project.list_scenarios()
print("\nFinal scenario summary:")
for _, scenario in final_scenarios.iterrows():
    project.use_scenario(scenario['scenario_name'])
    link_count = len(project.network.links.data)
    result_count = len(project.results.list())
    print(f"  {scenario['scenario_name']}: {link_count} links, {result_count} results")
    print(f"    Description: {scenario['description']}")
Final scenario summary:
  root: 76 links, 0 results
    Description: The default, and root, scenario for an AequilbraE project. The name "root" is treat as special case.
  test_modifications: 0 links, 0 results
    Description: Scenario for testing network modifications
  limited_capacity: 76 links, 1 results
    Description: Testing different assignment parameters

Clean up

project.use_scenario("root")  # Always end on root scenario
mat.close()
project.close()
This project at /tmp/c209fbddcf054b1b94a3bcbccd398a83 is already closed

Total running time of the script: (0 minutes 3.385 seconds)

Gallery generated by Sphinx-Gallery