Adaptive AI Traffic Signal Control and Optimization
Fixed-cycle traffic lights cause 30% of urban traffic delays. Every day, millions of drivers lose hours in congestion, and cities bear economic losses. We develop adaptive systems based on Multi-Agent Reinforcement Learning (MARL) that reduce average waiting time by 15-30%. For instance, in Hangzhou, such a system cut congestion by 22%, and in Saudi Arabia by 18%. Our approach uses MARL: each intersection is an agent with local observations optimizing phases in real time. A city with a population of 500,000 can save up to 10 million rubles per year in reduced fuel consumption and travel time.
Why RL and MARL Are the Best Approach for Traffic Signal Control?
Fixed cycles work well under predictable flow, but real traffic is unpredictable. Adaptive systems like SCOOT and SCATS require manual calibration and handle anomalies poorly. An RL agent directly optimizes phases for current traffic without manual tuning and adapts to accidents, rain, and events. Training is done in a simulator, then transferred to real controllers. In our tests, MARL outperforms SCOOT by 20-30% in average travel time.
The problem: N intersections, each with K phases (directions). The agent selects the current phase and duration to minimize total waiting time.
Simulation and Training Environment
CityFlow Simulation Environment
import cityflow
# City configuration from JSON (roads, intersections, traffic)
eng = cityflow.Engine('config.json', thread_num=4)
# Intersection state
lane_vehicles = eng.get_lane_vehicle_count() # vehicles per lane
lane_waiting = eng.get_lane_waiting_vehicle_count()
current_phase = eng.get_current_phase(intersection_id)
# Action: change phase
eng.set_tl_phase(intersection_id, new_phase)
eng.next_step()
For detailed microsimulation, we also use SUMO—it models individual car behavior more accurately.
Gym-Compatible Environment
class TrafficEnv(gym.Env):
def __init__(self, n_intersections, config_path):
self.n = n_intersections
self.eng = cityflow.Engine(config_path)
# observation per intersection: vehicle counts + waiting + phase
obs_dim = 12 + 12 + 8 # 12 approaching lanes, 8 phases
self.observation_space = spaces.Box(
low=0, high=100, shape=(n_intersections, obs_dim))
# action: select phase for each intersection
self.action_space = spaces.MultiDiscrete([8] * n_intersections)
def step(self, actions):
for i, action in enumerate(actions):
self.eng.set_tl_phase(f'intersection_{i}', int(action))
# multiple simulation steps per agent decision
for _ in range(self.control_interval): # 10–30 sec
self.eng.next_step()
obs = self._get_obs()
reward = -self.eng.get_average_travel_time() # minimize ATT
return obs, reward, False, False, {}
Building the MARL System
Cooperation Algorithms
Independent DQN (InDQN) is a simple baseline: each intersection trains independently, treating others as part of the environment. CoLight uses attention to account for neighboring intersections:
class CoLightAttention(nn.Module):
def forward(self, own_obs, neighbor_obs):
# own_obs: [batch, obs_dim]
# neighbor_obs: [batch, n_neighbors, obs_dim]
query = self.q_proj(own_obs).unsqueeze(1)
keys = self.k_proj(neighbor_obs)
values = self.v_proj(neighbor_obs)
attention = F.softmax(
torch.bmm(query, keys.transpose(1,2)) / math.sqrt(self.d_k), dim=-1
)
context = torch.bmm(attention, values).squeeze(1)
return self.output_proj(torch.cat([own_obs, context], dim=-1))
MPLight combines pressure-based feature engineering (queue pressure) with MARL, showing superior results on CityFlow benchmarks.
Reward Design
| Option | Formula | Note |
|---|---|---|
| Queue length | -sum of lane queues | Simple, but ignores downstream |
| Pressure | -(incoming - outgoing queues) | Accounts for neighbor load |
| Average Travel Time | -global ATT | Global metric, slower convergence |
Pressure-based reward yields the best results in multi-agent settings.
Integration with Real Controllers
Most cities use SCATS (Australia) or SCOOT (UK). Our RL solution outputs signals in these systems' format via the NTCIP protocol (national ITS standard). For compatibility, we implement an SNMP adapter. In case of RL failure (network outage), the system automatically falls back to actuated control with vehicle detectors. NTCIP 1202 v03 is the key standard for interoperability.
What Data Is Needed?
Data sources: video detectors (real-time queues), inductive loops (exact counts), GPS fleet (travel time feedback), Connected Vehicles (V2X/C-V2X) for proactive optimization. An MLOps pipeline automatically updates the model with new data. For training, 1-3 months of detector recordings suffice. If V2X data is available, accuracy improves by 10-15%.
KPIs Tracked
| KPI | Description | Target Improvement |
|---|---|---|
| ATT (Average Travel Time) | Mean travel time | -20% vs fixed phases |
| Queue length per lane | Queue length | -30% |
| Number of stops | Number of stops | -25% |
| Throughput | Capacity | +15% |
Contact us for a personalized KPI assessment.
Work Process
- Analysis: Collect traffic data, calibrate simulator. Build a digital twin of the district. Set up a predictive model.
- Design: Choose agent topology (Independent / CoLight / MPLight), design reward.
- Implementation: Train in CityFlow (1000+ episodes), test on real scenarios.
- Testing: A/B test on a dedicated intersection, verify KPIs.
- Deployment: Integrate with NTCIP controllers, fallback modes, MLOps monitoring.
What's Included
- MARL model with CoLight/MPLight support
- CityFlow simulator configured for your district
- Reward engineering tailored to your KPIs
- NTCIP adapter (SCATS/SCOOT)
- Documentation, operator training, 3 months of support
Deployment Timeline
A single intersection in simulation: 4 weeks. A district (20-50 intersections) with coordinated agents: 12 weeks. Full deployment with city infrastructure: 20-24 weeks.
We can evaluate your project in 2 days. Contact us for a consultation—our engineers have experience in cities with populations over 5 million and guarantee congestion reduction.







