7.10. Forecasting

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

## Imports
from uuid import uuid4
from tempfile import gettempdir
from os.path import join
from aequilibrae.utils.create_example import create_example
from aequilibrae import logger
import logging
import sys

We create the example project inside our temp folder

fldr = join(gettempdir(), uuid4().hex)

project = create_example(fldr)

# We the project open, 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;%(name)s;%(levelname)s ; %(message)s")
stdout_handler.setFormatter(formatter)
logger.addHandler(stdout_handler)
## Traffic assignment with skimming
from aequilibrae.paths import TrafficAssignment, TrafficClass
# we build all graphs
project.network.build_graphs()
# We get warnings that several fields in the project are filled with NaNs.  Which is true, but we won't use those fields

Out:

2021-02-18 10:20:33,368;aequilibrae;WARNING ; Field(s) name, lanes has(ve) at least one NaN value. Check your computations
2021-02-18 10:20:33,426;aequilibrae;WARNING ; Field(s) name, lanes has(ve) at least one NaN value. Check your computations
2021-02-18 10:20:33,484;aequilibrae;WARNING ; Field(s) name, lanes has(ve) at least one NaN value. Check your computations
2021-02-18 10:20:33,543;aequilibrae;WARNING ; Field(s) name, lanes has(ve) at least one NaN value. Check your computations
# we grab the graph for cars
graph = project.network.graphs["c"]

# let's say we want to minimize 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 compute going through other centroids/centroid connectors
# required for the Sioux Falls network, as all nodes are centroids
graph.set_blocked_centroid_flows(False)

Out:

