[9]:
%matplotlib inline
Advanced example¶
This is an advanced example of UXsim with automated network generation and traffic management. First, import and setup the simulation world.
[1]:
from uxsim import *
import pandas as pd
[2]:
# Simulation definition
W = World(
name="",
deltan=5,
tmax=6000,
print_mode=1, save_mode=1, show_mode=1,
random_seed=0,
)
Now we are going to define fairly large-scale simulation scenario by code. This is a grid-shaped arterial road network with diagonal highway. The traffic demand is set to travel from one end of the network to the other. We are going to test how highway toll can improve the traffic situation. Note that we specified user-defined attribute
of Link to distinguish arterial and highway links.
[3]:
# Scenario definition
#automated network generation
#generate nodes to create (imax, imax) grid network
imax = 11
jmax = imax
nodes = {}
for i in range(imax):
for j in range(jmax):
nodes[i,j] = W.addNode(f"n{(i,j)}", i, j)
#grid-shaped arterial roads
links = {}
for i in range(imax):
for j in range(jmax):
if i != imax-1:
ii = i+1
jj = j
links[i,j,ii,jj] = W.addLink(f"l{(i,j,ii,jj)}", nodes[i,j], nodes[ii,jj], length=1000,
free_flow_speed=15, jam_density=0.2, attribute="arterial")
if i != 0:
ii = i-1
jj = j
links[i,j,ii,jj] = W.addLink(f"l{(i,j,ii,jj)}", nodes[i,j], nodes[ii,jj], length=1000,
free_flow_speed=15, jam_density=0.2, attribute="arterial")
if j != jmax-1:
ii = i
jj = j+1
links[i,j,ii,jj] = W.addLink(f"l{(i,j,ii,jj)}", nodes[i,j], nodes[ii,jj], length=1000,
free_flow_speed=15, jam_density=0.2, attribute="arterial")
if j != 0:
ii = i
jj = j-1
links[i,j,ii,jj] = W.addLink(f"l{(i,j,ii,jj)}", nodes[i,j], nodes[ii,jj], length=1000,
free_flow_speed=15, jam_density=0.2, attribute="arterial")
#diagonal highway
for i in range(imax):
j = i
if i != imax-1:
ii = i+1
jj = j+1
links[i,j,ii,jj] = W.addLink(f"l{(i,j,ii,jj)}", nodes[i,j], nodes[ii,jj], length=1000*np.sqrt(2),
free_flow_speed=30, jam_density=0.2, attribute="highway")
if i != 0:
ii = i-1
jj = j-1
links[i,j,ii,jj] = W.addLink(f"l{(i,j,ii,jj)}", nodes[i,j], nodes[ii,jj], length=1000*np.sqrt(2),
free_flow_speed=30, jam_density=0.2, attribute="highway")
#traffic demand from edge to edge in grid network
demand_flow = 0.03
demand_duration = 3600
for n1 in [(0,j) for j in range(jmax)]:
for n2 in [(imax-1,j) for j in range(jmax)]:
W.adddemand(nodes[n2], nodes[n1], 0, demand_duration, demand_flow)
W.adddemand(nodes[n1], nodes[n2], 0, demand_duration, demand_flow)
for n1 in [(i,0) for i in range(imax)]:
for n2 in [(i,jmax-1) for i in range(imax)]:
W.adddemand(nodes[n2], nodes[n1], 0, demand_duration, demand_flow)
W.adddemand(nodes[n1], nodes[n2], 0, demand_duration, demand_flow)
In order to compare no-toll and with-toll scenarios, we copy the scenario for later re-use.
[4]:
#copy scenario for re-use (copy.deepcopy does not work for some reason)
import pickle
W_orig = pickle.loads(pickle.dumps(W))
No-toll scenario¶
Execute the no-toll scenario and show the results.
[5]:
W.name = "_notoll"
# Simulation execution
W.exec_simulation()
# Result visualization
W.analyzer.print_simple_stats()
W.analyzer.macroscopic_fundamental_diagram(figtitle="all")
W.analyzer.macroscopic_fundamental_diagram(figtitle="arterial", links=[link for link in W.LINKS if link.attribute == "arterial"])
W.analyzer.macroscopic_fundamental_diagram(figtitle="highway", links=[link for link in W.LINKS if link.attribute == "highway"])
#trajectories on highway
W.analyzer.time_space_diagram_traj_links([links[i,i,i+1,i+1] for i in range(0,imax-1)])
W.analyzer.time_space_diagram_traj_links([links[i,i,i-1,i-1] for i in range(imax-1,0,-1)])
W.analyzer.network_anim(animation_speed_inverse=5, timestep_skip=200, detailed=0, network_font_size=0, figsize=(4,4))
from IPython.display import display, Image
with open("out_notoll/anim_network0.gif", "rb") as f:
display(Image(data=f.read(), format='png'))
simulation setting:
scenario name: _notoll
simulation duration: 6000 s
number of vehicles: 50820 veh
total road length: 468284.27124746144 m
time discret. width: 5 s
platoon size: 5 veh
number of timesteps: 1200
number of platoons: 10164
number of links: 460
number of nodes: 121
setup time: 1.67 s
simulating...
time| # of vehicles| ave speed| computation time
0 s| 0 vehs| 0.0 m/s| 0.00 s
600 s| 7175 vehs| 11.5 m/s| 2.60 s
1200 s| 13205 vehs| 10.5 m/s| 6.35 s
1800 s| 15900 vehs| 9.8 m/s| 11.59 s
2400 s| 19120 vehs| 9.3 m/s| 17.39 s
3000 s| 20210 vehs| 8.5 m/s| 22.71 s
3600 s| 22780 vehs| 8.4 m/s| 31.52 s
4200 s| 14190 vehs| 9.6 m/s| 36.65 s
4800 s| 4635 vehs| 13.6 m/s| 39.18 s
5400 s| 125 vehs| 14.1 m/s| 42.17 s
6000 s| 0 vehs| 0.0 m/s| 42.36 s
simulation finished
results:
average speed: 10.6 m/s
number of completed trips: 50820 / 50820
average travel time of trips: 1412.0 s
average delay of trips: 659.7 s
delay ratio: 0.467
total distance traveled: 741551771.9 m



