.. _numerical_study_traffic_assignment: Traffic Assignment ================== Similar to other complex algorthms that handle a large amount of data through complex computations, traffic assignment procedures can always be subject to at least one very reasonable question: Are the results right? For this reason, we have used all equilibrium traffic assignment algorithms available in AequilibraE to solve standard instances used in academia for comparing algorithm results, some of which have are available with highly converged solutions (~1e-14). Instances can be downloaded `here `_. Sioux Falls ----------- Network has: * Links: 76 * Nodes: 24 * Zones: 24 .. image:: ../images/sioux_falls_msa-500_iter.png :align: center :width: 590 :alt: Sioux Falls MSA 500 iterations | .. image:: ../images/sioux_falls_frank-wolfe-500_iter.png :align: center :width: 590 :alt: Sioux Falls Frank-Wolfe 500 iterations | .. image:: ../images/sioux_falls_cfw-500_iter.png :align: center :width: 590 :alt: Sioux Falls Conjugate Frank-Wolfe 500 iterations | .. image:: ../images/sioux_falls_bfw-500_iter.png :align: center :width: 590 :alt: Sioux Falls Biconjugate Frank-Wolfe 500 iterations Anaheim ------- Network has: * Links: 914 * Nodes: 416 * Zones: 38 .. image:: ../images/anaheim_msa-500_iter.png :align: center :width: 590 :alt: Anaheim MSA 500 iterations | .. image:: ../images/anaheim_frank-wolfe-500_iter.png :align: center :width: 590 :alt: Anaheim Frank-Wolfe 500 iterations | .. image:: ../images/anaheim_cfw-500_iter.png :align: center :width: 590 :alt: Anaheim Conjugate Frank-Wolfe 500 iterations | .. image:: ../images/anaheim_bfw-500_iter.png :align: center :width: 590 :alt: Anaheim Biconjugate Frank-Wolfe 500 iterations Winnipeg -------- Network has: * Links: 914 * Nodes: 416 * Zones: 38 .. image:: ../images/winnipeg_msa-500_iter.png :align: center :width: 590 :alt: Winnipeg MSA 500 iterations | .. image:: ../images/winnipeg_frank-wolfe-500_iter.png :align: center :width: 590 :alt: Winnipeg Frank-Wolfe 500 iterations | .. image:: ../images/winnipeg_cfw-500_iter.png :align: center :width: 590 :alt: Winnipeg Conjugate Frank-Wolfe 500 iterations | .. image:: ../images/winnipeg_bfw-500_iter.png :align: center :width: 590 :alt: Winnipeg Biconjugate Frank-Wolfe 500 iterations The results for Winnipeg do not seem extremely good when compared to a highly, but we believe posting its results would suggest deeper investigation by one of our users :-) Barcelona --------- Network has: * Links: 2,522 * Nodes: 1,020 * Zones: 110 .. image:: ../images/barcelona_msa-500_iter.png :align: center :width: 590 :alt: Barcelona MSA 500 iterations | .. image:: ../images/barcelona_frank-wolfe-500_iter.png :align: center :width: 590 :alt: Barcelona Frank-Wolfe 500 iterations | .. image:: ../images/barcelona_cfw-500_iter.png :align: center :width: 590 :alt: Barcelona Conjugate Frank-Wolfe 500 iterations | .. image:: ../images/barcelona_bfw-500_iter.png :align: center :width: 590 :alt: Barcelona Biconjugate Frank-Wolfe 500 iterations Chicago Regional ---------------- Network has: * Links: 39,018 * Nodes: 12,982 * Zones: 1,790 .. image:: ../images/chicago_regional_msa-500_iter.png :align: center :width: 590 :alt: Chicago MSA 500 iterations | .. image:: ../images/chicago_regional_frank-wolfe-500_iter.png :align: center :width: 590 :alt: Chicago Frank-Wolfe 500 iterations | .. image:: ../images/chicago_regional_cfw-500_iter.png :align: center :width: 590 :alt: Chicago Conjugate Frank-Wolfe 500 iterations | .. image:: ../images/chicago_regional_bfw-500_iter.png :align: center :width: 590 :alt: Chicago Biconjugate Frank-Wolfe 500 iterations Convergence Study ----------------- Besides validating the final results from the algorithms, we have also compared how well they converge for the largest instance we have tested (Chicago Regional), as that instance has a comparable size to real-world models. .. image:: ../images/convergence_comparison.png :align: center :width: 590 :alt: Algorithm convergence comparison | Not surprinsingly, one can see that Frank-Wolfe far outperforms the Method of Successive Averages for a number of iterations larger than 25, and is capable of reaching 1.0e-04 just after 800 iterations, while MSA is still at 3.5e-4 even after 1,000 iterations. The actual show, however, is left for the Biconjugate Frank-Wolfe implementation, which delivers a relative gap of under 1.0e-04 in under 200 iterations, and a relative gap of under 1.0e-05 in just over 700 iterations. This convergence capability, allied to its computational performance described below suggest that AequilibraE is ready to be used in large real-world applications. Computational performance ------------------------- Running on a IdeaPad laptop equipped with a 6 cores (12 threads) Intel Core i7-10750H CPU @ 2.60 GHz, and 32GB of RAM, AequilibraE performed 1,000 iterations of Frank-Wolfe assignment on the Chicago Network in just under 18 minutes, while Bi-conjugate Frank Wolfe takes just under 19 minutes, or a little more than 1s per All-or-Nothing iteration. Compared with AequilibraE previous versions, we can notice a reasonable decrease in processing time. Noteworthy items ---------------- .. note:: The biggest opportunity for performance in AequilibraE right now it to apply network contraction hierarchies to the building of the graph, but that is still a long-term goal Want to run your own convergence study? --------------------------------------- If you want to run the convergence study in your machine, with Chicago Regional instance or any other instance presented here, check out the code block below! Please make sure you have already imported `TNTP files `_ into your machine. In the first part of the code, we'll parse TNTP instances to a format AequilibraE can understand, and then we'll perform the assignment. .. _code-block-for-convergence-study: .. code-block:: python # Imports import os import numpy as np import pandas as pd from aequilibrae.matrix import AequilibraeMatrix, AequilibraeData from aequilibrae.paths import TrafficAssignment from aequilibrae.paths.traffic_class import TrafficClass import statsmodels.api as sm from aequilibrae.paths import Graph from copy import deepcopy # Folders data_folder = 'C:/your/path/to/TransportationNetworks/chicago-regional' matfile = os.path.join(data_folder, 'ChicagoRegional_trips.tntp') # Creating the matrix f = open(matfile, 'r') all_rows = f.read() blocks = all_rows.split('Origin')[1:] matrix = {} for k in range(len(blocks)): orig = blocks[k].split('\n') dests = orig[1:] orig=int(orig[0]) d = [eval('{'+a.replace(';',',').replace(' ','') +'}') for a in dests] destinations = {} for i in d: destinations = {**destinations, **i} matrix[orig] = destinations zones = max(matrix.keys()) index = np.arange(zones) + 1 mat = np.zeros((zones, zones)) for i in range(zones): for j in range(zones): mat[i, j] = matrix[i+1].get(j+1,0) # Let's save our matrix in AequilibraE Matrix format aemfile = os.path.join(folder, "demand.aem") aem = AequilibraeMatrix() kwargs = {'file_name': aem_file, 'zones': zones, 'matrix_names': ['matrix'], "memory_only": False} # in case you want to save the matrix in your machine aem.create_empty(**kwargs) aem.matrix['matrix'][:,:] = mtx[:,:] aem.index[:] = index[:] # Now let's parse the network net = os.path.join(data_folder, 'ChicagoRegional_net.tntp') net = pd.read_csv(net, skiprows=7, sep='\t') network = net[['init_node', 'term_node', 'free_flow_time', 'capacity', "b", "power"]] network.columns = ['a_node', 'b_node', 'free_flow_time', 'capacity', "b", "power"] network = network.assign(direction=1) network["link_id"] = network.index + 1 # If you want to create an AequilibraE matrix for computation, then it follows g = Graph() g.cost = net['free_flow_time'].values g.capacity = net['capacity'].values g.free_flow_time = net['free_flow_time'].values g.network = network g.network.loc[(g.network.power < 1), "power"] = 1 g.network.loc[(g.network.free_flow_time == 0), "free_flow_time"] = 0.01 g.network_ok = True g.status = 'OK' g.prepare_graph(index) g.set_graph("free_flow_time") g.set_skimming(["free_flow_time"]) g.set_blocked_centroid_flows(True) # We run the traffic assignment for algorithm in ["bfw", "fw", "cfw", "msa"]: mat = AequilibraeMatrix() mat.load(os.path.join(data_folder, "demand.aem")) mat.computational_view(["matrix"]) assigclass = TrafficClass("car", g, mat) assig = TrafficAssignment() assig.set_classes([assigclass]) assig.set_vdf("BPR") assig.set_vdf_parameters({"alpha": "b", "beta": "power"}) assig.set_capacity_field("capacity") assig.set_time_field("free_flow_time") assig.max_iter = 1000 assig.rgap_target = 1e-10 assig.set_algorithm(algorithm) assig.execute() assigclass.results.save_to_disk( os.path.join(data_folder, f"convergence_study/results-1000.aed")) assig.report().to_csv(os.path.join(data_folder, f"{algorithm}_computational_results.csv")) As we've exported the assignment's results into CSV files, we can use Pandas to read the files, and plot a graph just :ref:`like the one above `.