How Olus works
A deep dive into the optimizer formulation, cascade predictor, crew legality engine, and data sources powering the simulation.
The $34B cascade problem
U.S. flight disruptions cost approximately $34 billion annually as of 2026. Weather causes ~74% of delays. The core challenge is cascade propagation: airlines reuse aircraft 4–5 times per day, so a single late inbound flight propagates into late departures for the next 18+ hours.
Large carriers (Delta, United) operate proprietary Operations Control Center (OCC) software built over decades. Regional carriers — Breeze, Avelo, Frontier, JSX, Sun Country — rely on expensive third-party tools and manual dispatcher judgment. Olus is an open-source OCC reference implementation.
Recovery optimizer (MILP)
The recovery optimizer is formulated as a Mixed-Integer Linear Program solved by Google OR-Tools CP-SAT. It runs three times with different weight vectors to produce Plans A, B, and C.
Decision variables
| Variable | Domain | Meaning |
|---|---|---|
| x[f] | {0, 1} | 1 if flight f operates, 0 if cancelled |
| d[f] | ℤ⁺ (slots) | Delay in 15-min slots (0 = on time) |
| a[f][ac] | {0, 1} | 1 if aircraft ac operates flight f |
| c[f][crew] | {0, 1} | 1 if crew pairing operates flight f |
Objective function
minimize α·Σ(cancel_cost[f] · (1 − x[f])) # Plan A: α=10
+ β·Σ(pax_delay_min[f] · passengers[f]) # Plan B: β=10
+ γ·Σ(crew_overtime_hours) #
+ δ·Σ(aircraft_out_of_position_penalty) # Plan C: δ=10
Constants:
cancel_cost_per_flight = $15,000
pax_delay_cost_per_min = $1.50 (DOT methodology)
crew_overtime_per_hour = $450Hard constraints
- →Aircraft continuity: if A operates f1 (lands at ORD at T), next flight must depart ORD ≥ T + min_turn_time
- →FAR 117 duty limits: enforced as hard constraints via crew legality engine
- →Airport capacity: Σ(departures/hour) ≤ airport.hourly_capacity
- →Event constraints: no flight can depart/arrive at a closed airport during event window
- →Each operating flight must have exactly one aircraft and one crew pairing
Weight configurations
| Plan | Objective | α (cancel) | β (pax) | γ (crew) | δ (position) |
|---|---|---|---|---|---|
| A | Minimize cost | 10.0 | 1.0 | 5.0 | 2.0 |
| B | Minimize pax impact | 1.0 | 10.0 | 2.0 | 1.0 |
| C | Protect tomorrow | 2.0 | 3.0 | 2.0 | 10.0 |
Solver target: <30 seconds on a single CPU for the 200-flight, 40-aircraft instance. On timeout, falls back to a greedy nearest-aircraft swap heuristic and flags the plan as heuristic.
Cascade predictor (XGBoost)
An XGBoost ensemble (classifier + regressor) predicts, for each flight in the next 18 hours: P(delay > 15 min) and expected delay in minutes.
Feature set
| Feature | Description |
|---|---|
| origin, destination | Encoded airport IDs |
| departure_hour, day_of_week | Temporal features (high delay correlation) |
| aircraft_type | B737 vs A320 vs E175 — different turn times |
| inbound_delay_minutes | Critical cascade feature: how late is the inbound? |
| origin/dest METAR | Wind, visibility, ceiling, flight category (VFR/IFR/LIFR) |
| event_distance_nm | Proximity to active disruption polygon |
| event_severity_encoded | mild=0.4, moderate=0.7, severe=0.9, extreme=1.0 |
| crew_duty_remaining_min | Hours remaining on crew's duty clock |
| route_on_time_pct_90d | Historical baseline: how often does this route run on time? |
Training data: BTS On-Time Performance (2023–2024) joined with historical METAR archives. Validate on 2025. When no trained model is present, falls back to deterministic rule-based propagation with realistic cascade decay (severity × 0.4–0.9 multiplier).
Crew legality engine (FAR 117)
The crew legality engine hard-codes FAR Part 117 for 2-pilot passenger operations. Every recovery plan is checked against these rules before being presented.
| Rule | Limit | FAR Reference |
|---|---|---|
| Max flight time / FDP | 9 hours (2-pilot) | 117.65 |
| Flight Duty Period limit | 9–14h by report time | 117.13 Table B |
| Min rest before FDP | 10 consecutive hours | 117.25(a) |
| Max flight time / 7 days | 60 hours | 117.23(a) |
| Max flight time / 28 days | 100 hours | 117.23(b) |
| Max flight time / 365 days | 1,000 hours | 117.23(c) |
| WOCL restriction | 0200–0559 local | 117.3, 117.13 |
# Usage
engine = CrewLegalityEngine()
result = engine.validate(
crew={
"duty_start": datetime(2024, 1, 15, 8, 0),
"flight_time_7d_minutes": 3420, # 57h
"last_rest_end": datetime(2024, 1, 15, 7, 50),
...
},
proposed_pairing={
"departure": datetime(2024, 1, 15, 9, 0),
"arrival": datetime(2024, 1, 15, 11, 30),
"flight_time_minutes": 150,
}
)
result.is_legal # → True
result.violations # → []
result.warnings # → ["Flight in WOCL window"]
result.flight_time_remaining_minutes # → 180Data sources
Free, no API key. METAR observations for all 15 Nimbus airports, fetched every 5 minutes. Used for live weather layer on the map and as predictor features.
https://aviationweather.gov/api/data/metar?ids=KORD,...&format=jsonHistorical training data for the XGBoost cascade predictor. 2023–2025 CSVs. Used only at build time.
transtats.bts.gov40 aircraft, 200 daily flights, 60 crew pairings, 15 airports — fully generated by generate_network.py with seed=42 for reproducibility.
data/network/*.yamlSystem architecture
┌──────────────────────────────────────┐
External data → │ Weather fetch (httpx + asyncio) │
└──────────────┬───────────────────────┘
↓
┌──────────────────────────────────────┐
│ PostgreSQL 16 + TimescaleDB │
│ Redis 7 (cache + task queue) │
└──────────────┬───────────────────────┘
↓
┌──────────────────┐ ┌─────────────────────┐ ┌─────────────────┐
│ CascadePredictor │→ │ RecoveryOptimizer │→ │ CrewLegality │
│ (XGBoost) │ │ (OR-Tools CP-SAT) │ │ Engine (FAR117) │
└──────────────────┘ └──────────┬──────────┘ └─────────────────┘
↓
┌──────────────────────────────────────┐
│ FastAPI (REST + WebSocket) │
│ ECS Fargate · 2 vCPU · 4GB │
└──────────────┬───────────────────────┘
↓
┌──────────────────────────────────────┐
│ Next.js 15 dashboard │
│ SVG map · Recharts · Zustand │
└──────────────────────────────────────┘