schedlab
A public demo of a constraint scheduler, on generated data.
It generates a week of work, lets you break it, and then either repairs the schedule or tells you that no valid one exists.
Try the live demo Hosted. All data is generated.
What it does
Load a generated week of work. Break it with three controls. Watch a CP-SAT solver fix it or refuse.
Every block on the board is clickable. Clicking one shows the constraints that actually bound that assignment, rather than a summary of the model in general.
When there is no valid schedule, the demo says so. It names what binds, proposes candidate relaxations, and re-solves each one to check it, flagging any it could not verify. It never returns a plausible-looking schedule that violates a hard constraint.
- OR-Tools CP-SAT
- 3-second limit
- 4 workers
- Fixed-seed generation
What it looks like
Synthetic data, and where this came from
Everything in the demo is procedurally generated from a fixed seed. The same seed produces the same problem on any machine. There is no client, no real site, no real person, no real rate, and no figure taken from any real operation.
This is an independent implementation, written clean-room, informed by a production scheduling system built for a marine service company in South Florida. No code, no data, and no measurement from that system is present here.
Measured results
50 seeds per preset, 3-second limit, 4 workers. Medians.
| invalid | overdue | travel | balance spread | |
|---|---|---|---|---|
| Greedy dispatch heuristic | 65 | 1 | 40.2 h | 863 min |
| Greedy, constraint-aware | 0 (p90 2) | 5 | 50.5 h | 808 min |
| CP-SAT optimizer | 0 | 2 | 49.2 h | 644 min |
| invalid | overdue | travel | balance spread | |
|---|---|---|---|---|
| Greedy dispatch heuristic | 54 | 1 | 16.9 h | 790 min |
| Greedy, constraint-aware | 0 | 1 | 13.1 h | 1358 min |
| CP-SAT optimizer | 0 | 1 | 16.3 h | 222 min |
| marine | lab | |
|---|---|---|
| the weighted objective both are scored on | better on 30/30, median +23.7%, worst +8.5% | better on 50/50, median +37.3%, worst +12.6% |
| overdue tasks | better on 43/50 | tied on 50/50 |
| balance spread | better on 42/50 | better on 50/50 |
| travel hours | better on 23/50 | better on 1/50 |
The last row is the one worth reading twice. The constraint-aware baseline beats the optimizer on travel hours, because it minimizes travel and nothing else while the optimizer also prices balance. Reporting the objective win without this line overstates the result.
What this demo does not claim
- CP-SAT does not reach proven optimality in 3 seconds. The median optimality gap is 0.39 on marine and 0.34 on lab. It returns good feasible schedules under a hard deadline, which is what the demo claims and all it claims.
- The naive baseline is constraint-blind by construction, so its invalid-assignment count is partly a tautology. That is why the third column exists.
- The zero invalid count is itself partly tautological: tier, capability, availability, parts and pins are enforced by variable omission, so the model cannot express those violations. Capacity is the exception and the real test.
- Skill tiers are ground truth here only because the generator wrote them. In real work-order data they usually are not. Nothing in the demo should be read as evidence that tiers can be inferred from data.
- CP-SAT with more than one worker is not bitwise reproducible. Scenario generation is.
How it is built
Python, FastAPI, Google OR-Tools CP-SAT, and a hand-written vanilla HTML/CSS/JS front end with no framework and no build step.