/home/runner/work/aequilibrae/aequilibrae/aequilibrae/paths/graph.py:445: UserWarning: Cost field with wrong type. Converting to float64
  warn("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
proj_matrices = project.matrices
proj_matrices.list()
name file_name cores procedure procedure_id timestamp description status
0 demand_aem demand.aem 1 None None 2020-11-24 08:46:42 Original data imported to AEM format\n
1 demand_omx demand.omx 1 None None 2020-11-24 08:47:18 Original data imported to OMX format
2 skims skims.omx 2 None None Example skim


# Let's get it in this better way
demand = proj_matrices.get_matrix("demand_omx")
demand.computational_view(["matrix"])
assig = TrafficAssignment()

# Creates the assignment class
assigclass = TrafficClass(graph, 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

Out:

/home/runner/work/aequilibrae/aequilibrae/aequilibrae/paths/graph.py:445: UserWarning: Cost field with wrong type. Converting to float64
  warn("Cost field with wrong type. Converting to float64")
2021-02-18 10:20:34,043;aequilibrae;INFO ; bfw Assignment STATS
2021-02-18 10:20:34,044;aequilibrae;INFO ; Iteration, RelativeGap, stepsize
2021-02-18 10:20:34,145;aequilibrae;INFO ; 1,inf,1.0
2021-02-18 10:20:34,248;aequilibrae;INFO ; 2,0.8485503509703024,0.36497345609427145
2021-02-18 10:20:34,350;aequilibrae;INFO ; 3,0.3813926225800203,0.2298356924660528
2021-02-18 10:20:34,453;aequilibrae;INFO ; 4,0.19621277462606984,0.18591312145268074
2021-02-18 10:20:34,555;aequilibrae;INFO ; 5,0.09069073200924213,0.7090816523174254
2021-02-18 10:20:34,658;aequilibrae;INFO ; 6,0.20600048221061426,0.1229016022154401
2021-02-18 10:20:34,761;aequilibrae;INFO ; 7,0.06710568925282254,0.38638656717489844
2021-02-18 10:20:34,865;aequilibrae;INFO ; 8,0.10307514154369488,0.1093055036410267
2021-02-18 10:20:34,969;aequilibrae;INFO ; 9,0.04222147191362779,0.2487805192125393
2021-02-18 10:20:35,072;aequilibrae;INFO ; 10,0.05926435464772421,0.15904810628271004
2021-02-18 10:20:35,177;aequilibrae;INFO ; 11,0.03453951151333739,0.5180973804491722
2021-02-18 10:20:35,281;aequilibrae;INFO ; 12,0.059426517206032654,0.10197123112986584
2021-02-18 10:20:35,384;aequilibrae;INFO ; 13,0.023239895792359067,0.1780595483940025
2021-02-18 10:20:35,488;aequilibrae;INFO ; 14,0.017873783562205998,0.9787872930853664
2021-02-18 10:20:35,593;aequilibrae;INFO ; 15,0.049661371545771556,0.08320656307451389
2021-02-18 10:20:35,696;aequilibrae;INFO ; 16,0.021382882276233087,0.11517403065013918
2021-02-18 10:20:35,802;aequilibrae;INFO ; 17,0.013141542820482906,0.10640369388111594
2021-02-18 10:20:35,905;aequilibrae;INFO ; 18,0.009902228209039313,0.10710395766777006
2021-02-18 10:20:36,007;aequilibrae;INFO ; 19,0.008834657139075773,0.2524678977926848
2021-02-18 10:20:36,113;aequilibrae;INFO ; 20,0.01037104162273405,0.672783938935575
2021-02-18 10:20:36,216;aequilibrae;INFO ; 21,0.011090096306112919,0.07468060074370476
2021-02-18 10:20:36,319;aequilibrae;INFO ; 22,0.006512685266481729,0.12485017624661685
2021-02-18 10:20:36,422;aequilibrae;INFO ; 23,0.005238884615251675,0.06316016574610187
2021-02-18 10:20:36,525;aequilibrae;INFO ; 24,0.003949529236289854,0.09717896243712648
2021-02-18 10:20:36,627;aequilibrae;INFO ; 25,0.003282221301580423,0.1577590171880403
2021-02-18 10:20:36,732;aequilibrae;INFO ; 26,0.0057928324528667054,0.45247656699511957
2021-02-18 10:20:36,835;aequilibrae;INFO ; 27,0.0066823585472082035,0.7851865570315525
2021-02-18 10:20:36,940;aequilibrae;INFO ; 28,0.005992619218871392,0.03909810047559774
2021-02-18 10:20:37,044;aequilibrae;INFO ; 29,0.0040313646880229485,0.04253018777364977
2021-02-18 10:20:37,147;aequilibrae;INFO ; 30,0.0027696521195955236,0.022512872266868305
2021-02-18 10:20:37,251;aequilibrae;INFO ; 31,0.0024846461521885483,0.045801692933285426
2021-02-18 10:20:37,355;aequilibrae;INFO ; 32,0.0016385526468732255,0.03429583308494769
2021-02-18 10:20:37,458;aequilibrae;INFO ; 33,0.0014956911143795503,0.03539200254746481
2021-02-18 10:20:37,560;aequilibrae;INFO ; 34,0.0011355392148568219,0.05358983822746
2021-02-18 10:20:37,663;aequilibrae;INFO ; 35,0.0012151973759507247,0.047571304687631016
2021-02-18 10:20:37,768;aequilibrae;INFO ; 36,0.001239365147988278,0.06536473861293134
2021-02-18 10:20:37,870;aequilibrae;INFO ; 37,0.0010684962819863329,0.10703952287434068
2021-02-18 10:20:37,976;aequilibrae;INFO ; 38,0.0010899690080088834,0.0986406240944672
2021-02-18 10:20:38,081;aequilibrae;INFO ; 39,0.0009886948497197317,0.06027623911565202
2021-02-18 10:20:38,184;aequilibrae;INFO ; 40,0.0012632086912186262,0.22288089471588354
2021-02-18 10:20:38,286;aequilibrae;INFO ; 41,0.001165571653411883,0.1977596494198537
2021-02-18 10:20:38,389;aequilibrae;INFO ; 42,0.0012299958308316802,0.3170348486824528
2021-02-18 10:20:38,491;aequilibrae;INFO ; 43,0.0012902531663786525,0.3422879827743953
2021-02-18 10:20:38,594;aequilibrae;INFO ; 44,0.0009979531087593776,0.7332060974425909
2021-02-18 10:20:38,594;aequilibrae;INFO ; bfw Assignment finished. 44 iterations and 0.0009979531087593776 final gap
# Convergence report is easy to see
import pandas as pd

convergence_report = assig.report()
convergence_report.head()
iteration rgap alpha warnings beta0 beta1 beta2
0 1 inf 1.000000 1.000000 0.000000 0.000000
1 2 0.848550 0.364973 1.000000 0.000000 0.000000
2 3 0.381393 0.229836 1.000000 0.000000 0.000000
3 4 0.196213 0.185913 0.959771 0.040229 0.000000
4 5 0.090691 0.709082 0.687640 0.286705 0.025654


volumes = assig.results()
volumes.head()
matrix_ab matrix_ba matrix_tot Congested_Time_AB Congested_Time_BA Congested_Time_Max Delay_factor_AB Delay_factor_BA Delay_factor_Max VOC_AB VOC_BA VOC_max PCE_AB PCE_BA PCE_tot
link_id
1 4570.421761 NaN 4570.421761 6.000883 NaN 6.000883 1.000147 NaN 1.000147 0.176463 NaN 0.176463 4570.421761 NaN 4570.421761
2 8275.382482 NaN 8275.382482 4.009065 NaN 4.009065 1.002266 NaN 1.002266 0.353596 NaN 0.353596 8275.382482 NaN 8275.382482
3 4675.373252 NaN 4675.373252 6.000899 NaN 6.000899 1.000150 NaN 1.000150 0.180515 NaN 0.180515 4675.373252 NaN 4675.373252
4 5900.513362 NaN 5900.513362 6.547982 NaN 6.547982 1.309596 NaN 1.309596 1.190056 NaN 1.190056 5900.513362 NaN 5900.513362
5 8170.430991 NaN 8170.430991 4.008970 NaN 4.008970 1.002243 NaN 1.002243 0.349112 NaN 0.349112 8170.430991 NaN 8170.430991


# We could export it to CSV or AequilibraE data, but let's put it directly into the results database
assig.save_results("base_year_assignment")
# And save the skims
assig.save_skims("base_year_assignment_skims", which_ones="all", format="omx")

Out:

2021-02-18 10:20:38,884;aequilibrae;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
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
proj_matrices.list()
name file_name cores procedure procedure_id timestamp description status
0 demand_aem demand.aem 1 None None 2020-11-24 08:46:42 Original data imported to AEM format\n
1 demand_omx demand.omx 1 None None 2020-11-24 08:47:18 Original data imported to OMX format
2 skims skims.omx 2 None None Example skim
3 base_year_assignment_skims base_year_assignment_skims.omx 4 Traffic Assignment c43e1c8718d649e3a602ef802ffe2441 2021-02-18 10:20:33.708364 Skimming for assignment procedure


# We need the demand
demand = proj_matrices.get_matrix("demand_aem")

# And the skims
imped = proj_matrices.get_matrix("base_year_assignment_skims")
# We can check which matrix cores were created for our skims to decide which one to use
imped.names

# Where free_flow_time_final is actually the congested time for the last iteration

Out:

['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

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
imped.save(names=["final_time_with_intrazonals"])
# This also updates these new matrices as those being used for computation
# As one can verify below
imped.view_names

Out:

['final_time_with_intrazonals']
# We set the matrices for being used in computation
demand.computational_view(["matrix"])
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")

Out:

/home/runner/work/aequilibrae/aequilibrae/aequilibrae/distribution/gravity_application.py:316: RuntimeWarning: divide by zero encountered in power
  * a)[:]
/home/runner/work/aequilibrae/aequilibrae/aequilibrae/distribution/gravity_application.py:326: RuntimeWarning: invalid value encountered in multiply
  self.output.matrix_view[:, :] = self.output.matrix_view[:, :] * non_inf
## Forecast
#  * We create a set of * 'future' * vectors using some random growth factors
#  * We apply the model for inverse power, as the TFLD seems to be a better fit for the actual one
from aequilibrae.distribution import Ipf, GravityApplication, SyntheticGravityModel
from aequilibrae.matrix import AequilibraeData
import numpy as np
# We compute the vectors from our matrix
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% - Plus 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
imped = proj_matrices.get_matrix("base_year_assignment_skims")
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)
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")
    apply = GravityApplication()
    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")

Out:

2021-02-18 10:20:40,076;aequilibrae;WARNING ; Matrix Record has been saved to the database
2021-02-18 10:20:40,415;aequilibrae;WARNING ; Matrix Record has been saved to the database
# We update the matrices table/records and verify that the new matrices are indeed there
proj_matrices.update_database()
proj_matrices.list()
name file_name cores procedure procedure_id timestamp description status
0 demand_aem demand.aem 1 None None 2020-11-24 08:46:42 Original data imported to AEM format\n
1 demand_omx demand.omx 1 None None 2020-11-24 08:47:18 Original data imported to OMX format
2 skims skims.omx 2 None None Example skim
3 base_year_assignment_skims base_year_assignment_skims.omx 4 Traffic Assignment c43e1c8718d649e3a602ef802ffe2441 2021-02-18 10:20:33.708364 Skimming for assignment procedure
4 demand_power_modeled demand_power_modeled.omx 1 Synthetic gravity trip distribution 648062fa682145e8b96a734f13b1cc64 2021-02-18 10:20:39.903831 Synthetic gravity trip distribution. POWER
5 demand_expo_modeled demand_expo_modeled.omx 1 Synthetic gravity trip distribution c4290359fda2400296b5481ffbbaf495 2021-02-18 10:20:40.242892 Synthetic gravity trip distribution. EXPO


### We now run IPF for the future vectors
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")

Out:

2021-02-18 10:20:40,642;aequilibrae;WARNING ; Matrix Record has been saved to the database
2021-02-18 10:20:40,832;aequilibrae;WARNING ; Matrix Record has been saved to the database

<aequilibrae.project.data.matrix_record.MatrixRecord object at 0x7f18e6f193d0>
proj_matrices.list()
name file_name cores procedure procedure_id timestamp description status
0 demand_aem demand.aem 1 None None 2020-11-24 08:46:42 Original data imported to AEM format\n
1 demand_omx demand.omx 1 None None 2020-11-24 08:47:18 Original data imported to OMX format
2 skims skims.omx 2 None None Example skim
3 base_year_assignment_skims base_year_assignment_skims.omx 4 Traffic Assignment c43e1c8718d649e3a602ef802ffe2441 2021-02-18 10:20:33.708364 Skimming for assignment procedure
4 demand_power_modeled demand_power_modeled.omx 1 Synthetic gravity trip distribution 648062fa682145e8b96a734f13b1cc64 2021-02-18 10:20:39.903831 Synthetic gravity trip distribution. POWER
5 demand_expo_modeled demand_expo_modeled.omx 1 Synthetic gravity trip distribution c4290359fda2400296b5481ffbbaf495 2021-02-18 10:20:40.242892 Synthetic gravity trip distribution. EXPO
6 demand_ipfd demand_ipfd.aem 1 Iterative Proportional fitting dd59253dc017483b9104641f72371c8d 2021-02-18 10:20:40.518877 None
7 demand_ipfd_omx demand_ipfd.omx 1 Iterative Proportional fitting dd59253dc017483b9104641f72371c8d 2021-02-18 10:20:40.518877 None


## Future traffic assignment
from aequilibrae.paths import TrafficAssignment, TrafficClass
from aequilibrae import logger
logger.info("\n\n\n TRAFFIC ASSIGNMENT FOR FUTURE YEAR")

Out:

2021-02-18 10:20:40,922;aequilibrae;INFO ;


 TRAFFIC ASSIGNMENT FOR FUTURE YEAR
demand = proj_matrices.get_matrix("demand_power_modeled")

# let's see what is the core we ended up getting. It should be 'gravity'
demand.names

Out:

['gravity']
# Let's use the IPF matrix
demand.computational_view("gravity")

assig = TrafficAssignment()

# Creates the assignment class
assigclass = TrafficClass(graph, demand)

# The first thing to do is to add at 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 = 1000
assig.rgap_target = 0.0001

assig.execute()  # we then execute the assignment

Out:

/home/runner/work/aequilibrae/aequilibrae/aequilibrae/paths/graph.py:445: UserWarning: Cost field with wrong type. Converting to float64
  warn("Cost field with wrong type. Converting to float64")
2021-02-18 10:20:41,393;aequilibrae;INFO ; bfw Assignment STATS
2021-02-18 10:20:41,393;aequilibrae;INFO ; Iteration, RelativeGap, stepsize
2021-02-18 10:20:41,495;aequilibrae;INFO ; 1,inf,1.0
2021-02-18 10:20:41,597;aequilibrae;INFO ; 2,0.8869185206419594,0.2949026040834314
2021-02-18 10:20:41,701;aequilibrae;INFO ; 3,0.588015612525359,0.19768688064832907
2021-02-18 10:20:41,805;aequilibrae;INFO ; 4,0.2889812379086869,0.2060170031866801
2021-02-18 10:20:41,908;aequilibrae;INFO ; 5,0.16050523639494185,0.4634702151143747
2021-02-18 10:20:42,013;aequilibrae;INFO ; 6,0.1816762043788088,0.662460952586707
2021-02-18 10:20:42,116;aequilibrae;INFO ; 7,0.18233373059700111,0.1531308565130455
2021-02-18 10:20:42,219;aequilibrae;INFO ; 8,0.09324136985368256,0.217098492066391
2021-02-18 10:20:42,321;aequilibrae;INFO ; 9,0.0917922227940775,0.40560618410083055
2021-02-18 10:20:42,424;aequilibrae;INFO ; 10,0.09541307470223052,0.1317007335702223
2021-02-18 10:20:42,527;aequilibrae;INFO ; 11,0.05532891653016809,0.2542502273921534
2021-02-18 10:20:42,629;aequilibrae;INFO ; 12,0.07122804426870828,0.7269773288457817
2021-02-18 10:20:42,732;aequilibrae;INFO ; 13,0.10697840737360402,0.08127463419343302
2021-02-18 10:20:42,836;aequilibrae;INFO ; 14,0.03704907731458983,0.18521577573018747
2021-02-18 10:20:42,938;aequilibrae;INFO ; 15,0.037219544060874465,0.24730710646023193
2021-02-18 10:20:43,041;aequilibrae;INFO ; 16,0.033934442418399435,0.7568432640876742
2021-02-18 10:20:43,144;aequilibrae;INFO ; 17,0.05541977224186314,0.05976603861950719
2021-02-18 10:20:43,249;aequilibrae;INFO ; 18,0.026930808809218033,0.14173526628126604
2021-02-18 10:20:43,352;aequilibrae;INFO ; 19,0.02302945715046113,0.26708632984431163
2021-02-18 10:20:43,457;aequilibrae;INFO ; 20,0.02282882402297576,0.5185952228353777
2021-02-18 10:20:43,560;aequilibrae;INFO ; 21,0.018483453607451426,0.8681299394472989
2021-02-18 10:20:43,664;aequilibrae;INFO ; 22,0.022325299923591578,0.047696010314943915
2021-02-18 10:20:43,769;aequilibrae;INFO ; 23,0.01004122186821739,0.09378603478281151
2021-02-18 10:20:43,872;aequilibrae;INFO ; 24,0.011712071636473509,0.17260495615199578
2021-02-18 10:20:43,976;aequilibrae;INFO ; 25,0.012756996591750655,0.19439731839221525
2021-02-18 10:20:44,079;aequilibrae;INFO ; 26,0.012536799894475495,0.18547498777793955
2021-02-18 10:20:44,181;aequilibrae;INFO ; 27,0.009980951374883805,0.403170942161783
2021-02-18 10:20:44,284;aequilibrae;INFO ; 28,0.013775105104312305,0.8238042610358633
2021-02-18 10:20:44,388;aequilibrae;INFO ; 29,0.013324549163614113,0.03788228727469217
2021-02-18 10:20:44,491;aequilibrae;INFO ; 30,0.0077442421944975155,0.07165351790730007
2021-02-18 10:20:44,593;aequilibrae;INFO ; 31,0.007821532834290087,0.06735814516209085
2021-02-18 10:20:44,696;aequilibrae;INFO ; 32,0.005592099541250802,0.09660403410175603
2021-02-18 10:20:44,799;aequilibrae;INFO ; 33,0.004678867820026161,0.18871450868751974
2021-02-18 10:20:44,904;aequilibrae;INFO ; 34,0.0063504285660024255,0.2757172933476472
2021-02-18 10:20:45,007;aequilibrae;INFO ; 35,0.006199604607905618,0.37207639120901087
2021-02-18 10:20:45,110;aequilibrae;INFO ; 36,0.006838687947857594,0.5801728421645576
2021-02-18 10:20:45,213;aequilibrae;INFO ; 37,0.004418599066521518,0.8912628141579837
2021-02-18 10:20:45,317;aequilibrae;INFO ; 38,0.005501599096386511,0.016135741720802888
2021-02-18 10:20:45,421;aequilibrae;INFO ; 39,0.00258796628849951,0.012999709578847086
2021-02-18 10:20:45,528;aequilibrae;INFO ; 40,0.0020711128857675695,0.6091738008367833
2021-02-18 10:20:45,632;aequilibrae;INFO ; 41,0.002979403195056885,0.9583859969971712
2021-02-18 10:20:45,735;aequilibrae;INFO ; 42,0.0021910475349452684,0.011041894435877617
2021-02-18 10:20:45,838;aequilibrae;INFO ; 43,0.0014926920682489997,0.01947783351919215
2021-02-18 10:20:45,942;aequilibrae;INFO ; 44,0.00142924488611853,0.017620785894387293
2021-02-18 10:20:46,045;aequilibrae;INFO ; 45,0.001601648095347361,0.031940760171249256
2021-02-18 10:20:46,148;aequilibrae;INFO ; 46,0.0018563918994951283,0.037306459268010204
2021-02-18 10:20:46,252;aequilibrae;INFO ; 47,0.0017343529817500872,0.10351516365981342
2021-02-18 10:20:46,356;aequilibrae;INFO ; 48,0.0031209343916088835,0.2545573447837624
2021-02-18 10:20:46,459;aequilibrae;INFO ; 49,0.0031938937914114678,0.1254550551110894
2021-02-18 10:20:46,561;aequilibrae;INFO ; 50,0.0025165837702627015,0.0989251657124465
2021-02-18 10:20:46,664;aequilibrae;INFO ; 51,0.001694781216143684,0.13922944824915734
2021-02-18 10:20:46,766;aequilibrae;INFO ; 52,0.0027111355994742597,0.15280683097306944
2021-02-18 10:20:46,869;aequilibrae;INFO ; 53,0.0020211380287558627,0.1225621731715659
2021-02-18 10:20:46,972;aequilibrae;INFO ; 54,0.001555012718187175,0.07629320199949229
2021-02-18 10:20:47,077;aequilibrae;INFO ; 55,0.0013356817942195211,0.1332807411613251
2021-02-18 10:20:47,179;aequilibrae;INFO ; 56,0.0013848446173182658,0.08618620116632922
2021-02-18 10:20:47,282;aequilibrae;INFO ; 57,0.001296959674886513,0.06800613642910683
2021-02-18 10:20:47,386;aequilibrae;INFO ; 58,0.0014540815135828335,0.08295554076387648
2021-02-18 10:20:47,490;aequilibrae;INFO ; 59,0.0010113474461896559,0.07008885708748151
2021-02-18 10:20:47,592;aequilibrae;INFO ; 60,0.0014511817919706216,0.06263780879116987
2021-02-18 10:20:47,695;aequilibrae;INFO ; 61,0.0012892870749688712,0.09698115906000165
2021-02-18 10:20:47,798;aequilibrae;INFO ; 62,0.0013452810224726286,0.09088717170826374
2021-02-18 10:20:47,901;aequilibrae;INFO ; 63,0.0013211320056163863,0.23373943231751143
2021-02-18 10:20:48,004;aequilibrae;INFO ; 64,0.001505376011811344,0.4563621595817925
2021-02-18 10:20:48,106;aequilibrae;INFO ; 65,0.001952246715315088,0.6396981239168877
2021-02-18 10:20:48,209;aequilibrae;INFO ; 66,0.0020711412348888795,0.005122028419646269
2021-02-18 10:20:48,312;aequilibrae;INFO ; 67,0.0012136112642739017,0.010186676981305454
2021-02-18 10:20:48,417;aequilibrae;INFO ; 68,0.0008291376869490191,0.008297158885505867
2021-02-18 10:20:48,521;aequilibrae;INFO ; 69,0.0007505584479753556,0.010393518207368028
2021-02-18 10:20:48,625;aequilibrae;INFO ; 70,0.0008509479729728319,0.019533368383428087
2021-02-18 10:20:48,727;aequilibrae;INFO ; 71,0.0008145990545891626,0.017068941823450395
2021-02-18 10:20:48,833;aequilibrae;INFO ; 72,0.0005646548137295848,0.02734364534558361
2021-02-18 10:20:48,938;aequilibrae;INFO ; 73,0.000595904442284007,0.03121986122906667
2021-02-18 10:20:49,040;aequilibrae;INFO ; 74,0.000711798849674591,0.0381576461441203
2021-02-18 10:20:49,143;aequilibrae;INFO ; 75,0.0006915743781048434,0.032076724662211197
2021-02-18 10:20:49,247;aequilibrae;INFO ; 76,0.00040057700461107037,0.017912441325390504
2021-02-18 10:20:49,352;aequilibrae;INFO ; 77,0.0004261302524838105,0.023504260808075515
2021-02-18 10:20:49,457;aequilibrae;INFO ; 78,0.0004248435881948729,0.04199437153181703
2021-02-18 10:20:49,561;aequilibrae;INFO ; 79,0.0006898350439722776,0.05149448360541459
2021-02-18 10:20:49,664;aequilibrae;INFO ; 80,0.000597578393182954,0.04025640547609996
2021-02-18 10:20:49,767;aequilibrae;INFO ; 81,0.0005757801443597037,0.02181138987415942
2021-02-18 10:20:49,871;aequilibrae;INFO ; 82,0.0005091197485470857,0.048991234074100706
2021-02-18 10:20:49,976;aequilibrae;INFO ; 83,0.0004815771039532207,0.039701294903883716
2021-02-18 10:20:50,079;aequilibrae;INFO ; 84,0.00043451440454763654,0.041377126709858825
2021-02-18 10:20:50,184;aequilibrae;INFO ; 85,0.0004361428395797134,0.04578682515510653
2021-02-18 10:20:50,289;aequilibrae;INFO ; 86,0.0005725324652484132,0.11091581087706058
2021-02-18 10:20:50,394;aequilibrae;INFO ; 87,0.0006028063775225079,0.1275279287512066
2021-02-18 10:20:50,497;aequilibrae;INFO ; 88,0.0005971650294881656,0.0989899353513331
2021-02-18 10:20:50,601;aequilibrae;INFO ; 89,0.0006662549381065007,0.12202101737024314
2021-02-18 10:20:50,704;aequilibrae;INFO ; 90,0.0005399211585659303,0.24826965763266498
2021-02-18 10:20:50,809;aequilibrae;INFO ; 91,0.0006080343599214994,0.25444251201240337
2021-02-18 10:20:50,914;aequilibrae;INFO ; 92,0.0005630104886945532,0.5134625344490855
2021-02-18 10:20:51,017;aequilibrae;INFO ; 93,0.0004617637393901471,0.6707674242526727
2021-02-18 10:20:51,120;aequilibrae;INFO ; 94,0.00038293806803260254,0.003481604882310088
2021-02-18 10:20:51,223;aequilibrae;INFO ; 95,0.000498684356756774,0.006307221059531465
2021-02-18 10:20:51,326;aequilibrae;INFO ; 96,0.0003936058016806088,0.005361302677816026
2021-02-18 10:20:51,429;aequilibrae;INFO ; 97,0.0003537797193419004,0.0061738195353352255
2021-02-18 10:20:51,532;aequilibrae;INFO ; 98,0.000384269057994639,0.018576637246314795
2021-02-18 10:20:51,635;aequilibrae;INFO ; 99,0.0006564033521152243,0.05003480290822521
2021-02-18 10:20:51,739;aequilibrae;INFO ; 100,0.0007652129935651653,0.04971241299265019
2021-02-18 10:20:51,845;aequilibrae;INFO ; 101,0.00041661093607663253,0.01481751080499359
2021-02-18 10:20:51,949;aequilibrae;INFO ; 102,0.0004261093328976528,0.0163781613973041
2021-02-18 10:20:52,053;aequilibrae;INFO ; 103,0.00029373029117321517,0.010396166570911487
2021-02-18 10:20:52,158;aequilibrae;INFO ; 104,0.000329320121180928,0.008648024662756562
2021-02-18 10:20:52,261;aequilibrae;INFO ; 105,0.00022478994702593776,0.01011986024479549
2021-02-18 10:20:52,365;aequilibrae;INFO ; 106,0.00022782123276748214,0.003650615109348965
2021-02-18 10:20:52,468;aequilibrae;INFO ; 107,0.00013780454694990951,0.006972676031332353
2021-02-18 10:20:52,573;aequilibrae;INFO ; 108,0.0002038080138896186,0.006762001397051689
2021-02-18 10:20:52,676;aequilibrae;INFO ; 109,0.00017092979969150288,0.007029547500354097
2021-02-18 10:20:52,779;aequilibrae;INFO ; 110,0.00019431956688401288,0.013918518212906725
2021-02-18 10:20:52,882;aequilibrae;INFO ; 111,0.00018392318338677553,0.014286466583695276
2021-02-18 10:20:52,985;aequilibrae;INFO ; 112,0.00022416544239709486,0.02125457303906268
2021-02-18 10:20:53,091;aequilibrae;INFO ; 113,0.00023000989471792346,0.028036474109013602
2021-02-18 10:20:53,194;aequilibrae;INFO ; 114,0.00028937641608934266,0.03425145990925873
2021-02-18 10:20:53,297;aequilibrae;INFO ; 115,0.0003225857983508608,0.047067713163790686
2021-02-18 10:20:53,401;aequilibrae;INFO ; 116,0.00021849218486898837,0.008274744293602889
2021-02-18 10:20:53,506;aequilibrae;INFO ; 117,0.00020365708997543928,0.007928247277044668
2021-02-18 10:20:53,609;aequilibrae;INFO ; 118,0.00018381738640249604,0.015853499457346137
2021-02-18 10:20:53,712;aequilibrae;INFO ; 119,0.0001928454130895287,0.01639716463257601
2021-02-18 10:20:53,818;aequilibrae;INFO ; 120,0.00022846608624769638,0.02354456168752016
2021-02-18 10:20:53,921;aequilibrae;INFO ; 121,0.00025066395421076225,0.029956337818356653
2021-02-18 10:20:54,024;aequilibrae;INFO ; 122,0.00021210688925997164,0.021192450133486262
2021-02-18 10:20:54,126;aequilibrae;INFO ; 123,0.0001495099878148145,0.015804940773610054
2021-02-18 10:20:54,229;aequilibrae;INFO ; 124,0.00017380071536776882,0.02587549448866636
2021-02-18 10:20:54,334;aequilibrae;INFO ; 125,0.0001363109958606895,0.01757762085514827
2021-02-18 10:20:54,438;aequilibrae;INFO ; 126,0.00013690169578739697,0.016687380236161693
2021-02-18 10:20:54,541;aequilibrae;INFO ; 127,0.00016667638722538542,0.028681072043548538
2021-02-18 10:20:54,644;aequilibrae;INFO ; 128,0.0001424780967764896,0.026211121113087966
2021-02-18 10:20:54,748;aequilibrae;INFO ; 129,0.0001305528398859378,0.034551058346546065
2021-02-18 10:20:54,852;aequilibrae;INFO ; 130,0.000178124672709283,0.03720786263188335
2021-02-18 10:20:54,956;aequilibrae;INFO ; 131,0.00015376350099660812,0.03224538138008354
2021-02-18 10:20:55,058;aequilibrae;INFO ; 132,0.00016245512090658335,0.053728005477472696
2021-02-18 10:20:55,163;aequilibrae;INFO ; 133,0.00023110692351780205,0.04763837625681554
2021-02-18 10:20:55,266;aequilibrae;INFO ; 134,0.00014324405570671894,0.03799154084435219
2021-02-18 10:20:55,372;aequilibrae;INFO ; 135,0.00017271980060685894,0.014509914813839356
2021-02-18 10:20:55,476;aequilibrae;INFO ; 136,0.0001293585482256135,0.03577650998302448
2021-02-18 10:20:55,579;aequilibrae;INFO ; 137,0.00011504770327205402,0.014528199895281974
2021-02-18 10:20:55,682;aequilibrae;INFO ; 138,0.00013340647028784467,0.04142136002359936
2021-02-18 10:20:55,784;aequilibrae;INFO ; 139,0.00014527124985634212,0.04051031561164441
2021-02-18 10:20:55,887;aequilibrae;INFO ; 140,0.00014750273237711646,0.04706660050579762
2021-02-18 10:20:55,990;aequilibrae;INFO ; 141,0.00016767853811447875,0.03573400667071823
2021-02-18 10:20:56,092;aequilibrae;INFO ; 142,0.00021133551536609474,0.12058203701724501
2021-02-18 10:20:56,198;aequilibrae;INFO ; 143,0.0002643586476991359,0.13255804681772607
2021-02-18 10:20:56,302;aequilibrae;INFO ; 144,0.00027023046229496055,0.1348384023743591
2021-02-18 10:20:56,407;aequilibrae;INFO ; 145,0.00022585620848965927,0.06302691890041356
2021-02-18 10:20:56,510;aequilibrae;INFO ; 146,0.00016688158636147437,0.0961601071082684
2021-02-18 10:20:56,612;aequilibrae;INFO ; 147,0.0001411488914643167,0.03748049365917197
2021-02-18 10:20:56,715;aequilibrae;INFO ; 148,0.0001499698087788164,0.048697610059297285
2021-02-18 10:20:56,819;aequilibrae;INFO ; 149,0.0001504538087922177,0.03555459799689903
2021-02-18 10:20:56,923;aequilibrae;INFO ; 150,0.00011647690264123426,0.024645214381956698
2021-02-18 10:20:57,027;aequilibrae;INFO ; 151,0.00010843795562528193,0.023279041790168698
2021-02-18 10:20:57,131;aequilibrae;INFO ; 152,9.7970116104514e-05,0.039607937451787596
2021-02-18 10:20:57,234;aequilibrae;INFO ; 153,0.00012551740307337493,0.02339609871875548
2021-02-18 10:20:57,338;aequilibrae;INFO ; 154,0.00010291497142593013,0.041920707949084396
2021-02-18 10:20:57,441;aequilibrae;INFO ; 155,0.00010524327594840423,0.021974955389637667
2021-02-18 10:20:57,545;aequilibrae;INFO ; 156,9.594869019373251e-05,0.04378530857292892
2021-02-18 10:20:57,546;aequilibrae;INFO ; bfw Assignment finished. 156 iterations and 9.594869019373251e-05 final gap
# 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")

Out:

2021-02-18 10:20:57,758;aequilibrae;WARNING ; Matrix Record has been saved to the database

We can also plot convergence

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()
plot forecasting

Close the project

project.close()

Out:

2021-02-18 10:20:58,361;aequilibrae;INFO ; Closed project on /tmp/fd15f0d73aa34d76a46459e8aac7b6af

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

Gallery generated by Sphinx-Gallery