Note
Go to the end to download the full example code.
Graph from arbitrary data#
In this example, we demonstrate how to create an AequilibraE Graph from an arbitrary network.
We are using Sioux Falls data, from TNTP.
See also
Several functions, methods, classes and modules are used in this example:
# Imports
import numpy as np
import pandas as pd
from aequilibrae.paths import Graph
We start by adding the path to load our arbitrary network.
net_file = "https://raw.githubusercontent.com/bstabler/TransportationNetworks/master/SiouxFalls/SiouxFalls_net.tntp"
Let’s read our data! We’ll be using Sioux Falls transportation network data, but without geometric information. The data will be stored in a Pandas DataFrame containing information about initial and final nodes, link distances, travel times, etc.
net = pd.read_csv(net_file, skiprows=8, sep="\t", lineterminator="\n", usecols=np.arange(1, 11))
The Graph object requires several default fields: link_id, a_node, b_node, and direction.
We need to manipulate the data to add the missing fields (link_id and direction) and rename the node columns accordingly.
net.insert(0, "link_id", np.arange(1, net.shape[0] + 1))
net = net.assign(direction=1)
net.rename(columns={"init_node": "a_node", "term_node": "b_node"}, inplace=True)
Now we can take a look in our network file
net.head()
Building an AequilibraE graph from our network is pretty straightforward. We assign our network to be the graph’s network …
graph = Graph()
graph.network = net
… and then set the graph’s configurations.
graph.prepare_graph(np.arange(1, 25)) # sets the centroids for which we will perform computation
graph.set_graph("length") # sets the cost field for path computation
graph.set_skimming(["length", "free_flow_time"]) # sets the skims to be computed
graph.set_blocked_centroid_flows(False) # we don't block flows through centroids because all nodes
# in the Sioux Falls network are centroids
Cost field with wrong type. Converting to float64
Two of AequilibraE’s new features consist in directly computing path or skims.
Let’s compute the path between nodes 1 and 17…
res = graph.compute_path(1, 17)
… and print the corresponding nodes…
res.path_nodes
array([ 1, 2, 6, 8, 16, 17])
… and the path links.
res.path
array([ 1, 4, 16, 22, 49])
For path computation, when we call the method graph.compute_path(1, 17)
, we are calling the class
PathComputation
and storing its results into a variable.
Notice that other methods related to path computation, such as milepost
can also be used with
res
.
For skim computation, the process is quite similar. When calligng the method graph.compute_skims()
we are actually calling the class NetworkSkimming
, and storing its results into skm
.
skm = graph.compute_skims()
: 0%| | 0/24 [00:00<?, ?it/s]
1/24 : 4%|▍ | 1/24 [00:00<00:00, 563.98it/s]
2/24 : 8%|▊ | 2/24 [00:00<00:00, 1003.42it/s]
3/24 : 12%|█▎ | 3/24 [00:00<00:00, 1377.14it/s]
4/24 : 17%|█▋ | 4/24 [00:00<00:00, 1695.87it/s]
5/24 : 21%|██ | 5/24 [00:00<00:00, 1955.93it/s]
6/24 : 25%|██▌ | 6/24 [00:00<00:00, 2195.40it/s]
7/24 : 29%|██▉ | 7/24 [00:00<00:00, 2409.13it/s]
8/24 : 33%|███▎ | 8/24 [00:00<00:00, 2601.72it/s]
9/24 : 38%|███▊ | 9/24 [00:00<00:00, 2776.25it/s]
10/24 : 42%|████▏ | 10/24 [00:00<00:00, 2932.05it/s]
11/24 : 46%|████▌ | 11/24 [00:00<00:00, 3055.66it/s]
12/24 : 50%|█████ | 12/24 [00:00<00:00, 3184.74it/s]
13/24 : 54%|█████▍ | 13/24 [00:00<00:00, 3304.00it/s]
14/24 : 58%|█████▊ | 14/24 [00:00<00:00, 3414.96it/s]
15/24 : 62%|██████▎ | 15/24 [00:00<00:00, 3516.74it/s]
16/24 : 67%|██████▋ | 16/24 [00:00<00:00, 3610.14it/s]
17/24 : 71%|███████ | 17/24 [00:00<00:00, 3679.59it/s]
18/24 : 75%|███████▌ | 18/24 [00:00<00:00, 3760.77it/s]
19/24 : 79%|███████▉ | 19/24 [00:00<00:00, 3836.87it/s]
20/24 : 83%|████████▎ | 20/24 [00:00<00:00, 3909.13it/s]
21/24 : 88%|████████▊ | 21/24 [00:00<00:00, 3977.98it/s]
22/24 : 92%|█████████▏| 22/24 [00:00<00:00, 4040.58it/s]
23/24 : 96%|█████████▌| 23/24 [00:00<00:00, 4081.27it/s]
24/24 : 100%|██████████| 24/24 [00:00<00:00, 4135.54it/s]
Saving Outputs : 100%|██████████| 24/24 [00:00<00:00, 3772.14it/s]
Let’s get the values for ‘free_flow_time’ matrix.
skims = skm.results.skims
skims.get_matrix("free_flow_time")
array([[ 0., 6., 4., 8., 10., 11., 16., 13., 15., 18., 14., 8., 11.,
18., 23., 18., 20., 18., 22., 22., 18., 20., 17., 15.],
[ 6., 0., 10., 11., 9., 5., 10., 7., 14., 16., 17., 14., 17.,
21., 19., 12., 14., 12., 16., 16., 22., 21., 23., 21.],
[ 4., 10., 0., 4., 6., 10., 15., 12., 11., 14., 10., 4., 7.,
14., 19., 17., 19., 17., 21., 20., 14., 16., 13., 11.],
[ 8., 11., 4., 0., 2., 6., 11., 8., 7., 10., 6., 8., 11.,
10., 15., 13., 15., 13., 17., 17., 18., 18., 14., 15.],
[10., 9., 6., 2., 0., 4., 9., 6., 5., 8., 8., 10., 13.,
12., 14., 11., 13., 11., 15., 15., 19., 17., 16., 17.],
[11., 5., 10., 6., 4., 0., 5., 2., 9., 11., 12., 14., 17.,
16., 14., 7., 9., 7., 11., 11., 17., 16., 20., 20.],
[16., 10., 15., 11., 9., 5., 0., 3., 12., 9., 14., 19., 19.,
17., 12., 5., 7., 2., 9., 6., 12., 11., 15., 15.],
[13., 7., 12., 8., 6., 2., 3., 0., 10., 9., 14., 16., 19.,
17., 12., 5., 7., 5., 9., 9., 15., 14., 18., 18.],
[15., 14., 11., 7., 5., 9., 12., 10., 0., 3., 8., 14., 17.,
12., 9., 7., 9., 10., 11., 14., 14., 12., 16., 17.],
[18., 16., 14., 10., 8., 11., 9., 9., 3., 0., 5., 11., 14.,
9., 6., 4., 6., 7., 8., 11., 11., 9., 13., 14.],
[14., 17., 10., 6., 8., 12., 14., 14., 8., 5., 0., 6., 9.,
4., 9., 9., 11., 12., 12., 16., 13., 12., 8., 10.],
[ 8., 14., 4., 8., 10., 14., 19., 16., 14., 11., 6., 0., 3.,
10., 15., 15., 17., 18., 18., 16., 10., 12., 9., 7.],
[11., 17., 7., 11., 13., 17., 19., 19., 17., 14., 9., 3., 0.,
10., 12., 18., 17., 17., 15., 13., 7., 9., 6., 4.],
[18., 21., 14., 10., 12., 16., 17., 17., 12., 9., 4., 10., 10.,
0., 5., 12., 10., 15., 8., 12., 9., 8., 4., 6.],
[23., 19., 19., 15., 14., 14., 12., 12., 9., 6., 9., 15., 12.,
5., 0., 7., 5., 10., 3., 7., 5., 3., 7., 8.],
[18., 12., 17., 13., 11., 7., 5., 5., 7., 4., 9., 15., 18.,
12., 7., 0., 2., 3., 4., 7., 12., 10., 14., 15.],
[20., 14., 19., 15., 13., 9., 7., 7., 9., 6., 11., 17., 17.,
10., 5., 2., 0., 5., 2., 6., 10., 8., 12., 13.],
[18., 12., 17., 13., 11., 7., 2., 5., 10., 7., 12., 18., 17.,
15., 10., 3., 5., 0., 7., 4., 10., 9., 13., 13.],
[22., 16., 21., 17., 15., 11., 9., 9., 11., 8., 12., 18., 15.,
8., 3., 4., 2., 7., 0., 4., 8., 6., 10., 11.],
[22., 16., 20., 17., 15., 11., 6., 9., 14., 11., 16., 16., 13.,
12., 7., 7., 6., 4., 4., 0., 6., 5., 9., 9.],
[18., 22., 14., 18., 19., 17., 12., 15., 14., 11., 13., 10., 7.,
9., 5., 12., 10., 10., 8., 6., 0., 2., 5., 3.],
[20., 21., 16., 18., 17., 16., 11., 14., 12., 9., 12., 12., 9.,
8., 3., 10., 8., 9., 6., 5., 2., 0., 4., 5.],
[17., 23., 13., 14., 16., 20., 15., 18., 16., 13., 8., 9., 6.,
4., 7., 14., 12., 13., 10., 9., 5., 4., 0., 2.],
[15., 21., 11., 15., 17., 20., 15., 18., 17., 14., 10., 7., 4.,
6., 8., 15., 13., 13., 11., 9., 3., 5., 2., 0.]])
Now we’re all set!
Graph image credits to Behance-network icons created by Sumitsaengtong - Flaticon
Total running time of the script: (0 minutes 0.375 seconds)