Cellular Automata: Traffic Flow Simulation using the Nagel-Schreckenberg Model
Page content
Summary
The Nagel-Schreckenberg (NaSch) model is a traffic flow model which uses used cellular automata to simulate and predict traffic on roads.
Design of the Nagel-Schreckenberg Model
-
Discrete Space and Time:
- The road is divided into cells, each representing a fixed length (e.g., a few meters).
- Time advances in discrete steps.
-
Vehicle Representation:
- Each cell is either empty or occupied by a single vehicle.
- Each vehicle has a velocity (an integer) which determines how many cells it moves in a single time step.
Rules of the Model:
- The NaSch model uses local rules to update the state of each vehicle at every time step. These rules are:
-
Acceleration:
- A vehicle increases its velocity by 1 unit (up to a maximum velocity \(v_{\text{max}}\)).
-
Deceleration:
- If the distance to the next vehicle ahead is less than the current velocity, the vehicle slows down to avoid a collision.
-
Randomization:
- With a probability \(p\), a vehicle randomly decreases its velocity by 1 unit to account for driver imperfections or road conditions.
-
Movement:
- Each vehicle moves forward by the updated velocity.
-
Parameters:
- Road length: Total number of cells.
- Vehicle density: Fraction of cells occupied by vehicles.
- Maximum velocity (\(v_{\text{max}}\)): Maximum speed of the vehicles.
- Randomization probability (\(p\)): Likelihood of a vehicle slowing down randomly.
Steps in the Simulation
-
Initialization:
- Place vehicles on the road randomly or with a specific density.
- Assign each vehicle an initial velocity (often 0).
-
Iterative Updates:
- For each time step, apply the four rules (acceleration, deceleration, randomization, and movement) to update the positions and velocities of all vehicles.
-
Observation:
- Measure traffic metrics like flow, density, and average velocity to analyze traffic behavior under different conditions.
Python Implementation
This python code will generate a road and show traversal along that road using the model.
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import HTML
# Simulation parameters
road_length = 100 # Length of the road (number of cells)
num_cars = 30 # Number of cars on the road
max_speed = 5 # Maximum speed of cars (cells per time step)
p_slow = 0.3 # Probability of random slowing down
num_steps = 100 # Number of time steps to simulate
# road: An array representing the road where -1 indicates an empty cell.
# Initialize the road with empty cells (-1)
road = np.full(road_length, -1)
# Randomly place cars on the road with random initial speeds
car_positions = np.random.choice(road_length, num_cars, replace=False)
# Random initial speeds assigned to each car.
initial_speeds = np.random.randint(0, max_speed + 1, num_cars)
road[car_positions] = initial_speeds
def update_road(road):
new_road = np.full_like(road, -1)
road_length = len(road)
for i in range(road_length):
if road[i] != -1:
speed = road[i]
# Step 1: Acceleration
if speed < max_speed:
speed += 1
# Step 2: Slowing down due to other cars
distance = 1
while distance <= speed and road[(i + distance) % road_length] == -1:
distance += 1
distance -= 1
speed = min(speed, distance)
# Step 3: Randomization
if speed > 0 and np.random.rand() < p_slow:
speed -= 1
# Step 4: Move the car
new_position = (i + speed) % road_length
new_road[new_position] = speed
return new_road
# Store the history of the road for visualization
road_history = [road.copy()]
for step in range(num_steps):
road = update_road(road)
road_history.append(road.copy())
# Prepare the figure
fig, ax = plt.subplots(figsize=(12, 6))
ax.set_xlabel("Position on Road")
ax.set_ylabel("Time Step")
# Convert road history to a 2D array for visualization
road_display = []
for state in road_history:
display_state = np.where(state >= 0, 1, 0) # 1 for car, 0 for empty
road_display.append(display_state)
road_display = np.array(road_display)
# Display the simulation as an image
im = ax.imshow(road_display, cmap="Greys", interpolation="none", aspect="auto")
print(
"""Explanation: We create a 2D array where rows represent time steps and columns represent positions on the road.
A value of 1 indicates a car, and 0 indicates an empty cell.
We then use imshow to display this array as an image.
We then save the traverse of the road as an animated gif and show that."""
)
# Show the generated road plot
plt.show()
image_filenames = []
for i, r in enumerate(road_display):
ax.clear()
ax.imshow([r], cmap="Greys", aspect="auto")
ax.set_title(f"Time Step {i}")
ax.set_xlabel("Position on Road")
ax.set_yticks([])
save_path = f"traffic_{i}.png"
fig.savefig(save_path, dpi=300)
image_filenames.append(save_path)
def create_gif(image_filenames, output_filename="traffic.gif", fps=2):
"""
Creates an animated GIF from a list of image filenames.
"""
from PIL import Image
images = [Image.open(filename) for filename in image_filenames]
images[0].save(
output_filename,
save_all=True,
append_images=images[1:],
duration=1000 // fps,
loop=0,
)
create_gif(image_filenames, output_filename="traffic.gif", fps=2)
from IPython.display import Image
Image(filename="traffic.gif")
The map
Traversal
Traffic Flow Dynamics
The NaSch model reproduces key traffic phenomena, including:
- Free Flow: At low vehicle densities, vehicles travel at their maximum velocity without interference.
- Congested Flow: At higher densities, vehicles form clusters, leading to slower movement and stop-and-go traffic.
- Jam Formation: With very high densities, vehicles are nearly stationary, forming traffic jams.
Applications of the NaSch Model
-
Traffic Management:
- Predict traffic congestion under varying densities and road conditions.
- Evaluate the effects of traffic control measures (e.g., speed limits or lane closures).
-
Urban Planning:
- Model the impact of new road networks or infrastructure changes on traffic flow.
-
Driver Behavior Analysis:
- Incorporate different probabilities \(p\) to study the effects of driver aggressiveness or cautiousness.
-
Autonomous Vehicles:
- Test traffic flow patterns in mixed environments with autonomous and human-driven vehicles.
Strengths and Limitations
Strengths:
- Simple and computationally efficient.
- Captures realistic traffic dynamics like free flow, congestion, and jams.
- Flexible for extensions (e.g., multi-lane roads or variable \(v_{\text{max}}\)).
Limitations:
- Simplistic representation of vehicle and road dynamics.
- Does not account for detailed vehicle interactions like lane-changing or acceleration profiles.
- Randomization oversimplifies driver behavior.
Code Examples
Check out the ca notebooks for the code used in this post and additional examples.