then
model Bcapacity linked: $\sum_i s_i x_{ib} \le C\,y_b$ the linked assignment model: LP bound 2.4 on the example; 8/10 solved in then
configuration B′model B with SCIP's symmetry handling off 8/10 solved in then, SGM 4.00 s
configuration CB + symmetry breaking: $y_b \ge y_{b+1}$, item $i$ only in bins $0..i$ 9/10 solved in then, SGM 3.80 s
configuration DC with only as many bins as FFD uses, and bins $0..L_2-1$ fixed open the bounded model: 10/10 solved in then, SGM 3.43 s
configuration ED + FFD's packing given as a MIP start 9/10 solved in then, SGM 3.02 s
model F: arc flowone path per bin from 0 to $C$; item arcs are contents, loss arcs empty space LP bound 2.5 on the example; 10/10 solved in then, median 1 node. Its graph for the example, optimal flow thick:
Part VI · making it real · spine
What presolve does and what defeats it, symmetry, big-M against indicators, starts, reading the log, and the discovery that most single-run speed-ups are noise.
needs 26, 08~1½ h slides + 2½ h lablab: uv run co lab 27
27 · overview
Presolve, bound and coefficient tightening; the habits that defeat them; indicators.
Why interchangeable objects cost exponentially, and three ways to stop paying.
MIP starts, solution pools, bounds from heuristics, and changing the model entirely.
Reading a statistics report; seeds; MIPLIB 2017 as shared reality.
Words with a dotted underline are glossary terms: click one for its definition. G lists every term in the unit, N shows the notes. Optional extra: interactive figures, linked from the slides they support by a small ▸ chip; skip them freely.
section 1
The model the solver actually solves isn't the one you wrote.
27 · presolve · example
Sizes $3, 3, 2, 2, 2$ (total 12), capacity 5. Any bin holds a 3 and a 2, or two 2s, or one item.
| what | bins |
|---|---|
| first-fit decreasing: $\{3,2\}\{3,2\}\{2\}$ | 3 |
| area bound $\lceil 12/5 \rceil$ | 3 |
| Martello–Toth L2 | 3 |
| optimum | 3 |
Here the heuristic and the bounds already agree: 3 is proved without any search.
| model | LP |
|---|---|
| A: capacity constraints, separate $x \le y$ | 1.0 |
| B: capacity linked, $\text{load} \le 5\,y$ | 2.4 |
| F: arc flow | 2.5 |
A's LP spreads every item as ⅕ over five bins, each bin open only ⅕. B's LP is the area bound $12/5$. Arc flow's 2.5 rounds up to the optimum: the round-up property.
27 · presolve
| reduction | example |
|---|---|
| bound tightening | $x + 10y \le 12$, $y \in \{0,1\}$ ⇒ $x \le 12$ |
| coefficient tightening | $x \le 1000y$ with $x \le 50$ ⇒ $x \le 50y$ |
| dual fixing | a variable that only hurts the objective and only helps constraints → its bound |
| aggregation | $x = y + z$ substituted away |
| probing | fix a binary both ways and learn implications |
| clique detection | pairwise conflicts merged into one constraint |
Achterberg et al., "Presolve reductions in mixed integer programming", INFORMS JoC 32 (2020).
$y = 1 \Rightarrow a^\top x \le b$, stated as such. The solver chooses between big-M reformulation (with the tightest M it can derive), branching on the implication, or SOS1. It's often better, sometimes worse. Measure.
27 · presolve · example
Constraint 1 with $y \ge 0$ gives $x \le 12 - 10y \le 12$. The bound $x \le 50$ becomes $x \le 12$.
Constraint 2 only matters when $y = 0$, where it says $x \le 0$. When $y = 1$ it allows 1000, but $x$ can't exceed 12 anyway. So 1000 can shrink to 12: $x \le 12\,y$, the same integer solutions.
The point $x = 11$, $y = 0.011$ satisfies the original constraints: $11 + 0.11 \le 12$ and $11 \le 11$. After step 2 it needs $11 \le 0.132$: cut off.
Same integer points, a much tighter relaxation. That is the whole value of presolve, and why the tightening in step 2 needed step 1's bound first.
If $x$ had no upper bound (the "unbounded continuous variable" habit), constraint 1 still supplies $x \le 12$. Without it as well, nothing bounds $x$, and the 1000 has to stay.
section 2
The single biggest lever on many models.
27 · symmetry
In the assignment model (symmetry), any permutation of the bins maps a packing to another packing of the same cost. With 17 bins, every solution has up to 17! ≈ 3.6 × 10¹⁴ copies, and branch and bound can prove infeasibility of a subtree only by visiting its copies too.
Modern solvers detect symmetry themselves (SCIP: misc/usesymmetry). Explicit constraints can duplicate that work, or conflict with the solver's choice of representative.
Lab then, same linked model:
| variant | solved | SGM s |
|---|---|---|
| B SCIP symmetry handling on | 8/10 | 5.32 |
| B′ off | 8/10 | 4.00 |
| C on + your constraints | 9/10 | 3.80 |
Within noise: four seeds on one instance gave B 20, 15.3, 20, 1.7 s and B′ 1.6, 11.3, 2.8, 11.4 s.
27 · symmetry · example
Pack the five items into 3 labelled bins, 0, 1, 2. Count the assignments that use all three bins:
| what | count |
|---|---|
| different packings (bins unlabelled) | 12 |
| labellings of each packing | $3! = 6$ |
| optimal assignments the model sees | 72 |
| … with "item $i$ only in bins $0..i$" | 12 |
The constraint keeps exactly one labelling per packing: 72 copies become 12 solutions.
Packing $\{3_a, 2_a\}\ \{3_b, 2_b\}\ \{2_c\}$ as "bin of each item" (items in order $3_a, 3_b, 2_a, 2_b, 2_c$):
01012, 02021, 10102, 12120, 20201, 21210
Only 01012 has every item $i$ in a bin numbered at most $i$. A branch-and-bound tree proving "no 2-bin packing" would otherwise meet this packing six times.
section 3
Tell the solver what you know.
27 · what you know
| configuration | solved | SGM s | median nodes |
|---|---|---|---|
| A x ≤ y linking | 6/10 | 9.97 | 942 |
| B capacity linked | 8/10 | 5.32 | 870 |
| C + symmetry breaking | 9/10 | 3.80 | 598 |
| D + FFD bins, L2 fixing | 10/10 | 3.43 | 1 380 |
| E + FFD as a start | 9/10 | 3.02 | 1 576 |
| F arc flow | 10/10 | 1.40 | 1 |
10 instances, SCIP 10, 20 s limit, shift 1 s.
Arc flow's LP proves optimality at the root on these instances. On the triplet instances (C = 1000) its graph is ten times bigger and it's slower than C–E.
27 · what you know · example
A bin is a path from 0 to 5: its item arcs are its contents, loss arcs (along the line) are empty space. Thick: two bins "3 then 2". Dashed: one bin "waste 1, then 2, then 2".
2 units along $0 \xrightarrow{3} 3 \xrightarrow{2} 5$ and 1 unit along $0 \to 1 \xrightarrow{2} 3 \xrightarrow{2} 5$. Flow out of node 0 is 3: three bins.
Size-3 arcs carry 2 (two items of size 3), size-2 arcs carry $1 + 3 = 4 \ge 3$: the extra unit is a 2-slot left empty.
The graph has 3 + 4 item arcs and 5 loss arcs for capacity 5. At capacity 1000 it has thousands: the pseudo-polynomial size of the previous slide.
No bin labels appear anywhere, so there is no symmetry to break.
section 4
Where did the time go, and would it go there again?
27 · the log
| section | read it for |
|---|---|
| Presolvers | which reductions fired: fixed vars, deleted constraints, changed coefficients |
| Constraints | which constraint handlers did the propagating and separating |
| Separators | cuts found and applied per family; > rows split a separator by cut class |
| Primal Heuristics | which heuristic found solutions, and which found the best |
| Branching Rules | how many children, cutoffs and domain reductions |
| B&B Tree | nodes (total), depth, nodes left |
| Root Node | first LP value against the final dual bound: what cuts bought |
| Solution | primal and dual bounds, gap, found by <heuristic> |
Lab step 6 parses the statistics report into a dict and checks it against SCIP's API. Its traps: "nodes" appears twice, and "cut pool" isn't a separator.
27 · variability
Four SCIP random seeds on instances where consecutive configurations disagreed (seconds, 20 = limit):
| instance, step | before | after |
|---|---|---|
| triplets #1, A → B | 20 13.8 12.5 20 | 6.4 1.9 3.1 2.0 |
| triplets #3, B → B′ | 20 15.3 20 1.7 | 1.6 11.3 2.8 11.4 |
| uniform #3, B′ → C | 20 2.9 7.1 8.6 | 2.9 3.2 9.6 10.7 |
| uniform #2, D → E | 15.9 19.3 1.9 20 | 20 1.7 10.0 4.9 |
| uniform #2, E → F | 20 1.7 10.1 4.9 | 0.4 0.4 0.3 0.3 |
Linking (A → B) and reformulation (→ F). The rest are within noise on ten instances. Two runs of the whole script also disagreed on solved counts (A: 5 then 6; B: 9 then 8), because runs near the time limit flip.
MIP solvers are chaotic in the technical sense (performance variability): a tiny change (a seed, constraint order, a different but equivalent model) changes branching decisions early, and the tree grows differently from there. Lodi & Tramontani (2013) document this across solvers.
MIPLIB 2017 (Gleixner et al. 2021): 1 065 instances, a 240-instance benchmark set, and many still open. The shared reality check. then section 2 runs any MIPLIB files you download.
27 · lab
uv run co test 27
uv run co then 27 # seven configurations × ten instances · per-instance times · seed re-runs (≈ 30 min)
27 · checkpoint
Achterberg et al., INFORMS JoC 32 (2020).
Lodi & Tramontani, TutORials in OR (2013).
Margot, in 50 Years of Integer Programming (2010).
Delorme, Iori & Martello, EJOR 255 (2016).
28 experimental method: the harness, the plots, and an audit of earlier conclusions.