When the algorithm is a table

The argmin that cannot go backwards

The same triangular table, the same ninety-one cells, the same tree at the end of it — and 364 transitions one way against 156 the other. At 256 keys the ratio is 38. What removes the factor is not a property of the recurrence but a property of the numbers it is given, and the recurrence does not mention them.

The previous rung ended on a question rather than a result. An interval table’s cell considers every split point inside its own interval, that is where the cubic comes from, and nothing in the counter says whether all those candidates need examining.

They do not, and the reason is a sentence about the weights rather than about the algorithm: the split point that wins for an interval cannot lie to the left of the one that wins for the interval with one fewer key on the right, nor to the right of the one that wins for the interval with one fewer key on the left. Written down that way it sounds like bookkeeping. It removes a factor of nn.

The monotone range: 156 transitions over the same 91 cellsThe triangular table of an optimal binary search tree over 12 keys: one cell for each range of keys, nothing below the diagonal, and in each cell the number of split points the monotone rule left it to consider. 91 cells, 156 transitions, 1.7 per cell.01234567891011120123456789101112122332223333122222332231222222223122222233122222221222222122222122221222122121one unit = one subproblem given a value91 cells, 156 transitions, 1.7 per cell
Fig. 1 The same triangle as the previous rung, drawn under the monotone rule. Each cell’s number is no longer the length of its interval but the number of split points it actually has to examine — bounded above and below by what its two neighbours already found. The totals: ninety-one cells either way, 364 transitions before and 156 after, and the same tree at the end. What changed is not what is computed but how much of each cell’s search survives.

It is worth being clear about what is and is not being claimed, because the sentence is easy to over-read. Nothing is skipped. Every cell is still filled, every cell still gets the same number, and the tree that comes out is the same tree — the gate holds all three of those to equality at every size. What changes is the set of candidates each cell examines on the way to its number, and the claim is that the candidates outside a certain window cannot win. A search that never examines a losing candidate has lost nothing.

What the property says, and what it is a property of

Write K(i,j)K(i, j) for the split point that achieves the minimum for the interval [i,j)[i, j), choosing the leftmost when several tie. The claim is

K(i,j1)K(i,j)K(i+1,j)K(i, j-1) \le K(i, j) \le K(i+1, j)

for every interval, and both neighbours are intervals one key shorter — so by the time [i,j)[i, j) is filled, both bounds are already sitting in the table.

The inner loop then runs from K(i,j1)K(i, j-1) to K(i+1,j)K(i+1, j) instead of from ii to j1j-1. On any single cell that might save nothing at all. Across a whole diagonal it telescopes: the lower ends are non-decreasing and the upper ends are non-decreasing, so the total length of all the ranges on one diagonal is at most nn plus the number of cells on it. A diagonal costs O(n)O(n) transitions rather than O(n2)O(n^2), there are nn diagonals, and the computation is quadratic.

The important word in the claim is weights. The monotonicity is not true of interval recurrences in general; it is true when the weight function satisfies a quadrangle inequality — informally, that widening an interval on both sides costs at least as much as widening it on each side separately. A range’s total frequency satisfies it. Plenty of other weight functions do not, and for those the same recurrence over the same triangle really is cubic.

So this is the sharpest instance in the field of a rule this collection keeps meeting: a property of the numbers decides what is available to the algorithm, and the algorithm’s description does not contain the numbers. A distance that is not a distance is the same shape from the other side — there a cost matrix removes a guarantee a structure was relying on, here a weight function grants a shortcut nobody could see in the recurrence.

The telescoping is worth doing slowly once, because it is the whole of the saving and it is short. Fix a diagonal — all the intervals of length \ell — and walk it left to right. Cell [i,i+)[i, i+\ell) searches from K(i,i+1)K(i, i+\ell-1) to K(i+1,i+)K(i+1, i+\ell). The next cell along searches from K(i+1,i+)K(i+1, i+\ell) to K(i+2,i++1)K(i+2, i+\ell+1), and its lower bound is the previous cell’s upper bound. So the ranges are consecutive intervals of a non-decreasing sequence, they overlap only at endpoints, and their total length is at most the sequence’s whole span — which is nn — plus one per cell for the endpoints. That is O(n)O(n) per diagonal against O(n2)O(n^2), and it is the entire argument.

