Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ok-landscape
GitHub Repository: Ok-landscape/computational-pipeline
Path: blob/main/latex-templates/templates/civil-engineering/traffic_flow.tex
51 views
unlisted
1
\documentclass[11pt,a4paper]{article}
2
\usepackage[utf8]{inputenc}
3
\usepackage[T1]{fontenc}
4
\usepackage{amsmath,amssymb}
5
\usepackage{graphicx}
6
\usepackage{booktabs}
7
\usepackage{siunitx}
8
\usepackage{geometry}
9
\geometry{margin=1in}
10
\usepackage{pythontex}
11
\usepackage{hyperref}
12
\usepackage{float}
13
14
\title{Traffic Flow\\LWR Model and Congestion}
15
\author{Civil Engineering Research Group}
16
\date{\today}
17
18
\begin{document}
19
\maketitle
20
21
\begin{abstract}
22
This report presents a comprehensive computational analysis of traffic flow theory, implementing the Lighthill-Whitham-Richards (LWR) continuum model, Greenshields' fundamental diagram, and queuing analysis at signalized intersections. We derive traffic wave propagation characteristics, compute capacity using fundamental relationships, analyze Webster's delay formula for signal timing optimization, and demonstrate shock wave formation during congestion onset. The analysis provides quantitative tools for traffic engineers to predict flow breakdown, optimize signal timing, and estimate delay under varying demand conditions.
23
\end{abstract}
24
25
\section{Introduction}
26
27
Traffic flow theory provides the mathematical foundation for understanding vehicular movement on roadways, enabling engineers to predict congestion, optimize signal timing, and design efficient transportation systems. The fundamental diagram relating flow ($q$), density ($k$), and speed ($v$) was first proposed by Greenshields in 1935 and remains the cornerstone of traffic analysis \cite{Greenshields1935}. Building on this foundation, Lighthill and Whitham (1955) and independently Richards (1956) developed the LWR continuum model, which treats traffic as a compressible fluid and predicts shock wave formation during congestion \cite{Lighthill1955,Richards1956}. For signalized intersections, Webster's delay formula (1958) provides closed-form estimates of average vehicle delay as a function of cycle length, green time, and degree of saturation \cite{Webster1958}. This report integrates these classical theories with modern computational methods to analyze traffic phenomena including capacity computation, wave speed derivation, queuing dynamics, and delay optimization. Understanding these relationships is critical for urban planners managing increasing traffic demand with limited infrastructure capacity.
28
29
\begin{pycode}
30
31
import numpy as np
32
import matplotlib.pyplot as plt
33
from scipy.integrate import odeint
34
from scipy.optimize import fsolve
35
from scipy import stats
36
plt.rcParams['text.usetex'] = True
37
plt.rcParams['font.family'] = 'serif'
38
39
# Traffic flow parameters (Greenshields model)
40
k_jam = 150.0 # jam density (veh/km)
41
v_free = 100.0 # free-flow speed (km/h)
42
q_max = v_free * k_jam / 4.0 # maximum flow capacity (veh/h)
43
k_crit = k_jam / 2.0 # critical density at capacity (veh/km)
44
45
# Signalized intersection parameters
46
green_time = 30.0 # green phase duration (s)
47
red_time = 60.0 # red phase duration (s)
48
cycle_length = green_time + red_time # total cycle (s)
49
saturation_flow = 1800.0 # saturation flow rate (veh/h)
50
arrival_rate = 600.0 # vehicle arrival rate (veh/h)
51
52
\end{pycode}
53
54
\section{Fundamental Diagram: Flow-Density Relationship}
55
56
The Greenshields model assumes a linear speed-density relationship:
57
\begin{equation}
58
v(k) = v_f \left(1 - \frac{k}{k_j}\right)
59
\end{equation}
60
where $v_f = \py{v_free}$ km/h is the free-flow speed and $k_j = \py{k_jam}$ veh/km is the jam density. Traffic flow is given by $q = k \cdot v$:
61
\begin{equation}
62
q(k) = v_f k \left(1 - \frac{k}{k_j}\right) = v_f k - \frac{v_f}{k_j} k^2
63
\end{equation}
64
Maximum capacity occurs at critical density $k_c = k_j/2$:
65
\begin{equation}
66
q_{\text{max}} = \frac{v_f k_j}{4} = \py{f'{q_max:.0f}'} \text{ veh/h}
67
\end{equation}
68
69
\begin{pycode}
70
# Fundamental diagram computation
71
k_range = np.linspace(0, k_jam, 200)
72
v_k = v_free * (1 - k_range / k_jam) # speed as function of density
73
q_k = k_range * v_k # flow-density relationship
74
75
# Identify critical point (capacity)
76
idx_crit = np.argmax(q_k)
77
k_at_capacity = k_range[idx_crit]
78
q_capacity = q_k[idx_crit]
79
80
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
81
82
# Plot 1: Flow vs Density
83
ax1.plot(k_range, q_k, 'b-', linewidth=2.5, label='Greenshields Model')
84
ax1.plot(k_at_capacity, q_capacity, 'ro', markersize=10, label=f'Capacity = {q_capacity:.0f} veh/h')
85
ax1.axvline(k_at_capacity, color='r', linestyle='--', alpha=0.5)
86
ax1.axhline(q_capacity, color='r', linestyle='--', alpha=0.5)
87
ax1.set_xlabel('Density $k$ (veh/km)', fontsize=12)
88
ax1.set_ylabel('Flow $q$ (veh/h)', fontsize=12)
89
ax1.set_title('Fundamental Diagram: Flow-Density', fontsize=13, weight='bold')
90
ax1.grid(True, alpha=0.3)
91
ax1.legend(fontsize=10)
92
ax1.set_xlim(0, k_jam)
93
ax1.set_ylim(0, q_capacity * 1.1)
94
95
# Plot 2: Speed vs Density
96
ax2.plot(k_range, v_k, 'g-', linewidth=2.5, label='Speed-Density')
97
ax2.plot(k_at_capacity, v_k[idx_crit], 'ro', markersize=10, label=f'Critical Density = {k_at_capacity:.1f} veh/km')
98
ax2.axvline(k_at_capacity, color='r', linestyle='--', alpha=0.5)
99
ax2.set_xlabel('Density $k$ (veh/km)', fontsize=12)
100
ax2.set_ylabel('Speed $v$ (km/h)', fontsize=12)
101
ax2.set_title('Speed-Density Relationship', fontsize=13, weight='bold')
102
ax2.grid(True, alpha=0.3)
103
ax2.legend(fontsize=10)
104
ax2.set_xlim(0, k_jam)
105
ax2.set_ylim(0, v_free * 1.1)
106
107
plt.tight_layout()
108
plt.savefig('traffic_flow_plot1.pdf', dpi=150, bbox_inches='tight')
109
plt.close()
110
\end{pycode}
111
112
\begin{figure}[H]
113
\centering
114
\includegraphics[width=0.95\textwidth]{traffic_flow_plot1.pdf}
115
\caption{Fundamental traffic flow relationships derived from the Greenshields model. Left panel shows the parabolic flow-density relationship with maximum capacity $q_{\text{max}} = \py{f'{q_capacity:.0f}'}$ veh/h occurring at critical density $k_c = \py{f'{k_at_capacity:.1f}'}$ veh/km. Right panel displays the linear speed-density relationship, showing speed declining from free-flow \py{f'{v_free:.0f}'} km/h to zero at jam density. The critical density represents the transition between free flow (low density, high speed) and congested flow (high density, low speed).}
116
\end{figure}
117
118
\section{LWR Model: Traffic Wave Propagation}
119
120
The Lighthill-Whitham-Richards (LWR) model treats traffic as a one-dimensional continuum governed by the conservation equation:
121
\begin{equation}
122
\frac{\partial k}{\partial t} + \frac{\partial q}{\partial x} = 0
123
\end{equation}
124
Using the fundamental diagram $q = q(k)$, the wave speed (kinematic wave celerity) is:
125
\begin{equation}
126
c(k) = \frac{dq}{dk} = v_f \left(1 - \frac{2k}{k_j}\right)
127
\end{equation}
128
At free flow ($k \to 0$), waves propagate at $c = v_f$. At jam density ($k = k_j$), $c = -v_f$ (backward-moving waves). At capacity ($k = k_c$), $c = 0$ (stationary bottleneck).
129
130
\begin{pycode}
131
# Wave speed computation
132
c_k = v_free * (1 - 2 * k_range / k_jam) # kinematic wave speed
133
134
# Shock wave between two states (k1 < k2)
135
k_upstream = 30.0 # upstream density (veh/km)
136
k_downstream = 120.0 # downstream density (veh/km)
137
q_upstream = k_upstream * v_free * (1 - k_upstream / k_jam)
138
q_downstream = k_downstream * v_free * (1 - k_downstream / k_jam)
139
shock_speed = (q_downstream - q_upstream) / (k_downstream - k_upstream) # km/h
140
141
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
142
143
# Plot 1: Wave speed vs density
144
ax1.plot(k_range, c_k, 'b-', linewidth=2.5, label='Wave Speed $c(k)$')
145
ax1.axhline(0, color='k', linestyle='-', linewidth=0.8)
146
ax1.fill_between(k_range, 0, c_k, where=(c_k >= 0), alpha=0.2, color='green', label='Forward Waves')
147
ax1.fill_between(k_range, c_k, 0, where=(c_k < 0), alpha=0.2, color='red', label='Backward Waves')
148
ax1.plot(k_at_capacity, 0, 'ro', markersize=10, label='Critical Point')
149
ax1.set_xlabel('Density $k$ (veh/km)', fontsize=12)
150
ax1.set_ylabel('Wave Speed $c$ (km/h)', fontsize=12)
151
ax1.set_title('Kinematic Wave Speed', fontsize=13, weight='bold')
152
ax1.grid(True, alpha=0.3)
153
ax1.legend(fontsize=10)
154
ax1.set_xlim(0, k_jam)
155
156
# Plot 2: Shock wave on fundamental diagram
157
ax2.plot(k_range, q_k, 'b-', linewidth=2.5, label='Flow-Density Curve')
158
ax2.plot([k_upstream, k_downstream], [q_upstream, q_downstream], 'ro-', markersize=8, linewidth=2, label=f'Shock Wave: {shock_speed:.1f} km/h')
159
ax2.arrow((k_upstream + k_downstream)/2, (q_upstream + q_downstream)/2, 10, shock_speed*10/v_free*q_capacity/10, head_width=5, head_length=200, fc='red', ec='red', alpha=0.7)
160
ax2.set_xlabel('Density $k$ (veh/km)', fontsize=12)
161
ax2.set_ylabel('Flow $q$ (veh/h)', fontsize=12)
162
ax2.set_title('Shock Wave Formation', fontsize=13, weight='bold')
163
ax2.grid(True, alpha=0.3)
164
ax2.legend(fontsize=10)
165
ax2.set_xlim(0, k_jam)
166
ax2.set_ylim(0, q_capacity * 1.1)
167
168
plt.tight_layout()
169
plt.savefig('traffic_flow_plot2.pdf', dpi=150, bbox_inches='tight')
170
plt.close()
171
\end{pycode}
172
173
\begin{figure}[H]
174
\centering
175
\includegraphics[width=0.95\textwidth]{traffic_flow_plot2.pdf}
176
\caption{Kinematic wave analysis from the LWR continuum model. Left panel shows wave speed $c(k) = dq/dk$ as a function of density, demonstrating forward-propagating waves in free flow (green region) and backward-propagating waves in congestion (red region). The critical density marks the transition where wave speed equals zero. Right panel illustrates shock wave formation when upstream density ($k_1 = \py{f'{k_upstream:.0f}'}$ veh/km) meets downstream congestion ($k_2 = \py{f'{k_downstream:.0f}'}$ veh/km), producing a discontinuity traveling at \py{f'{shock_speed:.1f}'} km/h. Shock waves represent abrupt transitions such as the onset of congestion at bottlenecks.}
177
\end{figure}
178
179
\section{Signalized Intersection: Queuing Dynamics}
180
181
At a signalized intersection, vehicles arrive at rate $\lambda = \py{f'{arrival_rate:.0f}'}$ veh/h and depart at saturation flow $s = \py{f'{saturation_flow:.0f}'}$ veh/h during green. The degree of saturation is:
182
\begin{equation}
183
x = \frac{\lambda}{s \cdot g/C} = \frac{\lambda \cdot C}{s \cdot g}
184
\end{equation}
185
where $g = \py{f'{green_time:.0f}'}$ s is green time and $C = \py{f'{cycle_length:.0f}'}$ s is cycle length. When $x > 1$, the queue grows indefinitely (unstable). Webster's delay formula estimates average delay per vehicle:
186
\begin{equation}
187
d = \frac{C(1 - g/C)^2}{2(1 - x \cdot g/C)} + \frac{x^2}{2\lambda(1 - x)}
188
\end{equation}
189
190
\begin{pycode}
191
# Queue dynamics over multiple cycles
192
num_cycles = 10
193
time_total = num_cycles * cycle_length
194
dt = 1.0 # time step (s)
195
time = np.arange(0, time_total, dt)
196
queue_length = np.zeros_like(time)
197
198
# Simulate queuing
199
lambda_per_sec = arrival_rate / 3600.0 # veh/s
200
s_per_sec = saturation_flow / 3600.0 # veh/s
201
202
for i in range(1, len(time)):
203
t_in_cycle = time[i] % cycle_length
204
is_green = t_in_cycle < green_time
205
206
arrivals = lambda_per_sec * dt
207
departures = s_per_sec * dt if (is_green and queue_length[i-1] > 0) else 0
208
209
queue_length[i] = max(0, queue_length[i-1] + arrivals - departures)
210
211
# Compute degree of saturation and delay
212
green_ratio = green_time / cycle_length
213
x_saturation = arrival_rate / (saturation_flow * green_ratio)
214
if x_saturation < 1:
215
webster_delay = (cycle_length * (1 - green_ratio)**2) / (2 * (1 - x_saturation * green_ratio)) + (x_saturation**2) / (2 * (arrival_rate/3600) * (1 - x_saturation))
216
else:
217
webster_delay = np.inf
218
219
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))
220
221
# Plot 1: Queue length over time
222
ax1.plot(time, queue_length, 'b-', linewidth=2)
223
for cycle in range(num_cycles):
224
t_start = cycle * cycle_length
225
ax1.axvspan(t_start, t_start + green_time, alpha=0.15, color='green', label='Green' if cycle == 0 else '')
226
ax1.axvspan(t_start + green_time, t_start + cycle_length, alpha=0.15, color='red', label='Red' if cycle == 0 else '')
227
ax1.set_xlabel('Time (s)', fontsize=12)
228
ax1.set_ylabel('Queue Length (vehicles)', fontsize=12)
229
ax1.set_title(f'Queuing at Signalized Intersection ($x = {x_saturation:.2f}$)', fontsize=13, weight='bold')
230
ax1.grid(True, alpha=0.3)
231
ax1.legend(fontsize=10)
232
233
# Plot 2: Delay vs arrival rate
234
arrival_rates = np.linspace(100, saturation_flow * green_ratio * 0.95, 100)
235
delays = []
236
for arr in arrival_rates:
237
x_val = arr / (saturation_flow * green_ratio)
238
if x_val < 0.99:
239
d_val = (cycle_length * (1 - green_ratio)**2) / (2 * (1 - x_val * green_ratio)) + (x_val**2) / (2 * (arr/3600) * (1 - x_val))
240
delays.append(d_val)
241
else:
242
delays.append(np.nan)
243
244
ax2.plot(arrival_rates, delays, 'r-', linewidth=2.5)
245
ax2.axvline(arrival_rate, color='b', linestyle='--', linewidth=2, label=f'Current Demand: {arrival_rate:.0f} veh/h')
246
ax2.axhline(webster_delay, color='b', linestyle='--', linewidth=1.5, label=f'Delay = {webster_delay:.1f} s')
247
ax2.set_xlabel('Arrival Rate (veh/h)', fontsize=12)
248
ax2.set_ylabel('Average Delay (s/veh)', fontsize=12)
249
ax2.set_title("Webster's Delay Formula", fontsize=13, weight='bold')
250
ax2.grid(True, alpha=0.3)
251
ax2.legend(fontsize=10)
252
ax2.set_xlim(arrival_rates[0], arrival_rates[-1])
253
ax2.set_ylim(0, min(150, max(delays)))
254
255
plt.tight_layout()
256
plt.savefig('traffic_flow_plot3.pdf', dpi=150, bbox_inches='tight')
257
plt.close()
258
\end{pycode}
259
260
\begin{figure}[H]
261
\centering
262
\includegraphics[width=0.95\textwidth]{traffic_flow_plot3.pdf}
263
\caption{Queuing analysis at a signalized intersection with \py{f'{green_time:.0f}'}-second green and \py{f'{red_time:.0f}'}-second red phases. Top panel shows queue buildup during red (shaded) and dissipation during green, demonstrating cyclic behavior. With arrival rate \py{f'{arrival_rate:.0f}'} veh/h and saturation flow \py{f'{saturation_flow:.0f}'} veh/h, the degree of saturation is $x = \py{f'{x_saturation:.2f}'}$, resulting in stable operation. Bottom panel displays Webster's delay formula, showing average delay per vehicle increasing nonlinearly as arrival rate approaches capacity. At current demand, average delay is \py{f'{webster_delay:.1f}'} seconds per vehicle.}
264
\end{figure}
265
266
\section{Space-Time Diagram: Traffic Propagation}
267
268
The space-time diagram visualizes vehicle trajectories and shock wave propagation. Individual vehicle paths have slope $dx/dt = v(k)$, while kinematic waves propagate at slope $dx/dt = c(k) = dq/dk$.
269
270
\begin{pycode}
271
# Space-time diagram showing shock wave propagation
272
x_road = np.linspace(0, 10, 200) # roadway position (km)
273
t_sim = np.linspace(0, 0.3, 200) # time (hours)
274
275
# Create space-time mesh
276
X_mesh, T_mesh = np.meshgrid(x_road, t_sim)
277
278
# Initial condition: shock at x = 5 km separating free flow and congestion
279
k_initial = np.where(x_road < 5, k_upstream, k_downstream)
280
281
# Density field evolution (simplified LWR solution)
282
# Shock position: x_shock(t) = 5 + shock_speed * t
283
density_field = np.zeros_like(X_mesh)
284
for i, t in enumerate(t_sim):
285
x_shock = 5 + shock_speed * t # shock position at time t
286
density_field[i, :] = np.where(X_mesh[i, :] < x_shock, k_upstream, k_downstream)
287
288
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
289
290
# Plot 1: Space-time density contour
291
cs = ax1.contourf(X_mesh, T_mesh, density_field, levels=15, cmap='RdYlGn_r')
292
cbar = plt.colorbar(cs, ax=ax1)
293
cbar.set_label('Density (veh/km)', fontsize=11)
294
295
# Add shock trajectory
296
t_shock_line = np.linspace(0, 0.3, 50)
297
x_shock_line = 5 + shock_speed * t_shock_line
298
ax1.plot(x_shock_line, t_shock_line, 'b-', linewidth=3, label=f'Shock Wave: {shock_speed:.1f} km/h')
299
300
ax1.set_xlabel('Position $x$ (km)', fontsize=12)
301
ax1.set_ylabel('Time $t$ (hours)', fontsize=12)
302
ax1.set_title('Space-Time Diagram: Density Evolution', fontsize=13, weight='bold')
303
ax1.legend(fontsize=11, loc='upper left')
304
ax1.grid(True, alpha=0.3)
305
306
# Plot 2: Vehicle trajectories
307
num_vehicles = 8
308
x0_free = np.linspace(0, 4.5, num_vehicles//2) # vehicles in free flow
309
x0_cong = np.linspace(5.5, 9, num_vehicles//2) # vehicles in congestion
310
311
for x0 in x0_free:
312
v_traj = v_free * (1 - k_upstream / k_jam)
313
x_traj = x0 + v_traj * t_sim
314
ax2.plot(x_traj, t_sim, 'g-', linewidth=1.5, alpha=0.7)
315
316
for x0 in x0_cong:
317
v_traj = v_free * (1 - k_downstream / k_jam)
318
x_traj = x0 + v_traj * t_sim
319
ax2.plot(x_traj, t_sim, 'r-', linewidth=1.5, alpha=0.7)
320
321
# Add shock trajectory
322
ax2.plot(x_shock_line, t_shock_line, 'b--', linewidth=3, label='Shock Wave')
323
ax2.set_xlabel('Position $x$ (km)', fontsize=12)
324
ax2.set_ylabel('Time $t$ (hours)', fontsize=12)
325
ax2.set_title('Vehicle Trajectories', fontsize=13, weight='bold')
326
ax2.legend(fontsize=11)
327
ax2.grid(True, alpha=0.3)
328
329
plt.tight_layout()
330
plt.savefig('traffic_flow_plot4.pdf', dpi=150, bbox_inches='tight')
331
plt.close()
332
\end{pycode}
333
334
\begin{figure}[H]
335
\centering
336
\includegraphics[width=0.98\textwidth]{traffic_flow_plot4.pdf}
337
\caption{Space-time representation of traffic shock wave propagation. Left panel shows density contours evolving in space and time, with a shock wave (blue line) separating upstream free flow (green, $k = \py{f'{k_upstream:.0f}'}$ veh/km) from downstream congestion (red, $k = \py{f'{k_downstream:.0f}'}$ veh/km). The shock propagates backward at \py{f'{shock_speed:.1f}'} km/h, characteristic of queue formation when demand exceeds capacity. Right panel displays individual vehicle trajectories, with green paths showing higher speeds in free flow and red paths showing slower speeds in congestion. The shock represents the queue tail moving upstream.}
338
\end{figure}
339
340
\section{Signal Timing Optimization}
341
342
Optimal signal timing minimizes total delay. Webster's optimal cycle length is:
343
\begin{equation}
344
C_{\text{opt}} = \frac{1.5L + 5}{1 - Y}
345
\end{equation}
346
where $L$ is total lost time per cycle and $Y = \sum (q_i / s_i)$ is the critical flow ratio. For green time allocation:
347
\begin{equation}
348
g_i = (C - L) \cdot \frac{y_i}{Y}
349
\end{equation}
350
where $y_i = q_i / s_i$ for approach $i$.
351
352
\begin{pycode}
353
# Optimize cycle length and green time
354
lost_time = 10.0 # lost time per cycle (s)
355
Y_critical = arrival_rate / saturation_flow # critical flow ratio
356
357
# Webster's optimal cycle length
358
C_opt = (1.5 * lost_time + 5) / (1 - Y_critical)
359
g_opt = (C_opt - lost_time) * Y_critical
360
361
# Compare delays for different cycle lengths
362
cycle_range = np.linspace(30, 180, 100)
363
delays_cycle = []
364
x_values = []
365
366
for C_test in cycle_range:
367
g_test = (C_test - lost_time) * Y_critical
368
if g_test > 0 and g_test < C_test:
369
x_test = arrival_rate / (saturation_flow * g_test / C_test)
370
if x_test < 0.99:
371
d_test = (C_test * (1 - g_test/C_test)**2) / (2 * (1 - x_test * g_test/C_test)) + (x_test**2) / (2 * (arrival_rate/3600) * (1 - x_test))
372
delays_cycle.append(d_test)
373
x_values.append(x_test)
374
else:
375
delays_cycle.append(np.nan)
376
x_values.append(np.nan)
377
else:
378
delays_cycle.append(np.nan)
379
x_values.append(np.nan)
380
381
# Delay at optimal cycle
382
x_opt = arrival_rate / (saturation_flow * g_opt / C_opt)
383
d_opt = (C_opt * (1 - g_opt/C_opt)**2) / (2 * (1 - x_opt * g_opt/C_opt)) + (x_opt**2) / (2 * (arrival_rate/3600) * (1 - x_opt))
384
385
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
386
387
# Plot 1: Delay vs cycle length
388
ax1.plot(cycle_range, delays_cycle, 'b-', linewidth=2.5)
389
ax1.plot(C_opt, d_opt, 'ro', markersize=12, label=f'Optimal: $C = {C_opt:.0f}$ s, $d = {d_opt:.1f}$ s')
390
ax1.axvline(C_opt, color='r', linestyle='--', alpha=0.5)
391
ax1.set_xlabel('Cycle Length $C$ (s)', fontsize=12)
392
ax1.set_ylabel('Average Delay $d$ (s/veh)', fontsize=12)
393
ax1.set_title("Webster's Optimal Cycle Length", fontsize=13, weight='bold')
394
ax1.grid(True, alpha=0.3)
395
ax1.legend(fontsize=11)
396
ax1.set_ylim(0, min(100, max([d for d in delays_cycle if not np.isnan(d)])))
397
398
# Plot 2: Sensitivity to arrival rate
399
arrival_test = np.linspace(200, saturation_flow * 0.8, 100)
400
delays_arrival = []
401
for arr in arrival_test:
402
Y_test = arr / saturation_flow
403
C_test_opt = (1.5 * lost_time + 5) / (1 - Y_test)
404
g_test_opt = (C_test_opt - lost_time) * Y_test
405
x_test = arr / (saturation_flow * g_test_opt / C_test_opt)
406
if x_test < 0.99:
407
d_test = (C_test_opt * (1 - g_test_opt/C_test_opt)**2) / (2 * (1 - x_test * g_test_opt/C_test_opt)) + (x_test**2) / (2 * (arr/3600) * (1 - x_test))
408
delays_arrival.append(d_test)
409
else:
410
delays_arrival.append(np.nan)
411
412
ax2.plot(arrival_test, delays_arrival, 'g-', linewidth=2.5)
413
ax2.axvline(arrival_rate, color='b', linestyle='--', linewidth=2, label=f'Current: {arrival_rate:.0f} veh/h')
414
ax2.set_xlabel('Arrival Rate (veh/h)', fontsize=12)
415
ax2.set_ylabel('Optimal Delay (s/veh)', fontsize=12)
416
ax2.set_title('Delay vs Demand (Optimized Timing)', fontsize=13, weight='bold')
417
ax2.grid(True, alpha=0.3)
418
ax2.legend(fontsize=11)
419
420
plt.tight_layout()
421
plt.savefig('traffic_flow_plot5.pdf', dpi=150, bbox_inches='tight')
422
plt.close()
423
\end{pycode}
424
425
\begin{figure}[H]
426
\centering
427
\includegraphics[width=0.95\textwidth]{traffic_flow_plot5.pdf}
428
\caption{Signal timing optimization using Webster's method. Left panel shows average delay as a function of cycle length for fixed demand (\py{f'{arrival_rate:.0f}'} veh/h), with the optimal cycle length $C_{\text{opt}} = \py{f'{C_opt:.0f}'}$ s minimizing delay at \py{f'{d_opt:.1f}'} s/veh. Shorter cycles waste time on phase transitions, while longer cycles increase queue buildup. Right panel demonstrates sensitivity to traffic demand: as arrival rate increases toward capacity, even optimized signal timing produces exponentially increasing delays. This underscores the importance of capacity expansion for high-demand corridors.}
429
\end{figure}
430
431
\section{Capacity Analysis: Flow Breakdown}
432
433
Traffic capacity is the maximum sustainable flow. Beyond capacity, flow drops precipitously as density increases (capacity drop phenomenon). The Highway Capacity Manual (HCM) defines level of service (LOS) based on density ranges.
434
435
\begin{pycode}
436
# Flow-speed diagram showing capacity drop
437
v_range = np.linspace(0, v_free, 200)
438
k_from_v = k_jam * (1 - v_range / v_free)
439
q_from_v = k_from_v * v_range
440
441
# Empirical capacity drop: flow drops 5-10% after breakdown
442
capacity_drop_factor = 0.92
443
q_congested_capacity = q_max * capacity_drop_factor
444
445
# HCM Level of Service boundaries (density-based)
446
los_boundaries = {
447
'A': (0, 10), # free flow
448
'B': (10, 20), # stable flow
449
'C': (20, 30), # stable flow, maneuverability limited
450
'D': (30, 45), # approaching unstable
451
'E': (45, 70), # unstable, at capacity
452
'F': (70, k_jam), # forced flow, breakdown
453
}
454
455
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
456
457
# Plot 1: Flow-speed relationship
458
ax1.plot(v_range, q_from_v, 'b-', linewidth=2.5, label='Theoretical Curve')
459
# Show capacity drop
460
v_at_capacity = v_free / 2
461
idx_capacity = np.argmin(np.abs(v_range - v_at_capacity))
462
ax1.plot(v_at_capacity, q_max, 'go', markersize=10, label=f'Pre-breakdown: {q_max:.0f} veh/h')
463
ax1.plot(v_at_capacity * 0.7, q_congested_capacity, 'ro', markersize=10, label=f'Post-breakdown: {q_congested_capacity:.0f} veh/h')
464
ax1.arrow(v_at_capacity, q_max, -5, -(q_max - q_congested_capacity)*0.8, head_width=2, head_length=200, fc='red', ec='red', linewidth=2)
465
ax1.set_xlabel('Speed $v$ (km/h)', fontsize=12)
466
ax1.set_ylabel('Flow $q$ (veh/h)', fontsize=12)
467
ax1.set_title('Flow-Speed Relationship & Capacity Drop', fontsize=13, weight='bold')
468
ax1.grid(True, alpha=0.3)
469
ax1.legend(fontsize=10)
470
ax1.set_xlim(0, v_free)
471
ax1.set_ylim(0, q_max * 1.1)
472
473
# Plot 2: Level of Service regions on fundamental diagram
474
colors_los = {'A': 'green', 'B': 'lightgreen', 'C': 'yellow', 'D': 'orange', 'E': 'red', 'F': 'darkred'}
475
for los, (k_min, k_max) in los_boundaries.items():
476
k_los = np.linspace(k_min, k_max, 50)
477
q_los = k_los * v_free * (1 - k_los / k_jam)
478
ax2.fill_between(k_los, 0, q_los, alpha=0.3, color=colors_los[los], label=f'LOS {los}')
479
480
ax2.plot(k_range, q_k, 'k-', linewidth=2.5)
481
ax2.set_xlabel('Density $k$ (veh/km)', fontsize=12)
482
ax2.set_ylabel('Flow $q$ (veh/h)', fontsize=12)
483
ax2.set_title('Highway Capacity Manual: Level of Service', fontsize=13, weight='bold')
484
ax2.legend(fontsize=10, loc='upper right')
485
ax2.grid(True, alpha=0.3)
486
ax2.set_xlim(0, k_jam)
487
ax2.set_ylim(0, q_max * 1.1)
488
489
plt.tight_layout()
490
plt.savefig('traffic_flow_plot6.pdf', dpi=150, bbox_inches='tight')
491
plt.close()
492
\end{pycode}
493
494
\begin{figure}[H]
495
\centering
496
\includegraphics[width=0.95\textwidth]{traffic_flow_plot6.pdf}
497
\caption{Capacity analysis and level of service classification. Left panel illustrates the capacity drop phenomenon: when flow exceeds capacity and breakdown occurs, the sustainable flow drops by approximately 8\% (from \py{f'{q_max:.0f}'} to \py{f'{q_congested_capacity:.0f}'} veh/h) even though vehicles are still present. This hysteresis effect makes congestion recovery difficult. Right panel shows Highway Capacity Manual (HCM) Level of Service (LOS) regions on the fundamental diagram, ranging from LOS A (free flow, low density) to LOS F (forced flow, breakdown). Engineers use LOS to evaluate roadway performance and justify capacity improvements.}
498
\end{figure}
499
500
\section{Results Summary}
501
502
\begin{pycode}
503
results = [
504
['Free-Flow Speed $v_f$', f'{v_free:.0f} km/h'],
505
['Jam Density $k_j$', f'{k_jam:.0f} veh/km'],
506
['Critical Density $k_c$', f'{k_crit:.0f} veh/km'],
507
['Maximum Capacity $q_{{\\text{{max}}}}$', f'{q_max:.0f} veh/h'],
508
['Shock Wave Speed', f'{shock_speed:.1f} km/h'],
509
['Degree of Saturation $x$', f'{x_saturation:.3f}'],
510
['Webster Delay (current)', f'{webster_delay:.1f} s/veh'],
511
['Optimal Cycle Length $C_{{\\text{{opt}}}}$', f'{C_opt:.0f} s'],
512
['Optimal Green Time $g_{{\\text{{opt}}}}$', f'{g_opt:.0f} s'],
513
['Optimal Delay (minimized)', f'{d_opt:.1f} s/veh'],
514
]
515
516
print(r'\begin{table}[H]')
517
print(r'\centering')
518
print(r'\caption{Traffic Flow Analysis Results}')
519
print(r'\begin{tabular}{@{}lc@{}}')
520
print(r'\toprule')
521
print(r'Parameter & Value \\')
522
print(r'\midrule')
523
for row in results:
524
print(f"{row[0]} & {row[1]} \\\\")
525
print(r'\bottomrule')
526
print(r'\end{tabular}')
527
print(r'\end{table}')
528
\end{pycode}
529
530
\section{Conclusions}
531
532
This computational analysis has implemented fundamental traffic flow theory to predict roadway performance and optimize signal timing. Using the Greenshields model, we established the flow-density-speed relationships and determined that maximum capacity of \py{f'{q_max:.0f}'} veh/h occurs at critical density \py{f'{k_crit:.0f}'} veh/km. The LWR kinematic wave model revealed that shock waves propagate backward at \py{f'{shock_speed:.1f}'} km/h when downstream congestion ($k = \py{f'{k_downstream:.0f}'}$ veh/km) meets upstream free flow ($k = \py{f'{k_upstream:.0f}'}$ veh/km), explaining the characteristic backward propagation of queue tails at bottlenecks.
533
534
For signalized intersections operating at arrival rate \py{f'{arrival_rate:.0f}'} veh/h with saturation flow \py{f'{saturation_flow:.0f}'} veh/h, the degree of saturation $x = \py{f'{x_saturation:.3f}'}$ indicates stable operation. Webster's formula predicts average delay of \py{f'{webster_delay:.1f}'} seconds per vehicle under current \py{f'{green_time:.0f}'}/\py{f'{red_time:.0f}'} second timing. Optimization yields an improved cycle length of \py{f'{C_opt:.0f}'} seconds with \py{f'{g_opt:.0f}'} seconds green time, reducing delay to \py{f'{d_opt:.1f}'} s/veh—a \py{f'{100*(webster_delay - d_opt)/webster_delay:.1f}'}\% improvement.
535
536
The capacity drop phenomenon demonstrates that post-breakdown flow (\py{f'{q_congested_capacity:.0f}'} veh/h) is approximately 8\% lower than pre-breakdown capacity, illustrating the hysteresis effect that makes congestion recovery challenging. Highway Capacity Manual level-of-service analysis provides a framework for evaluating roadway performance, with LOS E (density 45–70 veh/km) representing operation at or near capacity.
537
538
These models form the quantitative basis for traffic engineering decisions including bottleneck identification, signal timing optimization, and capacity expansion planning. Future extensions should incorporate stochastic arrivals, multi-class traffic (cars, trucks, buses), and adaptive signal control algorithms to better represent real-world variability and improve urban mobility.
539
540
\begin{thebibliography}{99}
541
542
\bibitem{Greenshields1935}
543
B.D. Greenshields, ``A study of traffic capacity,'' \textit{Highway Research Board Proceedings}, vol. 14, pp. 448--477, 1935.
544
545
\bibitem{Lighthill1955}
546
M.J. Lighthill and G.B. Whitham, ``On kinematic waves. II. A theory of traffic flow on long crowded roads,'' \textit{Proceedings of the Royal Society of London. Series A}, vol. 229, no. 1178, pp. 317--345, 1955.
547
548
\bibitem{Richards1956}
549
P.I. Richards, ``Shock waves on the highway,'' \textit{Operations Research}, vol. 4, no. 1, pp. 42--51, 1956.
550
551
\bibitem{Webster1958}
552
F.V. Webster, ``Traffic signal settings,'' Road Research Technical Paper No. 39, Road Research Laboratory, London, 1958.
553
554
\bibitem{HCM2016}
555
Transportation Research Board, \textit{Highway Capacity Manual}, 6th ed. Washington, DC: National Academies Press, 2016.
556
557
\bibitem{Daganzo1994}
558
C.F. Daganzo, ``The cell transmission model: A dynamic representation of highway traffic consistent with the hydrodynamic theory,'' \textit{Transportation Research Part B}, vol. 28, no. 4, pp. 269--287, 1994.
559
560
\bibitem{Newell1993}
561
G.F. Newell, ``A simplified theory of kinematic waves in highway traffic, part I: General theory,'' \textit{Transportation Research Part B}, vol. 27, no. 4, pp. 281--287, 1993.
562
563
\bibitem{Papageorgiou1991}
564
M. Papageorgiou, J.-M. Blosseville, and H. Hadj-Salem, ``Modelling and real-time control of traffic flow on the southern part of Boulevard Périphérique in Paris,'' \textit{Transportation Research Part A}, vol. 24, no. 5, pp. 345--359, 1990.
565
566
\bibitem{Cassidy1999}
567
M.J. Cassidy and R.L. Bertini, ``Some traffic features at freeway bottlenecks,'' \textit{Transportation Research Part B}, vol. 33, no. 1, pp. 25--42, 1999.
568
569
\bibitem{Banks1991}
570
J.H. Banks, ``Two-capacity phenomenon at freeway bottlenecks: A basis for ramp metering?,'' \textit{Transportation Research Record}, no. 1320, pp. 83--90, 1991.
571
572
\bibitem{Kerner2004}
573
B.S. Kerner, \textit{The Physics of Traffic}. Berlin: Springer-Verlag, 2004.
574
575
\bibitem{Treiber2013}
576
M. Treiber and A. Kesting, \textit{Traffic Flow Dynamics: Data, Models and Simulation}. Berlin: Springer-Verlag, 2013.
577
578
\bibitem{Daganzo1997}
579
C.F. Daganzo, \textit{Fundamentals of Transportation and Traffic Operations}. Oxford: Pergamon-Elsevier, 1997.
580
581
\bibitem{May1990}
582
A.D. May, \textit{Traffic Flow Fundamentals}. Englewood Cliffs, NJ: Prentice Hall, 1990.
583
584
\bibitem{Gazis2002}
585
D.C. Gazis, ``Traffic theory,'' in \textit{International Series in Operations Research \& Management Science}, vol. 50. Boston: Springer, 2002.
586
587
\bibitem{Papageorgiou2007}
588
M. Papageorgiou, C. Diakaki, V. Dinopoulou, A. Kotsialos, and Y. Wang, ``Review of road traffic control strategies,'' \textit{Proceedings of the IEEE}, vol. 91, no. 12, pp. 2043--2067, 2003.
589
590
\bibitem{Hoogendoorn2001}
591
S.P. Hoogendoorn and P.H.L. Bovy, ``State-of-the-art of vehicular traffic flow modelling,'' \textit{Proceedings of the Institution of Mechanical Engineers, Part I: Journal of Systems and Control Engineering}, vol. 215, no. 4, pp. 283--303, 2001.
592
593
\bibitem{Aw2000}
594
A. Aw and M. Rascle, ``Resurrection of `second order' models of traffic flow,'' \textit{SIAM Journal on Applied Mathematics}, vol. 60, no. 3, pp. 916--938, 2000.
595
596
\bibitem{Helbing2001}
597
D. Helbing, ``Traffic and related self-driven many-particle systems,'' \textit{Reviews of Modern Physics}, vol. 73, no. 4, pp. 1067--1141, 2001.
598
599
\end{thebibliography}
600
601
\end{document}
602
603