drawing trajectories...

drawing trajectories...

generating animation...

According to “delay ratio” value, this is a quite congested state in overall. We can also confirm that highway links are significantly congested according to time-space diagrams and network animation. This was due to the fact that many travelers were concentrated on the highways, causing huge traffic jams.
With-toll scenario¶
Now let’s see how highway toll can resolve this issue. We load the defined scenario to new World W2
. Highway toll can be implemented by setting route_choice_penalty
parameter of Link
object. The value of it works as penalty for traveler’s route choice as virtually additional travel time (in second). 70 seconds of route_choice_penalty
roughtly corresponds to 0.5 USD assuming the standard value of time; for example, a traveler who uses 4 highway links (or 5.7km highway road) needs
to pay 2 USD.
[6]:
W2 = pickle.loads(pickle.dumps(W_orig))
W2.name = "_withtoll"
#fixed toll for highway (toll corresponds to route_choice_penalty seconds of travel time per link)
for link in W2.LINKS:
if link.attribute == "highway":
link.route_choice_penalty = 70
[7]:
# Simulation execution
W2.exec_simulation()
# Result visualization
W2.analyzer.print_simple_stats()
W2.analyzer.macroscopic_fundamental_diagram(figtitle="all")
W2.analyzer.macroscopic_fundamental_diagram(figtitle="arterial", links=[link for link in W2.LINKS if link.attribute == "arterial"])
W2.analyzer.macroscopic_fundamental_diagram(figtitle="highway", links=[link for link in W2.LINKS if link.attribute == "highway"])
#trajectories on highway
W2.analyzer.time_space_diagram_traj_links([links[i,i,i+1,i+1] for i in range(0,imax-1)])
W2.analyzer.time_space_diagram_traj_links([links[i,i,i-1,i-1] for i in range(imax-1,0,-1)])
W2.analyzer.network_anim(animation_speed_inverse=5, timestep_skip=200, detailed=0, network_font_size=0, figsize=(4,4))
from IPython.display import display, Image
with open("out_withtoll/anim_network0.gif", "rb") as f:
display(Image(data=f.read(), format='png'))
simulation setting:
scenario name: _withtoll
simulation duration: 6000 s
number of vehicles: 50820 veh
total road length: 468284.27124746144 m
time discret. width: 5 s
platoon size: 5 veh
number of timesteps: 1200
number of platoons: 10164
number of links: 460
number of nodes: 121
setup time: 85.32 s
simulating...
time| # of vehicles| ave speed| computation time
0 s| 0 vehs| 0.0 m/s| 0.00 s
600 s| 7175 vehs| 11.5 m/s| 2.55 s
1200 s| 13215 vehs| 11.3 m/s| 6.58 s
1800 s| 15250 vehs| 10.7 m/s| 11.84 s
2400 s| 17610 vehs| 11.2 m/s| 18.88 s
3000 s| 16595 vehs| 11.2 m/s| 25.54 s
3600 s| 16920 vehs| 11.9 m/s| 29.91 s
4200 s| 7465 vehs| 14.2 m/s| 33.33 s
4800 s| 210 vehs| 14.6 m/s| 34.19 s
5400 s| 0 vehs| 0.0 m/s| 34.33 s
6000 s| 0 vehs| 0.0 m/s| 34.44 s
simulation finished
results:
average speed: 12.4 m/s
number of completed trips: 50820 / 50820
average travel time of trips: 1140.1 s
average delay of trips: 387.8 s
delay ratio: 0.340
total distance traveled: 698125872.2 m