Transitions considered, against the number of keysEvery split point at a measured slope of 2.89; The monotone range at a measured slope of 2.03. The subproblems are the contiguous ranges of an index set, so there are n(n+1)/2 of them however the transitions behave. A slope near 3 is a cell whose cost grows with the interval; a slope near 2 is a cell that costs a constant, and the difference between them is a property of the cost function rather than of the recurrence.1010010010³10⁴10⁵keys in the interval tabletransitions consideredEvery split point · 2.89The monotone range · 2.03one unit = one subproblem given a valuetransitions considered, n from 8 to 128
Fig. 2 The two fills across a range of sizes, on the same logarithmic axes every growth claim on this site is fitted on. The slopes are three and two: 120 transitions against 67 at eight keys, and 2,829,056 against 74,275 at two hundred and fifty-six. Two curves with different slopes rather than two curves a constant apart, which is the difference between an optimisation and a change of class.

The saving, measured

The two fills are the same code with two lines changed, and both are run on the same weights at every size.

keys cells every split point monotone range ratio
8 45 120 67 1.79
16 153 816 273 2.99
32 561 5,984 1,125 5.32
64 2,145 45,760 4,562 10.03
128 8,385 357,760 18,374 19.47
256 33,153 2,829,056 74,275 38.09

The cell column is identical down the table, which is the check that matters. A version that skipped cells would evaluate less and answer differently; a version that narrowed the range by a constant would save a constant. Here the cells agree exactly, the answer agrees exactly, and the ratio doubles every time the key count doubles — which is a factor of nn and not a factor.

The ratio is not n/1n/1 but roughly n/6.7n/6.7, and the constant is worth a sentence rather than a shrug. The monotone version still pays one transition per cell even when the range collapses to a single candidate, so its cost is Θ(n2)\Theta(n^2) with a constant near one, and the cubic version’s cost is n3/6n^3/6 because the average interval is n/3n/3 long. The measured ratio is the quotient of those two, and it agrees.

The monotone range: 255 transitions over the same 153 cellsThe triangular table of an optimal binary search tree over 16 keys: one cell for each range of keys, nothing below the diagonal, and in each cell the number of split points the monotone rule left it to consider. 153 cells, 255 transitions, 1.7 per cell.0123456789101112131415160123456789101112131415161213311115111411123111455224411121114212131111224421213111123222213111122121131141222133114121331114123112441212231122231123211212123121one unit = one subproblem given a value153 cells, 255 transitions, 1.7 per cell
Fig. 3 Sixteen keys with frequencies drawn at random rather than following a smooth profile, filled under the monotone rule. The ranges are narrower in some places and wider in others than they were on the smooth weights, and the total is 255 against the 816 the interval lengths would have demanded. That the saving survives a rough weight profile is not obvious from the inequality — the inequality is about the weights being a range sum, and any range sum satisfies it however rough the individual frequencies are.

What that ratio does to the reachable problem size is the practical point. A cubic fill over a thousand keys is about 1.7×1081.7 \times 10^8 transitions, which is a few seconds and is fine; over ten thousand it is 1.7×10111.7 \times 10^{11}, which is not. The quadratic fill over ten thousand is 10810^8, back to a few seconds. The optimisation does not make a computation faster so much as it makes a size available, and the sizes it makes available are the ones a real key set has. That is the same distinction the table nobody has to keep draws about space: past a certain point a resource is not a cost that trades against another, it is a gate.

Why the bounds are already in the table

The elegance of the method is that it needs nothing stored beyond what it is already computing.

Filling by increasing interval length, the cell [i,j)[i, j) is reached after every shorter interval. Its two bounding neighbours, [i,j1)[i, j-1) and [i+1,j)[i+1, j), are both exactly one shorter. So the argmin table — one integer per cell, the same triangle again — is available in full, and the lookup is two array reads.

That costs a second table of n2/2n^2/2 integers, which is the entire price. In the accounting this field keeps, the monotone version has the same cell count, roughly twice the space, and a third fewer transitions at eight keys rising to a thirty-eighth at two hundred and fifty-six. It is the rare case where the space cost is a constant factor and the time saving is a factor of nn, and it is worth naming as rare, because most of the trades in this field go the other way — the table nobody has to keep buys a factor of nn in space and gives up the traceback to get it.

The fill order is also forced rather than chosen. Row order does not work here: filling [i,j)[i, j) before [i+1,j)[i+1, j) leaves one bound missing. The previous rung noted that an interval table has one degree of freedom in its order where an edit-distance table has three, and this is what the freedom was spent on — the order that makes the bounds available is the same order the dependencies already required, so the optimisation is free of any scheduling cost. That is worth contrasting with the rectangular case, where the same table, filled two ways found three valid orders and had to choose between them on other grounds; here there is one order and it happens to be the one this rung needs.

