PhaseFlow, Open-Pit Production Schedule with a Certified Bound

Published:

An open-pit production schedule, solved with a certified bound and animated year by year over the block model. Live at phaseflow.fasl-work.com, part of the Faena hub.

PhaseFlow: a year-coloured pit with NPV, bound, gap and spatial-coherence readouts

Which blocks, then when

PitForge answers which blocks are worth mining. PhaseFlow answers when, subject to slope precedence in every period and to the mining and processing capacity of each year, maximising discounted NPV. That is the constrained pit limit problem, and it is NP-hard, so nobody solves it to proven optimality at real size. Without a bound, a scheduling tool can report any NPV it likes.

Measured against work that is not mine

The trust anchor is the published MineLib newman1.cpit solved as published, on its own six periods, its own eight percent discount rate and its own two capacities. The ultimate pit optimum reproduces exactly at 26,086,899, the joint LP bound lands at 24,486,184 against a published PCPSP LP bound of 24,486,549. The check that the bound is real is its ordering: a CPIT LP bound must sit below a PCPSP LP bound, because PCPSP is the richer problem, and it does, by 365 units in 24.5 million.

The best schedule, a sliding time window, is worth 24,149,869, 1.37 percent below its own LP bound. The 2018 paper’s 1.26 percent is measured against its PCPSP bound, so the two percentages sit side by side and are not a contest. An external AMPL and Gurobi log later reports a CPIT integer optimum of 24,176,864.82, which PhaseFlow cites and has not reproduced: the schedule is 0.11 percent below it, so most of the 1.37 percent is the LP’s integrality gap and not a loss of the scheduling method. The gap read 2.49 percent until the sliding window turned out to be a one-period greedy whose look-ahead argument changed nothing; fixing it closed the gap.

The learned expected-time surrogate is characterised by when it fails, and that answer changed twice under measurement: a discount-rate rule fell to a recall of 0.625 on a third split and exposed a sweep that moved the rate and the plant capacity together. On a crossed sweep the signal is the orebody. The product now measures instead of predicting: each baked case shows the learned plan’s ratio to the exact plan next to the method selector (the held-out worst case is 0.561), and the live lane says it has no usable guard yet.

Three things that follow from the bound being cheap

The critical multiplier algorithm solves the CPIT LP relaxation exactly in O(mn log n) as parametric maximum closures, with no LP solver, which is why a TypeScript port re-solves the whole problem live in the browser with a parity test asserting it reproduces the Python bound. Two bounds run on every case, a certified-but-loose one and the joint Bienstock-Zuckerberg bound, and the app names which one it used, because the difference between them is the part of a gap that belongs to the bound rather than to the plan; on a single-resource instance the two agree to machine precision. And spatial coherence is a first-class KPI (components per period, largest-component share, narrowest mined run) because the algorithm’s own authors predict block-level schedules scatter.

Scope, stated in the product: no stockpiles, no blending, no minimum-production constraints, no two-stage stochastic integer programming, and not for production mine planning. The engine is the separately published oreblocks package; PhaseFlow declares none of its own. Thirteen baked cases, version 0.07.005. Live · source.