Forecasting#

In this example, we present a full forecasting workflow for the Sioux Falls example model.

Imports

[1]:
from uuid import uuid4
from tempfile import gettempdir
from os.path import join
from aequilibrae.utils.create_example import create_example
import logging
import sys

We create the example project inside our temp folder

[2]:
fldr = join(gettempdir(), uuid4().hex)

project = create_example(fldr)
logger = project.logger

# We get the project open, and we can tell the logger to direct all messages to the terminal as well
stdout_handler = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter("%(asctime)s;%(levelname)s ; %(message)s")
stdout_handler.setFormatter(formatter)
logger.addHandler(stdout_handler)

Traffic assignment with skimming#

[3]:
from aequilibrae.paths import TrafficAssignment, TrafficClass

We build all graphs

[4]:
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
2023-10-09 07:31:49,707;WARNING ; Field(s) name, lanes has(ve) at least one NaN value. Check your computations
2023-10-09 07:31:49,763;WARNING ; Field(s) name, lanes has(ve) at least one NaN value. Check your computations
2023-10-09 07:31:49,819;WARNING ; Field(s) name, lanes has(ve) at least one NaN value. Check your computations
2023-10-09 07:31:49,874;WARNING ; Field(s) name, lanes has(ve) at least one NaN value. Check your computations
2023-10-09 07:31:49,931;WARNING ; Field(s) name, lanes has(ve) at least one NaN value. Check your computations
2023-10-09 07:31:49,986;WARNING ; Field(s) name, lanes has(ve) at least one NaN value. Check your computations

We grab the graph for cars

[5]:
graph = project.network.graphs["c"]

# Let's say we want to minimize the free_flow_time
graph.set_graph("free_flow_time")

# And will skim time and distance while we are at it
graph.set_skimming(["free_flow_time", "distance"])

# 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)
2023-10-09 07:31:50,044;WARNING ; Cost field with wrong type. Converting to float64

We get the demand matrix directly from the project record So let’s inspect what we have in the project

[6]:
proj_matrices = project.matrices
print(proj_matrices.list())
         name      file_name  cores procedure procedure_id  \
0  demand_omx     demand.omx      1      None         None
1   demand_mc  demand_mc.omx      3      None         None
2       skims      skims.omx      2      None         None
3  demand_aem     demand.aem      1      None         None

             timestamp                           description status
0  2020-11-24 08:47:18  Original data imported to OMX format
1  2021-02-24 00:51:35                                  None
2                 None                          Example skim
3  2020-11-24 08:46:42  Original data imported to AEM format

Let’s get it in this better way

[7]:
demand = proj_matrices.get_matrix("demand_omx")
demand.computational_view(["matrix"])
[8]:
assig = TrafficAssignment()

# Create the assignment class
assigclass = TrafficClass(name="car", graph=graph, matrix=demand)

# The first thing to do is to add at list of traffic classes to be assigned
assig.add_class(assigclass)

# We set these parameters only after adding one class to the assignment
assig.set_vdf("BPR")  # This is not case-sensitive

# Then we set the volume delay function
assig.set_vdf_parameters({"alpha": "b", "beta": "power"})  # And its parameters

assig.set_capacity_field("capacity")  # The capacity and free flow travel times as they exist in the graph
assig.set_time_field("free_flow_time")

# And the algorithm we want to use to assign
assig.set_algorithm("bfw")

# Since I haven't checked the parameters file, let's make sure convergence criteria is good
assig.max_iter = 1000
assig.rgap_target = 0.001