The monotone range: 67 transitions over the same 45 cellsThe triangular table of an optimal binary search tree over 8 keys: one cell for each range of keys, nothing below the diagonal, and in each cell the number of split points the monotone rule left it to consider. 45 cells, 67 transitions, 1.5 per cell.012345678012345678122332221222223122222122221222122121one unit = one subproblem given a value45 cells, 67 transitions, 1.5 per cell
Fig. 4 The eight-key table under the rule, small enough that the arithmetic can be checked by eye. Sixty-seven transitions across forty-five cells: about one and a half per cell, against the two and a third the interval lengths would have demanded. The cells beside the diagonal have nothing to search — one candidate — and the cells in the corner have a range of three or four where the interval is seven.

What it costs to have found this

Two of the three problems in the previous section were solved by somebody who already knew this trick, and the third — the alphabetic tree — was solved twice, once cubically and once quadratically, four years apart. That gap is the ordinary situation for a result of this kind and it is worth understanding why.

The recurrence is the same on both sides of the improvement. The table is the same. The answer is the same. Nothing about the program suggests that a smaller search would do, because the program’s text contains no information about the weights: it takes an array of numbers and consults them. The evidence that the range can be narrowed lives entirely in an inequality about what those numbers can be, and that inequality is not written anywhere the program can see.

This site has a name for the general case — the cost model is an input — and this is its sharpest instance. Most of the time a cost model decides what the answer is. Here it decides what the algorithm is allowed to skip, and the same source code is cubic or quadratic depending on a fact about the caller’s data that no type signature and no test could express.

What the check has to rule out

An optimisation that produces the right answer for the wrong reason is the ordinary failure here, and there are two obvious ways to get one.

The bounds can be transposed. Taking K(i+1,j)K(i+1, j) as the lower end and K(i,j1)K(i, j-1) as the upper is one character different, it is what the rule looks like when it is remembered rather than derived, and it produces a range that is usually empty or backwards. Fed that version, the same weights that give a tree of weighted cost 12,689 give 70,406 — a factor of 5.5, and an answer rather than a crash. The gate performs exactly that transposition and requires the wrong answer, because an optimisation whose failure mode is silent needs a test whose failure mode is not.

And the property can be assumed rather than held. Nothing in the code checks that the weights satisfy the inequality; the code narrows the range and trusts. On weights that do not satisfy it, the narrowed range can exclude the true optimum, and the computation returns a tree that is not the best one and no indication that anything happened. That is a genuine hazard and it is the reason this optimisation is described in the literature with its precondition attached and implemented in practice without it.

Every split point: 364 transitions over 91 cellsThe triangular table of an optimal binary search tree over 12 keys: one cell for each range of keys, nothing below the diagonal, and in each cell the number of split points filling it had to consider. 91 cells, 364 transitions, 4.0 per cell.01234567891011120123456789101112123456789101112123456789101112345678910123456789123456781234567123456123451234123121one unit = one subproblem given a value91 cells, 364 transitions, 4.0 per cell
Fig. 5 The cubic fill of the same table, for comparison: every cell searching its whole interval, three hundred and sixty-four transitions against a hundred and fifty-six. Both plates fill the same ninety-one cells with the same ninety-one numbers. Set them side by side and the only visible difference is the digits inside the cells, which is what an optimisation that changes a class rather than a result looks like when it is drawn.

The general form of that second hazard is worth stating, because it is the one this collection is most concerned with. An optimisation with a precondition has two failure modes and only one of them is visible. If the precondition is checked and fails, the program falls back and is slow. If it is not checked and fails, the program is fast and wrong, and nothing distinguishes its output from the right answer except knowing the right answer. The bound with a precondition makes exactly this point about a shortest-path algorithm on a graph with a negative arc — the answer that comes back is a number, it is plausible, and it is wrong on four vertices — and the shape here is identical with weights in place of arc costs.

The reason implementations ship it unchecked is also worth naming rather than tutting at. Verifying the quadrangle inequality directly means checking a condition over every quadruple of indices, which is Θ(n4)\Theta(n^4) — vastly more than the cubic fill the optimisation was meant to avoid. So there is no cheap check, only a proof about the particular weight function, and a proof lives in a paper rather than in a program. The precondition is unverifiable at run time in any useful sense, which is a real reason for its absence and not an excuse for it.

What else the same rule reaches

