Getting a Mathematical Programming Model to Work in Production

You spend about three weeks building what you think is a solid optimization model, then it chokes on your real data. This is normal. The gap between textbook examples and actual production data is where most projects stall out, and the people who close that gap are the ones who ship. I spent years working with solver backends across supply chain, scheduling, and resource allocation projects, and the pattern never really changes. You build a model. It runs. It returns garbage. You fix the constraints. It crashes. You fix the data pipeline. You get results, but they take four hours to solve. Then you optimize the formulation and it finishes in twelve minutes.

The Practical Process of Model Building In Mathematical Programming

Start by defining the decision variables. Every variable should map to something you can actually act on. Don't create a binary variable for every possible supplier-customer pair across a year if half of those combinations are physically impossible. I've seen models with forty thousand binary variables where eight thousand were the only ones that ever took nonzero values in any optimal solution. That's not a modeling choice, that's negligence. Write the objective function second. It sounds obvious, but I've sat in meetings where the stakeholders agreed on constraints for an hour and nobody had pinned down whether they were minimizing cost, maximizing throughput, or balancing both with a weighted sum. The solver will happily optimize whatever you give it. That doesn't mean it will optimize what you need. Formulate the constraints in groups. Separate hard constraints from soft ones. Hard constraints are things that are literally impossible to violate. If a machine cannot process two products simultaneously, that's a hard constraint. Soft constraints are trade-offs. Demand not fully met, delivery after a preferred date, overtime work. Put soft constraints in the objective with penalty coefficients, not as constraints. Beginners mix these up constantly and wonder why the solver returns infeasible when the problem clearly has a feasible solution with slight violations.

Here's a specific edge case that nearly killed a project of mine last year. We were building a vehicle routing model with time windows and capacity constraints. The model worked fine on synthetic data and small instances. Then we fed it real customer locations with overlapping time windows and irregular service times. The solver would declare infeasibility even though we could visually see feasible routes on the map. The issue was subtle. We had modeled the arrival time as a single continuous variable without accounting for the fact that queuing at a location could push the actual service start beyond the time window upper bound. The time window constraint was written as strict, but the physical reality allowed waiting. The fix was straightforward once identified: we added a waiting time variable between arrival and service start, decoupled the service start time from the arrival time with a separate constraint, and allowed the solver to push service starts past the time window when waiting was necessary, while still penalizing late arrivals in the objective. It took about two days to diagnose and restructure that section.

Get the Full Details

Amazon | Model Building in Mathematical Programming | Williams, H. Paul | Applied
Amazon | Model Building in Mathematical Programming | Williams, H. Paul | Applied

Scaling and Solver Selection

MIP solvers like Gurobi, CPLEX, and SCIP handle integer constraints differently. Gurobi tends to outperform on large mixed-integer problems with good default settings. CPLEX is stronger on pure LP problems and has better presolve routines that can eliminate entire variable groups before solving begins. SCIP is free for academic use and has improved significantly, but it still lags behind the commercial options on problems above fifty thousand variables with dense constraint matrices. The presolve step matters more than most modelers realize. A well-structured model with redundant constraints can sometimes solve faster than a leaner model because the presolve phase can detect and exploit the redundancy. I had a scheduling model where removing what looked like obviously redundant constraints actually doubled the solve time because those constraints were helping the presolve cut the search space. The lesson is that model sparsity is not always better. Sometimes you need structure the solver can work with. For problems larger than roughly one hundred thousand variables, you need to think about decomposition before you think about solver selection. Benders decomposition splits the problem into a master problem and subproblems. Dantzig-Wolfe decomposition works the other direction, breaking column generation into manageable pieces. Neither approach is straightforward to implement. I've spent weeks getting a Benders cut to converge properly on a facility location problem, only to find that a simpler reformulation with aggregate constraints solved in under an hour on the same hardware. Decomposition is not a magic bullet. It adds complexity that sometimes isn't worth the speedup.

Common Pitfalls That Waste Weeks

Big M constraints are the most common source of numerical instability. When you model a conditional constraint using a large constant, the solver's branch-and-bound tree becomes numerically unstable because the solver has trouble distinguishing between variables that are effectively zero and variables that are genuinely small. I've seen M values set to one million on problems where the natural scale of the data was in the tens. The fix is to tighten the M value to the smallest number that still makes the constraint valid. In practice, that often means analyzing the data range rather than picking a round number. Another pitfall is asymmetry in the model. If one constraint uses seconds and another uses hours, the solver sees a coefficient matrix with entries spanning several orders of magnitude. Scale everything to the same unit before feeding it to the solver. I once spent an afternoon debugging a model that kept returning suboptimal solutions, only to discover the time constraints were in minutes while the cost coefficients were per hour. The solver was optimizing a distorted objective function because of the scaling mismatch. Model Building In Mathematical Programming also suffers from a particular kind of overconfidence among people coming from spreadsheet-based planning. Spreadsheets let you change one cell and see the result instantly. Solvers don't work that way. Adding a new constraint can make a solvable problem infeasible without any visible warning until you run the solver. Running a quick feasibility check before adding expensive constraints is a habit that saves a lot of rework.

Data Quality and Sensitivity

Your model is only as reliable as your input data. Parameter uncertainty is a real problem that most beginners ignore until their optimized schedule falls apart when actual demand deviates by five percent. Robust optimization adds uncertainty sets to your parameters, but it makes the problem harder to solve. Simple stochastic programming with scenario trees is easier to implement and often good enough if you have historical data. I've used a three-scenario approach for demand uncertainty on a production planning problem and got results that held up reasonably well across six months of actual operation. Sensitivity analysis is not a luxury. Run it after you get a solution. Change one coefficient at a time and observe how the objective value shifts. If a ten percent change in a cost parameter flips the optimal solution entirely, your model is unstable and your implementation team will lose trust in it quickly. You need to know which parameters the solution is sensitive to so you can focus your data collection efforts on those items first.

Model Building in Mathematical Programming (5th ed.)
Model Building in Mathematical Programming (5th ed.)

Implementation Reality

Writing the model in a modeling language like AMPL, GAMS, or Python with PuLP or Pyomo is standard. But the transition from prototype to production is where things get messy. Your model needs to read from a database, handle missing data gracefully, log solver output, and produce results in a format the operations team can use. I've seen models that took four hours to solve become acceptable because the operations team learned to run them overnight and used the results the next morning. The technical solution was simpler than most people expect. Automate the data pipeline, run the solver on a schedule, and build a simple dashboard for results. The tools are accessible. Gurobi has a free academic license and a ten-variable free tier for commercial use that covers small problems. CPLEX offers a community edition with similar restrictions. Pyomo is open source and integrates well with open-source solvers like CBC and HiGHS. If you're starting a project today, I'd recommend Pyomo with Gurobi if you have access, or Pyomo with HiGHS if you need something free and competent for medium-scale LP and MIP problems. There are cases where mathematical programming simply will not help you. When the problem involves human behavior that cannot be quantified, when the data changes faster than you can rebuild the model, or when the constraints are so loose that every feasible solution is approximately optimal, the effort required to build and maintain the model exceeds the value it provides. In those cases, a heuristic or simulation approach is more practical. Recognizing those situations early prevents months of wasted development.