assig.execute()  # we then execute the assignment
2023-10-09 07:31:50,585;INFO ; Traffic Class specification
2023-10-09 07:31:50,586;INFO ; {'car': {'Graph': "{'Mode': 'c', 'Block through centroids': False, 'Number of centroids': 24, 'Links': 76, 'Nodes': 24}", 'Matrix': "{'Source': '/tmp/81560d1a49c543a180dde23967ececc7/matrices/demand.omx', 'Number of centroids': 24, 'Matrix cores': ['matrix'], 'Matrix totals': {'matrix': 360600.0}}"}}
2023-10-09 07:31:50,587;INFO ; Traffic Assignment specification
2023-10-09 07:31:50,589;INFO ; {'VDF parameters': {'alpha': 'b', 'beta': 'power'}, 'VDF function': 'bpr', 'Number of cores': 2, 'Capacity field': 'capacity', 'Time field': 'free_flow_time', 'Algorithm': 'bfw', 'Maximum iterations': 250, 'Target RGAP': 0.0001}
2023-10-09 07:31:50,603;WARNING ; Cost field with wrong type. Converting to float64
2023-10-09 07:31:50,608;INFO ; bfw Assignment STATS
2023-10-09 07:31:50,615;INFO ; Iteration, RelativeGap, stepsize
2023-10-09 07:31:50,638;INFO ; 1,inf,1.0
2023-10-09 07:31:50,650;INFO ; 2,0.8550751349428284,0.32839952448634563
2023-10-09 07:31:50,665;INFO ; 3,0.4763455007221067,0.18660240547488702
2023-10-09 07:31:50,678;INFO ; 4,0.2355126365951965,0.2411477440291793
2023-10-09 07:31:50,695;INFO ; 5,0.10924072010481088,0.8185470737942447
2023-10-09 07:31:50,711;INFO ; 6,0.1980945227617506,0.14054330572978305
2023-10-09 07:31:50,727;INFO ; 7,0.0668172221544687,0.36171152718899247
2023-10-09 07:31:50,751;INFO ; 8,0.06792122267870587,0.9634685345644044
2023-10-09 07:31:50,771;INFO ; 9,0.10705582933092855,0.13757153109677187
2023-10-09 07:31:50,792;INFO ; 10,0.04038814432034622,0.1609403425427973
2023-10-09 07:31:50,813;INFO ; 11,0.025801226183773084,0.716435057617116
2023-10-09 07:31:50,825;INFO ; 12,0.042846437173170424,0.08581544277016687
2023-10-09 07:31:50,838;INFO ; 13,0.016971662333407043,0.1660157969033195
2023-10-09 07:31:50,859;INFO ; 14,0.020396548012132195,0.4461322062863191
2023-10-09 07:31:50,875;INFO ; 15,0.025887901335905694,0.08515995223661561
2023-10-09 07:31:50,893;INFO ; 16,0.015188959427663162,0.1988698342670051
2023-10-09 07:31:50,905;INFO ; 17,0.01475141964322897,0.3548856159715819
2023-10-09 07:31:50,933;INFO ; 18,0.015582407302127808,0.06145415154081679
2023-10-09 07:31:50,948;INFO ; 19,0.008935871473338547,0.08603462968532699
2023-10-09 07:31:50,963;INFO ; 20,0.008477045208211683,0.1668913886047936
2023-10-09 07:31:50,997;INFO ; 21,0.009517581409988221,0.4917099156011133
2023-10-09 07:31:51,015;INFO ; 22,0.013060711845093087,0.060284308755231206
2023-10-09 07:31:51,031;INFO ; 23,0.006861821876765184,0.10954009782378307
2023-10-09 07:31:51,057;INFO ; 24,0.006201113315688483,0.12230718464290123
2023-10-09 07:31:51,069;INFO ; 25,0.0074574049738041406,0.3080614235512652
2023-10-09 07:31:51,098;INFO ; 26,0.006900497787039256,0.32835666337221175
2023-10-09 07:31:51,114;INFO ; 27,0.006963554132391016,0.7377893941135681
2023-10-09 07:31:51,128;INFO ; 28,0.006817764279834173,0.0443870768699142
2023-10-09 07:31:51,147;INFO ; 29,0.004277860366532555,0.05431813621783447
2023-10-09 07:31:51,165;INFO ; 30,0.004136181096381436,0.05758294976347482
2023-10-09 07:31:51,178;INFO ; 31,0.0031483923250298237,0.0918038853550363
2023-10-09 07:31:51,191;INFO ; 32,0.0034184967969881734,0.12279944254979965
2023-10-09 07:31:51,202;INFO ; 33,0.002738614050254322,0.08799214942487946
2023-10-09 07:31:51,213;INFO ; 34,0.0023403784016331874,0.1098259985006849
2023-10-09 07:31:51,251;INFO ; 35,0.0023185435502055523,0.18741920884713098
2023-10-09 07:31:51,267;INFO ; 36,0.0023838181828793143,0.1404967362503087
2023-10-09 07:31:51,284;INFO ; 37,0.0017801377860521138,0.25278698153070905
2023-10-09 07:31:51,297;INFO ; 38,0.0019264349761422953,0.30768123024764726
2023-10-09 07:31:51,308;INFO ; 39,0.0018408894375062524,0.3982324050247662
2023-10-09 07:31:51,324;INFO ; 40,0.0018205742523357215,0.5255149131180074
2023-10-09 07:31:51,335;INFO ; 41,0.0020224171108353135,0.012343794696331265
2023-10-09 07:31:51,356;INFO ; 42,0.001423836778473865,0.03045402621736974
2023-10-09 07:31:51,372;INFO ; 43,0.0011877471305860427,0.02283308748607117
2023-10-09 07:31:51,385;INFO ; 44,0.0012106681494599195,0.06969126002892805
2023-10-09 07:31:51,397;INFO ; 45,0.0011336232568064097,0.038970964685986896
2023-10-09 07:31:51,414;INFO ; 46,0.0009780989052684459,0.022071990851560294
2023-10-09 07:31:51,417;INFO ; bfw Assignment finished. 46 iterations and 0.0009780989052684459 final gap

Convergence report is easy to see

[9]:
import pandas as pd

convergence_report = assig.report()
print(convergence_report.head())
   iteration      rgap     alpha warnings     beta0     beta1  beta2
0          1       inf  1.000000           1.000000  0.000000    0.0
1          2  0.855075  0.328400           1.000000  0.000000    0.0
2          3  0.476346  0.186602           1.000000  0.000000    0.0
3          4  0.235513  0.241148           1.000000  0.000000    0.0
4          5  0.109241  0.818547           0.607382  0.392618    0.0
[10]:
volumes = assig.results()
print(volumes.head())
           matrix_ab  matrix_ba   matrix_tot  Congested_Time_AB  \
link_id
1        4565.043510        NaN  4565.043510           6.000869
2        8152.210795        NaN  8152.210795           4.008833
3        4552.603997        NaN  4552.603997           6.000859
4        5988.789717        NaN  5988.789717           6.596350
5        8164.650309        NaN  8164.650309           4.008888

         Congested_Time_BA  Congested_Time_Max  Delay_factor_AB  \
link_id
1                      NaN            6.000869         1.000145
2                      NaN            4.008833         1.002208
3                      NaN            6.000859         1.000143
4                      NaN            6.596350         1.319270
5                      NaN            4.008888         1.002222

         Delay_factor_BA  Delay_factor_Max    VOC_AB  VOC_BA   VOC_max  \