The property is not about search trees. It holds for a family of problems whose weight functions satisfy the same inequality, and three of them are worth naming because they are the ones people meet.

The optimal alphabetic tree — the same problem with the constraint that the keys keep their order in the tree, which is the case here.

A one-dimensional partition into kk pieces minimising a convex cost, which is what a histogram builder, a text justifier and a segmented regression all reduce to. The same telescoping applies along the piece index rather than along an interval length.

And the shortest-path formulation of a sequence alignment with a concave gap penalty, where the same argument gives O(n2logn)O(n^2 \log n) in place of O(n3)O(n^3) by a slightly different mechanism. That one sits directly beside a cell that has to know where it is, which reaches an affine gap by carrying three tables; a concave penalty cannot be reached that way at all, and the monotone argument is what makes it tractable instead.

What none of them shares is the recurrence’s shape, and that is the point worth carrying. These are not all interval dynamic programs. They are problems whose cost functions have a common property, and the property is what the optimisation attaches to. A technique that attaches to a property of the input rather than to the form of the recurrence is one nobody finds by staring at the loops, which is why it took until 1971 for this one to be written down and why it is absent from most implementations that would benefit.

There is one more reading of this rung that is worth having, and it connects to how this site grants classes at all. Every complexity claim here is fitted to measurements across three orders of magnitude and granted only if the fit holds, which is the discipline fitting a class to measurements sets out. Apply that discipline to the two fills and something slightly awkward appears: both of them fit something, the cubic version fits n3n^3 and the quadratic version fits n2n^2, and the fitting procedure has no way of knowing that the second one’s class depends on a property of its input.

Feed the same code weights that break the inequality and it will still fit n2n^2 — it will still narrow the range, still run quadratically, and still return an answer. The fit would be perfect and the answer would be wrong. A measured class is a statement about the runs that were measured, and where the class depends on a precondition, the sweep has to be run on inputs that satisfy it and on inputs that do not, or the fit is evidence about the generator rather than about the algorithm.

What the counter still cannot see

Two limits, and the second matters for anyone reading the ratio as a speedup.

A transition is one unit. The monotone version does slightly more work per candidate — two extra array reads to fetch the bounds — and the counter charges nothing for those. At a range of one candidate that overhead is a third of the cell’s cost, so the quadratic version’s constant is worse than the count suggests, and the crossover where it starts winning is a little later than the table implies. At sixteen keys it is already ahead by a factor of three, so nothing on the plate changes; at four keys it would not be.

The weights are a range sum and nothing else was tried. Every measurement here uses frequencies summed over an interval, which satisfies the inequality for a short and general reason. A weight function that satisfied it for a subtler reason, or that satisfied it only on some inputs, would be the interesting test case — and there is none on this page, so the plates are evidence that the optimisation works where it is known to work rather than evidence about its boundary. One run, four counts, four answers is the standing reminder that a measurement on one input family is a measurement of that family.

And the space is not counted here at all. The argmin table doubles the memory, and this field’s counter reports cells given a value rather than bytes allocated. That is the same gap measuring what an algorithm keeps exists to close for arrays, and it is not closed for a second table of integers sitting beside the first.

Where this ladder goes from here: the order that has a depth

Every fill on this page and the last is a sequence: one cell, then the next, in an order the dependencies permit. The count of transitions is a total over that sequence, and a total says nothing about what had to wait for what.

A table is the one place in this collection where that second question has an exact answer that needs no model of a machine. The recurrence is a directed acyclic graph over the cells; its longest path is the number of rounds that no amount of parallel work can get under; and a given fill order achieves some number of rounds between that path and the cell count. Three numbers of one computation, all of them integers, all of them the same on every machine.

The interval table’s own answer is worth having, because the length-ordered fill it is forced into is exactly a wavefront: every cell on the diagonal of length \ell depends only on shorter ones, so a whole diagonal is independent and the depth is nn against a cell count of n2/2n^2/2. This rung’s optimisation does not change that at all, and the fact that a factor-of-nn saving in transitions leaves the depth untouched is the clearest possible argument for measuring the two separately — which is the next rung, taken on the rectangular table where the three orders can be compared.

Named alongside this one

Essays reaching for the same objects. Nobody chose these; they are what the concept index makes visible.

What links here

Every essay whose body links to this one.

The objects this essay names

Each one links to every other essay that touches it.

Complexity classCost modelDynamic programmingInterval dpMeasured countMonotonicityOptimal binary search treePruningQuadrangle inequalityRecurrenceSubproblemTransitions