Pit Optimisation
Which blocks should be mined to maximise profit? Learn block economic values, slope precedence, the Lerchs–Grossmann algorithm and pseudoflow, revenue-factor nested pits, pit-by-pit graphs, and how optimised shells become practical pushbacks — with a Python dynamic-programming pit optimiser.
A block model may contain millions of blocks, each ore or waste. Removing an ore block requires removing all blocks above it within the slope cone. Pit optimisation finds the set of blocks with maximum total value that respects these slope constraints — the ultimate pit.
The Lerchs–Grossmann algorithm (1965) solves this exactly; modern software (Whittle, Deswik, MineSight) uses LG or faster pseudoflow methods.
An analogy
Pit optimisation is like deciding how deep to dig into a cake to reach cherries: each cherry costs you all the cake above it, so only cherries worth more than their 'cake cone' are worth taking.
Block economic values
Each block gets a dollar value: revenue from recovered metal minus mining and processing cost if it is ore, or minus mining cost if waste. The optimiser only needs these values and slope precedence rules.
Nested pits and pit-by-pit analysis
Running the optimiser at a range of revenue factors (e.g. 30–130 % of base price) generates nested shells from the highest-value core outward. The pit-by-pit graph shows cumulative ore, waste and discounted value per shell — used to select the ultimate pit and pushbacks.
From shell to design
Optimised shells have jagged block outlines; engineers design practical pits with ramps, minimum mining widths and berms. Design usually loses a few percent of shell value.
Beyond LG
LG maximises undiscounted value; NPV depends on sequence. Direct block scheduling (MILP), stochastic optimisation under grade uncertainty, and simultaneous optimisation of pit, stockpiles and cut-off (e.g. SimSched, Whittle SIP) improve NPV.
Formulas
- Ore block value:
BEV = T_b × g × R × P − T_b × (C_m + C_p) - Waste block value:
BEV = −T_b × C_m - Objective:
max Σ BEV_i x_i s.t. x_i ≤ x_j for all j above i in slope cone - Nested pits:
Run with price × RF, RF = 0.3 … 1.3
Worked example: Ore block value
Given: Block 10 000 t @ 0.8 % Cu, recovery 88 %; Net price $8.5/kg; Mining $2.5/t, processing $12/t
Find: BEV.
- Recovered Cu = 10 000 × 0.008 × 0.88 = 70.4 t
- Revenue = 70 400 × 8.5 = $598 400
- Cost = 10 000 × 14.5 = $145 000 → BEV = $453 400
Answer: +$453k (a waste block of same size = −$25k)
Worked example: 2D pit
Given: Block values in the code sample
Find: Optimal pit.
- Mine to bench 3 (row 2): cone cost row 0 = −20k, row 1 = +22k, row 2 = +22k
- Mining the bottom block adds +12k but needs 6 more waste blocks (−24k) → net −12k
Answer: Optimal value $24k — the deepest ore block is left
2D Lerchs–Grossmann (dynamic programming)
import numpy as np
# Block economic values ($k): rows = benches (0 = top), cols = x
V = np.array([
[-4, -4, -4, -4, -4, -4, -4],
[-4, -4, 6, 10, 6, -4, -4],
[-4, -4, -4, 22, -4, -4, -4],
[-4, -4, -4, 12, -4, -4, -4],
], dtype=float)
def optimal_pit_2d(V):
"""Lerchs-Grossmann 2D dynamic programme, 45-degree slopes."""
nz, nx = V.shape
# add an 'air' row on top (value 0) and cumulative column values
M = np.vstack([np.zeros(nx), np.cumsum(V, axis=0)])
P = np.full((nz + 1, nx + 1), -np.inf)
P[0, 0] = 0.0 # start outside the pit, at surface
for x in range(1, nx + 1):
for z in range(nz + 1):
best_prev = max(P[zz, x - 1] for zz in (z - 1, z, z + 1) if 0 <= zz <= nz)
P[z, x] = M[z, x - 1] + best_prev
return max(P[0, nx], P[1, nx]), P # pit exits at the surface edge
value, P = optimal_pit_2d(V)
print(f"Optimal pit value: ${value:.0f}k") # -> $24k (mine down to bench 3)Each column's pit bottom can change by at most one bench from its neighbour (45° slopes with square blocks). M holds the cumulative value of mining a column to depth z; P accumulates the best pit ending at each column. The deepest block (value 12) is left because its cone of waste (row 0–2 extensions) costs more than it earns.
Common mistakes
- Wrong: Choosing the maximum undiscounted-value shell. — Right: Consider discounting and risk — smaller shells are often better for NPV.
- Wrong: Using overall slopes without ramps in the optimiser. — Right: Use slopes that account for ramp allowances.
Applications
- Ultimate pit limits: Defines reserves and waste dump capacity.
- Pushback design: Nested shells guide mining phases.
- Price scenarios: Revenue factors test robustness to price.
Key takeaways
- BEV = revenue − costs per block.
- LG finds the max-value pit under slope precedence.
- Nested shells via revenue factors.
- Design turns shells into practical pits.
Going further
- Pseudoflow: Hochbaum's algorithm — much faster than LG on large models.
- Direct block scheduling: MILP optimises what and when to mine.
- Stochastic optimisation: Multiple simulated orebodies manage grade risk.