link_id
1                    NaN          1.000145  0.176255     NaN  0.176255
2                    NaN          1.002208  0.348333     NaN  0.348333
3                    NaN          1.000143  0.175775     NaN  0.175775
4                    NaN          1.319270  1.207860     NaN  1.207860
5                    NaN          1.002222  0.348865     NaN  0.348865

              PCE_AB  PCE_BA      PCE_tot
link_id
1        4565.043510     NaN  4565.043510
2        8152.210795     NaN  8152.210795
3        4552.603997     NaN  4552.603997
4        5988.789717     NaN  5988.789717
5        8164.650309     NaN  8164.650309

We could export it to CSV or AequilibraE data, but let’s put it directly into the results database

[11]:
assig.save_results("base_year_assignment")

And save the skims

[12]:
assig.save_skims("base_year_assignment_skims", which_ones="all", format="omx")
2023-10-09 07:31:51,643;WARNING ; Matrix Record has been saved to the database

Trip distribution#

Calibration ~~~~~~~~~~~ We will calibrate synthetic gravity models using the skims for TIME that we just generated

[13]:
import numpy as np
from aequilibrae.distribution import GravityCalibration

Let’s take another look at what we have in terms of matrices in the model

[14]:
print(proj_matrices.list())
                             name                           file_name  cores  \
0                      demand_omx                          demand.omx      1
1                       demand_mc                       demand_mc.omx      3
2                           skims                           skims.omx      2
3                      demand_aem                          demand.aem      1
4  base_year_assignment_skims_car  base_year_assignment_skims_car.omx      4

            procedure                      procedure_id  \
0                None                              None
1                None                              None
2                None                              None
3                None                              None
4  Traffic Assignment  9f2698274a58428dbca33ebbec35e539

                    timestamp                                   description  \
0         2020-11-24 08:47:18          Original data imported to OMX format
1         2021-02-24 00:51:35                                          None
2                        None                                  Example skim
3         2020-11-24 08:46:42          Original data imported to AEM format
4  2023-10-09 07:31:50.160764  Skimming for assignment procedure. Class car

  status
0
1
2
3
4

We need the demand

[15]:
demand = proj_matrices.get_matrix("demand_aem")

# And the skims
imped = proj_matrices.get_matrix("base_year_assignment_skims_car")

We can check which matrix cores were created for our skims to decide which one to use

[16]:
imped.names

# Where ``free_flow_time_final`` is actually the congested time for the last iteration
[16]:
['distance_blended',
 'distance_final',
 'free_flow_time_blended',
 'free_flow_time_final']

But before using the data, let’s get some impedance for the intrazonals Let’s assume it is 75% of the closest zone

[17]:
imped_core = "free_flow_time_final"
imped.computational_view([imped_core])

# If we run the code below more than once, we will be overwriting the diagonal values with non-sensical data
# so let's zero it first
np.fill_diagonal(imped.matrix_view, 0)

# We compute it with a little bit of NumPy magic
intrazonals = np.amin(imped.matrix_view, where=imped.matrix_view > 0, initial=imped.matrix_view.max(), axis=1)
intrazonals *= 0.75

# Then we fill in the impedance matrix
np.fill_diagonal(imped.matrix_view, intrazonals)

Since we are working with an OMX file, we cannot overwrite a matrix on disk So we give a new name to save it

[18]:
imped.save(names=["final_time_with_intrazonals"])

This also updates these new matrices as those being used for computation As one can verify below

[19]:
imped.view_names
[19]:
['final_time_with_intrazonals']

We set the matrices for being used in computation

[20]:
demand.computational_view(["matrix"])
[21]:
for function in ["power", "expo"]:
    gc = GravityCalibration(matrix=demand, impedance=imped, function=function, nan_as_zero=True)
    gc.calibrate()
    model = gc.model
    # We save the model
    model.save(join(fldr, f"{function}_model.mod"))

    # We can save the result of applying the model as well
    # We can also save the calibration report
    with open(join(fldr, f"{function}_convergence.log"), "w") as otp:
        for r in gc.report:
            otp.write(r + "\n")

Forecast#

We create a set of ‘future’ vectors using some random growth factors. We apply the model for inverse power, as the trip frequency length distribution (TFLD) seems to be a better fit for the actual one.

[22]:
from aequilibrae.distribution import Ipf, GravityApplication, SyntheticGravityModel
from aequilibrae.matrix import AequilibraeData

We compute the vectors from our matrix

[23]:
origins = np.sum(demand.matrix_view, axis=1)
destinations = np.sum(demand.matrix_view, axis=0)

args = {
    "file_path": join(fldr, "synthetic_future_vector.aed"),
    "entries": demand.zones,
    "field_names": ["origins", "destinations"],
    "data_types": [np.float64, np.float64],
    "memory_mode": False,
}

vectors = AequilibraeData()
vectors.create_empty(**args)

vectors.index[:] = demand.index[:]

# Then grow them with some random growth between 0 and 10%, and balance them
vectors.origins[:] = origins * (1 + np.random.rand(vectors.entries) / 10)
vectors.destinations[:] = destinations * (1 + np.random.rand(vectors.entries) / 10)
vectors.destinations *= vectors.origins.sum() / vectors.destinations.sum()

Impedance#

[24]:
imped = proj_matrices.get_matrix("base_year_assignment_skims_car")
imped.computational_view(["final_time_with_intrazonals"])

