Traffic Assignment without an AequilibraE Model#
In this example, we show how to perform Traffic Assignment in AequilibraE without a model.
We are using Sioux Falls data, from TNTP.
Imports
[1]:
import os
import pandas as pd
import numpy as np
from tempfile import gettempdir
from aequilibrae.matrix import AequilibraeMatrix
from aequilibrae.paths import Graph
from aequilibrae.paths import TrafficAssignment
from aequilibrae.paths.traffic_class import TrafficClass
We load the example file from the GMNS GitHub repository
[2]:
net_file = "https://raw.githubusercontent.com/bstabler/TransportationNetworks/master/SiouxFalls/SiouxFalls_net.tntp"
demand_file = "https://raw.githubusercontent.com/bstabler/TransportationNetworks/master/SiouxFalls/CSV-data/SiouxFalls_od.csv"
Let’s use a temporary folder to store our data
[3]:
folder = gettempdir()
First we load our demand file. This file has three columns: O, D, and Ton. O and D stand for origin and destination, respectively, and Ton is the demand of each OD pair.
[4]:
dem = pd.read_csv(demand_file)
zones = int(max(dem.O.max(), dem.D.max()))
index = np.arange(zones) + 1
Since our OD-matrix is in a different shape than we expect (for Sioux Falls, that would be a 24x24 matrix), we must create our matrix.
[5]:
mtx = np.zeros(shape=(zones, zones))
for element in dem.to_records(index=False):
mtx[element[0]-1][element[1]-1] = element[2]
Now let’s create an AequilibraE Matrix with out data
[6]:
aemfile = os.path.join(folder, "demand.aem")
aem = AequilibraeMatrix()
kwargs = {'file_name': aemfile,
'zones': zones,
'matrix_names': ['matrix'],
"memory_only": False} # We'll save it to disk so we can use it later
aem.create_empty(**kwargs)
aem.matrix['matrix'][:,:] = mtx[:,:]
aem.index[:] = index[:]
Let’s import information about our network. As we’re loading data in TNTP format, we should do these manipulations.
[7]:
net = pd.read_csv(net_file, skiprows=2, sep="\t", lineterminator=";", header=None)
net.columns = ["newline", "a_node", "b_node", "capacity", "length", "free_flow_time", "b", "power", "speed", "toll", "link_type", "terminator"]
net.drop(columns=["newline", "terminator"], index=[76], inplace=True)
[8]:
network = net[['a_node', 'b_node', "capacity", 'free_flow_time', "b", "power"]]
network = network.assign(direction=1)
network["link_id"] = network.index + 1
network = network.astype({"a_node":"int64", "b_node": "int64"})
Let’s build our Graph! In case you’re in doubt about the Graph, click here <aequilibrae-graphs> to read more about it. %%
[9]:
g = Graph()
g.cost = network['free_flow_time'].values
g.capacity = network['capacity'].values
g.free_flow_time = network['free_flow_time'].values
g.network = network
g.network_ok = True
g.status = 'OK'
g.prepare_graph(index)
g.set_graph("free_flow_time")
g.cost = np.array(g.cost, copy=True)
g.set_skimming(["free_flow_time"])
g.set_blocked_centroid_flows(False)
g.network["id"] = g.network.link_id
Let’s perform our assignment. Feel free to try different algorithms, as well as change the maximum number of iterations and the gap.
[10]:
aem = AequilibraeMatrix()
aem.load(aemfile)
aem.computational_view(["matrix"])
assigclass = TrafficClass("car", g, aem)
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.set_algorithm("fw")
assig.max_iter = 100
assig.rgap_target = 1e-6
assig.execute()
Now let’s take a look at the Assignment results
[11]:
print(assig.results())
matrix_ab matrix_ba matrix_tot Congested_Time_AB \
link_id
1 4532.416460 NaN 4532.416460 6.000844
2 8124.962104 NaN 8124.962104 4.008716
3 4528.444976 NaN 4528.444976 6.000841
4 6001.323525 NaN 6001.323525 6.609756
5 8128.933588 NaN 8128.933588 4.008733
... ... ... ... ...
72 9643.868005 NaN 9643.868005 12.303788
73 7855.662507 NaN 7855.662507 3.717544
74 11101.449987 NaN 11101.449987 17.563454
75 10255.489839 NaN 10255.489839 11.738819
76 7923.866336 NaN 7923.866336 3.777973
Congested_Time_BA Congested_Time_Max Delay_factor_AB \
link_id
1 NaN 6.000844 1.000141
2 NaN 4.008716 1.002179
3 NaN 6.000841 1.000140
4 NaN 6.609756 1.321951
5 NaN 4.008733 1.002183
... ... ... ...
72 NaN 12.303788 3.075947
73 NaN 3.717544 1.858772
74 NaN 17.563454 4.390863
75 NaN 11.738819 3.912940
76 NaN 3.777973 1.888986
Delay_factor_BA Delay_factor_Max VOC_AB VOC_BA VOC_max \
link_id
1 NaN 1.000141 0.174995 NaN 0.174995
2 NaN 1.002179 0.347169 NaN 0.347169
3 NaN 1.000140 0.174842 NaN 0.174842
4 NaN 1.321951 1.210388 NaN 1.210388
5 NaN 1.002183 0.347339 NaN 0.347339
... ... ... ... ... ...
72 NaN 3.075947 1.928774 NaN 1.928774
73 NaN 1.858772 1.546844 NaN 1.546844
74 NaN 4.390863 2.180493 NaN 2.180493
75 NaN 3.912940 2.099230 NaN 2.099230
76 NaN 1.888986 1.560274 NaN 1.560274
PCE_AB PCE_BA PCE_tot
link_id
1 4532.416460 NaN 4532.416460
2 8124.962104 NaN 8124.962104
3 4528.444976 NaN 4528.444976
4 6001.323525 NaN 6001.323525
5 8128.933588 NaN 8128.933588
... ... ... ...
72 9643.868005 NaN 9643.868005
73 7855.662507 NaN 7855.662507
74 11101.449987 NaN 11101.449987
75 10255.489839 NaN 10255.489839
76 7923.866336 NaN 7923.866336
[76 rows x 15 columns]
And at the Assignment report
[12]:
print(assig.report())
iteration rgap alpha warnings
0 1 inf 1.000000
1 2 0.855131 0.328177
2 3 0.476738 0.186185
3 4 0.239622 0.229268
4 5 0.139851 0.314341
.. ... ... ... ...
95 96 0.001999 0.011309
96 97 0.001431 0.006948
97 98 0.001405 0.014356
98 99 0.001814 0.012088
99 100 0.001577 0.007687
[100 rows x 4 columns]