This is the Nagel–Schreckenberg cellular automaton on an open road (not a ring): every step, every car in parallel applies
1. Accelerate: v ← min(v+1, v_max)
2. Brake: v ← min(v, gap-to-car-ahead)
3. Randomize: with prob. p, v ← max(v-1, 0)
4. Move: x ← x + v; exits if x ≥ L
Cars enter the left edge with probability α whenever the entry cell is free. A second stream — the on-ramp — enters at a fixed point along the road with probability β; if the merge cell is occupied the ramp car waits in a queue instead of vanishing. That queue is the bottleneck's memory: it is what a real on-ramp back-up looks like as a number.
- Road view — cars colour-coded by speed (red = stopped, green = v_max); the triangle marks the ramp.
- Space-time diagram — one new row per step, newest at the bottom. Unlike a ring road, the congestion here is anchored at the ramp: the diagonal jam stripes consistently originate at the merge point and drift upstream (left) from it, rather than nucleating at random locations from noise alone.
- Throughput trace — downstream flow (cars/step, smoothed). Push β up past what the merge can absorb and this line drops even though more cars are trying to get onto the road — the textbook capacity-drop signature of a bottleneck.