Dispatch Optimizer
A constraint-based field-service dispatch optimizer for Atlas Field Services, a synthetic commercial-facilities maintenance company. It uses a synthetic backlog, technician capacity, skill matching, SLA rules, travel penalties, and scenario controls to recommend operationally feasible job assignments, then benchmarks an OR-Tools CP-SAT optimized plan against a naive manual dispatch baseline to show measurable operational impact. This is the project in the portfolio that does not just report on a business: it makes a decision.





Problem
On a typical day a field-service dispatcher faces more work than the crews can finish: twelve technicians, more than a hundred jobs, six skills, hard SLA deadlines, travel between sites, fixed shifts, limited overtime, and some jobs blocked on parts. The common-sense approach, highest priority first to the nearest qualified technician, makes locally reasonable choices that are globally poor: it strands specialists, books avoidable travel, and breaches SLAs that better sequencing would have saved.
The question is not what happened. It is what should we do next, given limited people, time, travel, skills, and SLA risk. That is an optimization problem, not a reporting problem, and it is the gap this project fills: operational decision-making under constraints rather than another dashboard.
Users or audience
The primary audience is hiring managers and technical interviewers evaluating practical operations-research and decision-support engineering: model formulation, the honesty of the comparison, live solve performance, and how constraints and trade-offs are surfaced to a non-technical operator.
The interactive demo is built for portfolio demonstration on a fully synthetic, seeded dataset. No proprietary or employer data is used. It is not a production dispatch system for a real field-service operation.
Solution
Technician dispatch is modelled as a vehicle-routing problem with time windows plus assignment and solved with Google OR-Tools CP-SAT. Per technician, a routing circuit is built over home plus candidate jobs using AddCircuit, with self-loop arcs making each job optional and arc literals carrying travel time. Start times respect travel and service sequencing, skills and certifications restrict which assignments can exist, parts-blocked jobs are never candidates, and the objective maximizes priority-weighted completion minus travel, SLA-breach, and overtime penalties. SLAs are soft by default and become hard for top-priority jobs under strict mode.
The comparison is the point. A deliberately naive manual baseline obeys the same feasibility rules, so the delta is planning quality, not different assumptions. Two techniques keep an eight-second live solve reliable: per-technician candidate capping keeps routing circuits small, and the baseline is warm-started into CP-SAT as a complete feasible incumbent, so the optimized plan never loses to the baseline even when optimality cannot be proven in the time budget. The solver also reports its optimality gap so the user knows how close the incumbent is to the proven bound.
Architecture
Results
On the canonical day (seed 42, default settings), the optimized plan beats the manual baseline on every operational axis at once: more jobs completed and fewer SLA breaches and less overtime, with the same crew. The exact figures move with the solver time budget, but the direction is stable.
Tools used
Key features
- A real optimizer, not a heuristic dressed up as one: a VRPTW plus assignment model in OR-Tools CP-SAT with a bounded live solve.
- An honest baseline foil that obeys the same feasibility rules, so the measured delta is planning quality rather than different assumptions.
- Warm start plus per-technician candidate capping, which keeps the live solve tractable and guarantees the optimized plan never loses to the baseline.
- Optimality-gap reporting so the operator knows how close the returned incumbent is to CP-SAT's proven bound.
- Decision support, not just assignment: bottleneck-skill detection, the overtime-versus-SLA trade-off, and explicit reason-coded deferrals on every unassigned job.
- Marginal Value of Capacity: a crew-size sweep through the optimizer that charts the hire-versus-overtime decision frontier.
- Scenario Simulator: pull technicians, raise the traffic penalty, create a skill shortage, tighten SLA strictness, or spike emergencies, and re-solve live.
- A pluggable travel provider behind one seam: offline haversine by default, with real road durations from OpenRouteService or OSRM, set server-side or per visitor with no key stored.
- Full stack with a clean seam: a pure-Python, database-free optimizer core, SQLAlchemy persistence, portable analytical SQL views, and a seven-page dashboard.
Tradeoffs and constraints
A live, anytime solver on an eight-second budget cannot always prove optimality on the full instance. Candidate capping and the baseline warm start are the deliberate response: they shrink the search and guarantee a usable plan at least as good as the manual baseline on every solve, at the cost of occasionally leaving a small, reported optimality gap. The throughput floor keeps the optimizer from ever finishing fewer jobs than the baseline while it trims breaches, travel, and overtime above that floor.
The default travel model is offline haversine so the public demo is free, reproducible, and quota-free. Real road durations drop in through OpenRouteService or OSRM with no model change, because travel is resolved behind a single seam and the CP-SAT model already uses directional arcs that handle asymmetric road times.
Methodology
Appropriate use: portfolio demonstration of constraint-based optimization and decision support on a fully synthetic, seeded dataset.
Inappropriate use: as a production dispatch system, or as ground truth for staffing, routing, or service-level decisions in a real operation. The data is synthetic and the day is a single canonical instance.
Limitations
The optimizer plans a single canonical day from a seeded synthetic generator. It is deterministic and reproducible by design, not a forecast of real demand. SLA deadlines, durations, skills, and parts availability are modelled, but real-world frictions such as no-shows, re-work, mid-day reprioritisation, and stochastic travel are not.
The live solve is intentionally time-boxed, so on the hardest scenarios the returned plan can carry a small optimality gap rather than a proven optimum. The objective weights are sensible defaults exposed through the UI sliders; a real deployment would tune them against that operation's actual cost of a breach, an overtime hour, and a mile.
What I would improve next
Real road-network travel as the default rather than an option, with a cached matrix so quotas stay sane. Stochastic and rolling re-optimization so the plan absorbs no-shows and new emergencies through the day instead of solving one static instance. A learned or operator-tuned weighting fit to a specific operation's real costs. Multi-day and overtime-budget planning across a week. And a promotion gate that refuses to ship a model or parameter change unless it holds the optimized-never-loses guarantee across a battery of seeded scenarios.