drawing trajectories...

drawing trajectories...

generating animation...

You can see that the “delay ratio” is significantly reduced. Other visualization results also indicated that traffic situations were improved. This was due to the fact that inefficient usage of highway was reduced by toll.
Dataframe analysis¶
More quantitative analysis can be easily done by using pandas.Dataframe output. Here we compare some statistics between no-toll and with-toll scenarios.
[8]:
# Results comparison
df = W.analyzer.basic_to_pandas()
all_ave_tt = df["average_travel_time"][0]
all_ave_delay = df["average_delay"][0]
df = W.analyzer.link_to_pandas()
highway_user = (df
[df["link"].isin([l.name for l in W.LINKS if l.attribute=="highway"])]
["traffic_volume"]
.sum())
highway_ave_tt = (df
[df["link"].isin([l.name for l in W.LINKS if l.attribute=="highway"])]
["average_travel_time"]
.mean())
df = W2.analyzer.basic_to_pandas()
all_ave_tt2 = df["average_travel_time"][0]
all_ave_delay2 = df["average_delay"][0]
df = W2.analyzer.link_to_pandas()
highway_user2 = (df
[df["link"].isin([l.name for l in W.LINKS if l.attribute=="highway"])]
["traffic_volume"]
.sum())
highway_ave_tt2 = (df
[df["link"].isin([l.name for l in W.LINKS if l.attribute=="highway"])]
["average_travel_time"]
.mean())
print(f"""no toll case
- average travel time: {all_ave_tt}
- average delay: {all_ave_delay}
- # of highway link users: {highway_user}
- average highway link travel time: {highway_ave_tt}
toll case
- average travel time: {all_ave_tt2}
- average delay: {all_ave_delay2}
- # of highway link users: {highway_user2}
- average highway link travel time: {highway_ave_tt2}
""")
no toll case
- average travel time: 1412.0464384100749
- average delay: 659.6698588723114
- # of highway link users: 42760
- average highway link travel time: 107.4701619326083
toll case
- average travel time: 1140.1411845730026
- average delay: 387.7646050352395
- # of highway link users: 39390
- average highway link travel time: 70.02816778477828
You can see that the number of highway users were decreased, and the overall traffic efficiency was improved.