A traffic signal decides who gets the green, usually by a rule written by hand. Here it is learned. I built a small traffic simulator and trained a signal controller inside it with reinforcement learning, then ran that one policy at every intersection: it beats a hand-tuned timing plan on road networks from one signal to twenty-five, the same 62-thousand-parameter model unchanged. The learned controller wins, which isn't surprising. What's worth knowing is when one signal talking to its neighbors actually helps. Mostly it doesn't; this page shows the cases where it does, and why. The figures run live in your browser.
The usual way to run a signal is a rule someone wrote down, a fixed timing plan or a heuristic like MaxPressure that reads the queues and switches accordingly. Those are good: a tuned fixed-time plan is fine on steady demand, and MaxPressure is strong under load. Instead of writing the rule, I let each signal learn one. That is reinforcement learning: the controller (the agent) picks an action, gets a number back rating how well traffic then flowed (its reward), and shifts toward the choices that score higher, over and over. What it converges on is a policy, a mapping from what it sees to what it does. Run that for millions of steps inside a traffic simulator and it settles on a controller nobody hand-tuned.
Here, each intersection is one agent. It watches the queues on its incoming roads (its approaches) and a phase timer; that short list of numbers is its observation. Every few seconds it picks a phase: one of the handful of legal green patterns, like north–south through-traffic, or the protected left turns.
Its reward is negative pressure, roughly how much traffic is stacked up on its own approaches minus what is stacked downstream. It is cheap to compute from what one intersection can see, and it punishes flushing your queue into a street that is already full. Pressure is the exact quantity MaxPressure acts on; here it is what the policy is trained to reduce.
The three designs differ in how much each one gets to see. Independent: one network per intersection, each blind to its neighbors. Shared: one network, every intersection runs the same weights, and each still sees a short summary of its immediate neighbors. The third adds a critic that, during training only, sees the whole network at once. The shared policy is the one that ships. It's the cheapest to train (every intersection feeds the same network, so it gets N times the experience per step) and the only one that transfers to a road network of a different size without retraining.
All three beat a fixed-time cycle. So does seeing the neighbors help at all? To answer that you have to know what coordination even buys. The clearest case is a green wave.
Before putting a number on it, watch the policies drive. Here is the shared policy running a 3×3 grid of nine signals under a steady rush of traffic, next to the two controllers it has to beat: a fixed-time cycle that switches on a timer, and a random legal switcher. Same streets, same cars arriving in the same order; the only thing that changes is who decides the greens. Amber cars are moving; red cars are stopped; at each intersection a green stub marks the approach the signal is waving through right now. Flip between the three and watch which approaches each policy greens, and the running wait-time tally.
Shared (sees neighbors) against independent (blind), each trained from scratch on the same network at a demand high enough that queues outgrow their own block and spill back into the intersection upstream. Both are compared to a fixed-time cycle. The number that matters is the coordination premium: how much more the shared policy beats fixed-time than the blind one does. If the neighbor view is worthless, the premium is zero and the two policies tie.
Pick a network below. Some are ordinary grids; some are the kind of thing the neighbor view was supposed to help with: a couplet (a pair of one-way streets running opposite directions), or an arterial (a through-road carrying most of the traffic).
The couplet grid (a whole grid of those one-way pairs) is where the neighbor view pays the most: a car leaving one signal has nowhere to go but straight into the next, so a green wave is both available and necessary. The single arterial is the same story on a smaller network.
Then there are the flat cases. In the one-way pair embedded in a two-way grid, the arterial where side streets can only turn right on and off it (right-in, right-out, or RIRO), and the grid hit by platoon surges, the blind policy matches the neighbor-aware one exactly. These aren't easy networks: RIRO and the platoon grid are congested and hard. They tie because traffic has somewhere else to go. When there are alternative routes and slack, a light that sees only its own queues does just as well. The premium measures how tightly one intersection's decisions land on the next; a busy, complicated-looking network can still score zero.
Every figure is measured, but the budget was a laptop. The couplet and corridor coordination gaps come from three training runs each; the flat scenarios from two, and a few stress tests from one. The gaps hold across runs, but this is a workstation study, not a benchmark suite. I ran one layout per network type, with no sweeps over training settings.
The score is a within-simulator pressure return, not a field measurement, and it only compares within a network. A −112 on one map and a −4 on another are different maps, not a ranking. And each agent only ever sees one hop out (its immediate neighbors), so the observation itself limits how well any policy can do; some of the gap that stays open is baked into the inputs, not the model.
Three things set the ceiling here: what each agent can observe, how the reward is shaped, and how tightly the road geometry couples one intersection to the next. Model size isn't one of them. The biggest network on this page is a couple of megabytes. Coordination isn't free performance you can add anywhere; it pays only where the streets are tight, and you can now predict which streets those are.
The one-hop view (each signal sees only its immediate neighbors) is still a keyhole. The next rung is a policy that can look further than one hop, so a signal reacts to a jam building two or three blocks away before it arrives. After that, I want to drop all of this into a game where you build the streets yourself.