Prescriptive Optimisation: Where the Constraint Set Comes From
We once handed a client a production schedule that solved their stated problem perfectly. They rejected it in the first review — not because the math was wrong, but because the constraint that mattered most had never been written down.
We once handed a client a production-scheduling model that solved their stated problem perfectly — minimized changeover time across six lines, respected every constraint we'd been given, and produced a schedule that was, by every metric we'd been asked to optimize, better than what their planners had been doing by hand. They rejected it in the first review. Not because the math was wrong. Because it scheduled a changeover through their highest-margin product's dedicated line during a week their largest customer had an informal, never-written-down understanding that line would be held in reserve for a rush order that hadn't been placed yet, and wouldn't be, unless something went wrong elsewhere. That constraint existed nowhere in any system we'd been given access to. It lived in a plant manager's head, enforced by a phone call, honored for eleven years. The optimization was correct. The model was wrong, because the constraint set was wrong, and no amount of solver sophistication fixes a constraint set that doesn't reflect the business.
The math is the easy part, and treated as such
Every optimization engagement we run spends less time on the solver than on the thing that determines what the solver is actually allowed to do. Mixed-integer programming, constraint programming, heuristic search — these are mature, well-understood technologies with decades of tooling behind them, and picking the wrong one costs you performance, not correctness. Picking the wrong constraint set costs you correctness outright, and the model will tell you it succeeded while doing it, because a solver has no way to know a constraint is missing. It optimizes over what it's given and reports the optimum with complete confidence, whether or not what it was given describes the actual business.
Where real constraints hide
The constraints that get missed aren't the ones anyone forgets to mention — capacity limits, contractual minimums, regulatory thresholds all show up in the first requirements conversation, because they're written down somewhere. The ones that break a deployed model are the constraints nobody thought to state because everyone internally already assumes them: the plant manager's reserved-capacity understanding; a scheduling preference that exists purely to keep two specific supervisors from ever needing to coordinate, because of a personnel conflict from three reorganizations ago that's never been documented but is still very much load-bearing; a soft constraint against running two specific SKUs back-to-back because of a changeover contamination risk that's managed by tribal knowledge, not a formal cleaning protocol in any system. Eliciting these requires sitting with the people who currently make the decision by hand and asking not "what are your constraints" — which surfaces only the ones they've had to justify to someone else — but "what would you never actually do, even if the schedule told you to," which surfaces the ones enforced by instinct.
Soft constraints need to stay soft
A second, subtler failure: treating every elicited constraint as hard, because hard constraints are easier to encode and validate. Most real operational constraints are actually preferences with a cost attached, not absolutes — you can run those two SKUs back-to-back, it's just expensive, or you can schedule through the reserved line, it just carries risk that's worth quantifying rather than forbidding. Encoding a soft constraint as hard makes the model brittle in exactly the situations where flexibility matters most, like an actual rush order that needs the reserved line after all. We push, hard, to get a cost or penalty function attached to as many constraints as the business can tolerate quantifying, specifically so the solver can trade off between them the way a good human planner already does, instead of treating every rule as inviolable.
Validation means running the model past the people who'd catch it being wrong
The constraint set isn't done when the solver runs without error. It's done when the schedule it produces survives review by the people who'd have caught the eleven-year-old phone-call constraint — not a sign-off meeting, a working session where planners try to find the schedule doing something they'd never actually do, because that's the fastest way to surface a constraint nobody stated. We treat the first two or three optimization runs as elicitation tools in their own right: the model's mistakes are more informative than its successes, because every schedule a planner rejects tells you exactly which unstated rule you're missing. That iterative loop — propose, get told what's wrong, encode the missing constraint, repeat — is slower than writing the objective function. It's also the entire difference between a model that gets deployed and one that gets quietly ignored after the first bad recommendation erodes trust.