# If we wanted the main diagonal to not be considered...
# ``np.fill_diagonal(imped.matrix_view, np.nan)``
[25]:
for function in ["power", "expo"]:
    model = SyntheticGravityModel()
    model.load(join(fldr, f"{function}_model.mod"))

    outmatrix = join(proj_matrices.fldr, f"demand_{function}_model.aem")
    args = {
        "impedance": imped,
        "rows": vectors,
        "row_field": "origins",
        "model": model,
        "columns": vectors,
        "column_field": "destinations",
        "nan_as_zero": True,
    }

    gravity = GravityApplication(**args)
    gravity.apply()

    # We get the output matrix and save it to OMX too,
    gravity.save_to_project(name=f"demand_{function}_modeled", file_name=f"demand_{function}_modeled.omx")
2023-10-09 07:31:53,076;WARNING ; Matrix Record has been saved to the database
2023-10-09 07:31:53,210;WARNING ; Matrix Record has been saved to the database

We update the matrices table/records and verify that the new matrices are indeed there

[26]:
proj_matrices.update_database()
print(proj_matrices.list())
                             name                           file_name  cores  \
0                      demand_omx                          demand.omx      1
1                       demand_mc                       demand_mc.omx      3
2                           skims                           skims.omx      2
3                      demand_aem                          demand.aem      1
4  base_year_assignment_skims_car  base_year_assignment_skims_car.omx      4
5            demand_power_modeled            demand_power_modeled.omx      1
6             demand_expo_modeled             demand_expo_modeled.omx      1

                             procedure                      procedure_id  \
0                                 None                              None
1                                 None                              None
2                                 None                              None
3                                 None                              None
4                   Traffic Assignment  9f2698274a58428dbca33ebbec35e539
5  Synthetic gravity trip distribution  bec508263def4a94aba3978becae619e
6  Synthetic gravity trip distribution  c776dc35f937498db274ae7591567529

                    timestamp                                   description  \
0         2020-11-24 08:47:18          Original data imported to OMX format
1         2021-02-24 00:51:35                                          None
2                        None                                  Example skim
3         2020-11-24 08:46:42          Original data imported to AEM format
4  2023-10-09 07:31:50.160764  Skimming for assignment procedure. Class car
5  2023-10-09 07:31:53.004760    Synthetic gravity trip distribution. POWER
6  2023-10-09 07:31:53.141532     Synthetic gravity trip distribution. EXPO

  status
0
1
2
3
4
5
6

IPF for the future vectors#

[27]:
args = {
    "matrix": demand,
    "rows": vectors,
    "columns": vectors,
    "column_field": "destinations",
    "row_field": "origins",
    "nan_as_zero": True,
}

ipf = Ipf(**args)
ipf.fit()

ipf.save_to_project(name="demand_ipfd", file_name="demand_ipfd.aem")
ipf.save_to_project(name="demand_ipfd_omx", file_name="demand_ipfd.omx")
2023-10-09 07:31:53,490;WARNING ; Matrix Record has been saved to the database
2023-10-09 07:31:53,519;WARNING ; Matrix Record has been saved to the database
[27]:
<aequilibrae.project.data.matrix_record.MatrixRecord at 0x7f53c672cee0>
[28]:
df = proj_matrices.list()

Future traffic assignment#

[29]:
from aequilibrae.paths import TrafficAssignment, TrafficClass
[30]:
logger.info("\n\n\n TRAFFIC ASSIGNMENT FOR FUTURE YEAR")
2023-10-09 07:31:53,571;INFO ;


 TRAFFIC ASSIGNMENT FOR FUTURE YEAR
[31]:
demand = proj_matrices.get_matrix("demand_ipfd")

# Let's see what is the core we ended up getting. It should be 'gravity'
demand.names
[31]:
['matrix']

Let’s use the IPF matrix

[32]:
demand.computational_view("matrix")

assig = TrafficAssignment()

# Creates the assignment class
assigclass = TrafficClass(name="car", graph=graph, matrix=demand)

# The first thing to do is to add at a list of traffic classes to be assigned
assig.add_class(assigclass)

assig.set_vdf("BPR")  # This is not case-sensitive

# Then we set the volume delay function
assig.set_vdf_parameters({"alpha": "b", "beta": "power"})  # And its parameters

assig.set_capacity_field("capacity")  # The capacity and free flow travel times as they exist in the graph
assig.set_time_field("free_flow_time")

# And the algorithm we want to use to assign
assig.set_algorithm("bfw")

# Since I haven't checked the parameters file, let's make sure convergence criteria is good
assig.max_iter = 500
assig.rgap_target = 0.00001

OPTIONAL

[33]:
# If we want to execute select link analysis on a particular TrafficClass, we set the links we are analyzing.
# The format of the input select links is a dictionary (str: list[tuple]).
# Each entry represents a separate set of selected links to compute. The str name will name the set of links.
# The list[tuple] is the list of links being selected, of the form (link_id, direction), as it occurs in the Graph.
# Direction can be 0, 1, -1. 0 denotes bi-directionality
# For example, let's use Select Link on two sets of links:
[34]:
select_links = {
    "Leaving node 1": [(1, 1), (2, 1)],
    "Random nodes": [(3, 1), (5, 1)],
}
# We call this command on the class we are analyzing with our dictionary of values
assigclass.set_select_links(select_links)

