Driving a Linear Programming Solver
What you will be able to do
Given a formulated linear program and a named solver, the learner can convert it into that tool's expected argument form, state what each array position means, invoke it, and translate the reported status, point and objective value back into the terms of the original model.
Orientation
A correctly formulated program and a correctly operated solver can still produce the wrong answer, because the two have to agree about conventions neither one states.
A solver that minimises will accept a maximisation's coefficients without complaint and return the worst available plan, reporting success. A constraint entered in the wrong array describes a restriction the situation does not have. Neither is a modelling mistake or an arithmetic mistake; both are failures of translation at the boundary between a model and an interface.
This is applied practice rather than theory. Nothing else in the subject depends on it, and the specific menus and argument orders will change. What survives is the habit of asking what convention a tool imposes, and of reversing every conversion made on the way in.
Procedure
In, run, out
Before touching the tool. Write the model on paper: variables with units, objective with a direction, every constraint with its direction and right-hand side. Everything below is translation, and translating an unfinished model produces a confident answer to an unasked question.
Step 1: read the tool's convention. Three questions, answered from the vendor's documentation rather than from memory:
- Which direction does it optimise, and can that be changed?
- How are constraint directions expressed, separate arrays for inequalities and equalities, a comparison operator per row, or a required rewriting?
- Are variables nonnegative by default, or must bounds be stated?
Step 2: convert. Apply exactly the conversions the answers demand. Negating the objective to match a minimising tool, moving equalities into their own array, stating
Step 3: fix the correspondence. Decide which column index is which decision variable and which row is which constraint, and write it down. Every array must use the same order. This mapping exists nowhere in the tool.
Step 4: enter and run. Supply the arrays. Check the shapes agree before running: the objective vector's length is the number of variables, each constraint row has that same length, and the right-hand side has one entry per row.
Step 5: read the status first. Before looking at any number, read what the solver claims: an optimum found, infeasible, unbounded, or a limit reached. A point reported alongside a non-optimal status is not an answer, and on a limit status it is the best found so far rather than the best there is.
Step 6: reverse the conversions. Map the returned components back to named decisions. If the objective was negated, negate the reported value. If a variable was split or shifted, reassemble it.
Step 7: verify against the original model. Substitute into the constraints as first written, recompute the objective, and judge whether the status is credible. These checks belong to verification and are applied here to the original model, never to the solver's restatement of it. A transcription error is invisible to any check performed on the transcription.
Worked example
One program, entered into a minimising solver
The model. A workshop makes two products. Each unit of A takes 2 machine-hours and 1 labour-hour and contributes £30; each unit of B takes 1 and 1 and contributes £20. There are 100 machine-hours and 80 labour-hours, and at most 40 units of A can be sold.
Step 1: the convention. The tool minimises, takes inequalities as
Step 2: convert. The objective is a maximisation, so negate it:
The conversion to record: objective negated; the reported value must be negated back. All three constraints are already
Step 3: the correspondence. Column 1 is
Step 4: the arrays.
Shapes agree:
Step 5: the status. The solver reports an optimum found. Proceeding.
Step 6: the reported answer, and reversing. The solver returns
Reversing the one recorded conversion: the objective was negated, so the contribution is
Reporting
Step 7: verify against the original model.
- Machine-hours:
(binding) - Labour-hours:
(binding) - Sales limit:
(slack of 20) - Nonnegativity: both positive
- Objective:
, matching the reversed value
What the check found beyond agreement. Both resource constraints bind and the sales limit does not. So the plan is limited by capacity, not by demand, and the question worth asking next is what an extra machine-hour or labour-hour would be worth. A sensitivity question the solver can answer, and one that would be misdirected if the binding pattern had been misread.
What is not established. That 100 and 80 are this week's real capacities, that contributions are genuinely linear in volume, or that A and B are the only products competing for these hours. The solver was never in a position to check any of them.
Notation
What two common interfaces expect
Details below follow each vendor's own documentation and will drift; the conventions are the point, not the keystrokes.
MATLAB linprog. The routine solves a minimisation, with the problem expressed as a coefficient vector and separate arrays for inequality constraints, equality constraints and bounds:
The consequences for a modeller are three. A maximisation is entered as
Excel Solver. The model lives in cells rather than arrays. Decision variables are a range of changing cells, the objective is a formula cell referring to them, and each constraint is a row in a dialog naming a cell, a relation and a bound. The direction is chosen explicitly as Max, Min or a target value, so no negation is needed.
Two conventions matter more here than the arithmetic. The solving method must be set to the linear option for a linear program. The default is a nonlinear method that may stop at a point it cannot certify as optimal. And nonnegativity is a checkbox, not an assumption, so leaving it clear permits negative values in the changing cells.
Because the model is formulas over cells, a mis-typed cell reference produces a different program that still computes. This is the analogue of a positional error in an array interface, and it is harder to see: the spreadsheet displays values rather than the relationships between them.
What the two share. Each fixes a direction convention, a place for each kind of constraint, and a default about sign restrictions, and in each, the correspondence between positions and decisions exists only in the modeller's notes.
Warning
What a clean status does not certify
A status of optimal is a claim about one thing: the solver found the best point of the program it received. Four things it is regularly taken to mean, and does not.
That the program is the model you wrote. A transcribed coefficient, a constraint entered in the wrong array, a missing row. Each yields a valid program with a genuine optimum. The status reports on the transcription, and no check performed inside the tool can compare it against your intent.
That the data is right. A capacity of 1,000 entered as 10,000 optimises perfectly against a factory that does not exist. Dimensional errors survive too: a rate per hour against a budget per week is arithmetic the solver will do without objecting.
That the model represents the situation. Linearity, certainty of the data, and divisibility of the variables are modelling assumptions. A plan of 20.4 lorries is optimal for the program and unimplementable.
That the answer is unique. Many linear programs have a face of optima. The solver returns one of them, and a second run with different settings may return another with the same objective value. Treating the reported point as the answer, rather than an optimal answer, misleads anyone who has to act on which routes or products were chosen.
The one exception worth naming. A status of infeasible is more informative than it looks, because it is often a claim about the transcription rather than about the situation. Before concluding that a business problem has no solution, check the entry: a reversed inequality or a constraint in the wrong array makes a perfectly feasible situation unsatisfiable.
Numerical tolerance. A reported point may satisfy constraints only to within a tolerance. A value of
Contrast
Solving by hand against solving with a tool
| By hand | With a solver | |
|---|---|---|
| Scale | a few variables and constraints | thousands, routinely |
| Where errors arise | arithmetic within a known method | translation at the model–interface boundary |
| How errors show | a pivot that will not complete, a negative right-hand side | a clean status on the wrong program |
| What is visible | every intermediate quantity | the final answer, and whatever the tool chooses to report |
| What must be checked | the arithmetic | that the program entered is the model written |
The error profile inverts. Hand computation fails noisily: a wrong ratio test produces an infeasible point that the next step exposes. Tool use fails silently, because the tool has no view of what you meant and every syntactically valid program has an answer.
Why hand methods are still learned. Not as a substitute, nobody pivots a thousand-variable program by hand, but because the reported output is written in their vocabulary. A shadow price is a dual variable; a degenerate warning is a basic variable at zero; a variable at its bound is nonbasic. Without the methods, those outputs are strings rather than information.
What the tool adds that hand methods cannot. Sensitivity analysis on a realistic model, re-solving under changed data in seconds, and scale. The workshop example's binding pattern, capacity limiting, demand not, invites asking what an extra machine-hour is worth, and that question is answerable in one further run.
Where the competences meet. Verification is the same work in both cases: substitute into the constraints as written, recompute the objective, judge the status. The difference is that a hand solution's arithmetic is also open to inspection, whereas a solver's is not, which makes verification against the original model more important with a tool, not less.