Method
How it decides
Written for a railway officer rather than a mathematician. The formulation itself is code, in engine/solver/; this is what it means.
01
Both sides of the trade-off, in one unit
A block spends line capacity and buys risk reduction. To compare them you need one currency, and ours is detention-minute equivalents.
A defect’s price is the train detention it will cause if left alone: its daily failure hazard multiplied by the consequence of that failure, spread across the horizon.
ρ = ⌈ C × λ ÷ slots-per-day ⌉
λ comes from the survival model. C does not. The consequence table is a published policy input agreed with the division from incident records — it is where railway judgment enters the system, and burying it in model weights would make the system’s priorities unauditable.
The effect is that a degraded overdue rail prices at roughly 109× a fresh signal lamp. That ratio is derived, not hand-set, and it is directly comparable to detention. We do not rank tasks. We price them.
02
What the optimiser decides
One constraint-programming model decides, jointly for all three departments: which candidate windows to grant, how long each block runs, which tasks go inside it and where, and what to defer.
minimise αR·Σ ρt·τt + αR·Σ ρt·(T+Δ)(1−zt) + αD·Σ tblw[δw] + αF·K·Σ Gw − αC·B·Σ ew
The last term is the entire point of the system. ew counts the extra departments sharing block w — and it is the only quantity in the objective that no single department can see or express when it bids for its own block through BDMS.
The fourth term is why four one-hour blocks are worse than one four-hour block even at equal detention: protection, caution order and the first train back over the site cost the same whatever the block’s length.
03
The constraints that carry the domain
Eleven of them, each with a test that fails without it. They are named the way a division says them; the model’s own identifier is kept in brackets. These are descriptions of what the constraints do, not citations of the General and Subsidiary Rules — we have not checked them against that book, so we do not label them as if we had.
- Sanctioned window length C1
A granted block runs at least the minimum the corridor policy allows and no longer than its window; an ungranted one has zero length. - One sanction per work item C2
Each task is placed in exactly one block, or it is deferred and priced as deferred. Nothing is half-scheduled. - Statutory obligation C3
Criticality-A work is a hard constraint, solved first. A feasible plan is therefore a proof that every obligation is met, not a claim that the penalty was set high enough. - Due-date compliance C4
Statutory and scheduled work finishes on or before the date it is due. - No sanction without work C5
A block is granted only if a task uses it. The line is never closed for nothing. - Protection and clearance C6
Work starts only after protection is complete and ends before clearance begins. A block does not start when the gang starts. - Line occupation and power-block coupling C7
No two blocks hold the same road at once, and a section-scope window enters both roads at once - OHE work takes the section down and pays detention on both. - Machine and gang availability C8
One tower wagon, one tamper, two USFD units, gangs and crews, shared across the division. The single tower wagon is the classic binding constraint, and the model finds it without being told. - Blocks per section per day C9
A cap on how often one section is taken in a day - controller workload and caution-order churn, not track capacity. - Night-working limit C10
A cap on night blocks per section per week, because night working is rationed by gang welfare rules and not only by traffic. - Technological sequence C11
Work that must follow other work does: the USFD test precedes the rail renewal it justifies.
04
When the backlog exceeds the corridor
The statutory constraint runs hard first. If the backlog genuinely exceeds what the corridor can hold, the model is infeasible — and the system re-solves with the obligation softened, returning a plan plus an explicit shortfall list: which item, its priced risk, and which constraint bound.
An optimiser that answers “INFEASIBLE” is useless in an operating railway. That list is the artefact a DRM needs to argue for more block time with evidence rather than assertion.
05
Why constraint programming
Interval variables, no-overlap and cumulative resources are native, so disjunctive scheduling is handled by a dedicated propagator rather than by penalty terms in a fitness function.
More importantly it returns a proven bound. We can say that no plan of this work costs less than a stated figure. A genetic algorithm gives neither the propagators nor the bound, and on a problem this structured it is strictly worse.
06
Why each block is where it is
Click any block on the planner and it answers two questions, by exact accounting over the solved plan rather than by a second model. What did sharing save? The same jobs, each priced in the cheapest window it could have used on its own, against what they cost together. The alternative is given its best case, so a reported saving is a floor. What did this slot cost? The block against the cheapest window of the same length on its section.
The second answer is often not flattering, and it is shown anyway: most shared blocks sit in a dearer slot than the cheapest one available. The cheapest slot takes no account of due dates or of the one tower wagon, and the optimiser chose to pay the difference, so the reason is one of those.
07
A month, then a week
A month is planned a level up: which week each job goes in, and how much corridor each section needs that week. It cannot see roads or minutes, so it is held to the packing the weekly solver actually achieves on a full week, and every rule it keeps is a coarse form of a weekly one.
Then it is checked. Week 1’s allocation goes to the weekly solver unchanged; what does not fit to the minute rolls forward, and the rest of the month is re-planned with it. The fit rate is shown, not tuned away.
08
When the week does not go to plan
A defect found mid-week is not priced like the backlog. It is required: either it is dealt with by its deadline or the replan says it cannot be, in so many words. Blocks already worked are frozen exactly as they ran.
Then three questions, answered strictly in order, each one holding the answer to the one before: keep as many statutory jobs as can be kept; change as few approved jobs as possible; be as cheap as possible. Each is a separate solve, so the first two answers can be proven rather than traded against cost with a weight somebody chose, and on the scenario shipped here both are. A weighted version was tried first and kept none of the approved blocks: its search never got near the approved week. Every stage now starts from the approved plan.
Finally it re-solves with one more of each resource the defect needs, and reports which of them would have avoided the loss. That is the sentence a DRM can act on.
09
Checked before it can be approved
A solver can be wrong in a way its own output cannot show: a rule posted slightly wrongly is simply not a rule. So the plan is checked again, afterwards, by code that never saw the model — 12 checks, one per hard rule, run on the published plan itself.
A plan that fails any of them is never written, and the approval panel holds Submit and Approve unless a passing set belongs to the plan on screen. A check with nothing to examine says so, rather than wearing a pass it did not earn.
The panel is a courtesy; the database is the control. Submission and approval each re-run 9 of those rules in SQL, over the rows the database holds, and require the engine’s passing record of this exact plan for the rest. A plan that fails is refused whatever the page shows — and sending it back is never held.
10
Worked, not just approved
An approved programme is a promise about the week. Whether it was workable is only known afterwards, so the operating branch records each block as it happens: granted when, returned to traffic when, or not availed and why.
Each is set against its plan — late granted, late returned, block time used — from what was recorded and nothing else. A correction replaces the figure on screen and keeps the old one in the audit log.
What this method does not establish is set out on the limits page — data provenance, model validity bounds, the optimality gap, and what is designed but not built.