assig.execute()  # we then execute the assignment
2023-10-09 07:31:54,155;INFO ; Traffic Class specification
2023-10-09 07:31:54,156;INFO ; {'car': {'Graph': "{'Mode': 'c', 'Block through centroids': False, 'Number of centroids': 24, 'Links': 76, 'Nodes': 24}", 'Matrix': "{'Source': '/tmp/81560d1a49c543a180dde23967ececc7/matrices/demand_ipfd.aem', 'Number of centroids': 24, 'Matrix cores': ['matrix'], 'Matrix totals': {'matrix': 382128.47109537316}}", 'select_links': "{'Leaving node 1': [(1, 1), (2, 1)], 'Random nodes': [(3, 1), (5, 1)]}"}}
2023-10-09 07:31:54,157;INFO ; Traffic Assignment specification
2023-10-09 07:31:54,158;INFO ; {'VDF parameters': {'alpha': 'b', 'beta': 'power'}, 'VDF function': 'bpr', 'Number of cores': 2, 'Capacity field': 'capacity', 'Time field': 'free_flow_time', 'Algorithm': 'bfw', 'Maximum iterations': 250, 'Target RGAP': 0.0001}
2023-10-09 07:31:54,163;WARNING ; Cost field with wrong type. Converting to float64
2023-10-09 07:31:54,164;INFO ; bfw Assignment STATS
2023-10-09 07:31:54,165;INFO ; Iteration, RelativeGap, stepsize
2023-10-09 07:31:54,187;INFO ; 1,inf,1.0
2023-10-09 07:31:54,203;INFO ; 2,0.8843342979237877,0.3282601311230673
2023-10-09 07:31:54,235;INFO ; 3,0.5277862873791306,0.17497985566918453
2023-10-09 07:31:54,254;INFO ; 4,0.29194650140479117,0.17670436021350908
2023-10-09 07:31:54,270;INFO ; 5,0.11549192123326002,0.6086559353290888
2023-10-09 07:31:54,285;INFO ; 6,0.260238247786045,0.1186844643898462
2023-10-09 07:31:54,298;INFO ; 7,0.1149135036638274,0.1931127017872055
2023-10-09 07:31:54,311;INFO ; 8,0.06906613127222154,0.7468105137408743
2023-10-09 07:31:54,328;INFO ; 9,0.13129228847766145,0.1412777860147069
2023-10-09 07:31:54,347;INFO ; 10,0.05653065564288893,0.23360219622073072
/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/aequilibrae/paths/traffic_class.py:145: UserWarning: Input string name has a space in it. Replacing with _
  warnings.warn("Input string name has a space in it. Replacing with _")
