A Monte Carlo simulation of crusher queues at Rio Tinto's Boron mine, built as an intern. The project where I learned to code.
In the summer of 2010 I was a college intern at Rio Tinto's Boron operation, doing field survey work with the Drill and Blast crew in 110-degree Mojave heat. The engineers there were chewing on a question about the crusher: when a loaded haul truck arrives and finds a line, how long should it wait before giving up? They had heard I knew a little about numbers and data, so they assigned it to me as my summer project.
The fundamental cycle at a mine is simple: haul trucks get loaded with material and dump it somewhere, and the most important somewhere is the crusher, where rock gets broken down for processing. The crusher is a bottleneck, which means trucks sometimes queue for access. Waiting costs operator time and slows production. On the other hand, you can dump the material close by, but then it has to be rehandled to get it into the crusher, in this case with a front-end loader. The problem is that front-end loaders are costly to run. Rehandling means paying twice to move the same rock. Somewhere between never waiting and always waiting there's an optimum, and the mine wanted to know what number that was.
In my second year of college, back when I was still on a pre-business track, I'd taken a business mathematics class. The culminating project used Bayesian statistics to find the optimum queueing configuration for a bank: serpentine, linear, and so on. As part of it, they handed us a spreadsheet that ran Monte Carlo simulations of arrival and wait times. As soon as I heard about the crusher project I thought: huh, that's a pretty similar problem. The crusher was the teller and the trucks were the customers. I knew the shape of the answer the day I heard the question. What I didn't know was how to write a program. The class had shown me a machine that could answer this kind of question, but never how it worked. We could see the sheet's outputs; the code was all password protected. I was too young and naive to ask for an unlocked version, so I decided to teach myself to code and reinvent the whole thing. Which is what I spent the rest of the summer doing.
There's a cheap version of this analysis: take the average cycle time, the average crusher rate, the average gap between arrivals, and balance them in a spreadsheet. The trouble is that queues are made of variance. If trucks arrived on a perfectly even beat, a line would never form; the line exists because arrivals bunch up and processing stutters. On an average day there's barely a queue at all. The money burns on the bad days, when everything bunches at once, and averaging the inputs deletes the exact phenomenon you're studying. A real answer had to keep the randomness, which meant simulating the operation over and over, which meant code. That's what makes this problem such a good candidate for Monte Carlo simulation, where you sample inputs from random distributions to represent the real phenomenon: sometimes things are average, sometimes they're ideal, sometimes the shit hits the fan.
So I taught myself VBA on the job, in Excel, because Excel was the development environment I had and it's where I'd seen this solved before. A simulation is only as honest as its inputs, so I taught myself SQL too, and worked with operations and engineering staff to run queries against the mine's dispatch data. I cut each haul cycle into segments, fit a distribution to the real durations of each one, and had the simulation draw from those instead of textbook numbers, so my virtual mine misbehaved the way the real one did. Then I swept the decision rule: run the operation at each waiting threshold and watch where the combined cost of idling and rehandling bottomed out.
The sim answered the question as asked, and the answer was simple: always wait. The cost of rehandling was just too great, which the engineers I was working with found unsatisfying. My standing verdict to this day is that the threshold is a trap. Rehandle costs amortize across every load you bail on and quietly eat the savings; bailing never truly wins. The real fix is not a smarter rule for standing in line. It's keeping trucks out of the line in the first place, which is a dispatching problem. And it still bugs me that nearly every dispatching product on the market optimizes truck and shovel utilization, keeping expensive machines busy, when the thing worth optimizing is NPV, the value actually moving through the system. That crusher queue was my first look at the gap, and the industry still hasn't closed it.
Was the build sophisticated? No. I treated every random draw as independent, when the segments of a real haul cycle lean on each other; a slow pass at the shovel ripples into everything downstream. It was a first-time programmer's build, and I'm still damn proud of it. The impulse was right: see the pattern, keep the variance, let the machine misbehave like reality.
The code traveled further than I expected. The next year, Rio Tinto's Technology & Innovation group heard about the Boron simulation and pulled me onto a harder version of the same problem: simulating haulage for Oyu Tolgoi, a mine that didn't physically exist yet. But the summer's real output wasn't the spreadsheet. It was the playbook that has run my whole programming career: I know something is possible, and I figure out how to make it happen. The class showed me a locked box that could answer questions like this one. Boron handed me the question. I've been building boxes that answer questions ever since.
Say hi.
Got a problem that looks like this one? I want it.
Got one so new nobody's even scoped it? I want that one more.