Complete document
Dynamic Congestion Pricing for Urban Emission Exposure
Complete 41-page report covering the data pipeline, simulation architecture, validation, experiments and limitations.
A full-day agent-based model testing whether emissions-responsive tolls can protect the city centre without shifting the problem elsewhere.

Road pricing usually targets delay or revenue. This project treated pricing as an environmental controller: charges rise with modelled NO₂ exposure and influence route choice before core concentrations exceed 12 µg/m³. Dublin supplied a real road network, detector data and a clear test of the trade-off between local exposure, mobility and affordability.
I led development of the custom discrete-time Python engine and geographic-data workflow, turning the team's system logic into a 1,440-step daily simulation. OSMnx supplied road topology, Rustworkx and NetworkX handled repeated routing, and NumPy and SciPy supported demand and spatial exposure. Full-scale runs took 12-14 hours.
Each agent received a departure time, vehicle type, origin, destination, willingness to pay and time sensitivity. Demand came from Dublin SCATS detector counts; direct NO₂ factors came from COPERT v5 and roadside evidence.
Three nested zones charged entry according to local exposure. Agents balanced time against toll cost, while route emissions were assigned to a spatial grid and decayed minute by minute across the full day.

Dynamic pricing preserved completed trips while cutting core through-traffic by 80.8%. It detoured 619,520 trips, collected 55,525 tolls and generated €385,159 over the modelled day.
The benefit was not network-wide. External-boundary trips rose 18.9%, creating new exposure along parts of the cordon. The central finding is that protecting the core can transfer the burden unless the controller optimizes the surrounding network as well.
Full-scale simulation
| Metric | No toll | Dynamic pricing | Change |
|---|---|---|---|
| Trips completed | 1,004,545 | 1,004,545 | No change |
| Through-traffic | 113,573 | 21,845 | -80.8% |
| External-boundary trips | 486,279 | 578,007 | +18.9% |
| Trips detoured | - | 619,520 | 61.7% of completed |
| Tolls collected | - | 55,525 | €6.94 average |
| Total toll revenue | - | €385,158.97 | Full day |

Simplified atmospheric dispersion, relative detector counts, perfect-information routing and reduced-scale sensitivity tests limit policy interpretation. A next iteration should add queueing, sensitive locations, price inertia and a network-wide exposure objective.