2023-10-09 07:31:54,372;INFO ; 11,0.044336951104464055,0.5989559388596997
2023-10-09 07:31:54,384;INFO ; 12,0.07509216969478145,0.09319225506541512
2023-10-09 07:31:54,396;INFO ; 13,0.029745918777988097,0.1634229350206238
2023-10-09 07:31:54,416;INFO ; 14,0.02689895416146674,0.4852506196532049
2023-10-09 07:31:54,436;INFO ; 15,0.037629865519935426,0.10651389536765539
2023-10-09 07:31:54,462;INFO ; 16,0.01892319707744423,0.16007999664046615
2023-10-09 07:31:54,482;INFO ; 17,0.019615716598374848,0.4981300842915594
2023-10-09 07:31:54,496;INFO ; 18,0.029147663088116622,0.0786874636604352
2023-10-09 07:31:54,510;INFO ; 19,0.015949124824750735,0.07901084759546265
2023-10-09 07:31:54,522;INFO ; 20,0.007890226693601251,0.3446498211650339
2023-10-09 07:31:54,536;INFO ; 21,0.017878024125839897,0.546747552171347
2023-10-09 07:31:54,552;INFO ; 22,0.019877208763860833,0.04653727761300191
2023-10-09 07:31:54,567;INFO ; 23,0.009899820589308252,0.08273890286358307
2023-10-09 07:31:54,593;INFO ; 24,0.008203270608051788,0.0547667229484114
2023-10-09 07:31:54,613;INFO ; 25,0.00738910408998631,0.17841213134477812
2023-10-09 07:31:54,630;INFO ; 26,0.006143733097868434,0.17165453815167359
2023-10-09 07:31:54,653;INFO ; 27,0.0057571352949203555,0.14451383496777234
2023-10-09 07:31:54,669;INFO ; 28,0.0062886873525376,0.49302781040275967
2023-10-09 07:31:54,682;INFO ; 29,0.007620370560937511,0.040086892862043595
2023-10-09 07:31:54,698;INFO ; 30,0.004707622177050174,0.034645060283059956
2023-10-09 07:31:54,711;INFO ; 31,0.004021928245763552,0.06826083998945201
2023-10-09 07:31:54,730;INFO ; 32,0.005205802724573167,0.1361819635145941
2023-10-09 07:31:54,746;INFO ; 33,0.004086432161706526,0.11370092714692277
2023-10-09 07:31:54,779;INFO ; 34,0.004500640558131295,0.1398816890717838
2023-10-09 07:31:54,799;INFO ; 35,0.003962374811112155,0.16449173195073422
2023-10-09 07:31:54,815;INFO ; 36,0.004255140052009136,0.20948327402651998
2023-10-09 07:31:54,835;INFO ; 37,0.0032990381306931466,0.25407102360000955
2023-10-09 07:31:54,853;INFO ; 38,0.003421436096579938,0.33768570257389197
2023-10-09 07:31:54,875;INFO ; 39,0.004137760800660098,0.7875719251914378
2023-10-09 07:31:54,888;INFO ; 40,0.0037613820543678533,0.016887915734141067
2023-10-09 07:31:54,902;INFO ; 41,0.0023952255154947233,0.023016516102230405
2023-10-09 07:31:54,918;INFO ; 42,0.0017776642059765338,0.018066240608032177
2023-10-09 07:31:54,938;INFO ; 43,0.0018108667956604162,0.04530783729858078
2023-10-09 07:31:54,964;INFO ; 44,0.0019626927474460975,0.04423795135248905
2023-10-09 07:31:55,004;INFO ; 45,0.0014683280099512944,0.04219267476796814
2023-10-09 07:31:55,024;INFO ; 46,0.0015100435123120127,0.0737610573023989
2023-10-09 07:31:55,068;INFO ; 47,0.0014905997478915814,0.14228352918164372
2023-10-09 07:31:55,087;INFO ; 48,0.0015935721820305368,0.17282300593494632
2023-10-09 07:31:55,106;INFO ; 49,0.0014949719706013088,0.1208743134358608
2023-10-09 07:31:55,120;INFO ; 50,0.0013041009526372261,0.3628320579498655
2023-10-09 07:31:55,151;INFO ; 51,0.001867595055031321,0.5847964758440833
2023-10-09 07:31:55,172;INFO ; 52,0.0014568805193896205,0.01107086144230172
2023-10-09 07:31:55,199;INFO ; 53,0.0009919300907414805,0.009624410241602953
2023-10-09 07:31:55,223;INFO ; 54,0.0007579177495033876,0.010169523679002798
2023-10-09 07:31:55,241;INFO ; 55,0.000713041862769129,0.02721228399471518
2023-10-09 07:31:55,258;INFO ; 56,0.0007718426096723863,0.02598345051728639
2023-10-09 07:31:55,275;INFO ; 57,0.0006919406721210695,0.019005739035796047
2023-10-09 07:31:55,304;INFO ; 58,0.0006971045933573892,0.024697332269941235
2023-10-09 07:31:55,323;INFO ; 59,0.0006177572711413152,0.02625841389849434
2023-10-09 07:31:55,339;INFO ; 60,0.0004949390985351581,0.01816748642632108
2023-10-09 07:31:55,353;INFO ; 61,0.0005981133194640076,0.022815522776111534
2023-10-09 07:31:55,371;INFO ; 62,0.00042611379412362406,0.014645909913891786
2023-10-09 07:31:55,389;INFO ; 63,0.0004544883805301343,0.021248362420000232
2023-10-09 07:31:55,405;INFO ; 64,0.0005814642526996651,0.058967015177902024
2023-10-09 07:31:55,435;INFO ; 65,0.0008142019364808989,0.11853932928921254
2023-10-09 07:31:55,453;INFO ; 66,0.0009175430473762711,0.21101990574842533
2023-10-09 07:31:55,471;INFO ; 67,0.0012061630419058025,0.30669499803482064
2023-10-09 07:31:55,493;INFO ; 68,0.0009974844009979203,0.7927065979941759
2023-10-09 07:31:55,509;INFO ; 69,0.0011220663847968924,0.005221278410391384
2023-10-09 07:31:55,523;INFO ; 70,0.0006989206927902114,0.013664946888250123
2023-10-09 07:31:55,538;INFO ; 71,0.0008366585622320979,0.03272186434426746
2023-10-09 07:31:55,557;INFO ; 72,0.0006297596926160931,0.02525070963234062
2023-10-09 07:31:55,576;INFO ; 73,0.0004253848429756329,0.0066608203007047385
2023-10-09 07:31:55,596;INFO ; 74,0.000299984787156202,0.00834673823223034
2023-10-09 07:31:55,613;INFO ; 75,0.00038232423954093604,0.00918009707152828
2023-10-09 07:31:55,631;INFO ; 76,0.0002565371686394431,0.0043418716704208375
2023-10-09 07:31:55,665;INFO ; 77,0.0002376283991774165,0.005320567280347423
2023-10-09 07:31:55,683;INFO ; 78,0.0001935652130948001,0.006180806332267958
2023-10-09 07:31:55,733;INFO ; 79,0.00019903549698004565,0.008069198723698507
2023-10-09 07:31:55,752;INFO ; 80,0.00017992302520408707,0.007542292709527183
2023-10-09 07:31:55,771;INFO ; 81,0.00019960507386761021,0.013616724800290397
2023-10-09 07:31:55,792;INFO ; 82,0.00015811697867940754,0.009574604277446483
2023-10-09 07:31:55,830;INFO ; 83,0.00020426115277526432,0.01424588182820151
2023-10-09 07:31:55,849;INFO ; 84,0.0001918078543246969,0.022107377525382246
2023-10-09 07:31:55,871;INFO ; 85,0.00029740505096134294,0.03026331729622662
2023-10-09 07:31:55,885;INFO ; 86,0.0002676133058214241,0.022205103599881166
2023-10-09 07:31:55,903;INFO ; 87,0.00022167684931512343,0.018255110437366266
2023-10-09 07:31:55,915;INFO ; 88,0.0001856177769779457,0.01831098319954454
2023-10-09 07:31:55,931;INFO ; 89,0.00016882927804309894,0.019045235887754804
2023-10-09 07:31:55,949;INFO ; 90,0.00019794426056780786,0.045366940465589346
2023-10-09 07:31:55,971;INFO ; 91,0.00023008888929651133,0.03312855496043688
2023-10-09 07:31:55,988;INFO ; 92,0.00023655520492032252,0.04887093937042499
2023-10-09 07:31:56,002;INFO ; 93,0.00023895046518874688,0.03546014615602969
2023-10-09 07:31:56,029;INFO ; 94,0.00022377981768055506,0.0322241293603487
2023-10-09 07:31:56,045;INFO ; 95,0.00027253562038624814,0.08746706332325345
2023-10-09 07:31:56,062;INFO ; 96,0.0003523974816214655,0.09950711762113329
2023-10-09 07:31:56,075;INFO ; 97,0.00028386835765870837,0.0860076827348483
2023-10-09 07:31:56,116;INFO ; 98,0.0002860195943141491,0.05349061072167645
2023-10-09 07:31:56,132;INFO ; 99,0.0003023673486512206,0.14690845584851006
2023-10-09 07:31:56,155;INFO ; 100,0.00030973452384132973,0.10261083369150882
2023-10-09 07:31:56,171;INFO ; 101,0.00036899403443273535,0.2367515634808072
2023-10-09 07:31:56,188;INFO ; 102,0.0003017862758407539,0.21548575990212832
2023-10-09 07:31:56,208;INFO ; 103,0.00033933582392870604,0.2930065925180579
2023-10-09 07:31:56,221;INFO ; 104,0.00036780021271879315,0.5558395280385408
2023-10-09 07:31:56,242;INFO ; 105,0.0003095552989805466,0.7528901146530541
2023-10-09 07:31:56,259;INFO ; 106,0.00031243893493552766,0.0024957998215824092
2023-10-09 07:31:56,283;INFO ; 107,0.0002450093825249529,0.003093390917269248
2023-10-09 07:31:56,309;INFO ; 108,0.00025537517347196174,0.0035012321875870114
2023-10-09 07:31:56,328;INFO ; 109,0.0001966089358868067,0.0028980815160590686
2023-10-09 07:31:56,347;INFO ; 110,0.00016212413330880286,0.005023629531116648
2023-10-09 07:31:56,361;INFO ; 111,0.00022324574126136434,0.006465130190084674
2023-10-09 07:31:56,374;INFO ; 112,0.0001981770286909696,0.008281164571699454
2023-10-09 07:31:56,389;INFO ; 113,0.00015167610924008722,0.0029138844205597327
2023-10-09 07:31:56,409;INFO ; 114,0.00011547022176021668,0.0024568497912570305
2023-10-09 07:31:56,433;INFO ; 115,9.871862147921654e-05,0.00202440791280087
2023-10-09 07:31:56,466;INFO ; 116,9.656764517336227e-05,0.0030353788822396186
2023-10-09 07:31:56,478;INFO ; 117,9.579551362116193e-05,0.0020422208521644527
2023-10-09 07:31:56,489;INFO ; 118,8.712766602884791e-05,0.002483876891346481
2023-10-09 07:31:56,501;INFO ; 119,8.110143991339432e-05,0.004037823666232026
2023-10-09 07:31:56,519;INFO ; 120,7.741704583359372e-05,0.00334534425815646
2023-10-09 07:31:56,536;INFO ; 121,0.0001123569985212822,0.006025032410227118
2023-10-09 07:31:56,548;INFO ; 122,0.00011388495717775127,0.009067533072446902
2023-10-09 07:31:56,558;INFO ; 123,0.00011056943333696869,0.0085564826904109
2023-10-09 07:31:56,575;INFO ; 124,0.00014224617089015766,0.02315718208148245
2023-10-09 07:31:56,586;INFO ; 125,0.00018689709550805125,0.026104201526189034
2023-10-09 07:31:56,603;INFO ; 126,0.00021794712036293817,0.03233347823909251
2023-10-09 07:31:56,619;INFO ; 127,0.00016414861203827287,0.024396885940398624
2023-10-09 07:31:56,633;INFO ; 128,0.00016195919214398728,0.018482014635773474
2023-10-09 07:31:56,651;INFO ; 129,0.00014555827358171818,0.008280587438509658
2023-10-09 07:31:56,667;INFO ; 130,0.00012903858280085791,0.017968141624898227
2023-10-09 07:31:56,682;INFO ; 131,0.0001743944212108641,0.02426505472539434
2023-10-09 07:31:56,699;INFO ; 132,0.00012461337407151463,0.018429690761212092
2023-10-09 07:31:56,714;INFO ; 133,0.00011389596765378848,0.008842680147757114
2023-10-09 07:31:56,727;INFO ; 134,0.00010258551230223868,0.008963079594039414
2023-10-09 07:31:56,738;INFO ; 135,6.798991234962459e-05,0.006410206807342788
2023-10-09 07:31:56,751;INFO ; 136,6.669587806351073e-05,0.005418452110723722
2023-10-09 07:31:56,765;INFO ; 137,6.30236666127576e-05,0.0053447985223686965
2023-10-09 07:31:56,778;INFO ; 138,6.141377532546205e-05,0.004433022363197899
2023-10-09 07:31:56,797;INFO ; 139,7.220618247467896e-05,0.0065698111149973286
2023-10-09 07:31:56,810;INFO ; 140,7.614789051645418e-05,0.011209687118496266
2023-10-09 07:31:56,830;INFO ; 141,6.510846878560719e-05,0.0060910330897405805
2023-10-09 07:31:56,845;INFO ; 142,5.94344462982349e-05,0.010275571663576986
2023-10-09 07:31:56,863;INFO ; 143,7.179596596313111e-05,0.006521216217053161
2023-10-09 07:31:56,884;INFO ; 144,6.334583522155981e-05,0.013302814413644577
2023-10-09 07:31:56,912;INFO ; 145,7.618065667144573e-05,0.005908006866049342
2023-10-09 07:31:56,928;INFO ; 146,5.3768107174593674e-05,0.0066728482919122265
2023-10-09 07:31:56,941;INFO ; 147,4.18576558380483e-05,0.0023436815031303315
2023-10-09 07:31:56,960;INFO ; 148,3.646912384066605e-05,0.0025766504219339997
2023-10-09 07:31:56,978;INFO ; 149,4.484215409752458e-05,0.003732500032444048
2023-10-09 07:31:56,991;INFO ; 150,4.640000711797127e-05,0.002617526826737674
2023-10-09 07:31:57,013;INFO ; 151,4.2778490976889044e-05,0.003341881974358671
2023-10-09 07:31:57,032;INFO ; 152,5.141569452701294e-05,0.004910608892739774
2023-10-09 07:31:57,057;INFO ; 153,4.7700606288843167e-05,0.002770458215534712
2023-10-09 07:31:57,072;INFO ; 154,4.650484751747839e-05,0.0065575079050350146
2023-10-09 07:31:57,089;INFO ; 155,4.7043718381732305e-05,0.00487002674120595
2023-10-09 07:31:57,108;INFO ; 156,4.0264914138450706e-05,0.005757463906095804
2023-10-09 07:31:57,132;INFO ; 157,2.452541072967229e-05,0.0028350965820183077
2023-10-09 07:31:57,167;INFO ; 158,2.9748708335043127e-05,0.004005963035044772
2023-10-09 07:31:57,191;INFO ; 159,2.809958914462157e-05,0.002059383856483391
2023-10-09 07:31:57,208;INFO ; 160,1.820094546559795e-05,0.0017580165150991387
2023-10-09 07:31:57,220;INFO ; 161,2.308532226823603e-05,0.001492209348093131
2023-10-09 07:31:57,236;INFO ; 162,2.104826760485251e-05,0.001937622521697834
2023-10-09 07:31:57,253;INFO ; 163,2.584806992883653e-05,0.0016334068351464683
2023-10-09 07:31:57,269;INFO ; 164,1.941250952837056e-05,0.002560689311233179
2023-10-09 07:31:57,283;INFO ; 165,2.055860382495834e-05,0.003954133032793636
2023-10-09 07:31:57,301;INFO ; 166,2.808987505303838e-05,0.004002064880854289
2023-10-09 07:31:57,321;INFO ; 167,3.2858053136750916e-05,0.01267127900118853
2023-10-09 07:31:57,339;INFO ; 168,4.069898557502281e-05,0.004080448050157344
2023-10-09 07:31:57,354;INFO ; 169,2.5789081955787676e-05,0.002924423419043309
2023-10-09 07:31:57,367;INFO ; 170,2.3799337443575192e-05,0.003722737758890169
2023-10-09 07:31:57,387;INFO ; 171,2.1496258810747345e-05,0.0022959214471827676
2023-10-09 07:31:57,400;INFO ; 172,2.285974877676828e-05,0.0016708814902360017
2023-10-09 07:31:57,422;INFO ; 173,1.5367462794076137e-05,0.0006613164292586232
2023-10-09 07:31:57,442;INFO ; 174,1.5718726766941568e-05,0.0011022005921228054
2023-10-09 07:31:57,455;INFO ; 175,1.838900922999075e-05,0.0011729060483514312
2023-10-09 07:31:57,473;INFO ; 176,1.5464783188585626e-05,0.0009204983524819425
2023-10-09 07:31:57,488;INFO ; 177,1.1731812890521309e-05,0.0005180400888646862
2023-10-09 07:31:57,527;INFO ; 178,1.109904716148153e-05,0.0005174280822143347
2023-10-09 07:31:57,551;INFO ; 179,9.881494493705354e-06,0.00018450658896110745
2023-10-09 07:31:57,555;INFO ; bfw Assignment finished. 179 iterations and 9.881494493705354e-06 final gap

Now let us save our select link results, all we need to do is provide it with a name In addition to exporting the select link flows, it also exports the Select Link matrices in OMX format.

[35]:
assig.save_select_link_results("select_link_analysis")

Say we just want to save our select link flows, we can call:

[36]:
assig.save_select_link_flows("just_flows")

# Or if we just want the SL matrices:
assig.save_select_link_matrices("just_matrices")
# Internally, the save_select_link_results calls both of these methods at once.

# We could export it to CSV or AequilibraE data, but let's put it directly into the results database
assig.save_results("future_year_assignment")

# And save the skims
assig.save_skims("future_year_assignment_skims", which_ones="all", format="omx")
2023-10-09 07:31:57,706;WARNING ; Matrix Record has been saved to the database

We can also plot convergence#

[37]:
import matplotlib.pyplot as plt

df = assig.report()
x = df.iteration.values
y = df.rgap.values

fig = plt.figure()
ax = fig.add_subplot(111)

plt.plot(x, y, "k--")
plt.yscale("log")
plt.grid(True, which="both")
plt.xlabel(r"Iterations")
plt.ylabel(r"Relative Gap")
plt.show()
../../_images/_auto_examples_full_workflows_plot_forecasting_66_0.png

Close the project

[38]:
project.close()